'/releases/v7/', '8' => '/releases/v8/'); const PACKAGE_PHP5 = 'package2'; const PACKAGE_PHP7 = 'package7'; const PACKAGE_PHP71 = 'package8'; public function __construct($isCli = false) { ini_set('display_errors', 'on'); $this->_isCli = $isCli; if (isset($_GET['step'])) { $this->_step = $_GET['step']; } if (isset($_POST['step'])) { $this->_step = $_POST['step']; } date_default_timezone_set('Europe/Moscow'); if (!ini_get('session.save_handler') == 'files' && !@is_writable(ini_get('session.save_path'))) { ini_set('session.save_path', '/builds/apliteni/keitaro/upgrader8.php/models' . '/var/sessions'); } } public function log($msg) { file_put_contents('upgrader8.log', date('Y-m-d H:is') . ' ' . $msg . "\n", FILE_APPEND); } public function getCurrentStep() { return $this->_step; } public function getCurrentStepData() { $action = '_step' . $this->_step; if (method_exists($this, $action)) { return $this->{$action}(); } else { return array(); } } public function updateStep($newStep) { $this->_step = $newStep; } public function runMainAction() { } private function _step1() { $ip = false; if ($this->_isCli) { $ip = ParameterService::instance()->getPersistent(ParameterService::IP); } if (!$ip) { $ip = IdentityService::instance()->getIp(); } $data = new Step1ResultSet(); $data->ip = StatusCheckerService::checkIpStatus($ip); $data->ioncube = StatusCheckerService::checkIoncubeStatus(); $data->php = StatusCheckerService::checkPhpVersion(); $data->mysql = StatusCheckerService::checkMysqlStatus(); $data->safemode = StatusCheckerService::checkSafemodeStatus(); $data->xcache = StatusCheckerService::checkXcacheStatus(); $data->iconv = StatusCheckerService::checkIconvStatus(); $data->mbstring = StatusCheckerService::checkMbStatus(); $data->curl = StatusCheckerService::checkCurlStatus(); $data->zlib = StatusCheckerService::checkZlibStatus(); $data->zip = StatusCheckerService::checkZipStatus(); $data->json = StatusCheckerService::checkJsonStatus(); $data->hash = StatusCheckerService::checkHashStatus(); $data->permissions = StatusCheckerService::checkDirStatus(); return $data; } private function _isUpgrade() { $action = ParameterService::instance()->getPersistent('action'); return $action == 'upgrade'; } private function _isDowngrade() { $action = ParameterService::instance()->getPersistent('action'); return $action == 'downgrade'; } private function _step3() { $data = new SingleElementResultSet(); $action = ParameterService::instance()->getAction(); ParameterService::instance()->savePersistent('action', $action); $moveStat = ParameterService::instance()->getMoveStat(); ParameterService::instance()->savePersistent('move_stat', $moveStat); if ($this->_isUpgrade()) { $version = '8'; } elseif ($this->_isDowngrade()) { $version = '7'; } else { $data->element = new GeneralResult(false, ""); return $data; } $localPackage = 'package.pack'; $package = $this->_getPackageUrl($version); $data->element = DownloadService::instance()->download($package, $localPackage); return $data; } private function _checkVersionFile() { if (!file_exists('version.php')) { return false; } $version = (include 'version.php'); if ($this->_isUpgrade()) { return $version[0] = '8'; } else { return $version[0] = '7'; } } private function _step4() { @set_time_limit(180); $data = new SingleElementResultSet(); $localPackage = 'package.pack'; if (!file_exists($localPackage) || !filesize($localPackage)) { $data->element = new GeneralResult(false, KLocaleService::t('step4.download_error')); return $data; } if ($this->_isUpgrade()) { @mkdir('backup'); FileService::instance()->dirmv('application/filters', 'backup/filters'); @mkdir('application/filters'); FileService::instance()->dirmv('application/macros', 'backup/macros'); @mkdir('application/macros'); FileService::instance()->dirmv('application/redirects', 'backup/redirects'); @mkdir('application/redirects'); } $result = ArchiveService::instance()->unpack($localPackage); if (!$result->getStatus()) { $data->element = $result; return $data; } if (file_exists('www/version.php')) { FileService::instance()->dirmv('www', './', true); } if (!$this->_checkVersionFile()) { $data->element = new GeneralResult(false, KLocaleService::t('step4.unpack_error')); return $data; } $uid = fileowner(dirname(__FILE__)); $gid = filegroup(dirname(__FILE__)); FileService::instance()->chmod('var', 0777); FileService::instance()->chown('./', $uid, $gid); FileService::instance()->chown('www', $uid, $gid); @mkdir('var/cache', 0777); @chmod('var/cache', 0777); @mkdir('var/cron', 0777); @chmod('var/cron', 0777); @mkdir('var/exports', 0777); @mkdir('var/log', 0777); @mkdir('var/sessions', 0777); @chmod(ConfigService::instance()->getConfigIniPath(), 0777); @unlink($localPackage); FileService::instance()->rmdir('www'); if ($this->_isUpgrade()) { ConfigService::instance()->setCompatibility(); } elseif ($this->_isDowngrade()) { MysqlService::instance()->connectFromIni(); MysqlService::instance()->setCacheStorage('files'); @unlink('application/filters/example.php'); @unlink('application/macros/example.php'); @unlink('application/redirects/example.php'); } $data->element = new GeneralResult(true, ''); return $data; } private function _step5() { $data = new SingleElementResultSet(); $result = $this->_moveToKeitaro8Namespace(); if (!$result->getStatus()) { $data->element = $result; return $data; } $runner = new \Component\Migrations\Service\MigrationRunnerService(); try { $runner->runAll(true); } catch (ADODB_Exception $e) { $data->element = new GeneralResult(false, $e->getMessage()); return $data; } catch (\Exception $e) { $data->element = new GeneralResult(false, $e->getMessage()); return $data; } $data->element = new GeneralResult(true, KLocaleService::t('step5.migrations_success')); return $data; } private function _step6() { $lockName = 'var/locks/delayed_command.lock'; $data = new SingleElementResultSet(); $lock = NULL; for ($i = 0; $i < 10 && !$lock; $i++) { $lock = LockService::instance()->tryLock($lockName); } if ($lock) { set_time_limit(0); ignore_user_abort(true); $this->log('start converting stats'); $mysqlService = MysqlService::instance(); ConfigService::instance()->updateIniConfig(); $result = $mysqlService->connectFromIni(); if ($result->getStatus()) { $result = $this->_moveToKeitaro8Namespace(); if ($result->getStatus()) { $shards = $mysqlService->getShardList(); $logger = new \Component\Benchmark\NullTrafficLogger(); $campaigns = \Component\Campaigns\Repository\CampaignRepository::instance()->notDeleted(); $campaignsDic = []; foreach ($campaigns as $campaign) { $campaignsDic[$campaign->getId()] = $campaign; } \Component\DeviceDetection\Service\DeviceInfoService::instance()->disableCache(); $cb = function ($rawClick, $campaign) { $this->log('saving click ' . json_encode($rawClick->getData())); $pipeline = [new \Component\Clicks\ClickBuilding\GenerateIds($campaign), new \Component\Clicks\ClickBuilding\SetParams($campaign), new \Component\Clicks\ClickBuilding\SetCosts($campaign)]; foreach ($pipeline as $stage) { $stage->process($rawClick); } \Component\Clicks\Service\RawClickService::instance()->saveRawVisit($rawClick); }; foreach ($shards as $shard) { $shartTable = "keitaro_stats_{$shard[0]}"; $this->log('start shard ' . $shartTable); $mysqlService->processShard($shard[0], $logger, $campaignsDic, $cb); } $result = new GeneralResult(true, ''); } } $data->element = $result; LockService::instance()->unlock($lock, $lockName); } else { $data->element = new GeneralResult(false, KLocaleService::t('step6.already_processing')); } return $data; } private function _moveToKeitaro8Namespace() { $v8Autoload = './vendor/autoload.php'; if (!is_file($v8Autoload)) { return new GeneralResult(false, KLocaleService::t('step5.autoload_missing')); } define("ROOT", realpath('.')); require $v8Autoload; if (!class_exists('Core\\Context\\AdminContext')) { return new GeneralResult(false, KLocaleService::t('step5.autoload_missing')); } $context = new \Core\Context\AdminContext(); $context->init(); return new GeneralResult(true, ""); } private function _getPackageUrl($version) { if (class_exists('ZipArchive')) { return ConfigService::SITENAME . $this->_versions[$version] . $this->_getPackageName() . '.zip'; } else { return ConfigService::SITENAME . $this->_versions[$version] . $this->_getPackageName() . '.tar.gz'; } } private function _getPackageName() { if (version_compare(phpversion(), '7') >= 0 && version_compare(phpversion(), '7.1') < 0) { return self::PACKAGE_PHP7; } elseif (version_compare(phpversion(), '7.1') >= 0 && version_compare(phpversion(), '7.2') < 0) { return self::PACKAGE_PHP71; } else { return self::PACKAGE_PHP5; } } } } namespace Views { interface ViewInterface { public function renderStepPage($step, $data); } } namespace Views { use ResultSets\Step1ResultSet; use ResultSets\Step3ResultSet; use Services\KLocaleService; use Services\ConfigService; use Services\ParameterService; use Services\RedirectService; use Services\StatusCheckerService; use ResultSets\SingleElementResultSet; use ResultSets\ElementArrayResultSet; class WebView implements ViewInterface { const MAIN_TEMPLATE = << #TITLE# / #MAIN_TITLE#
#TITLE#
#CONTENT#
TPL; private $_title; private $_content; private $_footer; public function __construct() { header('Content-Type: text/html; charset=utf-8'); } private function _step1(Step1ResultSet $data) { $tableData = array(); $this->_title = KLocaleService::t('step1.title'); $this->_content .= '' . "\r\n"; foreach ($data as $key => $value) { $row = $data->getMemberRow($key); $header = $row[Step1ResultSet::HEADER_COL]; $text = $row[Step1ResultSet::STATUS_COL] ? $this->_wrapSuccess($row[Step1ResultSet::TEXT_COL]) : $this->_wrapError($row[Step1ResultSet::TEXT_COL]); $this->_content .= ''; } $this->_content .= '
' . $header . ':' . $text . '
'; if ($data->getStatus()) { if (defined('CHECKER') && CHECKER) { $this->_footer .= KLocaleService::t('step1.success') . "\r\n"; } else { $this->_footer .= '' . "\r\n"; } } else { $this->_footer .= '

' . KLocaleService::t('step1.failure') . '.

'; $this->_footer .= '' . "\r\n"; } } private function _step2() { $this->_title = KLocaleService::t('step2.title'); $this->_content .= '
'; $this->_content .= '' . KLocaleService::t('step2.choose_action') . ''; $this->_content .= '
'; $this->_content .= '
'; $this->_content .= ''; $this->_content .= '
'; $this->_footer .= ''; } private function _step3(SingleElementResultSet $data) { $this->_title = KLocaleService::t('step3.title'); if ($data->getStatus()) { $this->_content .= KLocaleService::t('step3.success'); $this->_footer .= ''; } else { $this->_content .= '
' . $data->getErrorText() . '
'; $this->_footer .= '"; } } private function _step4(SingleElementResultSet $data) { $this->_title = KLocaleService::t('step4.title'); if ($data->getStatus()) { $this->_content .= KLocaleService::t('step4.unpacked'); if (ConfigService::instance()->isKeitaro8()) { $this->_footer .= ''; } else { $this->_footer .= ''; } } else { $this->_content .= '
' . $data->getErrorText() . '
'; $this->_footer .= '"; } } private function _step5(SingleElementResultSet $data) { $this->_title = KLocaleService::t('step5.title'); if ($data->getStatus()) { $this->_content .= KLocaleService::t('step5.migrations_applied'); if (ParameterService::instance()->getPersistent('move_stat') == 1) { $this->_footer .= ''; } else { $this->_footer .= ''; } } else { $this->_content .= '
' . $data->getErrorText() . '
'; $this->_footer .= '"; } } private function _step6(SingleElementResultSet $data) { $this->_title = KLocaleService::t('step6.title'); if ($data->getStatus()) { $this->_content .= KLocaleService::t('step6.move_stat_success'); $this->_footer .= ''; } else { $this->_content .= '
' . $data->getErrorText() . '
'; $this->_footer .= '"; } } private function _step7($data) { $this->_title = KLocaleService::t('step7.title'); if (ConfigService::instance()->isKeitaro8()) { $this->_content .= KLocaleService::t('step7.installation_complete8'); } else { $this->_content .= KLocaleService::t('step7.installation_complete7'); } $this->_content .= ''; $this->_footer .= ''; } private function _step8($data) { header('LOCATION: ' . ConfigService::instance()->getPath() . '/admin/'); } private function _wrapSuccess($text) { return '
' . $text . '
'; } private function _wrapError($text) { return '
' . $text . '
'; } private function renderPage($step) { $content = self::MAIN_TEMPLATE; $content = str_replace('#DOMAIN#', ConfigService::SITENAME, $content); $content = str_replace('#CONTENT#', $this->_content, $content); $content = str_replace('#FOOTER#', $this->_footer, $content); $content = str_replace('#STEP#', (int) $step, $content); $content = str_replace('#TITLE#', $this->_title, $content); $content = str_replace('#MAIN_TITLE#', KLocaleService::t('main_title'), $content); $content = str_replace('#DOCUMENTATION#', KLocaleService::t('documentation'), $content); $content = str_replace('#CURRENT_STEP#', (int) $step, $content); $content = str_replace('#ANOTHER_LANG#', $this->_getAnotherLang(), $content); $content = str_replace('#CHANGE_LANG#', $this->_getChangeLangText(), $content); $content = str_replace('#WIKI#', $this->_getWikiDomain(), $content); echo $content; } private function _getWikiDomain() { if (KLocaleService::getPreferredLanguage() == 'ru') { return 'help.keitaro.io/ru/faq'; } else { return 'help.keitaro.io/en/faq'; } } private function _getAnotherLang() { if (KLocaleService::getPreferredLanguage() == 'ru') { return 'en'; } else { return 'ru'; } } private function _getChangeLangText() { if (KLocaleService::getPreferredLanguage() == 'ru') { return 'RU → EN'; } else { return 'EN → RU'; } } public function renderStepPage($step, $data) { $action = '_step' . $step; $this->{$action}($data); $this->renderPage($step); } } } namespace Controllers { use Views\ViewInterface; use Models\StepModelInterface; use Services\KLocaleService; class UpdateController { private $_view = null; private $_model = null; public function __construct(ViewInterface $view, StepModelInterface $model) { $this->_view = $view; $this->_model = $model; } private function _checkLang() { if (isset($_GET['lang'])) { KLocaleService::setPreferredLanguage($_GET['lang']); } } public function dispatchSingle() { $this->_checkLang(); $step = $this->_model->getCurrentStep(); $data = $this->_model->getCurrentStepData(); $this->_view->renderStepPage($step, $data); } } } namespace Services { class AbstractService { protected static $_instances = array(); public static function instance() { $className = get_called_class(); if (!isset(static::$_instances[$className])) { static::$_instances[$className] = new $className(); } return static::$_instances[$className]; } public static function isInitialized() { $className = get_called_class(); return isset(static::$_instances[$className]); } public static function reset() { $className = get_called_class(); static::$_instances[$className] = null; } } } namespace Services { use ResultSets\GeneralResult; class IdentityService extends AbstractService { public function getKey() { return file_get_contents('./var/license/key.lic'); } public function getIp() { $settingsIp = ParameterService::instance()->getIp(); if ($settingsIp) { return $settingsIp; } $resolveMethod = $this->getResolveMethod(); if ($this->_isValid($resolveMethod)) { return $resolveMethod; } return call_user_func(array($this, '_get' . ucfirst($resolveMethod) . 'Ip')); } private function _isValid($ip) { if (filter_var($ip, FILTER_VALIDATE_IP) === false) { return false; } if (strpos($ip, '127.') === 0) { return false; } return strpos($ip, '192.168.') !== 0; } public function getResolveMethod() { if ($ip = ParameterService::instance()->getPersistent(ParameterService::IP)) { $resolveMethod = $ip; } else { $resolveMethod = RESOLVE_METHOD; } if ($this->_isValid($resolveMethod)) { return $resolveMethod; } if ($resolveMethod == 'domain') { $order = array('domain', 'server'); } else { $order = array('server', 'domain'); } $ip = null; foreach ($order as $method) { $ip = call_user_func(array($this, '_get' . ucfirst($method) . 'Ip')); if ($this->_isValid($ip)) { return $method; } } return 'domain'; } private function _getServerIp() { $ip = isset($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR'] : '127.0.0.1'; $ip = str_replace('::ffff:', '', $ip); return $ip; } private function _getDomainIp() { return gethostbyname(@$_SERVER['HTTP_HOST']); } public function saveLicense($licenseKey) { if (!is_dir('./var')) { mkdir('./var', 0777); } if (!is_dir('./var/license')) { mkdir('./var/license', 0777); } if (!is_dir('./var/license/')) { return new GeneralResult(false, KLocaleService::t('step2.permission_error')); } file_put_contents('./var/license/key.lic', $licenseKey); return new GeneralResult(true, ""); } public function validateLicense($key) { $ip = $this->getIp(); $url = ConfigService::SITENAME . '/license/api/check?key=' . urlencode($key) . '&ip=' . $ip; $result = DownloadService::instance()->request($url); if (!$result->getStatus()) { return $result; } if (trim($result->getDesc()) == 'success') { return new GeneralResult(true, ""); } return new GeneralResult(false, KLocaleService::t('step2.license_error')); } } } namespace Services { class ParameterService extends AbstractService { const DOMAIN = 'cliDomain'; const IP = 'cliIp'; const KEY = 'cliKey'; const DB_HOST = 'cliDbHost'; const DB_PREFIX = 'cliDbPrefix'; const DB_USER = 'cliDbUser'; const DB_NAME = 'cliDbName'; const DB_PASS = 'cliDbPass'; const ADMIN_LOGIN = 'cliAdminLogin'; const ADMIN_PASS = 'cliAdminPass'; const ADMIN_PASS_CONFIRM = 'cliAdminPassConfirm'; const EXTRA_URL = 'cliExtraUrl'; const DRAFT_STORAGE = 'cliDraftStorage'; const CACHE_STORAGE = 'cliCacheStorage'; const LANGUAGE = 'cliLanguage'; const VERSION = 'cliVersion'; const TIMEZONE = 'cliTimezone'; const ACTION = 'cliAction'; const MOVE_STAT = 'cliMoveStat'; private $_cliParams = array(); private function isCli() { return php_sapi_name() == 'cli' && !defined("PRELOADER"); } private function setCliParam($key, $val) { $this->_cliParams[$key] = $val; } private function getCliParam($key) { if (isset($this->_cliParams[$key])) { return $this->_cliParams[$key]; } else { return false; } } private function getPostParam($name) { if (!empty($_POST[$name])) { return $_POST[$name]; } else { return false; } } private function saveInSession($key, $val) { $_SESSION[$key] = $val; } private function getFromSession($key) { return @$_SESSION[$key]; } private function removeFromSession($key) { unset($_SESSION[$key]); } public function getIp() { if ($this->isCli()) { return $this->getCliParam(self::IP); } else { return false; } } public function getLicense() { if ($this->isCli()) { return $this->getCliParam(self::KEY); } else { return $this->getPostParam('licenseKey'); } } public function getVersion() { if ($this->isCli()) { return $this->getCliParam(self::VERSION); } else { return $this->getPostParam('version'); } } public function getHostName() { if ($this->isCli()) { return $this->getCliParam(self::DB_HOST); } else { return $this->getPostParam('hostname'); } } public function getUserName() { if ($this->isCli()) { return $this->getCliParam(self::DB_USER); } else { return $this->getPostParam('username'); } } public function getPassword() { if ($this->isCli()) { return $this->getCliParam(self::DB_PASS); } else { return $this->getPostParam('password'); } } public function getDbName() { if ($this->isCli()) { return $this->getCliParam(self::DB_NAME); } else { return $this->getPostParam('dbname'); } } public function getCreateDatabaseParam() { if ($this->isCli()) { return false; } else { return $this->getPostParam('create'); } } public function getPrefixParam() { if ($this->isCli()) { return $this->getCliParam(self::DB_PREFIX); } else { return $this->getPostParam('prefix'); } } public function getKeitaroLogin() { if ($this->isCli()) { return $this->getCliParam(self::ADMIN_LOGIN); } else { return $this->getPostParam('login'); } } public function getKeitaroPass() { if ($this->isCli()) { return $this->getCliParam(self::ADMIN_PASS); } else { return $this->getPostParam('password'); } } public function getKeitaroPassConfirm() { if ($this->isCli()) { return $this->getCliParam(self::ADMIN_PASS_CONFIRM); } else { return $this->getPostParam('password-confirm'); } } public function getExtraUrl() { if ($this->isCli()) { return $this->getCliParam(self::EXTRA_URL); } else { return $this->getPostParam('extra-url'); } } public function getLanguage() { if ($this->isCli()) { return $this->getCliParam(self::LANGUAGE); } else { return $this->getPostParam('language'); } } public function getCacheStorage() { if ($this->isCli()) { $cache = $this->getCliParam(self::CACHE_STORAGE); } else { $cache = $this->getPostParam('cache_storage'); } if (!$cache) { $cache = 'files'; } return $cache; } public function getDraftStorage() { if ($this->isCli()) { $draft = $this->getCliParam(self::DRAFT_STORAGE); } else { $draft = $this->getPostParam('draft_storage'); } if (!$draft) { $draft = 'files'; } return $draft; } public function getTimezone() { if ($this->isCli()) { $timezone = $this->getCliParam(self::TIMEZONE); } else { $timezone = $this->getPostParam('timezone'); } return $timezone; } public function getAction() { if ($this->isCli()) { $timezone = $this->getCliParam(self::ACTION); } else { $timezone = $this->getPostParam('action'); } return $timezone; } public function getMoveStat() { if ($this->isCli()) { $timezone = $this->getCliParam(self::MOVE_STAT); } else { $timezone = $this->getPostParam('move_stat'); } return $timezone; } public function savePersistent($key, $val) { if ($this->isCli()) { $this->setCliParam($key, $val); } else { $this->saveInSession($key, $val); } } public function getPersistent($key) { if ($this->isCli()) { return $this->getCliParam($key); } else { return $this->getFromSession($key); } } public function removeAllPersistent() { session_unset(); } } } namespace ResultSets { interface ResultSetInterface { public function getStatus(); } } namespace ResultSets { use Services\ConfigService; use Services\IdentityService; use Services\KLocaleService; use Services\StatusCheckerService; class Step1ResultSet implements ResultSetInterface { const HEADER_COL = 0; const TEXT_COL = 1; const STATUS_COL = 2; public $ip = null; public $php = null; public $mysql = null; public $safemode = null; public $xcache = null; public $iconv = null; public $mbstring = null; public $zlib = null; public $curl = null; public $permissions = null; public $ioncube = null; public $zip = null; public $json = null; public $hash = null; public function getStatus() { $result = true; foreach ($this as $key => $value) { if (!$value->getStatus()) { $result = false; } } return $result; } public function getMemberRow($member) { $result = array(); $result[self::HEADER_COL] = KLocaleService::t('step1.' . $member); $result[self::TEXT_COL] = $this->{$member}->getDesc(); $result[self::STATUS_COL] = $this->{$member}->getStatus(); return $result; } } } namespace Services { use ResultSets\GeneralResult; class StatusCheckerService extends AbstractService { const IONCUBE_NOT_INSTALLED = 1; const IONCUBE_OLD_VERSION = 2; const IONCUBE_INSTALLED = 3; public static function checkMysqlStatus() { if (!extension_loaded('pdo_mysql')) { return new GeneralResult(false, KLocaleService::t('step1.not_installed')); } else { return new GeneralResult(true, KLocaleService::t('step1.installed')); } } public static function checkPhpVersion() { if (version_compare(phpversion(), ConfigService::MIN_PHP_VERSION) > 0) { return new GeneralResult(true, phpversion()); } else { return new GeneralResult(false, phpversion() . ' - ' . KLocaleService::t('step1.no_php5')); } } public static function checkXcacheStatus() { if (extension_loaded('xcache')) { return new GeneralResult(false, KLocaleService::t('step1.xcache_installed')); } else { return new GeneralResult(true, KLocaleService::t('step1.not_installed')); } } public static function checkIconvStatus() { if (!function_exists('iconv')) { return new GeneralResult(false, KLocaleService::t('step1.not_installed')); } else { return new GeneralResult(true, KLocaleService::t('step1.installed')); } } public static function checkCurlStatus() { if (!function_exists('curl_init')) { return new GeneralResult(false, KLocaleService::t('step1.not_installed')); } else { return new GeneralResult(true, KLocaleService::t('step1.installed')); } } public static function checkZlibStatus() { if (!function_exists('gzopen') && !function_exists('gzopen64')) { return new GeneralResult(false, KLocaleService::t('step1.not_installed')); } else { return new GeneralResult(true, KLocaleService::t('step1.installed')); } } public static function checkDirStatus() { if (!is_writeable('./')) { return new GeneralResult(false, KLocaleService::t('step1.dir_isnt_writable')); } else { return new GeneralResult(true, KLocaleService::t('step1.dir_is_writable')); } } public static function checkSafeModeStatus() { if (ini_get('safe_mode') == 1 || ini_get('safe_mode') === 'on') { return new GeneralResult(false, KLocaleService::t('step1.safe_mode_enable')); } else { return new GeneralResult(true, KLocaleService::t('step1.safe_mode_disable')); } } public static function checkMbStatus() { if (!function_exists('mb_internal_encoding')) { return new GeneralResult(false, KLocaleService::t('step1.not_installed')); } else { return new GeneralResult(true, KLocaleService::t('step1.installed')); } } public static function checkIpStatus($ip) { if (strpos($ip, '127.') === 0 || strpos($ip, '192.168.') === 0) { return new GeneralResult(false, '' . $ip . ' — ' . KLocaleService::t('step1.should_be_external')); } else { return new GeneralResult(true, $ip); } } public static function checkIoncubeStatus() { if (!extension_loaded('ionCube Loader')) { return new GeneralResult(false, KLocaleService::t('step1.not_installed') . ' — ' . KLocaleService::t('step1.ioncube_installation') . ''); } else { $version = ioncube_loader_version(); if (version_compare(ConfigService::MIN_IONCUBE_VERSION, $version) <= 0) { return new GeneralResult(true, KLocaleService::t('step1.installed')); } else { return new GeneralResult(false, ioncube_loader_version() . ' — ' . KLocaleService::t('step1.min_version') . ' ' . ConfigService::MIN_IONCUBE_VERSION); } } } public static function checkRedisStatus() { if (!class_exists('Redis')) { return new GeneralResult(false, ""); } else { return new GeneralResult(true, ""); } } public static function checkSqliteStatus() { if (!extension_loaded('pdo_sqlite')) { return new GeneralResult(false, ""); } else { return new GeneralResult(true, ""); } } public static function checkMemcacheStatus() { if (!function_exists("memcache_connect")) { return new GeneralResult(false, ""); } else { return new GeneralResult(true, ""); } } public static function checkZipStatus() { if (!extension_loaded('zip')) { return new GeneralResult(false, KLocaleService::t('step1.not_installed')); } else { return new GeneralResult(true, KLocaleService::t('step1.installed')); } } public static function checkJsonStatus() { if (!function_exists('json_encode')) { return new GeneralResult(false, KLocaleService::t('step1.not_installed')); } else { return new GeneralResult(true, KLocaleService::t('step1.installed')); } } public static function checkHashStatus() { if (!function_exists('hash')) { return new GeneralResult(false, KLocaleService::t('step1.not_installed')); } else { return new GeneralResult(true, KLocaleService::t('step1.installed')); } } public function getAvaliableCacheStorages() { $storages = array(array("files", KLocaleService::t('step9.files'))); if ($this->checkRedisStatus()->getStatus()) { $storages[] = array("redis", "Redis"); } if ($this->checkMemcacheStatus()->getStatus()) { $storages[] = array("memcache", "Memcache"); } if ($this->checkSqliteStatus()->getStatus()) { $storages[] = array("sqlite", "Sqlite"); } $storages[] = array("off", KLocaleService::t('step9.no_cache')); return $storages; } } } namespace ResultSets { interface ChunkResultSetInterface extends ResultSetInterface { public function getStatus(); public function getDesc(); } } namespace ResultSets { class GeneralResult implements ChunkResultSetInterface { private $_status; private $_desc; public function __construct($status, $desc) { $this->_status = $status; $this->_desc = $desc; } public function getStatus() { return $this->_status; } public function getDesc() { return $this->_desc; } } } namespace Services { use Services\IdentityService; use Services\KLocaleService; use ResultSets\GeneralResult; class ConfigService extends AbstractService { private $_cnf = array(); private $_versionPHP; const SITENAME = 'http://keitarotds.com'; const MIN_IONCUBE_VERSION = 5; const MIN_PHP_VERSION = '5.4.0'; public function __construct() { if (is_file($this->getConfigIniPath())) { $this->updateIniConfig(); } } public function getConfigIniPath() { return 'application/config/config.ini.php'; } public function getConfigIniSamplePath() { return 'application/config/config.ini.sample'; } public function getRemoteFiles() { $ip = IdentityService::instance()->getIp(); $key = IdentityService::instance()->getKey(); return array('GeoLiteCity' => array('path' => 'var/geoip/GeoLiteCity.dat', 'dataUrl' => 'http://keitarotds.com/db/GeoLiteCity.dat.gz', 'crcUrl' => 'http://keitarotds.com/db/GeoLiteCity.dat.crc'), 'SxGeoCity' => array('path' => 'var/geoip/SxGeoCity.dat', 'dataUrl' => 'http://keitarotds.com/db/SxGeoCity.gz', 'crcUrl' => 'http://keitarotds.com/db/SxGeoCity.crc'), 'operatorsV1' => array('path' => 'var/operators/operators.v1.dat', 'dataUrl' => 'http://keitarotds.com/db/operators.v1.dat.gz', 'crcUrl' => 'http://keitarotds.com/db/operators.v1.dat.crc'), 'operatorsV2' => array('path' => 'var/operators/operators.v2.dat', 'dataUrl' => 'http://keitarotds.com/db/operators.v2.dat.gz', 'crcUrl' => 'http://keitarotds.com/db/operators.v2.dat.crc'), 'bots' => array('path' => 'var/bots/bots.dat', 'dataUrl' => 'http://keitarotds.com/db/bots.dat.gz', 'crcUrl' => 'http://keitarotds.com/db/bots.dat.crc'), 'botsV2' => array('path' => 'var/bots/botsV2.dat', 'dataUrl' => 'http://keitarotds.com/files/botsdb?ip=' . $ip . '&key=' . $key . '&extension=gz', 'crcUrl' => 'http://keitarotds.com/files/botsdb?ip=' . $ip . '&key=' . $key . '&extension=crc'), 'carrierdb' => array('path' => 'var/geoip/carriers.dat', 'dataUrl' => 'http://keitarotds.com/files/carrierdb?ip=' . $ip . '&key=' . $key . '&extension=gz', 'crcUrl' => 'http://keitarotds.com/files/carrierdb?ip=' . $ip . '&key=' . $key . '&extension=crc')); } public function getDocumentRoot() { return dirname(__FILE__); } public function updateConfigFile($host, $user, $pass, $db, $prefix) { $salt = ''; $config = file_get_contents($this->getConfigIniSamplePath()); if (file_exists($this->getConfigIniPath())) { $oldCnf = parse_ini_string(file_get_contents($this->getConfigIniPath()), true); if ($oldCnf['system']['salt']) { $salt = $oldCnf['system']['salt']; } } if (!$salt) { $salt = uniqid(mt_rand(), true); } $config = str_replace('#type#', 'mysql', $config); $config = str_replace('#host#', $host, $config); $config = str_replace('#login#', $user, $config); $config = str_replace('#password#', $pass, $config); $config = str_replace('#dbname#', $db, $config); $config = str_replace('#prefix#', $prefix, $config); $config = str_replace('#salt#', $salt, $config); $config = str_replace('#resolve_method#', IdentityService::instance()->getResolveMethod(), $config); if (!file_put_contents($this->getConfigIniPath(), $config)) { return new GeneralResult(false, KLocaleService::t('step7.config_permission_error')); } else { return new GeneralResult(true, ""); } } public function updateIniConfig() { $this->_cnf = parse_ini_string(file_get_contents($this->getConfigIniPath()), true); } public function getPath() { $tmp = explode('/', $_SERVER["REQUEST_URI"]); unset($tmp[count($tmp) - 1]); return implode('/', $tmp); } public function getIniConfig() { return $this->_cnf; } public function updateIniStore() { $config = file_get_contents($this->getConfigIniPath()); if (!@file_put_contents($this->getConfigIniPath(), $config)) { return new GeneralResult(false, KLocaleService::t('step7.config_permission_error')); } else { return new GeneralResult(true, ""); } } public function getVersionPHP() { if (empty($this->_versionPHP)) { $versionFileName = getcwd() . '/version.php'; if (is_file($versionFileName)) { $this->_versionPHP = (require $versionFileName); } else { return null; } } return $this->_versionPHP; } public function isKeitaro8() { $version = $this->getVersionPHP(); return $version[0] == '8'; } public function getTimezones() { $timezones = []; foreach (\DateTimeZone::listIdentifiers() as $tz) { $time = new \DateTime('now', new \DateTimeZone($tz)); $name = '(GMT' . $time->format('P') . ') ' . $tz; $timezones[$name] = $tz; } ksort($timezones); return $timezones; } public function getDefaultTimezone() { return date_default_timezone_get(); } public function isValidTimezone($timezone) { return in_array($timezone, \DateTimeZone::listIdentifiers()); } public function getUTCTime() { return gmdate('Y-m-d H:i:s'); } public function setCompatibility() { $configPath = $this->getConfigIniPath(); if (is_file($configPath)) { $content = file_get_contents($configPath); if (strpos($content, 'compatibility_v6') == false) { file_put_contents($configPath, "\n" . 'compatibility_v6 = true', \FILE_APPEND); } if (strpos($content, 'compatibility_v7') == false) { file_put_contents($configPath, "\n" . 'compatibility_v7 = true', \FILE_APPEND); } } } } } namespace Services { class KLocaleService extends AbstractService { protected static $_data = array('ru' => array('main_title' => 'Установка Keitaro TDS', 'step1' => array('title' => 'Проверка конфигурации сервера', 'mysql' => 'Наличие PDO MySQL', 'safemode' => 'Отключенный Safemode', 'ioncube' => 'IonCube Loader', 'php' => 'Версия PHP 5.4 или выше', 'iconv' => 'Расширение iconv', 'mbstring' => 'Расширение mbstring', 'curl' => 'Расширение CURL', 'permissions' => 'Доступ к текущей директории', 'ip' => 'IP сервера', 'min_version' => 'Для Keitaro TDS 7 необходима версия 5.0 или выше', 'success' => '

Проверка прошла успешно.

Вы можете установить Keitaro TDS на этот сервер

', 'failure' => 'Сервер не соответствует требованиям', 'retry' => 'Проверить еще раз', 'not_installed' => 'Не установлено', 'installed' => 'Установлено', 'no_php5' => 'необходим PHP 5.4 или новее', 'dir_isnt_writable' => 'Нет прав на запись — установите права на запись папки с инсталятором', 'dir_is_writable' => 'Запись разрешена', 'safe_mode_enable' => 'Включен — необходимо отключить', 'safe_mode_disable' => 'Отключен', 'should_be_external' => 'необходим внешний IP', 'ioncube_installation' => 'инструкция по установке', 'storage_recommend' => 'Рекомендуется установить APC или Memcache (не обязательно)', 'zlib' => 'Расширение zlib', 'xcache' => 'Xcache', 'xcache_installed' => 'Включен. Наличие xcache может привести к периодическим появлениям ошибки "502 Bad Gateway".', 'zip' => 'Расширение Zip', 'json' => 'Расширение JSON', 'hash' => 'Расширение Hash'), 'step2' => array('title' => 'Выбор вида обновления', 'choose_action' => 'Выберите версию', 'upgrade' => 'Обновить до v8', 'downgrade' => 'Откатить на v7', 'move_stat' => 'Перенести статистику (процедура может занять длительное время)', 'faq' => 'FAQ по переходу с 7 версии на 8', 'download_error' => 'Не удалось загрузить файлы.', 'unpack_error' => 'Не удалось распаковать файлы. Убедитесь, что скрипту разрешена запись в текущую дируторию и свободного места не менее 30мб.'), 'step3' => array('title' => 'Загрузка файлов', 'connection_error' => 'Не удалось подключиться к серверу.', 'permission_error' => 'Не удалось записать файл. Установите права 777 папку с инсталятором.', 'tools_error' => 'На сервере нет инструментов для скачивания файлов. Дальнейшая установка невозможна.', 'success' => 'Архив с Keitaro TDS загружен. Дальше последует распаковка файлов.', 'download_error' => 'Не удалось загрузить файлы. Проверьте наличие прав на директорию.', 'curl_error' => 'curl_exec отключена в настройках PHP'), 'step4' => array('title' => 'Распаковка файлов', 'permission_error' => 'Не удалось записать файл. Установите права 777 папку с инсталятором.', 'unpacked' => 'Архив с Keitaro TDS распакован.', 'unpack_error' => 'Не удалось распаковать файлы. Убедитесь, что скрипту разрешена запись в текущую дируторию и свободного места не менее 30мб.'), 'step5' => array('title' => 'Обновление структуры базы данных', 'autoload_missing' => 'Ошибка применения миграций', 'migrations_applied' => 'Миграции базы данных успешно применены'), 'step6' => array('title' => 'Перенос статистики', 'move_stat_success' => 'Перенос статистики завершен', 'db_error' => 'Не удалось подключиться к базе данных', 'connection_error' => 'Не удалось подключиться к базе данных', 'already_processing' => 'Процедура переноса уже запущена. Подождите её завершения или запустите обновление без опции "Перенести статистику".'), 'step7' => array('title' => 'Установка завершена!', 'installation_complete8' => '

Поздравляем с успешным обновлением до Keitaro TDS 8.

При возникновении каких-либо проблем или технических неполадок, смело обращайтесь в нашу техподдержку.

Не забудьте удалить файл upgrader8.php


', 'installation_complete7' => '

Поздравляем с успешным откатом до Keitaro TDS 7.

При возникновении каких-либо проблем или технических неполадок, смело обращайтесь в нашу техподдержку.

Не забудьте удалить файл upgrader8.php


', 'start' => 'Перейти в админку'), 'documentation' => 'Помощь', 'continue' => 'Продолжить', 'retry' => 'Повторить', 'installation_locked' => 'Установка заблокирована', 'remove_lock' => 'Для разблокировки удалите файл "/var/install.lock".'), 'en' => array('main_title' => 'Keitaro TDS Installation', 'step1' => array('title' => 'Server Configuration', 'mysql' => 'PDO MySQL', 'safemode' => 'Safe-mode must be disabled', 'php' => 'PHP version 5.4 - 5.6', 'ioncube' => 'IonCube Loader', 'iconv' => 'Iconv extension', 'mbstring' => 'Mbstring extension', 'curl' => 'CURL extension', 'permissions' => 'Writable permissions to current directory', 'ip' => 'Server IP', 'min_version' => 'Keitaro TDS 7 requires 5.0 o greater', 'success' => '

Checks done.

You can install Keitaro TDS!

', 'failure' => 'Please fix the issues and press "Retry"', 'retry' => 'Retry', 'not_installed' => 'Not installed', 'installed' => 'Installed', 'no_php5' => 'Need PHP 5.4 or newer', 'dir_isnt_writable' => 'No writable permissions. Please set attributes for current directory to 775 or 777.', 'dir_is_writable' => 'Writable', 'safe_mode_enable' => 'Enabled. You must disable safe-mode.', 'safe_mode_disable' => 'Disabled', 'should_be_external' => 'IP must be external', 'ioncube_installation' => 'Instruction (RU)', 'storage_recommend' => 'APC or Memcache recommended', 'zlib' => 'Zlib extension', 'xcache' => 'Xcache', 'xcache_installed' => 'We recommend you to disable xcache extension.', 'zip' => 'Zip extension', 'json' => 'JSON extension', 'hash' => 'Hash extension'), 'step2' => array('title' => 'Choose update type', 'choose_action' => 'Choose update action', 'upgrade' => 'Upgrade to v8', 'downgrade' => 'Downgrade to v7', 'move_stat' => 'Move statistics (procedure might take long time)', 'faq' => 'FAQ about v7 to v8 transition', 'download_error' => 'Unable to download archive. Please, check your firewall settings.', 'unpack_error' => 'Unable to unpack files. Current directory must have writable permissions and free space should be more than 30MB.', 'curl_error' => 'curl_exec disabled in PHP settings'), 'step3' => array('title' => 'Install files', 'connection_error' => 'Can\'t connect to the server. Please check firewall settings.', 'permission_error' => 'Can\'t unpack files. Please check permissions to current directory.', 'tools_error' => 'Unable to use any tools to download package.', 'success' => 'Keitaro TDS has been downloaded', 'download_error' => 'Unable to download archive. Please, check your firewall settings.', 'curl_error' => 'curl_exec disabled in PHP settings'), 'step4' => array('title' => 'Unpacking', 'permission_error' => 'Can\'t unpack files. Please check permissions to current directory.', 'unpacked' => 'Keitaro TDS has been unpacked', 'unpack_error' => 'Unable to unpack files. Current directory must have writable permissions and free space should be more than 30MB.'), 'step5' => array('title' => 'Migrate Databases', 'autoload_missing' => 'Failed to apply migrations', 'migrations_applied' => 'Migrations successfully applied'), 'step6' => array('title' => 'Move statistics', 'move_stat_success' => 'Statistics successfully moved', 'connection_error' => 'Unable to connect to database', 'db_error' => 'Unable to connect to database. Please check username and password', 'already_processing' => 'Stats migration process hasn\'t finished yet. Please wait or restart without option "move statistics".'), 'step7' => array('title' => 'Installation Finished', 'installation_complete8' => '

Thank you for updating to Keitaro TDS 8.

If you have any questions about Keitaro TDS, please contact us through website http://keitarotds.com.

Now you can remove upgrader8.php.


', 'installation_complete7' => '

Successfully reverted to Keitaro TDS 7.

If you have any questions about Keitaro TDS, please contact us through website http://keitarotds.com.

Now you can remove upgrader8.php.


', 'start' => 'Go to the control panel'), 'documentation' => 'Help', 'continue' => 'Continue', 'retry' => 'Retry', 'installation_locked' => 'Installation is locked', 'remove_lock' => 'If you want to unlock remove file "/var/install.lock".')); protected static $_language; protected static $_languages = array('ru', 'en'); const DEFAULT_LANGUAGE = 'ru'; public static function setPreferredLanguage($lang) { if (!in_array($lang, self::$_languages)) { throw new Exception('Language ' . $lang . ' not exists'); } setcookie('installer_lang', $lang); $_COOKIE['installer_lang'] = $lang; } public static function getPreferredLanguage() { $lang = self::DEFAULT_LANGUAGE; if (isset($_COOKIE['installer_lang'])) { $lang = $_COOKIE['installer_lang']; } elseif (isset($_SERVER["HTTP_ACCEPT_LANGUAGE"])) { if (strstr($_SERVER["HTTP_ACCEPT_LANGUAGE"], 'en')) { $lang = 'en'; } if (strstr($_SERVER["HTTP_ACCEPT_LANGUAGE"], 'ru')) { $lang = 'ru'; } } if (!in_array($lang, self::$_languages)) { $lang = self::DEFAULT_LANGUAGE; } return $lang; } public static function get($key, $params = null) { $path = explode('.', $key); $data = self::$_data[self::getPreferredLanguage()]; $translation = self::_find($path, $data); if (!isset($translation)) { $translation = $key; } if ($params) { if (!is_array($params)) { $params = array($params); } $args = array_merge(array($translation), $params); $translation = call_user_func_array('sprintf', $args); } return $translation; } public static function t($key, $params = null) { return self::get($key, $params); } protected static function _find($path, $data) { $key = array_shift($path); if (!isset($data[$key])) { return null; } if (count($path)) { return self::_find($path, $data[$key]); } return $data[$key]; } } } namespace ResultSets { use Services\IdentityService; use Services\KLocaleService; class SingleElementResultSet implements ResultSetInterface { public $element = false; public function getStatus() { return $this->element->getStatus(); } public function getErrorText() { return $this->element->getDesc(); } } } namespace Services { class LockService extends AbstractService { public function unlock($lock, $lockPath) { if (!empty($lock)) { fclose($lock); } if (file_exists($lockPath)) { unlink($lockPath); } } public function tryLock($lockPath) { $this->_checkDirectory($lockPath); $lock = fopen($lockPath, 'w'); if ($lock == false) { return false; } if (!flock($lock, LOCK_EX | LOCK_NB)) { fclose($lock); return false; } return $lock; } private function _checkDirectory($lockPath) { $dir = dirname($lockPath); if (!is_dir($dir)) { mkdir($dir, 0777); } } } } namespace Services { use ResultSets\GeneralResult; class DownloadService extends AbstractService { public function request($url) { if (function_exists('curl_init')) { if ($this->_isCurlDisabled()) { return new GeneralResult(false, KLocaleService::t('step4.curl_error')); } $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_TIMEOUT, 10); curl_setopt($ch, CURLOPT_HEADER, 0); $content = curl_exec($ch); if ($error = curl_error($ch)) { return new GeneralResult(false, KLocaleService::t('step4.connection_error')); } curl_close($ch); } else { $f = fopen($url, 'r'); $content = fread($f, 512000); if (!$f) { return new GeneralResult(false, KLocaleService::t('step4.connection_error')); } } return new GeneralResult(true, $content); } public function download($from, $to) { @set_time_limit(180); if (!file_exists($from)) { if (!ini_get('allow_url_fopen')) { if (function_exists('curl_init')) { if ($this->_isCurlDisabled()) { return new GeneralResult(false, KLocaleService::t('step4.curl_error')); } $ch = curl_init($from); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_TIMEOUT, 100); curl_setopt($ch, CURLOPT_BINARYTRANSFER, true); curl_setopt($ch, CURLOPT_HEADER, 0); $content = curl_exec($ch); if ($error = curl_error($ch)) { return new GeneralResult(false, KLocaleService::t('step4.connection_error') . ' Curl error: ' . $error); } curl_close($ch); if (!file_put_contents($to, $content)) { return new GeneralResult(false, KLocaleService::t('step4.permission_error')); } } else { return new GeneralResult(false, KLocaleService::t('step4.tools_error')); } } else { file_put_contents($to, fopen($from, 'rb')); } } return new GeneralResult(true, ""); } public function downloadAndValidate($url, $crcUrl, $archive, $file) { $localArchive = $archive; $directory = dirname($localArchive); if (!file_exists($directory)) { mkdir($directory, 0777); } $result = $this->download($url, $localArchive); if (!$result->getStatus()) { return $result; } $this->download($crcUrl, $file . '.crc'); if (!$result->getStatus()) { return $result; } ArchiveService::instance()->unzip($localArchive, $file); $crc32 = file_get_contents($file . '.crc'); $downloadedFileCrc = $this->_calculateCrc32($file); if ($crc32 != $downloadedFileCrc) { return new GeneralResult(false, KLocaleService::t('step6.crc32_failed')); } else { return new GeneralResult(true, ""); } } private function _calculateCrc32($file) { $fileString = file_get_contents($file); $crc = crc32($fileString); return sprintf("%u", $crc); } private function _isCurlDisabled() { $disabled = explode(',', ini_get('disable_functions')); if (in_array('curl_exec', $disabled)) { return true; } return false; } } } namespace Services { use ResultSets\GeneralResult; class ArchiveService extends AbstractService { public function gzopen($filename, $mode, $use_include_path = 0) { if (!function_exists('gzopen') && function_exists('gzopen64')) { return gzopen64($filename, $mode, $use_include_path); } else { return gzopen($filename, $mode, $use_include_path); } } public function unpack($localPackage) { if (class_exists('ZipArchive')) { $zip = new \ZipArchive(); $zip->open($localPackage); $zip->extractTo('./'); $zip->close(); } elseif (class_exists('PharData')) { @mkdir('www', 0777); try { $archive = new \PharData($localPackage); $archive->extractTo('./', null, true); } catch (\Exception $e) { return new GeneralResult(false, $e->getMessage()); } } else { $disabled = ini_get('disable_functions'); if (!strstr($disabled, 'system')) { system("tar -xzf " . $localPackage); } elseif (!strstr($disabled, 'exec')) { exec("tar -xzf " . $localPackage); } } if (!file_exists('www/version.php')) { return new GeneralResult(false, "Unable to unpack. Please install php_zip."); } else { return new GeneralResult(true, ""); } } public function unzip($archive, $file) { $sfp = $this->gzopen($archive, "rb"); $fp = fopen($file, "w"); while ($string = gzread($sfp, 4096)) { fwrite($fp, $string, strlen($string)); } gzclose($sfp); fclose($fp); unlink($archive); } } } namespace Services { class FileService extends AbstractService { public function rmdir($path) { if (is_dir($path) and !is_link($path)) { foreach (scandir($path) as $value) { if ($value != "." && $value != "..") { $value = $path . "/" . $value; if (is_dir($value)) { $this->rmdir($value); } elseif (is_file($value)) { unlink($value); } } } return rmdir($path); } else { return false; } } public function chmod($path, $attr = 0777) { $d = @opendir($path); if (!@is_dir($d) || is_link($d)) { return; } while (($file = readdir($d)) !== false) { if ($file != "." && $file != ".." && $file != $_SERVER['PHP_SELF']) { $typepath = $path . "/" . $file; if (filetype($typepath) == 'dir') { $this->chmod($typepath, $attr); } @chmod($typepath, $attr); } } } public function chown($path, $uid, $gid) { $d = @opendir($path); if (!@is_dir($d) || is_link($d)) { return; } while (($file = readdir($d)) !== false) { if ($file != "." && $file != ".." && $file != $_SERVER['PHP_SELF']) { $typepath = $path . "/" . $file; if (filetype($typepath) == 'dir') { $this->chown($typepath, $uid, $gid); } @chown($typepath, $uid); @chgrp($typepath, $gid); } } } public function dirmv($src, $dest) { if (!is_dir($src)) { return false; } if (!is_dir($dest)) { if (!mkdir($dest)) { return false; } } $i = new \DirectoryIterator($src); foreach ($i as $f) { if ($f->isFile()) { copy($f->getRealPath(), "{$dest}/" . $f->getFilename()); @unlink($f->getRealPath()); } else { if (!$f->isDot() && $f->isDir()) { $this->dirmv($f->getRealPath(), "{$dest}/{$f}"); @unlink($f->getRealPath()); } } } @unlink($src); } } } namespace Services { class RedirectService extends AbstractService { public function toStep($step) { header('LOCATION:?step=' . $step); } } } namespace Services { use ResultSets\GeneralResult; class MysqlService extends AbstractService { private $pdo = NULL; public function checkDatabase($host, $user, $pass, $db) { return $this->connect($host, $user, $pass, $db, ParameterService::instance()->getCreateDatabaseParam()); } public function connectFromIni() { $cnf = ConfigService::instance()->getIniConfig(); return $this->connect($cnf['db']['server'], $cnf['db']['user'], $cnf['db']['password'], $cnf['db']['name'], false); } public function log($msg) { file_put_contents('upgrader8.log', date('Y-m-d H:is') . ' ' . $msg . "\n", FILE_APPEND); } public function setSetting($settingName, $value) { $cnf = ConfigService::instance()->getIniConfig(); $sql = "UPDATE " . $cnf['db']['prefix'] . "settings SET `value`='" . $value . "' WHERE `key`='" . $settingName . "'"; $this->pdo->exec($sql); $sql = "INSERT IGNORE " . $cnf['db']['prefix'] . "settings (`key`, `value`) VALUES ('" . $settingName . "', '" . $value . "')"; $this->pdo->exec($sql); } public function setCacheStorage($cache) { $this->setSetting('cache_storage', $cache); } public function getShardList() { $cnf = ConfigService::instance()->getIniConfig(); $stmt = $this->pdo->query("show tables like '" . $cnf['db']['prefix'] . "stats_%'"); $result = $stmt->fetchAll(\PDO::FETCH_NUM); if (empty($result)) { $result = []; } return $result; } private function buildV7($data, \Component\Campaigns\Model\Campaign $campaign, \Component\Traffic\TrafficLogger $logger) { $apiParams = ['language' => ['language'], 'referrer' => ['referrer'], 'user_agent' => ['user_agent'], 'search_engine' => ['search_engine']]; $rawClick = new \Component\Clicks\Model\RawClick($data); $rawClick->setIp($data['ip']); $rawClick->setDateTime(new \DateTime($data['datetime'])); foreach ($apiParams as $attr => $variations) { foreach ($variations as $param) { if (!empty($data[$param])) { $rawClick->set($attr, $data[$param]); } } } return $rawClick; } public function processShard($shard, $logger, $campaignsDic, $cb) { $this->pdo->setAttribute(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); $stmt = $this->pdo->query("select * from {$shard}"); while ($data = $stmt->fetch(\PDO::FETCH_ASSOC)) { $campaignId = $data['campaign_id']; $campaign = $campaignsDic[$campaignId]; if (empty($campaign)) { $this->log("Campaign #{$campaignId} not found"); continue; } $rawClick = $this->buildV7($data, $campaign, $logger); if (!empty($rawClick)) { $cb($rawClick, $campaign); } } } private function connect($host, $user, $pass, $db, $shouldCreate) { if (!$this->pdo instanceof \PDO) { $dsn = "mysql:host={$host};dbname=INFORMATION_SCHEMA;charset=utf8"; $opt = array(\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION, \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC); try { $this->pdo = new \PDO($dsn, $user, $pass, $opt); } catch (\PDOException $e) { return new GeneralResult(false, KLocaleService::t('step6.connection_error') . ': ' . $e->getMessage()); } } $stmt = $this->pdo->query("SELECT COUNT(*) FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = '" . $db . "'"); if (!(bool) $stmt->fetchColumn()) { return new GeneralResult(false, KLocaleService::t('step6.db_error') . ' "' . $db . '"'); } $this->pdo->exec('USE `' . $db . '`;'); $this->pdo->exec("set character_set_client=utf8"); $this->pdo->exec("set character_set_connection=utf8"); $this->pdo->exec("set character_set_results=utf8"); $this->pdo->exec("set collation_connection=utf8_unicode_ci"); return new GeneralResult(true, ""); } } } namespace { use Views\WebView; use Views\AjaxChunkedView; use Controllers\UpdateController; use Models\StepModel; session_start(); $model = new StepModel(); $view = new WebView(); $controller = new UpdateController($view, $model); $controller->dispatchSingle(); }