%PDF- %PDF-
| Direktori : /usr/local/prospamfilter/library/SpamFilter/ |
| Current File : //usr/local/prospamfilter/library/SpamFilter/Hooks.php |
<?php
/*
*************************************************************************
* *
* ProSpamFilter *
* Bridge between Webhosting panels & SpamExperts filtering *
* *
* Copyright (c) 2010-2011 SpamExperts B.V. All Rights Reserved, *
* *
*************************************************************************
* *
* Email: support@spamexperts.com *
* Website: htttp://www.spamexperts.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. No title to and ownership *
* of the software is hereby transferred. *
* *
* You may not reverse engineer, decompile or disassemble this software *
* product or software product license. *
* *
* SpamExperts may terminate this license if you don't comply with any *
* of the terms and conditions set forth in our end user *
* license agreement (EULA). In such event, licensee agrees to return *
* licensor or destroy all copies of software upon termination of the *
* license. *
* *
* Please see the EULA file for the full End User License Agreement. *
* *
*************************************************************************
* @category SpamExperts
* @package ProSpamFilter
* @author $Author$
* @copyright Copyright (c) 2011, SpamExperts B.V., All rights Reserved. (http://www.spamexperts.com)
* @license Closed Source
* @version 3.0
* @link https://my.spamexperts.com/kb/34/Addons
* @since 2.0
*/
class SpamFilter_Hooks
{
const SKIP_DATAINVALID = 'SKIP_DATAINVALID';
const SKIP_UNKNOWN = 'SKIP_UNKNOWN';
const SKIP_REMOTE = 'SKIP_REMOTE';
const SKIP_APIFAIL = 'SKIP_APIFAIL';
const SKIP_ALREADYEXISTS = 'SKIP_ALREADYEXISTS';
const SKIP_INVALID = 'SKIP_INVALID';
const SKIP_NOROOT = 'SKIP_NOROOT';
const ALREADYEXISTS_ROUTESET = 'ALREADYEXISTS_ROUTESET';
const ALREADYEXISTS_ROUTESETFAIL = 'ALREADYEXISTS_ROUTESETFAIL';
const ALREADYEXISTS_NOT_OWNER = 'ALREADYEXISTS_NOT_OWNER';
const API_REQUEST_FAILED = 'API_REQUEST_FAILED';
const DOMAIN_EXISTS = 'DOMAIN_EXISTS';
const ALIAS_EXISTS = 'ALIAS_EXISTS';
const DOMAIN_ADDED = 'OK';
const DOMAIN_LIMIT_REACHED = 'DOMAIN_LIMIT_REACHED';
const NO_SUCH_DOMAIN = 'NO_SUCH_DOMAIN';
const API_USER_INACTIVE = 'API_USER_INACTIVE';
const WRONG_DESTINATION_GIVEN = 'WRONG_DESTINATION_GIVEN';
const DOMAIN_HAS_FEATURE_DISABLED = 'DOMAIN_HAS_FEATURE_DISABLED';
const SKIP_EXTRA_ALIAS = 'SKIP_EXTRA_ALIAS';
const SKIP_ADDED_AS_ALIAS_NOT_DOMAIN = 'SKIP_ADDED_AS_ALIAS_NOT_DOMAIN';
const SKIP_ADDED_AS_DOMAIN_NOT_ALIAS = 'SKIP_ADDED_AS_DOMAIN_NOT_ALIAS';
const SKIP_PROCESS_OF_ADDON_DOMAINS_DISABLED = 'SKIP_PROCESS_OF_ADDON_DOMAINS_DISABLED';
const SKIP_OWNER_DOMAIN_NOT_FOUND = "SKIP_OWNER_DOMAIN_NOT_FOUND";
const SKIP_OWNER_VALIDATION_FAIL = "SKIP_OWNER_VALIDATION_FAIL";
/**
* @var SpamFilter_Logger
*/
protected $_logger;
/**
* @var SpamFilter_ResellerAPI
*/
public $_api;
/**
* @var stdClass
*/
var $_config;
/**
* Panel driver instance
*
* @access public
* @var SpamFilter_PanelSupport_Cpanel
*
* @todo I'm not 100% sure, but it must be at least protected (or even private)
*/
public $_panel;
public function __construct($logger = null, $config = null, $panel = null)
{
$this->_logger = null === $logger ? Zend_Registry::get('logger') : $logger;
if (null !== $config) {
$this->_config = $config;
}
if (null !== $panel) {
$this->_panel = $panel;
}
$this->_api = new SpamFilter_ResellerAPI;
if (!Zend_Registry::isRegistered('general_config')) {
$this->_logger->debug("[Hooks] Initializing settings.. ");
Zend_Registry::set('general_config', new SpamFilter_Configuration( CFG_PATH . '/settings.conf' )); // <-- General settings
}
$this->_config = Zend_Registry::get('general_config');
$this->_panel = new SpamFilter_PanelSupport();
}
/**
* Adds a domain to the spamfilter
*
* @param string $domain Domain to add
* @param SpamFilter_ResellerAPI $apiRef Override API reference with a local one
* @param bool $force Force the addition of the domain, would skip remote domains check.
* @param string $destination Override destination used. If none provided, auto guessing will be done
* @param array $aliases
*
* @return array Statuscode & responses
* @todo Rewrite this so it has less ifs / is less complex.
*
* @access public
*/
public function AddDomain($domain, SpamFilter_ResellerAPI $apiRef = null, $force = false, $destination = null, $aliases = null)
{
$this->_logger->debug("[Hook] Checking if we can add domain '{$domain}'. Auto add domain: {$this->_config->auto_add_domain}, force: {$force}");
if (!$this->_config->auto_add_domain && !$force) {
$this->_logger->debug("[Hook] NOT ADDING Domain: '{$domain}' due to setting (auto_add_domain)");
$response['status'] = false;
$response['reason'] = "DOMAIN_ADD_DISABLED";
$response['counts'] = SpamFilter_Panel_Protect::COUNTS_FAILED;
return $response;
}
$this->_logger->debug("[Hook] Checking if domain can be added during feature list permissions '{$domain}', force: {$force}");
if (!$this->_panel->hasFeatureEnabled($domain)) {
$this->_logger->debug("[Hook] NOT ADDING Domain: '{$domain}' due to be disabled on featurelist");
$response['status'] = false;
$response['reason'] = "DOMAIN_HAS_FEATURE_DISABLED";
$response['counts'] = SpamFilter_Panel_Protect::COUNTS_FAILED;
return $response;
}
// Check if this domain is remote
$configAddOnlyLocalDomains = (0 < $this->_config->handle_only_localdomains);
$isRemoteDomain = $this->_panel->IsRemoteDomain(array('domain' => $domain));
$logMsg1 = "The 'handle_only_localdomain' option is " . ($configAddOnlyLocalDomains ? 'on' : 'off');
$logMsg2 = "The domain is detected as " . ($isRemoteDomain ? 'remote' : 'local');
$this->_logger->debug("[Hook] Evaluating if we can add '{$domain}', since might be a remote domain. {$logMsg1}. {$logMsg2}. Force add is " . ($force ? 'enabled' : 'disabled'));
if ($configAddOnlyLocalDomains && $isRemoteDomain && !$force) {
// Not forced, but we handle only the LOCAL domains and this is a remote domain.
$this->_logger->debug("[Hook] NOT adding domain: '{$domain}', it is a remote domain and this is disabled.");
$response['status'] = false;
$response['reason'] = "SKIP_REMOTE";
$response['counts'] = SpamFilter_Panel_Protect::COUNTS_SKIPPED;
return $response;
}
// Add domain to the AntiSpam appliance
$this->_logger->debug("[Hook] Adding Domain: '{$domain}'");
$fallbackRouteIsUsed = false;
if (empty($destination)) {
// @TODO: Check this function call as it might return that there is no support even though there is.
try {
$this->_logger->debug("[Hook] Attempting to retrieve/use current destination");
// Obtain the destination
$destination = $this->_panel->getDestination($domain, 'hook');
} catch (Exception $e) {
$this->_logger->debug("[Hook] Unable to use the current destination: No panel support.");
}
if ((!isset($destination)) || empty($destination)) {
$this->_logger->debug("[Hook] No destination override, falling back to this servername");
$fallbackRouteIsUsed = (0 < $this->_config->use_existing_mx);
$destination = SpamFilter_Core::GetServerName();
}
}
$asciiSafeDestination = array();
$idn = new IDNA_Convert;
foreach (explode(',', $destination) as $eachDestinationHost) {
$dest = $idn->encode($eachDestinationHost);
/** @see https://trac.spamexperts.com/ticket/17816 */
if (0 < $this->_config->use_ip_address_as_destination_routes) {
$dest = gethostbyname($dest);
}
$asciiSafeDestination[] = $dest;
}
$addData = array(
'domain' => $domain,
'destinations' => Zend_Json::encode($asciiSafeDestination),
);
// If we receive aliases we should add them
if (!empty($aliases)) {
$addData['aliases'] = Zend_Json::encode($aliases);
}
$response = $this->_api->domain()->add($addData);
if(!is_array($response))
{
$this->_logger->err("[Hook-AddDomain] Domain '{$domain}' received a failed response (" . serialize($response) . ")");
// Before we did not return anything at this point.
$response['status'] = false;
$response['reason'] = "SKIP_APIFAIL";
}
elseif ( $response['status'] == false && $response['reason'] == "DOMAIN_EXISTS" )
{
$this->_logger->err("[Hook-AddDomain] Domain '{$domain}' already exists during addition.");
// Before we did not return anything at this point.
$response['status'] = false;
$response['reason'] = "SKIP_ALREADYEXISTS";
}
elseif ( $response['status'] == false && $response['reason'] == "ALREADYEXISTS_NOT_OWNER" )
{
$this->_logger->err("[Hook-AddDomain] Domain '{$domain}' already exists and user is not owner.");
// Before we did not return anything at this point.
$response['status'] = false;
$response['reason'] = "ALREADYEXISTS_NOT_OWNER";
}
elseif ($response['status'] == false && $response['reason'] == "DOMAIN_LIMIT_REACHED" )
{
$this->_logger->err("[Hook-AddDomain] Domain '{$domain}' has NOT been added, limit is reached.");
$response['status'] = false;
$response['reason'] = "DOMAIN_LIMIT_REACHED";
}
elseif ($response['status'] == false && $response['reason'] == "API_USER_INACTIVE" )
{
$this->_logger->err("[Hook-AddDomain] Domain '{$domain}' has NOT been added due to an API error ({$response['reason']}).");
// Before we did not return anything at this point.
$response['status'] = false;
$response['reason'] = "API_USER_INACTIVE";
}
elseif ($response['status'] == false && $response['reason'] == "WRONG_DESTINATION_GIVEN" )
{
$this->_logger->err("[Hook-AddDomain] Domain '{$domain}' has NOT been added due to an API error ({$response['reason']}).");
// Before we did not return anything at this point.
$response['status'] = false;
$response['reason'] = "WRONG_DESTINATION_GIVEN";
}
elseif ($response['status'] == false && $response['reason'] <> "DOMAIN_EXISTS" )
{
$this->_logger->err("[Hook-AddDomain] Domain '{$domain}' has NOT been added due to an API error ({$response['reason']}).");
// Before we did not return anything at this point.
$response['status'] = false;
$response['reason'] = "SKIP_APIFAIL";
} else {
/**
* Check do we need to protect the domain's aliases as well
* @see https://trac.spamexperts.com/ticket/17238
*/
if (0 < $this->_config->handle_extra_domains &&
0 < $this->_config->add_extra_alias &&
is_callable(array($this->_panel, 'getAliasDomains'))
) {
$domainAliases = $this->_panel->getAliasDomains($domain);
if (!empty($domainAliases) && is_array($domainAliases)) {
foreach ($domainAliases as $alias) {
$this->_panel->bulkProtect(array(
'domain' => $alias,
'type' => 'alias',
'owner_domain' => $domain,
));
}
}
}
// Things went fine so lets add the contactdetails to this domain
if (0 < $this->_config->set_contact) {
$contact = $this->_panel->getDomainContact(array(
'domain' => $domain,
));
if (!empty($contact)) {
$this->setContact($domain, $contact);
} else {
$this->_logger->debug(
"[Hook] NOT setting contact for '{$domain}' due to missing address in the controlpanel."
);
}
}
// Add SPF if setting is enabled
if ($this->_config->add_spf_to_domains
&& ($response['reason'] == 'DOMAIN_EXISTS' || $response['reason'] == true)) {
$this->_logger->debug("[Hook] Add/Edit SPF record for: '{$domain}'");
$spfSetupResult = $this->_panel->SetupSPF(array('domain' => $domain));
if (!$spfSetupResult) {
$this->_logger->debug("[Hook] Add/Edit SPF record failed for: '{$domain}'");
}
}
}
$result = array('counts' => null, 'reason' => $response['reason'], 'ok' => null, 'status' => $response['status']);
$domain_failed = $this->isDomainAddFailed( $domain, $response, '[HOOK]' );
if ($domain_failed['failed']) {
// Nay!
$result['counts'] = SpamFilter_Panel_Protect::COUNTS_SKIPPED;
$result['reason'] = $domain_failed['reason'];
} else {
$this->_updateDomainsMxRecords($domain, $apiRef);
}
return $result;
}
/**
* Set the contact address for a domain
*
* @param string $domain Domainname to set the contact for
* @param string $contact Contact address to set for the domain
*
* @return bool Status
*
* @access public
*/
public function setContact($domain, $contact)
{
$this->_logger->info("[Hook] Setting contact for '{$domain}' to '{$contact}'");
$contactData = array(
'domain' => $domain,
'email' => $contact,
);
$response = $this->_api->domaincontact()->set( $contactData );
if ( $response['status'] === false ) // new
{
$this->_logger->err("[Hook] Setting contact failed!: '" . serialize($response) . "'");
return false;
} else {
$this->_logger->debug("[Hook] Setting contact completed! '" . serialize($response) . "'");
return true;
}
}
/**
* Remove a domain from the spamfilter
*
* @param string $domain Domain to remove
* @param bool $force Force removal in case auto-removal is disabled. Only used in special cases
* @param bool $resetdns
*
* @return array Statuscode & responses
*
* @access public
*/
public function DelDomain($domain, $force = false, $resetdns = false)
{
if (0 < $this->_config->auto_del_domain || $force) {
$domainData = array('domain' => $domain);
if ($resetdns) {
$this->_logger->info("[Hook] Resetting MX records for '{$domain}'");
$routes = $this->_api->domain()->getRoute( array('domain' => $domain) );
SpamFilter_DNS::RevertMXs($domain, $routes);
$this->_logger->info("[Hook] Removing SPF record for '{$domain}'");
$this->_panel->RemoveSPF($domain);
}
$response = $this->_api->domain()->remove($domainData);
if ($response['status'] == false) {
$this->_logger->err(
"[Hook] Domain NOT deleted: '{$domain}' due to API error ({$response['reason']})"
);
return $response;
}
$this->_logger->info("[Hook] Domain deleted: '{$domain}'");
$response['status'] = true;
SpamFilter_Panel_Cache::clear('collectiondomains');
SpamFilter_Core::invalidateDomainsCaches();
SpamFilter_Panel_Cache::clear('user_domains_' . md5(SpamFilter_Core::getUsername()));
return $response;
} else {
$this->_logger->debug("[Hook] NOT DELETING Domain: '{$domain}' due to setting (auto_del_domain)");
$response['status'] = false;
$response['reason'] = "DOMAIN_DEL_DISABLED";
return $response;
}
}
/**
* Create an alias in the spamfilter
*
* @param string $domain Domain to create the alias for
* @param string $alias Alternative domainname for $domain
* @param bool $force Force addition, skips extra domain checks.
* @param SpamFilter_ResellerAPI $apiRef Optionally override API reference.
*
* @return array Status code & response
*
* @access public
*/
public function AddAlias($domain, $alias, $force = false, $apiRef = null)
{
$this->_logger->debug("[Hook] Add Alias domain: '{$alias}' and link to '{$domain}'");
$this->_logger->debug("[Hook] Checking if alias can be added during feature list permissions '{$alias}', domain: '{$domain}', force: {$force}");
if (!$this->_panel->hasFeatureEnabled($domain)) {
$this->_logger->debug("[Hook] NOT ADDING Alias: '{$alias}' due to be disabled on featurelist");
$response['status'] = false;
$response['reason'] = SpamFilter_Hooks::DOMAIN_HAS_FEATURE_DISABLED;
$response['counts'] = SpamFilter_Panel_Protect::COUNTS_FAILED;
return $response;
}
// Add domain as alias
if($this->_config->handle_extra_domains || $force)
{
$this->_logger->info("[Hook] Add Alias '{$alias}' to domain '{$domain}'");
$domainData = array(
'domain' => $domain,
'alias' => $alias,
);
$response = $this->_api->domainalias()->add( $domainData );
SpamFilter_Panel_Cache::clear(strtolower('user_domains_' . md5(SpamFilter_Core::getUsername())));
if(!is_array($response))
{
$this->_logger->err("[Hook-AddAlias] Alias '{$alias}' received a failed response");
} elseif ($response['status'] == false && in_array($response['reason'], array("DOMAIN_EXISTS", "ALIAS_EXISTS"))) {
$this->_logger->err("[Hook-AddAlias] Alias '{$alias}' already exists.");
return $response;
}
elseif ($response['status'] == false )
{
$this->_logger->err("[Hook-AddAlias] Alias '{$alias}' has NOT been added due to an API error ({$response['reason']}).");
}
else
{
// Edit MX to include new records.
$this->_updateDomainsMxRecords($alias, $apiRef);
}
// HMMM
$response['status'] = true;
return $response;
}
$this->_logger->debug("[Hook] NOT Adding Alias: '{$alias}' to '{$domain}' due to setting (handle_extra_domains)");
$response['status'] = false;
$response['reason'] = "ALIAS_DISABLED";
return $response;
//return false;
}
/**
* Remove the alias from the spamfilter
*
* @param string $domain Domain to remove the alias from
* @param string $alias Alias to remove
* @param bool $force Force deletion, skips extra_domain check
*
* @return array of status code / responeses
*
* @access public
*/
public function DelAlias($domain, $alias, $force = false)
{
$this->_logger->debug("[Hook] Delete Alias domain: '{$alias}' and unlink from '{$domain}'");
// Delete alias from domain
if($this->_config->handle_extra_domains || $force)
{
$this->_logger->info("[Hook] Delete Alias '{$alias}' from domain '{$domain}'");
$domainData = array(
'domain' => $domain,
'alias' => $alias,
);
$response = $this->_api->domainalias()->remove( $domainData );
if( $response['status'] == false )
{
$this->_logger->err("[Hook] Alias NOT removed: '{$alias}' due to API error ({$response['reason']})");
return $response;
}
// Success
SpamFilter_Panel_Cache::clear(strtolower('user_domains_' . md5(SpamFilter_Core::getUsername())));
$this->_logger->debug("[Hook] Alias removed: '{$alias}'");
$response['status'] = true;
return $response;
}
$this->_logger->debug("[Hook] NOT Deleting Alias: '{$alias}' from '{$domain}' due to setting (handle_extra_domains)");
$response['status'] = false;
$response['reason'] = "ALIAS_DISABLED";
return $response;
//return false;
}
/**
* Remove a whole account. This requires us to retrieve all domains/aliases and remove them all
*
* @param string $username Username that is being removed. Used as filter.
*
* @return array Status info
*
* @todo Rewrite this to rely on removal procedures in the PanelSupport driver (e.g. removeAccountDomains( $username ))
*
* @access public
*/
public function DeleteAccount($username)
{
// Get all of $username's domains using the panel hook.
$this->_logger->info("[Hook] DeleteAccount: '{$username}'");
$result = $this->_panel->getUsersDomains(array(
'username' => $username
));
//$domains = (!empty($result[0]['domain'])) ? $result['acct'] : null;
if (is_array($result) && count($result) > 0)
{
foreach($result as $domain)
{
$this->_logger->info("[Hook] Deleting domain: {$domain['domain']}..");
$this->DelDomain($domain['domain']);
$this->_logger->info("[Hook] Done\n");
}
}
if ( $this->_config->add_extra_alias == 0 )
{
// Only handle standalone domains not added as an alias
// Aliases are already being processed by the SE-api.
$addonDomains = $this->_panel->getAddonDomains( $username );
$countAddonDomains = is_array($addonDomains) ? count($addonDomains) : 0;
$this->_logger->debug("[WHM] Domain Removal, " . $countAddonDomains . " addon domains: " . serialize($addonDomains) );
if ($addonDomains !== false)
{
foreach ($addonDomains as $key => $addon)
{
$this->_logger->info("[Hook] Deleting addon domain: {$addon['alias']}..");
$this->DelDomain($addon['alias']);
$this->_logger->info("[Hook] Done\n");
}
}
$parkedDomains = $this->_panel->getParkedDomains( $username );
$countParkedDomains = is_array($parkedDomains) ? count($parkedDomains) : 0;
$this->_logger->debug("[WHM] Domain Removal, " . $countParkedDomains . " parked domains: " . serialize($parkedDomains) );
if ( $parkedDomains !== false )
{
foreach ($parkedDomains as $key => $parked)
{
$this->_logger->info("[Hook] Deleting parked domain: {$parked['alias']}..");
$this->DelDomain($parked['alias']);
$this->_logger->info("[Hook] Done\n");
}
}
$subDomains = $this->_panel->getSubDomains( $username );
$countSubDomains = is_array($subDomains) ? count($subDomains) : 0;
$this->_logger->debug("[WHM] Domain Removal, " . $countSubDomains . " subdomains: " . serialize($subDomains) );
if ( $subDomains !== false )
{
foreach ($subDomains as $key => $subDomain)
{
$this->_logger->info("[Hook] Deleting subdomain: {$subDomain['alias']}..");
$this->DelDomain($subDomain['alias']);
$this->_logger->info("[Hook] Done\n");
}
}
}
return array('status' => true);
}
/**
* Update destination / MX records for the domain
*
* @param string $domain Domain to update
* @param string $destination New destination to set. If unset, autoguessing is applied
* @param SpamFilter_ResellerAPI $apiRef Optionally override API reference
*
* @return bool Statuscode
*
* @access public
*/
public function updateData($domain, $destination = null, $apiRef = null)
{
$this->_logger->debug("[Hook] Updating data (MX+Destination) for '{$domain}'.");
if (empty($destination)) {
// Get our local hostname
$destination = SpamFilter_Core::GetServerName();
}
if (empty($destination)) {
$this->_logger->err("[Hook] Unable to update data for '{$domain}' since the destination is empty.");
return false;
}
/**
* @see https://trac.spamexperts.com/ticket/22936
*/
if (0 < $this->_config->use_ip_address_as_destination_routes) {
if (strstr($destination, ',')) {
foreach (explode(',', $destination) as $dest) {
$dest = gethostbyname($dest);
}
$newDestination[] = $dest;
} else {
$newDestination = array(gethostbyname($destination));
}
} else {
if (strstr($destination, ',')) {
$this->_logger->err("[Hook] Converting destination list to array.");
$newDestination = explode(',', $destination);
$this->_logger->err("[Hook] New destination:" . serialize($destination));
} else {
$newDestination = array($destination);
}
}
// Change the destination for the domain
$data = array(
'domain' => $domain,
'destinations' => $newDestination,
);
$response = $this->_api->domain()->edit($data);
if ($response['status'] == false) {
$this->_logger->err("[Hook] Changing the route for '{$domain}' has failed.");
return false;
} else {
$this->_updateDomainsMxRecords($domain, $apiRef);
$this->_logger->info("[Hook] The route configuration & MX records for '{$domain}' have been updated.");
return true;
}
}
/**
* Domain's MX records setter method
*
* @access private
*
* @param $domain
* @param $apiRef
*
* @return boolean
*/
private function _updateDomainsMxRecords($domain, $apiRef)
{ // Update MX records
if ($this->_config->provision_dns) {
$this->_logger->debug("[Hook] Changing MX records for: '{$domain}'");
return SpamFilter_DNS::ConfigureDNS($domain, $apiRef);
} else {
$this->_logger->debug(
"[Hook] NOT changing MX records for: '{$domain}' due to configuration restriction (provision_dns)"
);
return false;
}
}
/**
* Toggle the operation of the spamfilter based on the MXtype
*
* @param string $domain Domainname to switch for
* @param string $mxtype Type to work on
*
* @return mixed
*
* @access public
*/
public function setMailHandling($domain, $mxtype)
{
$this->_logger->info("[Hook] {$domain}'s route has changed to '{$mxtype}'");
if (!$this->_config->handle_route_switching) {
$this->_logger->info("[Hook] NOT executing actions linked to routing change, disabled in settings.");
return false;
}
$this->_logger->info("[Hook] Executing actions linked to routing change.");
// @TODO: Implement changing status if the status is set to 'local'.
// Auto / remote / backup does not count and should not be acted upon.
if (strtolower($mxtype) <> "local") {
// Domain NOT set to local, we should stop handling it
if ($this->_config->provision_dns) {
$this->_logger->info("[Hook] {$domain}'s MX records will be automatically reset, as configured in settings.");
/**
* Force remove the domain but skip MX records reset
*
* @see https://github.com/SpamExperts/cpanel-addon/issues/10
*/
$this->DelDomain($domain, true, false);
return $this->safeResetDns($domain);
} else {
$this->_logger->info("[Hook] {$domain}'s MX records will NOT be automatically reset, as configured in settings.");
return $this->DelDomain($domain, true); // Force remove it and don't change MX records
}
} else {
// Domain set to local, we should handle it.
$this->_logger->debug("[Hook] Domain '{$domain}' has been changed to local, making sure it exists in the filtering solution.");
return $this->AddDomain( $domain );
}
}
/**
* Check a domain added or not
*
* @param string $domain domain
* @param array $params array Statuscode & responses
* @param string $debugStr
*
* @return array failed & reason - if a domain hasn't been added 'failed' = true
*
* @access public
*/
public function isDomainAddFailed($domain, $params, $debugStr)
{
$result = array('failed' => false, 'reason' => '');
if (!is_array($params)) {
$result['failed'] = true;
$result['reason'] = self::SKIP_APIFAIL;
$this->_logger->debug(
$debugStr . " Normal domain '" . $domain . "' has NOT been added because of an API failure."
);
} elseif ($params['reason'] == self::DOMAIN_LIMIT_REACHED) {
$result['failed'] = true;
$result['reason'] = self::DOMAIN_LIMIT_REACHED;
$this->_logger->debug(
$debugStr . " Normal domain '" . $domain . "' has NOT been added because domain limit is reached."
);
} elseif ($params['reason'] == self::API_REQUEST_FAILED) {
$result['failed'] = true;
$result['reason'] = self::SKIP_APIFAIL;
$this->_logger->debug(
$debugStr . " Normal domain '" . $domain . "' has NOT been added because of an API error."
);
} elseif ($params['reason'] == self::API_USER_INACTIVE) {
$result['failed'] = true;
$result['reason'] = self::API_USER_INACTIVE;
$this->_logger->debug(
$debugStr . " Normal domain '" . $domain . "' has NOT been added because of the API user is inactive."
);
} elseif ($params['reason'] == self::WRONG_DESTINATION_GIVEN) {
$result['failed'] = true;
$result['reason'] = self::WRONG_DESTINATION_GIVEN;
$this->_logger->debug(
$debugStr . " Normal domain '" . $domain . "' has NOT been added because of a wrong destination has been given."
);
} elseif ($params['status'] == false
&& !in_array(
$params['reason'], array(self::DOMAIN_EXISTS, self::SKIP_ALREADYEXISTS)
)
) {
$result['failed'] = true;
$result['reason'] = self::SKIP_UNKNOWN;
$this->_logger->debug(
$debugStr . " Normal domain '" . $domain . "' has NOT been added ({$params['reason']})."
);
}
return $result;
}
/**
* isDataUpdated
* Check data updated or not
*
* @param string $status status
* @param $loginfo array of string (updated,skipped) info for logger
*
* @return array action & reason
*
* @access public
*/
public function isDataUpdated( $status, $loginfo )
{
if ($status) {
// OK
$result['action'] = 'updated';
$result['reason'] = self::ALREADYEXISTS_ROUTESET;
$this->_logger->debug($loginfo['updated']);
} else {
// Failed
$result['action'] = 'skipped';
$result['reason'] = self::ALREADYEXISTS_ROUTESETFAIL;
$this->_logger->debug($loginfo['skipped']);
}
return $result;
}
/**
* Migrate the domain to a different user
*
* @param string $domain Domain to move
* @param string $user User to move the domain to
* @param string $password Password of the destination user
*
* @return bool Status
*
* @access public
*/
public function MigrateDomain( $domain, $user, $password )
{
// Change the owner for the domain
$data = array(
'domains' => $domain,
'destination_username' => $user,
'destination_password' => $password,
);
$response = $this->_api->domain()->move( $data );
if ( $response['status'] == false )
{
if(is_array($domain))
{
$c = count($domain);
$this->_logger->debug("[Hook] {$c} domains cannot be migrated to user '{$user}'");
} else {
$this->_logger->err("[Hook] Changing the owner for '{$domain}' has failed.");
}
return false;
} else {
if(is_array($domain))
{
$c = count($domain);
$this->_logger->debug("[Hook] {$c} domains have succesfully been migrated to user '{$user}'");
} else {
$this->_logger->debug("[Hook] Domain '{$domain}' has succesfully been migrated to user '{$user}'");
}
return $response;
}
}
/**
* Get free limit for migration domains
*
* @param string $user User to move the domain to
* @param string $password Password of the destination user
*
* @return integer|string|bool Free limit
*
* @access public
*/
public function GetFreeLimit( $user, $password )
{
$data = array(
'destination_username' => $user,
'destination_password' => $password,
);
$response = $this->_api->domain()->getfreelimit( $data );
if ( empty($response['result']['freelimit']))
{
$this->_logger->debug("[Hook] cannot get free limit");
return false;
} else {
$this->_logger->debug("[Hook] free limit is '".$response['result']['freelimit']."'");
return $response['result']['freelimit'];
}
}
/**
* Get the domain destination(s)
*
* @param string $domain Domain
*
* @return array of string Destinations
*
* @access public
*/
public function GetRoute( $domain )
{
$routes = SpamFilter_Panel_Cache::get(md5($domain) . '_routes');
$info = array('additional' => '', 'reason' => '');
if (empty($routes)) {
$routes = array();
$response = (array)$this->_api->domain()->getroute( array('domain' => $domain) );
if (!empty($response) && empty($response["reason"])) {
try {
$this->_logger->debug("[Hook] routes '".implode(',',(array)$response)."'");
foreach ($response as $item) {
$routes[] = explode(':', $item);
}
}catch( Exception $e ) {}
} else {
$info = array('additional' => $response["additional"], 'reason' => $response["reason"]);
}
SpamFilter_Panel_Cache::set(md5($domain) . '_routes', $routes, 10);
}
return array('routes' => $routes, 'info' => $info);
}
/**
* This method implements the procedure of "safe" MX records reset as
* https://github.com/SpamExperts/cpanel-addon/issues/10 suggests
*
* @access public
*
* @param string $domain
*
* @return boolean
*/
public function safeResetDns($domain)
{
$existimgMxRecords = $this->_panel->getMxRecords($domain);
if (is_array($existimgMxRecords)) {
$recordsRemoved = 0;
$spamfilterMxRecords = $this->getFilteringClusterHostnames();
// Sort existing MX records by line in DESC order to avoid attempting
// entries with obsolete line reference
usort($existimgMxRecords, function ($a, $b) { return $b['Line'] > $a['Line'] ? 1 : -1; });
foreach ($existimgMxRecords as $existimgMxRec) {
if (in_array($existimgMxRec['exchange'], $spamfilterMxRecords)) {
$this->_panel->removeDNSRecord($domain, $existimgMxRec['Line']);
$recordsRemoved++;
}
}
if ($recordsRemoved === count($existimgMxRecords)) {
$this->_panel->addMxRecord($domain, 10, $this->getFallbackMxRecordHostname());
}
}
return true;
}
/**
* Wrapper for \SpamFilter_DNS::getFilteringClusterHostnames() for testability
*
* @return array
*/
public function getFilteringClusterHostnames()
{
return \SpamFilter_DNS::getFilteringClusterHostnames();
}
/**
* Wrapper for \SpamFilter_Core::GetServerName() for testability
*
* @return string
*/
public function getFallbackMxRecordHostname()
{
return gethostname();
}
}