| 
		     | 
		
		| (One intermediate revision not shown) | 
| Line 1: | 
Line 1: | 
| - | Before using this script, please make sure to read [[API General Examples|API General Examples]]
  | + | The script and additional documentation have been moved to our [https://support.openprovider.eu/hc/en-us/articles/360019994414 Knowledge Base]  | 
| - |    | + |  | 
| - | Using this script is at your own risk!
  | + |  | 
| - |    | + |  | 
| - |  <?php
  | + |  | 
| - |  
  | + |  | 
| - |    $help = "Available parameters:
  | + |  | 
| - |  -f: (required) name of file containing domains to transfer
  | + |  | 
| - |  -d: (optional) how to handle DNS zones; allowed values:
  | + |  | 
| - |      0: (default) do not create DNS zones in Openprovider; use existing
  | + |  | 
| - |         nameservers
  | + |  | 
| - |      1: create DNS zones in Openprovider based on TransIP DNS records;
  | + |  | 
| - |         put the domain on the Openprovider nameservers after transfer;
  | + |  | 
| - |         existing zones will not be overwritten
  | + |  | 
| - |      overwrite: create DNS zones, overwrite any existing zones
  | + |  | 
| - |  -h: (optional) how to handle contacts; allowed values:
  | + |  | 
| - |      0: (default) the script checks if another TransIP contact with the
  | + |  | 
| - |         same data was processed before; if so, re-use that contact instead
  | + |  | 
| - |         of creating a new one
  | + |  | 
| - |      1: create a new Openprovider handle for every domain contact, even if
  | + |  | 
| - |         the data is similar to a previously processed contact
  | + |  | 
| - |  -v: (optional) whether or not to show extended information during runtime;
  | + |  | 
| - |      allowed values:
  | + |  | 
| - |      0: (default) don't show additional ouput
  | + |  | 
| - |      1: show additional ouput
  | + |  | 
| - |  -t: (optional) whether to run in test mode or not; allowed values:
  | + |  | 
| - |      0: run live
  | + |  | 
| - |      1: (default) run in test mode / read-only; no contacts or zones will
  | + |  | 
| - |         be created, no domains will be transferred
  | + |  | 
| - |  
  | + |  | 
| - |  Examples:
  | + |  | 
| - |    Run in test mode, full debugging output:
  | + |  | 
| - |      php transfer-from-transip.php -f domains.txt -v1 -t1
  | + |  | 
| - |  
  | + |  | 
| - |    Run in live mode: transfer domains while create DNS zones (but do not
  | + |  | 
| - |    overwrite existing ones), show limited output:
  | + |  | 
| - |      php transfer-from-transip.php -f domains.txt -t0 -d1
  | + |  | 
| - |  
  | + |  | 
| - |  Full documentation is available at https://openprovider.zendesk.com/hc/en-us/articles/360019994414
  | + |  | 
| - |  ";
  | + |  | 
| - |  
  | + |  | 
| - |    // Openprovider API credentials
  | + |  | 
| - |    $auth = array('username' => $op_user, 'hash' => $op_hash);
  | + |  | 
| - |  
  | + |  | 
| - |    // TransIP and Openprovider API
  | + |  | 
| - |    require_once('Transip/DomainService.php');
  | + |  | 
| - |    require_once('API.php');
  | + |  | 
| - |    $api = new OP_API ('https://api.openprovider.eu');
  | + |  | 
| - |  
  | + |  | 
| - |    // Read runtime parameters
  | + |  | 
| - |    $opts = getopt('f:d:t:h:v:', array('help'));
  | + |  | 
| - |    $domainFile      = $opts['f']; // filename (required)
  | + |  | 
| - |    $withDns         = $opts['d']; // 0, 1 or overwrite (default = 0)
  | + |  | 
| - |    $forceNewHandles = $opts['h']; // 0 or 1 (default = 0)
  | + |  | 
| - |    $verbose         = $opts['v']; // 0 or 1 (default = 0)
  | + |  | 
| - |    $testMode        = $opts['t']; // 0 or 1 (default = 1)
  | + |  | 
| - |  
  | + |  | 
| - |    if (isset($opts['help'])) {
  | + |  | 
| - |      echo $help;
  | + |  | 
| - |      exit;
  | + |  | 
| - |    }
  | + |  | 
| - |  
  | + |  | 
| - |  
  | + |  | 
| - |    // Get list with domains to transfer
  | + |  | 
| - |    if (file_exists($domainFile)) {
  | + |  | 
| - |      $domains = file($domainFile, FILE_IGNORE_NEW_LINES);
  | + |  | 
| - |    }
  | + |  | 
| - |    else {
  | + |  | 
| - |      die("Cannot find domain list; file [$f] does not exist\n");
  | + |  | 
| - |    }
  | + |  | 
| - |  
  | + |  | 
| - |    // Check other parameters
  | + |  | 
| - |    if (!in_array($withDns, array(0, 1, 'overwrite'))) {
  | + |  | 
| - |      $withDns = 0;
  | + |  | 
| - |    }
  | + |  | 
| - |    if (!in_array($testMode, array(0, 1))) {
  | + |  | 
| - |      $testMode = 1;
  | + |  | 
| - |    }
  | + |  | 
| - |    if (!in_array($forceNewHandles, array(0, 1))) {
  | + |  | 
| - |      $forceNewHandles = 0;
  | + |  | 
| - |    }
  | + |  | 
| - |    if (!in_array($verbose, array(0, 1))) {
  | + |  | 
| - |      $verbose = 0;
  | + |  | 
| - |    }
  | + |  | 
| - |  
  | + |  | 
| - |    // Keep track of handles that were already created
  | + |  | 
| - |    $handleRelations = array();
  | + |  | 
| - |    if (!$forceNewHandles) {
  | + |  | 
| - |      if (file_exists('transip-handle-relations.dat')) {
  | + |  | 
| - |        if ($f = fopen('transip-handle-relations.dat', 'r')) {
  | + |  | 
| - |          while (!feof($f)) {
  | + |  | 
| - |            list($md5, $opHandle) = fgetcsv($f);
  | + |  | 
| - |            $handleRelations[$md5] = $opHandle;
  | + |  | 
| - |          }
  | + |  | 
| - |          fclose($f);
  | + |  | 
| - |        }
  | + |  | 
| - |        else {
  | + |  | 
| - |          die("Cannot open file transip-handle-relations.dat\n");
  | + |  | 
| - |        }
  | + |  | 
| - |      }
  | + |  | 
| - |      $fHandles = fopen('transip-handle-relations.dat', 'a');
  | + |  | 
| - |    }
  | + |  | 
| - |  
  | + |  | 
| - |    foreach ($domains as $dom) {
  | + |  | 
| - |      $continue = true;
  | + |  | 
| - |  
  | + |  | 
| - |      if ($verbose) {
  | + |  | 
| - |        echo "Starting domain $dom\n";
  | + |  | 
| - |        echo "Retrieve data for domain $dom from TransIP API\n";
  | + |  | 
| - |      }
  | + |  | 
| - |      try {
  | + |  | 
| - |        $domain = Transip_DomainService::getInfo($dom);
  | + |  | 
| - |        if ($verbose) {
  | + |  | 
| - |          echo "TransIP returned the following data for domain $dom:\n";
  | + |  | 
| - |          print_r($domain);
  | + |  | 
| - |        }
  | + |  | 
| - |      }
  | + |  | 
| - |      catch(SoapFault $e) {
  | + |  | 
| - |        // It is possible that an error occurs when connecting to the TransIP Soap API,
  | + |  | 
| - |        // those errors will be thrown as a SoapFault exception.
  | + |  | 
| - |        echo "@@ERROR: An error occurred while querying the TransIP API for domain [$dom]: ".htmlspecialchars($e->getMessage())."\n";
  | + |  | 
| - |        continue;
  | + |  | 
| - |      }
  | + |  | 
| - |  
  | + |  | 
| - |      $args = array();
  | + |  | 
| - |      
  | + |  | 
| - |      // Nameservers
  | + |  | 
| - |      if ($verbose) {
  | + |  | 
| - |        echo "Preparing nameservers for domain [$dom]\n";
  | + |  | 
| - |      }
  | + |  | 
| - |      if ($withDns) {
  | + |  | 
| - |        if (!$domain->dnsEntries) {
  | + |  | 
| - |          echo "@@ERROR: no DNS entries found for import in Openprovider for $dom; skipping this domain\n";
  | + |  | 
| - |          continue;
  | + |  | 
| - |        }
  | + |  | 
| - |        if (createOpenproviderZone($dom, $domain->dnsEntries)) {
  | + |  | 
| - |          $args['nsGroup'] = 'dns-openprovider';
  | + |  | 
| - |        }
  | + |  | 
| - |        else {
  | + |  | 
| - |          echo "@@ERROR: while creating DNS zone for $dom; skipping this domain\n";
  | + |  | 
| - |          continue;
  | + |  | 
| - |        }
  | + |  | 
| - |      }
  | + |  | 
| - |      else {
  | + |  | 
| - |        if (isset($domain->nameservers)) {
  | + |  | 
| - |          foreach ($domain->nameservers as $ns) {
  | + |  | 
| - |            $args['nameServers'][] = array(
  | + |  | 
| - |              'name' => $ns->hostname,
  | + |  | 
| - |              'ip'   => (isset($ns->ipv4) ? $ns->ipv4 : NULL),
  | + |  | 
| - |              'ip6'  => (isset($ns->ipv6) ? $ns->ipv6 : NULL),
  | + |  | 
| - |            );
  | + |  | 
| - |          }
  | + |  | 
| - |        }
  | + |  | 
| - |      }
  | + |  | 
| - |  
  | + |  | 
| - |      // Contacts (handles)
  | + |  | 
| - |      if ($verbose) {
  | + |  | 
| - |        echo "Preparing contact handles for domain [$dom]\n";
  | + |  | 
| - |      }
  | + |  | 
| - |      foreach ($domain->contacts as $contact) {
  | + |  | 
| - |        $type = '';
  | + |  | 
| - |        switch ($contact->type) {
  | + |  | 
| - |          case 'registrant'     : $type = 'owner'; break;
  | + |  | 
| - |          case 'administrative' : $type = 'admin'; break;
  | + |  | 
| - |          case 'technical'      : $type = 'tech'; break;
  | + |  | 
| - |          default               : echo "@@WARNING: invalid contact type ".$contact->type." for domain [$dom]; skipping\n"; break;
  | + |  | 
| - |        }
  | + |  | 
| - |        unset($contact->type);
  | + |  | 
| - |  
  | + |  | 
| - |        $hash = md5(implode('', get_object_vars($contact)));
  | + |  | 
| - |        if (!$forceNewHandles && isset($handleRelations[$hash])) {
  | + |  | 
| - |          $opHandle = $handleRelations[$hash];
  | + |  | 
| - |        }
  | + |  | 
| - |        else {
  | + |  | 
| - |          if ($opHandle = createOpenproviderContact($contact)) {
  | + |  | 
| - |            if (!$testMode) {
  | + |  | 
| - |              fwrite($fHandles, $hash.','.$opHandle."\n");
  | + |  | 
| - |              $handleRelations[$hash] = $opHandle;
  | + |  | 
| - |            }
  | + |  | 
| - |          }
  | + |  | 
| - |          else {
  | + |  | 
| - |            echo "@@ERROR while creating Openprovider contact for $type of $dom\n";
  | + |  | 
| - |            $continue = false;
  | + |  | 
| - |            continue 2;
  | + |  | 
| - |          }
  | + |  | 
| - |        }
  | + |  | 
| - |        $args[$type.'Handle'] = $opHandle;
  | + |  | 
| - |      }
  | + |  | 
| - |  
  | + |  | 
| - |      // Authcode
  | + |  | 
| - |      $args['authCode'] = $domain->authCode;
  | + |  | 
| - |  
  | + |  | 
| - |      // Unlock domain, if required
  | + |  | 
| - |      if ($verbose) {
  | + |  | 
| - |        echo "Unlocking domain [$dom] (if applicable)\n";
  | + |  | 
| - |      }
  | + |  | 
| - |      if ($domain->isLocked) {
  | + |  | 
| - |        if ($testMode) {
  | + |  | 
| - |          echo "TEST MODE: skipping unlocking domain\n";
  | + |  | 
| - |        }
  | + |  | 
| - |        else {
  | + |  | 
| - |          try {
  | + |  | 
| - |            $isLocked = Transip_DomainService::unsetLock($dom);
  | + |  | 
| - |          }
  | + |  | 
| - |          catch(SoapFault $e)
  | + |  | 
| - |          {
  | + |  | 
| - |            // It is possible that an error occurs when connecting to the TransIP Soap API,
  | + |  | 
| - |            // those errors will be thrown as a SoapFault exception.
  | + |  | 
| - |            echo "@@ERROR: An error occurred while unlocking domain [$dom]: " . htmlspecialchars($e->getMessage())."\n";
  | + |  | 
| - |          }
  | + |  | 
| - |        }
  | + |  | 
| - |      }
  | + |  | 
| - |  
  | + |  | 
| - |      list($d, $e) = explode('.', $dom, 2);
  | + |  | 
| - |      $args['domain'] = array(
  | + |  | 
| - |        'name' => $d,
  | + |  | 
| - |        'extension' => $e,
  | + |  | 
| - |      );
  | + |  | 
| - |      $args['period'] = 1;
  | + |  | 
| - |  
  | + |  | 
| - |      if ($verbose) {
  | + |  | 
| - |        echo "Start transfer for domain [$dom] in Openprovider with the following data array:\n";
  | + |  | 
| - |        print_r($args);
  | + |  | 
| - |      }
  | + |  | 
| - |      if ($testMode) {
  | + |  | 
| - |        echo "TEST MODE: skip domain transfer for [$dom]\n";
  | + |  | 
| - |      }
  | + |  | 
| - |      else {
  | + |  | 
| - |        $request = new OP_Request;
  | + |  | 
| - |        $request->setCommand('transferDomainRequest')
  | + |  | 
| - |          ->setAuth($auth)
  | + |  | 
| - |          ->setArgs($args);
  | + |  | 
| - |        $reply = $api->process($request);
  | + |  | 
| - |        if ($reply->getFaultCode() != 0) {
  | + |  | 
| - |          echo "@@ERROR on domain transfer [$dom]: ".$reply->getFaultCode().' - '.$reply->getFaultString()."\n";
  | + |  | 
| - |          if ($verbose) {
  | + |  | 
| - |            echo "Full data array:\n";
  | + |  | 
| - |            print_r($args);
  | + |  | 
| - |          }
  | + |  | 
| - |        }
  | + |  | 
| - |        else {
  | + |  | 
| - |          echo "Transfer for $dom successfully requested\n";
  | + |  | 
| - |        }
  | + |  | 
| - |      }
  | + |  | 
| - |    }
  | + |  | 
| - |  
  | + |  | 
| - |    function createOpenproviderZone($domain, $dnsEntries) {
  | + |  | 
| - |      global $api, $auth;
  | + |  | 
| - |      global $testMode, $withDns, $verbose;
  | + |  | 
| - |  
  | + |  | 
| - |      list($d, $e) = explode('.', $domain, 2);
  | + |  | 
| - |  
  | + |  | 
| - |      // Check if a zone already exists
  | + |  | 
| - |      $request = new OP_Request;
  | + |  | 
| - |      $request->setCommand('retrieveZoneDnsRequest')
  | + |  | 
| - |        ->setAuth($auth)
  | + |  | 
| - |        ->setArgs(array(
  | + |  | 
| - |          'name' => $domain,
  | + |  | 
| - |          'withRecords' => false,
  | + |  | 
| - |          'withHistory' => false
  | + |  | 
| - |        ));
  | + |  | 
| - |      $reply = $api->process($request);
  | + |  | 
| - |      $response = $reply->getValue();
  | + |  | 
| - |      if ($response) {
  | + |  | 
| - |        if ($withDns == 'overwrite') {
  | + |  | 
| - |          if ($testMode) {
  | + |  | 
| - |            echo "@@WARNING: TEST MODE: Zone for [$domain] already exists, skip removing of existing zone\n";
  | + |  | 
| - |          }
  | + |  | 
| - |          else {
  | + |  | 
| - |            echo "@@WARNING: Zone for [$domain] already exists; removing existing zone\n";
  | + |  | 
| - |  
  | + |  | 
| - |            $request = new OP_Request;
  | + |  | 
| - |            $request->setCommand('deleteZoneDnsRequest')
  | + |  | 
| - |              ->setAuth($auth)
  | + |  | 
| - |              ->setArgs(array(
  | + |  | 
| - |                'domain' => array(
  | + |  | 
| - |                  'name' => $d,
  | + |  | 
| - |                  'extension' => $e
  | + |  | 
| - |                ),
  | + |  | 
| - |              ));
  | + |  | 
| - |            $reply = $api->process($request);
  | + |  | 
| - |            $response = $reply->getValue();
  | + |  | 
| - |          }
  | + |  | 
| - |        }
  | + |  | 
| - |        else {
  | + |  | 
| - |          echo "@@WARNING: Zone for [$domain] already exists; skipping import\n";
  | + |  | 
| - |        }
  | + |  | 
| - |      }
  | + |  | 
| - |  
  | + |  | 
| - |      $records = array();
  | + |  | 
| - |      foreach ($dnsEntries as $record) {
  | + |  | 
| - |        if (in_array($record->type, array('NS', 'SOA'))) {
  | + |  | 
| - |          continue;
  | + |  | 
| - |        }
  | + |  | 
| - |  
  | + |  | 
| - |        if (in_array($record->type, array('MX', 'SRV'))) {
  | + |  | 
| - |          list($prio, $value) = explode(' ', $record->content, 2);
  | + |  | 
| - |        }
  | + |  | 
| - |        else {
  | + |  | 
| - |          $prio = NULL;
  | + |  | 
| - |          $value = $record->content;
  | + |  | 
| - |        }
  | + |  | 
| - |  
  | + |  | 
| - |        $records[] = array(
  | + |  | 
| - |          'type'  => $record->type,
  | + |  | 
| - |          'name'  => ($record->name == '@' ? '' : $record->name),
  | + |  | 
| - |          'value' => ($value == '@' ? $domain : $value),
  | + |  | 
| - |          'prio'  => $prio,
  | + |  | 
| - |          'ttl'   => ($record->expire < 600 ? 600 : $record->expire),
  | + |  | 
| - |        );
  | + |  | 
| - |      }
  | + |  | 
| - |  
  | + |  | 
| - |      if ($testMode) {
  | + |  | 
| - |        echo "TEST MODE - skip DNS zone creation for $domain\n";
  | + |  | 
| - |        if ($verbose) {
  | + |  | 
| - |          echo "Zone contents:\n";
  | + |  | 
| - |          print_r($records);
  | + |  | 
| - |        }
  | + |  | 
| - |        return true;
  | + |  | 
| - |      }
  | + |  | 
| - |      else {
  | + |  | 
| - |        $request = new OP_Request;
  | + |  | 
| - |        $request->setCommand('createZoneDnsRequest')
  | + |  | 
| - |          ->setAuth($auth)
  | + |  | 
| - |          ->setArgs(array(
  | + |  | 
| - |            'domain' => array(
  | + |  | 
| - |              'name' => $d,
  | + |  | 
| - |              'extension' => $e,
  | + |  | 
| - |            ),
  | + |  | 
| - |            'type' => 'master',
  | + |  | 
| - |            'records' => $records,
  | + |  | 
| - |          ));
  | + |  | 
| - |        $reply = $api->process($request);
  | + |  | 
| - |        if ($reply->getFaultCode() != 0) {
  | + |  | 
| - |          echo "@@ERROR on DNS zone creation for [$domain]: ".$reply->getFaultCode().' - '.$reply->getFaultString()."; full data array:\n";
  | + |  | 
| - |          print_r($records);
  | + |  | 
| - |          return false;
  | + |  | 
| - |        }
  | + |  | 
| - |        else {
  | + |  | 
| - |          if ($verbose) {
  | + |  | 
| - |            echo "DNS zone for $domain successfully created with the following records:\n";
  | + |  | 
| - |            print_r($records);
  | + |  | 
| - |          }
  | + |  | 
| - |          return true;
  | + |  | 
| - |        }
  | + |  | 
| - |      }
  | + |  | 
| - |    }
  | + |  | 
| - |    
  | + |  | 
| - |    function createOpenproviderContact($contact) {
  | + |  | 
| - |      global $api, $auth;
  | + |  | 
| - |      global $testMode, $verbose;
  | + |  | 
| - |  
  | + |  | 
| - |      // Split telephone number
  | + |  | 
| - |      // Country code separated?
  | + |  | 
| - |      $matches = array();
  | + |  | 
| - |      if (preg_match('/^(\+?\d+)[ \-\.](.*)$/', $contact->phoneNumber, $matches)) {
  | + |  | 
| - |        $tel1 = (substr($matches[1], 0, 1) == '+' ? '' : '+').$matches[1];
  | + |  | 
| - |        $rest = preg_replace('/[^\d]/', '', $matches[2]);
  | + |  | 
| - |      }
  | + |  | 
| - |      // Else consider first 2 numbers the country code
  | + |  | 
| - |      else {
  | + |  | 
| - |        $tel = preg_replace('/[^\d]/', '', $contact->phoneNumber);
  | + |  | 
| - |        $tel1 = '+'.substr($tel, 0, 2);
  | + |  | 
| - |        $rest = $matches[2];
  | + |  | 
| - |      }
  | + |  | 
| - |      $tel2 = substr($rest, 0, 2);
  | + |  | 
| - |      $tel3 = substr($rest, 2);
  | + |  | 
| - |  
  | + |  | 
| - |      // Split address number
  | + |  | 
| - |      $matches = array();
  | + |  | 
| - |      if (preg_match('/^\d+$/', $contact->number)) {
  | + |  | 
| - |        $number = $contact->number;
  | + |  | 
| - |        $suffix = NULL;
  | + |  | 
| - |      }
  | + |  | 
| - |      else if (preg_match('/^(\d+)([^\d].*)$/', $contact->number, $matches)) {
  | + |  | 
| - |        $number = $matches[1];
  | + |  | 
| - |        $suffix = $matches[2];
  | + |  | 
| - |      }
  | + |  | 
| - |      else {
  | + |  | 
| - |        $number = 1;
  | + |  | 
| - |        $suffix = $contact->number;
  | + |  | 
| - |      }
  | + |  | 
| - |  
  | + |  | 
| - |      $args = array(
  | + |  | 
| - |        'companyName' => $contact->companyName,
  | + |  | 
| - |        'name' => array(
  | + |  | 
| - |          'firstName' => $contact->firstName,
  | + |  | 
| - |          'prefix' => $contact->middleName,
  | + |  | 
| - |          'lastName' => $contact->lastName,
  | + |  | 
| - |        ),
  | + |  | 
| - |        'phone' => array(
  | + |  | 
| - |          'countryCode' => $tel1,
  | + |  | 
| - |          'areaCode' => $tel2,
  | + |  | 
| - |          'subscriberNumber' => $tel3,
  | + |  | 
| - |        ),
  | + |  | 
| - |        'address' => array(
  | + |  | 
| - |           'street' => $contact->street,
  | + |  | 
| - |           'number' => $number,
  | + |  | 
| - |           'suffix' => $suffix,
  | + |  | 
| - |           'zipcode' => $contact->postalCode,
  | + |  | 
| - |           'city' => $contact->city,
  | + |  | 
| - |           'country' => strtoupper($contact->country),
  | + |  | 
| - |        ),
  | + |  | 
| - |        'email' => $contact->email,
  | + |  | 
| - |        'additionalData' => ($contact->companyKvk ? array('companyRegistrationNumber' => $contact->companyKvk) : NULL),
  | + |  | 
| - |      );
  | + |  | 
| - |  
  | + |  | 
| - |      if ($testMode) {
  | + |  | 
| - |        echo "TEST MODE - skip handle creation\n";
  | + |  | 
| - |        if ($verbose) {
  | + |  | 
| - |          echo "Handle details are the following:\n";
  | + |  | 
| - |          print_r($args);
  | + |  | 
| - |        }
  | + |  | 
| - |        return true;
  | + |  | 
| - |      }
  | + |  | 
| - |      else {
  | + |  | 
| - |        $request = new OP_Request;
  | + |  | 
| - |        $request->setCommand('createCustomerRequest')
  | + |  | 
| - |          ->setAuth($auth)
  | + |  | 
| - |          ->setArgs($args);
  | + |  | 
| - |        $reply = $api->process($request);
  | + |  | 
| - |        if ($reply->getFaultCode() != 0) {
  | + |  | 
| - |          echo "@@ERROR on contact creation for [$domain]: ".$reply->getFaultCode().' - '.$reply->getFaultString()."; full data array:\n";
  | + |  | 
| - |          print_r($args);
  | + |  | 
| - |          return false;
  | + |  | 
| - |        }
  | + |  | 
| - |        else {
  | + |  | 
| - |          $response = $reply->getValue();
  | + |  | 
| - |          if ($verbose) {
  | + |  | 
| - |            echo "Successfully created handle ".$response['handle']."\n";
  | + |  | 
| - |          }
  | + |  | 
| - |          return $response['handle'];
  | + |  | 
| - |        }
  | + |  | 
| - |      }
  | + |  | 
| - |    }
  | + |  | 
| - |  
  | + |  | 
| - |  ?>
  | + |  |