| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719 |
- <?php
- /* * ********************************************************************
- * Rrgistrar Helper
- *
- *
- * CREATED BY MODULESGARDEN -> http://modulesgarden.com
- * CONTACT -> contact@modulesgarden.com
- * AUTHOR -> MODULESGARDEN
- * contact@modulesgarden.com
- *
- *
- *
- * This software is furnished under a license and may be used and copied
- * only in accordance with the terms of such license and with the
- * inclusion of the above copyright notice. This software or any other
- * copies thereof may not be provided or otherwise made available to any
- * other person. No title to and ownership of the software is hereby
- * transferred.
- *
- *
- * ******************************************************************** */
- namespace MGModule\DNSManager2\mgLibs\custom\dns\utils;
- use MGModule\DNSManager2\models\custom\reverse\Repository;
- use MGModule\DNSManager2\mgLibs\custom\dns\record\Record;
- use MGModule\DNSManager2\mgLibs\custom\dns\utils\ReverseDNSHelper;
- use MGModule\DNSManager2\mgLibs\exceptions\RegistrarDNSException;
- use MGModule\DNSManager2\mgLibs\MySQL as mysql;
- use MGModule\DNSManager2\mgLibs\MySQL\query;
- use MGModule\DNSManager2\addon;
- use MGModule\DNSManager2\mgLibs\custom\manager\ClientHelper;
- use MGModule\DNSManager2\models\custom\zone\Zone;
- use MGModule\DNSManager2\models\custom\zone\ZoneTypeEnum;
- use MGModule\DNSManager2 as main;
- /**
- * registrar helper for DNS Management
- * Please make sure that "mocks" folder is readable<br/>
- * Please also make sure that "function" folder is writable. It is necessairy to create dynamic files with specific DNS Functions
- */
- class CustomDnsRegistrarHelper
- {
- public $domainId = null;
- public $moduleName = null;
- private $package = null;
- /**
- * Current Module Parametrers for given domain
- * @var Array
- */
- protected $moduleParams = array();
- protected $availableTypes = array(
- 'A' => array(
- 'name' => 'A',
- 'ttl' => 14400
- ),
- 'AAAA' => array(
- 'name' => 'AAAA',
- 'ttl' => 14400
- ),
- 'MX' => array(
- 'name' => 'MX',
- 'ttl' => 14400
- ),
- 'CNAME' => array(
- 'name' => 'CNAME',
- 'ttl' => 14400
- ),
- 'TXT' => array(
- 'name' => 'SPF',
- 'ttl' => 14400,
- 'alias' => 'SPF'
- ),
- 'TXT' => array(
- 'name' => 'TXT',
- 'ttl' => 14400,
- 'alias' => 'SPF'
- )
- );
- const REGISTRAR_DOMAIN_ID_NOT_EXISTS = 100;
- const REGISTRAR_ZONE_NOT_FOUND = 101;
- const REGISTRAR_DOMAIN_DETAILS_NOT_FOUND = 102;
- const REGISTRAR_DOMAIN_NAME_NOT_FOUND = 103;
- const REGISTRAR_MODULE_NAME_NOT_FOUND = 104;
- const REGISTRAR_USER_ID_NOT_EXISTS = 105;
- static public $MSGS_LIST = array(
- 100 => "Domain ID cannot be empty. Please provide correct Domain ID in %s",
- 101 => "Unable to find zone for provided domain. Create a new zone first or contact your administrator",
- 102 => "Unable to get Domain Details Information in %s",
- 103 => "No Domain name has been provided for %s",
- 104 => "No Module Name has been found for %s",
- 105 => "Unable to get User ID in %s. Probably session has expired",
- );
- public final function __construct($domainId = null)
- {
- $this->domainId = $domainId;
- $this->getPackage();
- }
- public function setDomainId($domainId)
- {
- $this->domainId = $domainId;
- }
- public function getDNSRecords($domainId)
- {
- $params = $this->getModuleParams();
- addon::I(FALSE, $params);
- $helper = new ClientHelper($_SESSION['uid']);
- $zone = new Zone($this->getZoneIdForDomain($domainId));
- $dns = array();
- if(!$helper->isZoneOwnedByClient($zone))
- {
- return array(
- 'error' => main\mgLibs\lang::T('you_cannot_edit_this_zone_because_it_is_not_belongs_to_you')
- );
- }
- $module = $zone->getModule();
- $vars['records'] = $module->getRecords();
- $vars['records'] = array_merge($vars['records'], $this->getPTRRecords($zone));
- foreach($vars['records'] as &$record)
- {
- $record->encode();
- if(!isset($this->availableTypes[$record['type']]))
- {
- continue;
- }
- $priority = null;
- switch($record['type'])
- {
- case 'MX':
- $address = $record['rdata']->exchange;
- $priority = $record['rdata']->preference;
- break;
- case 'CNAME':
- $address = $record['rdata']['cname'];
- break;
- case 'A':
- $address = $record['rdata']['address'];
- break;
- case 'AAAA':
- $address = $record['rdata']['address'];
- break;
- case 'TXT':
- $address = $record['rdata']['txtdata'];
- break;
- default:
- }
- $dns[] = array(
- "hostname" => $record['name'],
- "line" => $record['line'],
- "type" => $record['type'],
- "address" => $address,
- "priority" => $priority,
- "name" => $record['name'],
- "class" => $record['class'],
- "ttl" => $record['ttl'],
- "rdlength" => $record['rdlength'],
- "rdata" => $record["rdata"]
- );
- }
-
- return $dns;
- }
- /**
- *
- * @param type $record
- * @return type
- */
- private function convertRecord($record)
- {
- //applying additional parameters to match DNS Manager spec
- $record['ttl'] = $this->availableTypes[trim(strtoupper($record['type']))]['ttl'];
- $record['name'] = $record['hostname'];
-
- if($record['type'] == "MX")
- {
- $record['exchange'] = $record['address'];
- $record['preference'] = (int) $record['priority'];
- $record['rdata']['exchange'] = $record['address'];
- $record['rdata']['preference'] = (int) $record['priority'];
- }
- if($record['type'] == "CNAME")
- {
- $record['rdata']['cname'] = $record['address'];
- }
- if($record['type'] == "TXT")
- {
- $record['rdata']['txtdata'] = $record['address'];
- }
- return $record;
- }
- private function transformRecords()
- {
- $records = $_POST['dnsrecordhost'];
- $recordsType = $_POST['dnsrecordtype'];
- $recordsAddress = $_POST['dnsrecordaddress'];
- $recordsPriority = $_POST['dnsrecordpriority'];
- $results = array();
- foreach($records as $key => $value)
- {
- $results[] = array(
- 'hostname' => $value,
- 'name' => $value,
- 'type' => $recordsType[$key],
- 'address' => $recordsAddress[$key],
- 'priority' => $recordsPriority[$key],
- 'ttl' => $this->availableTypes[trim(strtoupper($recordsType[$key]))]['ttl'],
- 'rdata' => array(
- 'hostname' => $value,
- 'name' => $value,
- 'type' => $recordsType[$key],
- 'address' => $recordsAddress[$key],
- 'priority' => $recordsPriority[$key],
- 'ttl' => $this->availableTypes[trim(strtoupper($recordsType[$key]))]['ttl'],
- ),
- );
- }
- return $results;
- }
- /**
- * This function is used to check if record type which is going to be created is allowed and available
- * @param String $type Name of the DNS record Type to check if is allowed to create
- * @see Registrar::availableTypes for available types
- * @return boolean True is returned is allowed - false otherwise
- */
- private function checkTypeIfAvailable($type = null)
- {
- if(empty($type))
- {
- return false;
- }
- foreach ($this->availableTypes as $key)
- {
- if ($key['name'] == trim(strtoupper($type)))
- {
- return true;
- }
- }
- return false;
- }
- /**
- * Function used to save or delete DNS record with provided details
- * @param type $domainId Id of the domain for whitch records would be deleted or created
- * @return Array . Void otherwise
- * @throws \Exception Array with error key is returend in case of failure. in that case an exception is thrown
- */
- public function saveDNSRecords($domainId = null)
- {
- if (empty($domainId))
- {
- $domainId = $this->domainId;
- }
- $zoneLoggerManager = new main\mgLibs\custom\helpers\ZoneLogger\Manager($_SESSION['uid']);
- $error = array();
- $params = $this->getModuleParams();
- addon::I(FALSE, $params);
- $helper = new ClientHelper($_SESSION['uid']);
- $zone = new Zone($this->getZoneIdForDomain($domainId));
- //getting den for
- $newDNSCollection = $this->transformRecords();
- $oldDNSCollection = $this->getDNSRecords($domainId);
- $limits = $this->checkPackageLimits($newDNSCollection);
- if($limits)
- {
- throw new \Exception($limits, 0);
- }
-
- if (!$helper->isZoneOwnedByClient($zone))
- {
- throw new \Exception(main\mgLibs\lang::T('you_cannot_edit_this_zone_because_it_is_not_belongs_to_you'), 0);
- }
- $module = $zone->getModule();
- foreach ($newDNSCollection as $newKey => $newValue)
- {
- $newValue = $this->convertRecord($newValue);
- //if such a key does not exists it could be a new one
- if (!array_key_exists($newKey, $oldDNSCollection))
- {
- if (empty($newValue['hostname']) && empty($newValue['address']))
- {
- continue;
- }
- //if type is not allowd - return error
- if (!$this->checkTypeIfAvailable($newValue['type']))
- {
- $error[] = $newValue['type'] . ' is not supported. Available types: A, AAAA, MX, CNAME, SPF(txt).';
- continue;
- }
- try
- {
- $record = $this->createRecordFromData($newValue);
- $module->addRecord($record);
- $zoneLoggerManager->logAddRecordToZone($zone, $record);
- }
- catch(\Exception $ex)
- {
- $error[] = $ex->getMessage();
- }
-
- continue;
- }
- //if there are no difference - do nothing
- if($newValue['hostname'] == $oldDNSCollection[$newKey]['hostname']
- && $newValue['address'] == $oldDNSCollection[$newKey]['address']
- && ($newValue['priority'] == $oldDNSCollection[$newKey]['priority'] || !is_numeric($newValue['priority'])))
- {
- continue;
- }
- //if there are discrepencies in a host name or IP address remove old record and add new one
- //or remove only those in which both hostname and address are empty
- try
- {
- $module->deleteRecord($record = $this->createRecordFromData($oldDNSCollection[$newKey]));
- $zoneLoggerManager->logRemoveRecordFromZone($record);
- //remove record and if values was empty - do nothing else
- if (empty($newValue['hostname']) && empty($newValue['address']))
- {
- continue;
- }
- }
- catch(\Exception $ex)
- {
- $error[] = $ex->getMessage();
- continue;
- }
- try
- {
- $module->addRecord($record = $this->createRecordFromData($newValue));
- }
- catch(\Exception $ex)
- {
- $error[] = $ex->getMessage();
- //rollbacking
- $module->addRecord($record = $this->createRecordFromData($oldDNSCollection[$newKey]));
- }
- $zoneLoggerManager->logAddRecordToZone($zone, $record);
- }
- if(!empty($error))
- {
- throw new \Exception(implode(". <br />\n", $error), 1);
- }
- }
- /**
- * Function used to create record from form data
- * @param Array $input Collection of form parameters sent by WHMCS while new DNS record creation
- * @return MGModule\DNSManager2\mgLibs\custom\dns\record\Record
- */
- private function createRecordFromData($input)
- {
- $record = Record::tryToCreateFromArray($input);
- $record->rdata->setDataFromArray($input['rdata']);
- return $record;
- }
- /**
- * Function used to get Current Domain ID
- * @return integer ID of the domain is used
- */
- protected function getDomainId()
- {
- return (int)$this->domainId;
- }
- private function getPTRRecords($zone)
- {
- $out = array();
- foreach(Repository::factory()->from($zone->getServer()->id, $zone->name)->get() as $data)
- {
- $ptr = new Record();
- $ptr->name = ReverseDNSHelper::getLastOctetFromIPv4($data->ip) . '.' . $data->name;
- $ptr->type = 'PTR';
- $ptr->ttl = $data->ttl;
- $ptr->ip = $data->ip;
- $ptr->createRDATAObject('PTR');
- $ptr->rdata->setFirstProperty(empty($data->sub) ? $data->from : $data->sub . '.' . $data->from);
- $out[] = $ptr;
- }
- return $out;
- }
- private function getZoneIdForDomain($domainId = null)
- {
- if (empty($domainId))
- {
- throw new RegistrarDNSException(sprintf(self::$MSGS_LIST[self::REGISTRAR_DOMAIN_ID_NOT_EXISTS], __FUNCTION__), self::REGISTRAR_DOMAIN_ID_NOT_EXISTS);
- }
- $clientid = $_SESSION['uid'];
- $details = query::query("
- SELECT CONCAT('#', tbldomains.id, ' ', tbldomains.domain) AS group_name,
- :type `type`,
- tbldomains.id AS relid,
- dns_manager2_zone.id AS zone_id,
- dns_manager2_zone.name AS zone_name,
- dns_manager2_zone.status AS zone_status
- FROM tbldomains
- LEFT JOIN dns_manager2_zone ON dns_manager2_zone.type = :type2
- AND dns_manager2_zone.relid = tbldomains.id
- AND dns_manager2_zone.clientid = :clientid
- WHERE tbldomains.status IN ('Active')
- AND tbldomains.id = :domainid
- AND tbldomains.userid = :clientid2", array(
- 'type' => ZoneTypeEnum::DOMAIN,
- 'type2' => ZoneTypeEnum::DOMAIN,
- 'clientid' => $clientid,
- 'clientid2' => $clientid,
- 'domainid' => $domainId
- ))->fetch();
- if(empty($details))
- {
- throw new RegistrarDNSException(sprintf(self::$MSGS_LIST[self::REGISTRAR_DOMAIN_DETAILS_NOT_FOUND], __FUNCTION__), self::REGISTRAR_DOMAIN_DETAILS_NOT_FOUND);
- }
- if(empty($details['zone_id']))
- {
- throw new RegistrarDNSException(sprintf(self::$MSGS_LIST[self::REGISTRAR_ZONE_NOT_FOUND], __FUNCTION__), self::REGISTRAR_ZONE_NOT_FOUND);
- }
- return $details['zone_id'];
- }
- /**
- * This function is used to get Current Module Name from DB
- * @return String Module Name is returned
- * @throws RegistrarDNSException An exception is thrown if no domainId has been set or nothign has been found in DB
- */
- public function getModuleName()
- {
- if(empty($this->domainId))
- {
- throw new RegistrarDNSException(sprintf(self::$MSGS_LIST[self::REGISTRAR_DOMAIN_ID_NOT_EXISTS], __FUNCTION__), self::REGISTRAR_DOMAIN_ID_NOT_EXISTS);
- }
- if(!isset($_SESSION['uid']))
- {
- throw new RegistrarDNSException(sprintf(self::$MSGS_LIST[self::REGISTRAR_USER_ID_NOT_EXISTS], __FUNCTION__), self::REGISTRAR_USER_ID_NOT_EXISTS);
- }
- $clientId = $_SESSION['uid'];
- $details = query::query("
- SELECT tbldomains.id AS domainId,
- tbldomains.registrar AS registrar
- FROM tbldomains
- WHERE tbldomains.status IN ('Active')
- AND tbldomains.id = :domainId
- AND tbldomains.userid = :clientId", array(
- 'domainId' => $this->domainId,
- 'clientId' => $clientId,
- ))->fetch();
- if(empty($details))
- {
- throw new RegistrarDNSException(sprintf(self::$MSGS_LIST[self::REGISTRAR_DOMAIN_DETAILS_NOT_FOUND], __FUNCTION__), self::REGISTRAR_DOMAIN_DETAILS_NOT_FOUND);
- }
- $this->moduleName = $details['registrar'];
- return $details['registrar'];
- }
- /**
- * This function is used to create dynamic file with DNS mamagement functions in it<br />
- * Generasted file is later included so the registrar could recognize a set of function so DNS Management section could be activated
- * @param String $currentPath Current path location of the DNS Manager hook file
- * @return String Name of the file to be included is returned. void in case of errors
- */
- public function creatreFunctionsFile($currentPath)
- {
- $sourceLocation = $currentPath.DS.'storage'.DS.'registrar'.DS.'mocks'.DS.'DNSMockFunction.txt';
- $moduleName = $this->getModuleName();
- $locaction = $currentPath.DS.'storage'.DS.'registrar'.DS.'functions'.DS;
- $file = $locaction . $moduleName . "_DNSFunctions.php";
- if(!file_exists($file))
- {
- if(!is_readable($currentPath.DS.'storage'.DS.'registrar'.DS.'mocks'.DS))
- {
- throw new \Exception(
- main\mgLibs\lang::T('Directory').': '.
- $currentPath . '/storage/registrar/mocks '.
- main\mgLibs\lang::T('is_not_readable')
- );
- }
- $fileContent = str_replace("%module_name%", $moduleName, file_get_contents($sourceLocation));
- if(!is_writable($locaction))
- {
- throw new \Exception(
- main\mgLibs\lang::T('Directory').': '.
- $locaction.
- main\mgLibs\lang::T('is_not_writable')
- );
- }
- file_put_contents($file, $fileContent);
- }
- return $file;
- }
- /**
- * This function is used to get Parameters saved for currently used module
- * @param String $module Name of the module we want to find parameters for
- * @return Array Collection of parameted is returned
- * @throws RegistrarDNSException An Exception is thrown in case of Errors
- */
- public function getModuleParams($module = null)
- {
- if (empty($module))
- {
- $module = $this->getModuleName();
- }
- if (empty($module))
- {
- throw new RegistrarDNSException();
- }
- $q = query::query(
- "SELECT * FROM `tblregistrars` WHERE `registrar`= :registrar ", array(
- 'registrar' => $module
- ))->fetchAll();
- $params = array();
- foreach ($q as $row)
- {
- $params[$row['setting']] = decrypt($row['value']);
- }
- return $params;
- }
- public function getTld()
- {
- $tld = false;
- $domain = \MGModule\DNSManager2\models\whmcs\domains\domain::factory($this->domainId);
- if($domain)
- {
- $name = $domain->domain;
- $pos = mb_stripos($name, '.');
- $tld = mb_substr($name, $pos);
- }
- return $tld;
- }
- public function getPackage()
- {
- $tldExtension = $this->getTld();
- $tld = main\models\whmcs\domains\pricing\domainpricing::getExtensionId($tldExtension); // id
- if($tld)
- {
- $dnsRegistrar = main\models\custom\package\registrar\Repository::factory()
- ->byTld($tld)->one();
- if($dnsRegistrar)
- {
- $this->package = new main\models\custom\package\Package($dnsRegistrar->packageid);
- }
- }
- }
- public function isPackageActive()
- {
- if($this->package)
- {
- if($this->package->status == "1" && $this->checkRegistrar())
- {
- return true;
- }
- }
- return false;
- }
- public function checkPackageLimits($newDNSCollection)
- {
- //if(!$this->isPackageActive())
- //{
- // main\mgLibs\lang::T('');
- //}
- $counts = $this->countRecords($newDNSCollection);
- $totalLimit = $this->getPackageTotalRecordsLimit();
- if((int)$totalLimit < $counts['all'])
- {
- return main\mgLibs\lang::T('recordLimitExceded');
- }
- $recordsLimits = $this->getPackageRecordsLimits();
- foreach($counts as $rName => $rCount)
- {
- if($rName == 'all')
- {
- continue;
- }
- if((int)$recordsLimits[$rName] < $rCount)
- {
- return main\mgLibs\lang::T('youCannotAddSpecificRecords')
- .' '.$rName.' '.main\mgLibs\lang::T('limitExceded');
- }
- }
- }
- public function countRecords($newDNSCollection)
- {
- $counts = array('all' => 0);
- foreach($newDNSCollection as $record)
- {
- if($record['hostname'] !== '')
- {
- $counts['all']++;
- if($counts[$record['type']])
- {
- $counts[$record['type']]++;
- }
- else
- {
- $counts[$record['type']] = 1;
- }
- }
- }
- return $counts;
- }
- private function getPackageRecordsLimits()
- {
- $allowedRecords = main\models\custom\package\setting\Repository::factory()
- ->byPackageID($this->package->id)
- ->byKey(main\models\custom\package\setting\PackageSettingEnum::ALLOWED_RECORD_TYPES)
- ->one();
- $result = $allowedRecords ? unserialize($allowedRecords->value) : false;
- return $result;
- }
- private function getPackageTotalRecordsLimit()
- {
- $limit = main\models\custom\package\item\Repository::factory()
- ->byPackageID($this->package->id)
- ->byType(main\models\custom\package\item\PackageItemTypeEnum::DOMAIN)
- ->byRelID($this->domainId)
- ->one();
- return $limit->limit;
- }
- public function checkRegistrar()
- {
- $reg = mysql\query::query("SELECT registrar FROM tbldomains WHERE id = :domainID ",
- array('domainID' => $this->domainId))->fetchColumn("registrar");
- $path = str_replace( DS.'addons'.DS.'DNSManager2'.DS.'mgLibs'.DS.'custom'.DS.'dns'.DS.'utils',
- DS.'registrars'.DS.$reg.DS.$reg.'.php', __DIR__ );
- if(file_exists($path))
- {
- if (!function_exists("getRegistrarConfigOptions")) {
- require ROOTDIR . "/includes/registrarfunctions.php";
- }
-
- require_once $path;
- if(!function_exists($reg.'_GetDNS') && !function_exists($reg.'_SaveDNS'))
- {
- return true;
- }
- }
- return false;
- }
- }
|