DNS4PSA.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. <?php
  2. namespace MGModule\DNSManager2\mgLibs\custom\dns\submodules;
  3. use \MGModule\DNSManager2\mgLibs\custom\dns;
  4. use \MGModule\DNSManager2\mgLibs\custom\dns\exceptions;
  5. use \MGModule\DNSManager2\mgLibs\custom\dns\interfaces;
  6. use \MGModule\DNSManager2\mgLibs\custom\dns\submodules\dns4psa\SoapClient4psa;
  7. use \MGModule\DNSManager2\mgLibs\custom\dns\utils\Patterns;
  8. use \SoapHeader;
  9. use \SoapVar;
  10. use \stdClass;
  11. /* define request type constant */
  12. define('CLIENT_TYPE', 'client');
  13. define('DNSZONE_TYPE', 'dnszone');
  14. define('DNSRECORD_TYPE', 'dnsrecord');
  15. ini_set('soap.wsdl_cache_enabled', 0);
  16. class DNS4PSA extends dns\SubmoduleAbstract implements interfaces\SubmoduleImportInterface, interfaces\SubmoduleIPInterface, interfaces\SubmoduleRDNSInterface
  17. {
  18. public $configFields = [
  19. 'username' => [
  20. 'friendlyName' => 'Username',
  21. 'validators' => [
  22. 'required' => 'required',
  23. ]
  24. ],
  25. 'password' => [
  26. 'friendlyName' => 'Password',
  27. 'type' => 'password',
  28. 'validators' => [
  29. 'required' => 'required',
  30. ]
  31. ],
  32. 'hostname' => [
  33. 'friendlyName' => 'Hostname',
  34. 'validators' => [
  35. 'required' => 'required',
  36. ]
  37. ],
  38. 'port' => [
  39. 'friendlyName' => 'Port',
  40. 'type' => 'number',
  41. ],
  42. 'template' => [
  43. 'friendlyName' => 'Template',
  44. ],
  45. 'client_name' => [
  46. 'friendlyName' => 'Client Name',
  47. ],
  48. 'ssl' => [
  49. 'friendlyName' => 'SSL',
  50. 'type' => 'yesno',
  51. ],
  52. 'default_ip' => [
  53. 'friendlyName' => 'Default IP',
  54. 'validators' => [
  55. 'required' => 'required',
  56. 'pattern' => Patterns::IP4_OR_IP6,
  57. ]
  58. ],
  59. 'override_wsdl_url' => [
  60. 'friendlyName' => 'Override WSDL URL',
  61. 'type' => 'yesno'
  62. ]
  63. ];
  64. public $availableTypes = ['A', 'AAAA', 'NS', 'MX', 'CNAME', 'TXT', 'SRV']; //'A', 'AAAA', 'NS', 'MX', 'CNAME', 'TXT', 'PTR', 'SRV', 'NAPTR'
  65. private function get($function, $params = null, $retback = false, $locationType = DNSZONE_TYPE)
  66. {
  67. $soap = $this->loadSoap();
  68. if (!$soap)
  69. {
  70. throw new exceptions\DNSSubmoduleException("SOAP Error: Cannot load soap class", dns\SubmoduleExceptionCodes::CONNECTION_PROBLEM);
  71. }
  72. try
  73. {
  74. //Optimization
  75. if( $this->config['override_wsdl_url'] === 'on' )
  76. {
  77. throw new \Exception('Skipping WSDL URL');
  78. }
  79. $result = $soap->$function($params);
  80. }
  81. catch( \Exception $exception ) //try with location changing
  82. {
  83. $soap = $this->loadSoap();
  84. $soap->__setLocation("http://{$this->config['hostname']}/soap/{$locationType}_agent.php"); // it is const
  85. $result = $soap->$function($params);
  86. }
  87. if ($retback && isset($result->$retback))
  88. {
  89. return true;
  90. }
  91. if (is_a($result, 'SoapFault'))
  92. {
  93. throw new exceptions\DNSSubmoduleException($result->getMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
  94. }
  95. elseif (isset($result->notice->message))
  96. {
  97. throw new exceptions\DNSSubmoduleException($result->notice->message, dns\SubmoduleExceptionCodes::COMMAND_ERROR);
  98. }
  99. else
  100. {
  101. if ($retback)
  102. {
  103. throw new exceptions\DNSSubmoduleException('Unexpected Error', dns\SubmoduleExceptionCodes::COMMAND_ERROR);
  104. }
  105. return $result;
  106. }
  107. }
  108. private function loadSoap()
  109. {
  110. /* the class that prepares the soapClient */
  111. require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'dns4psa' . DIRECTORY_SEPARATOR . 'misc.php');
  112. $files_location = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'dns4psa' . DIRECTORY_SEPARATOR;
  113. $dnsmanager_version = '1.5';
  114. $context = stream_context_create([
  115. 'ssl' => [
  116. 'verify_peer' => false,
  117. 'verify_peer_name' => false,
  118. 'allow_self_signed' => false
  119. ]
  120. ]);
  121. try
  122. {
  123. $client_class = new SoapClient4psa($files_location, ['trace' => 1, 'exceptions' => 1, 'connection_timeout' => 120, 'cache_wsdl' => WSDL_CACHE_NONE, 'stream_context' => $context], $this->config['hostname'], $this->config['port'] == '' ? 80 : $this->config['port'], $this->config['ssl'] == '1' ? 1 : 0, $dnsmanager_version);
  124. }
  125. catch (\Throwable $exception)
  126. {
  127. throw new exceptions\DNSSubmoduleException($exception->getMessage(), dns\SubmoduleExceptionCodes::CONNECTION_PROBLEM);
  128. }
  129. if ($client_class->error != '')
  130. {
  131. throw new exceptions\DNSSubmoduleException($client_class->error, dns\SubmoduleExceptionCodes::CONNECTION_PROBLEM);
  132. }
  133. $client = $client_class->getSoapClient();
  134. $auth = new stdClass();
  135. $auth->username = $this->config['username'];
  136. $auth->password = $this->config['password'];
  137. $authvalues = new SoapVar($auth, SOAP_ENC_OBJECT, 'http://4psa.com/HeaderData/' . $dnsmanager_version);
  138. $header = new SoapHeader('http://4psa.com/HeaderData/' . $dnsmanager_version, 'userCredentials', $authvalues, false);
  139. $client->__setSoapHeaders([$header]);
  140. return $client;
  141. }
  142. public function testConnection()
  143. {
  144. $ret = $this->get('GetDNSZone', '', 'DNSZone');
  145. }
  146. public function zoneExists()
  147. {
  148. try
  149. {
  150. $dns_zone = new stdClass();
  151. $dns_zone->DNSZoneName = $this->domain;
  152. $this->get('GetDNSZone', $dns_zone, 'DNSZone');
  153. }
  154. catch (exceptions\DNSSubmoduleException $e)
  155. {
  156. if ($e->getCode() == dns\SubmoduleExceptionCodes::COMMAND_ERROR)
  157. {
  158. return false;
  159. }
  160. throw $e;
  161. }
  162. return true;
  163. }
  164. public function getRecords($recordType = false)
  165. {
  166. $dns_zone = new stdClass();
  167. $dns_zone->DNSZoneName = $this->domain;
  168. try
  169. {
  170. $ret = $this->get('GetDNSRecord', $dns_zone);
  171. }
  172. catch (exceptions\DNSSubmoduleException $e)
  173. {
  174. if ($e->getMessage() != 'No DNS record has been found.')
  175. {
  176. throw $e;
  177. }
  178. }
  179. $out = [];
  180. if (!is_array($ret->DNSRecord))
  181. {
  182. $ret->DNSRecord = [$ret->DNSRecord];
  183. }
  184. foreach ($ret->DNSRecord as $r)
  185. {
  186. if (in_array((string)$r->type, $recordType !== false ? [strtoupper($recordType)] : $this->getAvailableRecordTypes()))
  187. {
  188. $record = new dns\record\Record();
  189. $record->line = (string)$r->DNSRecordId;
  190. $record->name = (string)$r->host;
  191. $record->type = (string)$r->type;
  192. //$record->ttl = (string)$r->TTL;
  193. $record->createRDATAObject();
  194. switch ((string)$r->type)
  195. {
  196. case 'MX':
  197. $record->rdata->preference = (string)$r->opt;
  198. $record->rdata->exchange = (string)$r->value;
  199. break;
  200. case 'NAPTR':
  201. $record->rdata->setDataFromArray((array)$r);
  202. $record->rdata->regexp = (string)$r->regex;
  203. $record->rdata->flags = (string)$r->flag;
  204. $record->rdata->replacement = (string)$r->replace;
  205. break;
  206. case 'SRV':
  207. //fucking 4PSA! it require new request to fetch details data
  208. $data = new \stdClass();
  209. $data->DNSRecordId = $r->DNSRecordId;
  210. $fullRecord = $this->get('GetDNSRecord', $data)->DNSRecord;
  211. $record->name = "{$fullRecord->service}.{$fullRecord->protocol}.{$fullRecord->host}";
  212. $record->rdata->setDataFromArray((array)$fullRecord);
  213. break;
  214. default:
  215. $record->rdata->setFirstProperty((string)$r->value);
  216. break;
  217. }
  218. $out[] = $record;
  219. }
  220. }
  221. return $out;
  222. }
  223. private function recordToParamsArray(dns\record\Record $record)
  224. {
  225. $dns_zone = new stdClass();
  226. $dns_zone->DNSZoneName = $this->domain;
  227. $dns_zone->host = $record->nameToAbsolute($this->domain);
  228. $dns_zone->type = $record->type;
  229. switch ($record->type)
  230. {
  231. case 'MX':
  232. $dns_zone->opt = $record->rdata->preference;
  233. $dns_zone->value = $record->rdata->exchange;
  234. break;
  235. case 'NAPTR':
  236. $dns_zone->order = $record->rdata->order;
  237. $dns_zone->preference = $record->rdata->preference;
  238. $dns_zone->flag = $record->rdata->flags;
  239. $dns_zone->replace = $record->rdata->replacement;
  240. $dns_zone->regex = $record->rdata->regexp;
  241. $dns_zone->services = $record->rdata->services;
  242. break;
  243. case 'SRV':
  244. $exploded = explode('.', $record->name, 3);
  245. list($service, $protocol, $name) = $exploded;
  246. $dns_zone->service = $service;
  247. $dns_zone->protocol = $protocol;
  248. $record->name = $name;
  249. $dns_zone->host = $record->nameToAbsolute($this->domain);
  250. $dns_zone->priority = $record->rdata->priority;
  251. $dns_zone->weight = $record->rdata->weight;
  252. $dns_zone->port = $record->rdata->port;
  253. $dns_zone->target = $record->rdata->target;
  254. break;
  255. case 'TXT':
  256. $dns_zone->value = trim($record->rdata->toString(), '"');
  257. break;
  258. default:
  259. $dns_zone->value = $record->rdata->toString();
  260. break;
  261. }
  262. return $dns_zone;
  263. }
  264. public function addRecord(dns\record\Record $record)
  265. {
  266. $dns_zone = $this->recordToParamsArray($record);
  267. $this->get('AddDNSRecord', $dns_zone);
  268. }
  269. public function editRecord(dns\record\Record $record)
  270. {
  271. $dns_zone = $this->recordToParamsArray($record);
  272. $dns_zone->DNSRecordId = $record->line;
  273. $this->get('EditDNSRecord', $dns_zone);
  274. }
  275. public function deleteRecord(dns\record\Record $record)
  276. {
  277. $dns_zone = $this->recordToParamsArray($record);
  278. $dns_zone->DNSRecordId = $record->line;
  279. $dns_zone = $this->prepareForDeleteOrEdit($dns_zone);
  280. $dns_zone_for_del = new stdClass();
  281. $dns_zone_for_del->DNSRecord = $dns_zone;
  282. $this->get('DelDNSRecord', $dns_zone_for_del);
  283. }
  284. public function prepareForDeleteOrEdit($dns_zone)
  285. {
  286. switch ($dns_zone->type)
  287. {
  288. case 'SRV':
  289. $dns_zone->host = "_{$dns_zone->service}._{$dns_zone->protocol}.{$dns_zone->host}";
  290. $dns_zone->value = $dns_zone->target;
  291. break;
  292. }
  293. return $dns_zone;
  294. }
  295. public function activateZone()
  296. {
  297. if ($this->ip != '')
  298. {
  299. if (!filter_var($this->ip, FILTER_VALIDATE_IP))
  300. {
  301. throw new exceptions\DNSSubmoduleException('IP is not valid!', dns\SubmoduleExceptionCodes::INVALID_PARAMETERS);
  302. }
  303. }
  304. else
  305. {
  306. $this->ip = $this->config['default_ip'];
  307. }
  308. $clients = $this->get('GetClient', null, false, CLIENT_TYPE);
  309. $dns_zone = new stdClass();
  310. $dns_zone->name = $this->domain;
  311. if ($this->config['template'])
  312. {
  313. $dns_zone->templateIP = $this->ip;
  314. $dns_zone->templateId = $this->config['template'];
  315. }
  316. // get client
  317. if (!empty($this->config['client_name']))
  318. {
  319. if (is_array($clients->client))
  320. {
  321. foreach ($clients->client as $client)
  322. {
  323. if ($client->name === $this->config['client_name'])
  324. {
  325. $dns_zone->clientId = $client->clientId;
  326. break;
  327. }
  328. }
  329. }
  330. else
  331. {
  332. if (!empty($clients->client->clientId) && $clients->client->name === $this->config['client_name'])
  333. {
  334. $dns_zone->clientId = $clients->client->clientId;
  335. }
  336. }
  337. }
  338. $this->get('AddDNSZone', $dns_zone);
  339. }
  340. public function terminateZone()
  341. {
  342. $dns_zone = new stdClass();
  343. $dns_zone->DNSZoneName = $this->domain;
  344. $this->get('DelDNSZone', $dns_zone);
  345. }
  346. public function getZones()
  347. {
  348. $ret = $this->get('GetDNSZone', new stdClass());
  349. if (!is_array($ret->DNSZone))
  350. {
  351. $ret->DNSZone = [$ret->DNSZone];
  352. }
  353. $out = [];
  354. foreach ($ret->DNSZone as $zone)
  355. {
  356. $zone->name = trim($zone->name, '.');
  357. $out[(string)$zone->name] = isset($zone->templateIP) ? (string)$zone->templateIP : '';
  358. }
  359. return $out;
  360. }
  361. }