array( 'friendlyName' => 'Host', 'validators' => array( 'required' => 'required', ) ), 'username' => array( 'friendlyName' => 'Username', 'validators' => array( 'required' => 'required', ) ), 'password' => array( 'friendlyName' => 'Password', 'type'=> 'password', 'validators' => array( 'required' => 'required', ) ), 'substriction_domain' => array( 'friendlyName' => 'Subscription Domain', 'validators' => array( 'required' => 'required', ) ), 'default_ip' => array( 'friendlyName' => 'Default IP', 'validators' => array( 'pattern' => Patterns::IP4_OR_IP6, ) ), ); public $availableTypes = array('A', 'AAAA', 'NS', 'MX', 'CNAME', 'TXT', 'SRV', 'PTR'); private $webspace_id = null; private function get($packet) { $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, "https://{$this->config['host']}:8443/enterprise/control/agent.php"); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_POSTFIELDS, $packet); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($curl, CURLOPT_HTTPHEADER, array( "HTTP_AUTH_LOGIN: {$this->config['username']}", "HTTP_AUTH_PASSWD: {$this->config['password']}", "HTTP_PRETTY_PRINT: TRUE", "Content-Type: text/xml") ); $retval = curl_exec($curl); if (curl_errno($curl)) { throw new exceptions\DNSSubmoduleException("cURL Error: " . curl_errno($curl) . " - " . curl_error($curl), dns\SubmoduleExceptionCodes::CONNECTION_PROBLEM); } curl_close($curl); @$result = simplexml_load_string($retval); if($result===FALSE) { throw new exceptions\DNSSubmoduleException('Unable to parse response', dns\SubmoduleExceptionCodes::INVALID_RESPONSE); } if($result->system->status == 'error') { throw new exceptions\DNSSubmoduleException((string)$result->system->errtext, dns\SubmoduleExceptionCodes::COMMAND_ERROR); } return $result; } public function testConnection(){ $this->webspace_id= $this->getWebspaceID(); $ok = $this->webspace_id !== false && $this->webspace_id > 0; return true; } private function getWebspaceID(){ if(empty($this->config['substriction_domain'])){ throw new exceptions\DNSSubmoduleException('Invalid substriction domain in configuration', dns\SubmoduleExceptionCodes::INVALID_PARAMETERS); } $packet = ' '.$this->config['substriction_domain'].' '; $return = $this->get($packet); if(isset($return->webspace->get->result->id)){ return (string)$return->webspace->get->result->id; }else{ if($return->webspace->get->result->errcode == 1013){ throw new exceptions\DNSSubmoduleException('Substriction domain does not exist', dns\SubmoduleExceptionCodes::COMMAND_ERROR); } $this->throwError($return->webspace->get->result); } } private function throwError($result) { if($result->status == 'error') { throw new exceptions\DNSSubmoduleException((string)$result->errtext, dns\SubmoduleExceptionCodes::COMMAND_ERROR); } else if (strpos($result, 'Please') !== false) { throw new exceptions\DNSSubmoduleException($result, dns\SubmoduleExceptionCodes::COMMAND_ERROR); } else { throw new exceptions\DNSSubmoduleException('Unexpected error', dns\SubmoduleExceptionCodes::COMMAND_ERROR); } } private function getDomainInfo(){ $packet = ' '.$this->domain.' '; $return = $this->get($packet); if(isset($return->site->get->result->result->id)){ return (int)$return->site->get->result->result->id; }elseif($return->site->get->result->status == 'ok'){ return (int)$return->site->get->result->id; }else{ $this->throwError($return->site->get->result); } } public function getRecords($recordType = false) { $domain_id = $this->getDomainInfo(); if($domain_id === false || $domain_id <= 0) return false; $packet = ' '.$domain_id.' '; $return = $this->get($packet); $out = array(); if((string)$return->dns->get_rec->result->status == 'ok'){ foreach($return->dns->get_rec->result as $record_data){ $type = strtoupper((string)$record_data->data->type); if(in_array($type, $recordType!==false ? array(strtoupper($recordType)) : $this->getAvailableRecordTypes())) { $record = new dns\record\Record(); $record->line = (string)$record_data->id; $record->name = (string)$record_data->data->host; $record->type = $type; $record->createRDATAObject($type); switch($type) { case 'MX': $record->rdata->preference = (string)$record_data->data->opt; $record->rdata->exchange = (string)$record_data->data->value; break; case 'SRV': $record->rdata->fromString((string)$record_data->data->opt . ' ' . (string)$record_data->data->value); break; case 'PTR': if($record_data->data->opt) $record->name .= "/" . $record_data->data->opt; $record->rdata->setFirstProperty((string)$record_data->data->value); break; default: $record->rdata->setFirstProperty((string)$record_data->data->value); break; } $out[] = $record; } } } else { $this->throwError($return->dns->get_rec->result); } return $out; } public function addRecord(dns\record\Record $record) { $domain_id = $this->getDomainInfo(); if($domain_id === false || $domain_id <= 0) return false; switch($record->type) { case 'MX': $value = $record->rdata->exchange; $opt = $record->rdata->preference; break; case 'SRV': $value = $record->rdata->target; $opt = str_replace("\t", ' ', $record->rdata->toString(['priority','weight','port'])); break; case 'TXT': $value = trim($record->rdata->toString(), '"'); $opt = ''; break; default: $value = $record->rdata->toString(); $opt = ''; break; } if($record->type === 'PTR') { $host = str_replace('@', '', $record->nameToRelative($this->domain)); $opt = explode('/',$host)[1]; if(!($opt == '8' || $opt =='16' || $opt =='24')) $this->throwError('Please specify the subnet mask for the IP. Right now Plesk supports only the 8, 16 and 24 masks.'); $host = explode('/',$host)[0]; $packet = ' ' . $domain_id . ' ' . $record->type . ' ' . $host . ' ' . $value . ' ' . (!empty($opt) ? "$opt" : '') . ' '; } else { $packet = ' ' . $domain_id . ' ' . $record->type . ' ' . str_replace('@', '', $record->nameToRelative($this->domain)) . ' ' . $value . ' ' . (!empty($opt) ? "$opt" : '') . ' '; } $return = $this->get($packet); if((string)$return->dns->add_rec->result->status === 'ok'){ return true; } $this->throwError($return->dns->add_rec->result); } public function editRecord(dns\record\Record $record) { $this->deleteRecord($record); $record->nameToAbsolute($this->domain); $this->addRecord($record); } public function deleteRecord(dns\record\Record $record) { $packet = ' '.$record->line.' '; $return = $this->get($packet); if((string)$return->dns->del_rec->result->status == 'ok'){ return true; } $this->throwError($return->dns->del_rec->result); } public function zoneExists() { try { $domain_id = $this->getDomainInfo(); } catch (exceptions\DNSSubmoduleException $e) { if($e->getCode() == dns\SubmoduleExceptionCodes::COMMAND_ERROR) { return false; } throw $e; } return $domain_id !== false && $domain_id > 0; } public function activateZone() { if(empty($this->webspace_id)){ $this->webspace_id = $this->getWebspaceID(); } if(empty($this->webspace_id)){ return false; //TODO: error? } $packet = ' '.$this->domain.' '.$this->webspace_id.' '; $return = $this->get($packet); if((string)$return->site->add->result->status == 'ok'){ return true; } $this->throwError($return->site->add->result); } public function terminateZone() { if($this->domain == $this->config['substriction_domain']){ throw new exceptions\DNSSubmoduleException('You cannot delete subscription domain', dns\SubmoduleExceptionCodes::INVALID_PARAMETERS); } if(empty($this->webspace_id)){ $this->webspace_id = $this->getWebspaceID(); } if(empty($this->webspace_id)){ return false; } $packet = ' '.$this->domain.' '; $return = $this->get($packet); if((string)$return->site->del->result->status == 'ok'){ return true; } $this->throwError($return->site->del->result); } public function getZones() { $packet = ' '; $return = $this->get($packet); $out = array(); if((string)$return->webspace->get->result->status == 'ok'){ foreach($return->webspace->get->result as $info) { $out[(string)$info->data->gen_info->name] = (string)$info->data->gen_info->dns_ip_address; } } return $out; } }