CPanelOldApi.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  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\utils\Patterns;
  7. //TODO: wersja dla najnowszego whma
  8. class CPanelOldApi extends dns\SubmoduleAbstract implements interfaces\SubmoduleIPInterface, interfaces\SubmoduleRDNSInterface, interfaces\SubmoduleTTLInterface, interfaces\SubmoduleImportInterface {
  9. public $configFields = array(
  10. 'username' =>array (
  11. 'friendlyName' => 'Username',
  12. 'validators' => array(
  13. 'required' => 'required',
  14. )
  15. ),
  16. 'password' =>array (
  17. 'friendlyName' => 'User password',
  18. 'type'=> 'password',
  19. ),
  20. 'hash' =>array (
  21. 'friendlyName' => 'Access key',
  22. 'type'=> 'textarea',
  23. ),
  24. 'hostname' =>array (
  25. 'friendlyName' => 'Hostname/IP',
  26. 'validators' => array(
  27. 'required' => 'required',
  28. )
  29. ),
  30. 'ssl' =>array (
  31. 'friendlyName' => 'Enable SSL',
  32. 'type'=> 'yesno',
  33. ),
  34. 'default_ip' =>array (
  35. 'friendlyName' => 'Default IP',
  36. 'validators' => array(
  37. 'required' => 'required',
  38. 'pattern' => Patterns::IP4_OR_IP6,
  39. )
  40. ),
  41. 'allow_create' =>array (
  42. 'friendlyName' => 'In cPanel Zones',
  43. 'type' => 'yesno',
  44. 'help' => 'Allow to create zones when already in CPanel as account',
  45. ),
  46. 'template' =>array (
  47. 'friendlyName' => 'Template',
  48. ),
  49. );
  50. public $availableTypes = array('A', 'AAAA', 'NS', 'MX', 'CNAME', 'DNAME', 'LOC', 'TXT', 'SRV', 'PTR', 'AFSDB', 'NAPTR', 'RP');
  51. public function testConnection() {
  52. try {
  53. $this->get('listaccts');
  54. return true;
  55. } catch (exceptions\DNSSubmoduleException $e) {
  56. $this->get('listzones', array(), true);
  57. return true;
  58. }
  59. }
  60. public function getRecords($recordType = false) {
  61. $out = $this->get('dumpzone', array(
  62. 'domain' => $this->domain
  63. ));
  64. $return = array();
  65. if(isset($out->result->record)){
  66. foreach($out->result->record as $r) {
  67. if(in_array((string)$r->type, $recordType!==false ? array(strtoupper($recordType)) : $this->getAvailableRecordTypes())) {
  68. $return[] = dns\record\Record::tryToCreateFromArray((array)$r);
  69. }
  70. }
  71. } else {
  72. throw new exceptions\DNSSubmoduleException('Unable to fetch records from server', dns\SubmoduleExceptionCodes::COMMAND_ERROR);
  73. }
  74. return $return;
  75. }
  76. public function addRecord(dns\record\Record $record) {
  77. $input = $record->toMergedArray(false);
  78. $input['domain'] = $this->domain;
  79. $input['name'] = $record->nameToAbsolute($this->domain);
  80. $this->get('addzonerecord', $input);
  81. return true;
  82. }
  83. public function editRecord(dns\record\Record $record) {
  84. $records = $this->getRecords();
  85. if(empty($records))
  86. return false;
  87. $lines = array();
  88. foreach($records as $r) {
  89. $lines[$r['line']] = $r;
  90. }
  91. if(!isset($lines[$record['line']]) || !$record->isEqualTo($lines[$record['line']])) {
  92. $input = $record->toMergedArray(false);
  93. $input['domain'] = $this->domain;
  94. $input['name'] = $record->nameToAbsolute($this->domain);
  95. $this->get('editzonerecord', $input);
  96. }
  97. }
  98. public function deleteRecord(dns\record\Record $record) {
  99. $this->get('removezonerecord', array(
  100. 'zone' => $this->domain,
  101. 'line' => $record['line']
  102. ));
  103. }
  104. public function zoneExists() {
  105. try {
  106. $out = $this->get('listzones', array() , true);
  107. } catch (exceptions\DNSSubmoduleException $e) {
  108. if($e->getCode() == dns\SubmoduleExceptionCodes::COMMAND_ERROR) {
  109. return false;
  110. }
  111. throw $e;
  112. }
  113. if(isset($out->zone)) {
  114. $k=0;
  115. while($out->zone[$k]) {
  116. if((string)$out->zone[$k]->domain == $this->domain)
  117. return true;
  118. $k++;
  119. }
  120. }
  121. return false;
  122. }
  123. public function activateZone() {
  124. if($this->ip != '') {
  125. if(!filter_var($this->ip, FILTER_VALIDATE_IP)) {
  126. throw new exceptions\DNSSubmoduleException('IP is not valid!', dns\SubmoduleExceptionCodes::INVALID_PARAMETERS);
  127. }
  128. } else {
  129. $this->ip = $this->config['default_ip'];
  130. }
  131. $params = array(
  132. 'domain' => $this->domain,
  133. 'ip' => $this->ip
  134. );
  135. if($this->config['template'] != "")
  136. $params['template'] = $this->config['template'];
  137. $this->get('adddns', $params);
  138. }
  139. public function terminateZone() {
  140. $this->get('killdns', array(
  141. 'domain' => $this->domain
  142. ));
  143. }
  144. public function getZones() {
  145. $out = array();
  146. $res = $this->get('listzones', array(), true);
  147. foreach ($res->zone as $zone) {
  148. $out[(string)$zone->domain] = '';
  149. }
  150. try {
  151. $res = $this->get('listaccts', array('want' => 'domain,ip'), true);
  152. foreach ($res->acct as $zone) {
  153. $out[(string)$zone->domain] = (string)$zone->ip;
  154. }
  155. } catch (exceptions\DNSSubmoduleException $e) {
  156. }
  157. return $out;
  158. }
  159. private function get($function, $params=array(), $nothing = false) {
  160. $url = ($this->config['ssl']? 'https://'.$this->config['hostname'].':2087' : 'http://'.$this->config['hostname'].':2086').'/xml-api/'.$function;
  161. $ch = curl_init();
  162. if(is_array($params)) {
  163. $url .= '?';
  164. foreach($params as $key=>$value) {
  165. $value = urlencode($value);
  166. $url .= "{$key}={$value}&";
  167. }
  168. }
  169. $url = trim($url, '&');
  170. $this->log($url);
  171. $chOptions = array (
  172. CURLOPT_URL => $url,
  173. CURLOPT_RETURNTRANSFER => true,
  174. CURLOPT_SSL_VERIFYPEER => false,
  175. CURLOPT_SSL_VERIFYHOST => false,
  176. CURLOPT_TIMEOUT => 50
  177. );
  178. if($this->config['hash'] != ''){
  179. $header[0] = 'Authorization: WHM '.$this->config['username'].':'.str_replace(array("\r", "\n"),"", $this->config['hash']);
  180. $chOptions[CURLOPT_HTTPHEADER] = $header;
  181. }elseif($this->config['password'] != ''){
  182. $chOptions[CURLOPT_USERPWD] = $this->config['username'].':'.$this->config['password'];
  183. }else{
  184. throw new exceptions\DNSSubmoduleException('Password or Access key is required', dns\SubmoduleExceptionCodes::CONNECTION_PROBLEM);
  185. }
  186. curl_setopt_array($ch, $chOptions);
  187. $out = curl_exec($ch);
  188. //cpanel sometimes appends the following text to the ned of response XML: <!-- Web Host Manager 11.54.0.17 (c) cPanel, Inc. 2015 http://cpanel.net/ Unauthorized copying is prohibited. -->
  189. if(($tagPos = strpos($out, '<!--')) > 0){
  190. $out = trim(substr($out, 0, $tagPos));
  191. }
  192. $this->log('SERVER RETURNS: ' . $out);
  193. $out_info = curl_getinfo($ch);
  194. if($out_info['http_code'] != 200){
  195. if($out_info['http_code'] == 301 || $out_info['http_code'] == 302){
  196. throw new exceptions\DNSSubmoduleException('Module require SSL', dns\SubmoduleExceptionCodes::CONNECTION_PROBLEM);
  197. }
  198. }
  199. if($out === false || $out == '') {
  200. throw new exceptions\DNSSubmoduleException(ucwords(curl_error($ch)), dns\SubmoduleExceptionCodes::CONNECTION_PROBLEM);
  201. }
  202. curl_close($ch);
  203. if(strpos($out, 'SSL encryption is required for access to this server') !== FALSE) {
  204. throw new exceptions\DNSSubmoduleException('SSL encryption is required for access to this server', dns\SubmoduleExceptionCodes::CONNECTION_PROBLEM);
  205. }
  206. @$a = simplexml_load_string($out);
  207. if($a===FALSE) {
  208. throw new exceptions\DNSSubmoduleException('Unable to parse response', dns\SubmoduleExceptionCodes::INVALID_RESPONSE);
  209. } else {
  210. if(isset($a->status)){
  211. if($a->status == 1)
  212. return $a;
  213. else{
  214. throw new exceptions\DNSSubmoduleException($a->statusmsg, dns\SubmoduleExceptionCodes::COMMAND_ERROR);
  215. }
  216. }elseif(isset($a->data->reason)){
  217. throw new exceptions\DNSSubmoduleException($a->data->reason, dns\SubmoduleExceptionCodes::COMMAND_ERROR);
  218. }elseif((integer)$a->result->status == 1)
  219. return $a;
  220. elseif(isset($a->result->statusmsg)){
  221. if(preg_match('/is owned by another user/', $a->result->statusmsg) && $this->config['allow_create'] == 'on')// && $this->checkZoneInDB() === false)
  222. return true;
  223. else
  224. throw new exceptions\DNSSubmoduleException($a->result->statusmsg, dns\SubmoduleExceptionCodes::COMMAND_ERROR);
  225. }
  226. elseif(isset($a->statusmsg))
  227. throw new exceptions\DNSSubmoduleException($a->statusmsg, dns\SubmoduleExceptionCodes::COMMAND_ERROR);
  228. elseif($nothing)
  229. return $a;
  230. else
  231. throw new exceptions\DNSSubmoduleException('Unknown error', dns\SubmoduleExceptionCodes::INVALID_RESPONSE);
  232. }
  233. }
  234. }