ProShell v2.0
Dashboard
Server Info
Server: 158.106.128.192
PHP: 8.2.33
home
planet5
public_html
bansibaba.com
2026-09-12 12:43:30
Editing: App.php
Cancel
Save Changes
<?php /** * aMember API bootstrap and required classes * @package Am_Utils * @author Alex Scott <alex@cgi-central.net> * @license http://www.amember.com/p/Main/License */ /** * Registry and bootstrapping of plugin objects * @package Am_Plugin */ class Am_Plugins { protected $type; protected $classNameTemplate = "%s"; // use %s for plugin name protected $configKeyTemplate = "%s.%s"; // default : type.pluginId protected $fileNameTemplates = array( '%s.php', '%1$s/%1$s.php', ); protected $cache = array(); protected $enabled = array(); protected $title; private $_di; function __construct(Am_Di $di, $type, $path, $classNameTemplate='%s', $configKeyTemplate='%s.%s', $fileNameTemplates=array('%s.php','%1$s/%1$s.php',) ) { $this->_di = $di; $this->type = $type; $this->paths = array($path); $this->classNameTemplate = $classNameTemplate; $this->configKeyTemplate = $configKeyTemplate; $this->fileNameTemplates = $fileNameTemplates; if ($type == 'modules') { $en = (array)$di->config->get('modules', array()); } else { $en = (array)$di->config->get('plugins.'.$type); } $this->setEnabled($en); } function getId() { return $this->type; } function setTitle($title) { $this->title = $title; } function getTitle() { return $this->title ? $this->title : ucfirst(fromCamelCase($this->getId())); } function getPaths() { return $this->paths; } function setPaths(array $paths) { $this->paths = (array)$paths; } function addPath($path) { $this->paths[] = (string)$path; } function setEnabled(array $list) { $this->enabled = array_unique($list); return $this; } function addEnabled($name) { $this->enabled[] = $name; $this->enabled = array_unique($this->enabled); return $this; } function getEnabled() { return (array)$this->enabled; } /** * @return array of strings - module or plugin ids */ function getAvailable() { $found = array(); foreach ($this->paths as $path) { foreach ($this->fileNameTemplates as $tpl) { $needle = strpos($tpl, '%1$s') !== false ? '%1$s' : '%s'; $regex = '|'.str_replace(preg_quote($needle), '([a-zA-Z0-9_-]+?)', preg_quote($tpl)).'|'; $glob = $path . '/' . str_replace($needle, '*', $tpl); foreach (glob($glob) as $s) { $s = substr($s, strlen($path)+1); if (preg_match($regex, $s, $regs)) { if ($regs[1] == 'default') continue; $found[] = $regs[1]; } } } } return $found; } /** * Return all enabled plugins * @return array of objects */ function getAllEnabled() { $ret = array(); foreach ($this->enabled as $pl) try { $ret[] = $this->get($pl); } catch (Am_Exception_InternalError $e) { trigger_error("Error loading plugin [$pl]: " . $e->getMessage(), E_USER_WARNING); } return $ret; } function isEnabled($name) { return in_array((string)$name, $this->enabled); } /** @return bool */ function load($name) { if (class_exists($this->getPluginClassName($name), false)) return true; $name = preg_replace('/[^a-zA-z0-9_-]/','',$name); if (!$name) throw new Am_Exception_Configuration("Could not load plugin - empty name after filtering"); foreach ($this->getPaths() as $base_dir) { $found = false; foreach ($this->fileNameTemplates as $tpl) { $file = $base_dir . DIRECTORY_SEPARATOR . sprintf($tpl, $name); if (file_exists($file)) { $found = true; break; } } if (!$found) continue; include_once $file; return true; } trigger_error("Plugin file for plugin ({$this->type}/$name) does not exists", E_USER_WARNING); return false; } function loadEnabled() { foreach ($this->getEnabled() as $name) $this->load($name); return $this; } /** * Create new plugin if not exists, or return existing one from cache * @param string name * @return Am_Plugin */ function get($name) { $name = preg_replace('/[^a-zA-Z0-9_-]/', '', $name); if ("" == $name) throw new Am_Exception_InternalError("An empty plugin name passed to ".__METHOD__); if (!$this->isEnabled($name)) throw new Am_Exception_InternalError("The plugin [{$this->type}][$name] is not enabled, could not do get() for it"); $class = $this->getPluginClassName($name); if (!class_exists($class, false)) throw new Am_Exception_InternalError("Error in plugin {$this->type}/$name: class [$class] does not exists!"); return array_key_exists($name, $this->cache) ? $this->cache[$name] : $this->register($name, $class); } function loadGet($name, $throwExceptions = true) { $name = filterId($name); if ($this->isEnabled($name) && $this->load($name)) return $this->get($name); if ($throwExceptions) throw new Am_Exception_InternalError("Could not loadGet([$name])"); } /** * Get Class name of plugin; * @param string plugin name * @return string class name; */ public function getPluginClassName($id) { return sprintf($this->classNameTemplate, ucfirst(toCamelCase($id))); } /** * Register a new plugin in the registry so it will be returned by @see get(type,name) * @param string $name * @param string|object $className class name or existing object * @return object resulting object */ function register($name, $className) { if (is_string($className)) { $configKey = $this->getConfigKey($name); return $this->cache[$name] = new $className($this->_di, (array)Am_Di::getInstance()->config->get($configKey)); } elseif (is_object($className)) return $this->cache[$name] = (object)$className; } function getConfigKey($pluginId) { return sprintf($this->configKeyTemplate, $this->type, $pluginId); } } /** * Base class for plugin or module entity * @package Am_Plugin */ class Am_Pluggable_Base { // build.xml script will run 'grep $_pluginStatus plugin.php' to find out status const STATUS_PRODUCTION = 1; // product - all ok const STATUS_BETA = 2; // beta - display warning on configuration page const STATUS_DEV = 4; // development - do not include into distrubutive // by default plugins are included into main build const COMM_FREE = 1; // separate plugin - do not include into dist const COMM_COMMERCIAL = 2; // commercial plugins, build separately /** to strip when calculating id from classname */ protected $_idPrefix = 'Am_Plugin_'; /** to automatically add after _initSetupForm */ protected $_configPrefix = null; protected $id; protected $config = array(); protected $version = null; private $_di; protected $readmeTpl = "Readme for <b>%title%</b> plugin<br /> Plugin has been tested with %tested%<br /> <b>Instruction</b> %guide% "; /** * Usually hooks are disabled when @see isConfigured * returns false. However hooks from this list will * anyway be enabled * @var array of hook names */ protected $hooksToAlwaysEnable = array('setupForms', 'adminWarnings'); function __construct(Am_Di $di, array $config) { $this->_di = $di; $this->config = $config; $this->setupHooks(); $this->init(); } function init() { } /** * get dependency injector * @return Am_Di */ function getDi() { return $this->_di; } function setupHooks() { $manager = $this->getDi()->hook; foreach ($this->getHooks() as $hook => $callback) $manager->add($hook, $callback); } /** * Returns false if plugin is not configured and most hooks must be disabled * @return bool */ public function isConfigured() { return true; } public function onAdminWarnings(Am_Event $event) { if (!$this->isConfigured()) $event->addReturn(___("Plugin [%s] is not configured", $this->getId())); } /** * @return array hookName (without Am_Event) => callback */ public function getHooks() { $ret = array(); $isConfigured = $this->isConfigured(); foreach (get_class_methods(get_class($this)) as $method) if (strpos($method, 'on')===0) { $hook = lcfirst(substr($method, 2)); if ($isConfigured || in_array($hook, $this->hooksToAlwaysEnable)) $ret[$hook] = array($this, $method); } return $ret; } function destroy() { $this->getDi()->hook->unregisterHooks($this); } function getTitle() { return $this->getId(false); } function getId($oldStyle=true) { if (null == $this->id) $this->id = str_ireplace($this->_idPrefix, '', get_class($this)); return $oldStyle ? fromCamelCase($this->id, '-') : $this->id; } public function getConfig($key=null, $default=null) { if ($key===null) return $this->config; $c = & $this->config; foreach (explode('.', $key) as $s) { $c = & $c[$s]; if (is_null($c) || (is_string($c) && $c == '')) return $default; } return $c; } /** * mostly for unit testing * @param array $config * @access private */ public function _setConfig(array $config) { $this->config = $config; } /** Function will be executed after plugin deactivation */ public function deactivate() { } /** Function will be executed after plugin activation */ static function activate($id, $pluginType) { } public function getVersion() { return $this->version === null ? AM_VERSION : $this->version; } /** * @return string|null directory of plugin if plugin has its own directory */ public function getDir() { $c = new ReflectionClass(get_class($this)); $fn = realpath($c->getFileName()); if (preg_match('|([\w_-]+)'.preg_quote(DIRECTORY_SEPARATOR).'\1\.php|', $fn)) { return dirname($fn); } } /** * @return string return formatted readme for the plugin */ public function getReadme() { $ref = new ReflectionClass(get_class($this)); $docComment = $ref->getDocComment(); if (!$docComment) return null; $res = preg_match('#/\*\*(.*?)\*/#s', $docComment, $match); if (!$res) return null; //no readme in comment found $lines = explode("\n", $match[1]); $info = array(); $buff = array(); $last_token = null; foreach ($lines as $line) { $line = preg_replace('#^\s*\*\s?#', '', $line); if (preg_match('#^@([a-zA-Z_]+)\s*(.*)#', $line, $match)) { if (!is_null($last_token)) { $info[$last_token] = implode("\n", array_filter($buff)); $buff = array(); } $last_token = $match[1]; array_push($buff, $match[2]); } else { array_push($buff, $line); } } if (!empty($buff)) $info[$last_token] = implode("\n", array_filter($buff)); $tpl = new Am_SimpleTemplate(); $tpl->assign($info); return $tpl->render($this->readmeTpl); } public function onSetupForms(Am_Event_SetupForms $event) { $m = new ReflectionMethod($this, '_initSetupForm'); if ($m->getDeclaringClass()->getName() == __CLASS__) return; $form = $this->_beforeInitSetupForm(); if (!$form) return; $this->_initSetupForm($form); $this->_afterInitSetupForm($form); $event->addForm($form); } /** @return Am_Form_Setup */ protected function _beforeInitSetupForm() { $form = new Am_Form_Setup($this->getId()); $form->setTitle($this->getTitle()); return $form; } protected function _afterInitSetupForm(Am_Form_Setup $form) { if ($this->_configPrefix) $form->addFieldsPrefix($this->_configPrefix . $this->getId() . '.'); if($plugin_readme = $this->getReadme()) { $plugin_readme = str_replace( array('%root_url%', '%root_surl%', '%root_dir%'), array(ROOT_URL, ROOT_SURL, ROOT_DIR), $plugin_readme); $form->addEpilog('<div class="info"><pre>'.$plugin_readme.'</pre></div>'); } if (defined($const = get_class($this)."::PLUGIN_STATUS") && (constant($const) == self::STATUS_BETA || constant($const) == self::STATUS_DEV)) { $beta = (constant($const) == self::STATUS_DEV) ? 'ALPHA' : 'BETA'; $form->addProlog("<div class='warning_box'>This plugin is currently in $beta testing stage, some features may be unstable. ". "Please test it carefully before use.</div>"); } } protected function _initSetupForm(Am_Form_Setup $form) { } } /** * Base class for plugin * @package Am_Plugin */ class Am_Plugin extends Am_Pluggable_Base { /** * Function will be called when user access amember/payment/pluginid/xxx url directly * This can be used for IPN actions, or for displaying confirmation page * @see getPluginUrl() * @param $actionName a string passed to 'a' parameter of incoming post, filtered for alnum * @param $vars - $_GET or $_POST */ function directAction(Am_Request $request, Zend_Controller_Response_Http $response, array $invokeArgs) { throw new Am_Exception_NotImplemented("'direct' action is not implemented in " . get_class($this)); } } /** * Base class for module bootstrap * @package Am_Plugin */ class Am_Module extends Am_Pluggable_Base { protected $_idPrefix = 'Bootstrap_'; } /** * Base class for custom theme * @package Am_Plugin */ class Am_Theme extends Am_Pluggable_Base { protected $_idPrefix = 'Am_Theme_'; /** * Array of paths (relative to application/default/themes/XXX/public/) * that must be routed via PHP to substitute vars * for example css/theme.css * all these files can be accessed directly so please do not put anything * sensitive inside * @var array */ protected $publicWithVars = array(); public function __construct(Am_Di $di, $id, array $config) { parent::__construct($di, $config); $this->id = $id; $rm = new ReflectionMethod(get_class($this), 'initSetupForm'); if ($rm->getDeclaringClass()->getName() != __CLASS__) { $this->getDi()->hook->add(Am_Event::SETUP_FORMS, array($this, 'eventSetupForm')); } } function eventSetupForm(Am_Event_SetupForms $event) { $form = new Am_Form_Setup_Theme($this->getId()); $form->setTitle(ucfirst($this->getId()) . ' Theme') ->setComment('Configure ' . ucfirst($this->getId()) . ' Theme'); $this->initSetupForm($form); $event->addForm($form); } /** You can override it and add elements to create setup form */ public function initSetupForm(Am_Form_Setup_Theme $form) {} public function getRootDir() { return APPLICATION_PATH . '/default/themes/' . $this->getId(); } public function printLayoutHead(Am_View $view) { $root = $this->getRootDir(); if (file_exists($root . '/public/' . 'css/theme.css')) { if (!in_array('css/theme.css', $this->publicWithVars)) $view->headLink()->appendStylesheet($view->_scriptCss('theme.css')); else $view->headLink()->appendStylesheet($this->urlPublicWithVars('css/theme.css')); } } function urlPublicWithVars($relPath) { return REL_ROOT_URL . '/public/theme/' . $relPath; } function parsePublicWithVars($relPath) { if (!in_array($relPath, $this->publicWithVars)) amDie("That files is not allowed to open via this URL"); $f = $this->getRootDir() . '/public/' . $relPath; if (!file_exists($f)) amDie("Could not find file [".htmlentities($relPath, ENT_QUOTES, 'UTF-8')."]"); $tpl = new Am_SimpleTemplate(); foreach ($this->config as $k => $v) $tpl->$k = $v; return $tpl->render(file_get_contents($f)); } } /*** Helper Functions **/ function memUsage($op) {} function tmUsage($op, $init=false, $start_anyway=false) { } /* ************** GLOBAL FUNCTIONS /** * Function displays nice-looking error message without * using of fatal_error function and template */ function amDie($string, $return=false) { $out= <<<CUT <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <title>Fatal Error</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <style type="text/css"> body { font: 80% verdana, arial, helvetica, sans-serif; text-align: center; /* for IE */ } #container { margin: 0 auto; /* align for good browsers */ text-align: left; /* counter the body center */ border: 2px solid #f00; background-color: #fdd; padding: 10px 10px 10px 10px; width: 80%; } .header { font-size: 12pt; font-weight: bold; } </style> <body> <p style="height: 50px;"></p> <div id="container"> <div class="header">Script Error</div> $string </div> </body></html> CUT; return $return ? $out : exit($out); } /** * Function displays nice-looking maintenance message without * using template */ function amMaintenance($string, $return=false) { $out= <<<CUT <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <title>Maintenance Mode</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <style type="text/css"> body { font: 80% verdana, arial, helvetica, sans-serif; text-align: center; /* for IE */ } #container { margin: 0 auto; /* align for good browsers */ text-align: left; /* counter the body center */ border: 2px solid #CCDDEB; background-color: #DFE8F0; padding: 10px 10px 10px 10px; width: 80%; } .header { font-size: 12pt; font-weight: bold; } </style> <body> <p style="height: 50px;"></p> <div id="container"> <div class="header">Maintenance Mode</div> $string </div> </body></html> CUT; return $return ? $out : exit($out); } /** * Block class - represents a renderable UI block * that can be injected into different views * @package Am_Block */ class Am_Block { const TOP = 100; const MIDDLE = 500; const BOTTOM = 900; protected $order = self::MIDDLE; protected $title = null; protected $id; protected $block; /** @var Am_Plugin */ protected $plugin; protected $path; protected $callback; /** * @param array|string $targets where to put the block, like cart/right * @param string $id unique id of the block * @param Am_Plugin $plugin * @param string|callback $pathOrCallback */ function __construct($targets, $title, $id, Am_Pluggable_Base $plugin = null, $pathOrCallback = null, $order = self::MIDDLE) { $this->targets = (array)$targets; $this->title = (string)$title; $this->id = $id; $this->plugin = $plugin; $this->order = (int)$order; if (is_callable($pathOrCallback)) { $this->callback = $pathOrCallback; } else { $this->path = $pathOrCallback; } } function getTargets() { return $this->targets; } function getTitle() { return $this->title; } function render(Am_View $view) { if ($this->path) { $view->block = $this; // add plugin folder to search path for blocks $paths = $view->getScriptPaths(); $newPaths = null; if ($this->plugin && !($this->plugin instanceof Am_Module) && $dir = $this->plugin->getDir()) { $newPaths = $paths; // we insert it to second postion, as first will be theme // lets keep there some place for redefenition array_splice($newPaths, 1, 0, array($dir)); $view->setScriptPath(array_reverse($newPaths)); } $pluginSaved = !empty($view->plugin) ? $view->plugin : null; if ($this->plugin) $view->plugin = $this->plugin; $out = $view->render("blocks/" . $this->path); $view->plugin = $pluginSaved; // remove plugin folder from view search path if (!empty($newPaths)) $view->setScriptPath(array_reverse($paths)); return $out; } elseif ($this->callback) { return call_user_func($this->callback, $view, $this); } else { throw new Am_Exception_InternalError("Unknown block path format"); } } function getId() { return $this->id; } function getOrder() { return (int)$this->order; } } /** * Block registry and rendering * @package Am_Block */ class Am_Blocks { protected $blocks = array(); function add(Am_Block $block) { foreach ($block->getTargets() as $t) $this->blocks[(string)$t][] = $block; return $this; } function remove($id) { foreach ($this->blocks as $k => $target) foreach ($target as $kk => $block) if ($block->getId() == $id) unset($this->blocks[$k][$kk]); return $this; } function addDefaultBlocks() { $this->add( new Am_Block('member/main/left', ___("Active Subscriptions"), 'member-main-subscriptions', null, 'member-main-subscriptions.phtml') )->add( new Am_Block('member/main/left', ___("Active Resources"), 'member-main-resources', null, 'member-main-resources.phtml') )->add( new Am_Block('member/main/right', ___("Useful Links"), 'member-main-links', null, 'member-main-links.phtml') ); if (!Am_Di::getInstance()->config->get('disable_unsubscribe_block', 0)) { $this->add( new Am_Block('member/main/left', ___("Unsubscribe from all e-mail messages"), 'member-main-unsubscribe', null, 'member-main-unsubscribe.phtml', Am_Block::BOTTOM + 100) ); } } /** * @param Zend_View_Abstract $view * @param $blockPattern string * exact path string or wildcard string * wildcard * - matches any word * wildcard ** - matches any number of words and delimiters * @return array */ function get(Zend_View_Abstract $view, $blockPattern) { $out = array(); $blockPattern = preg_quote($blockPattern, "|"); $blockPattern = str_replace('\*\*', '.+?', $blockPattern); $blockPattern = str_replace('\*', '.+?', $blockPattern); foreach (array_keys($this->blocks) as $target) { if (preg_match("|^$blockPattern\$|", $target)) foreach ($this->blocks[$target] as $block) { $blockRendered = array( 'content' => $block->render($view), 'title' => $block->getTitle(), 'id' => $block->getId(), ); if (!strlen($blockRendered['content'])) continue; $out[ $block->getOrder() ][] = $blockRendered; } } ksort($out); $ret = array(); foreach ($out as $sort => $arr) $ret = array_merge($ret, $arr); return $ret; } } /** * Check, store last run time and run cron jobs * @package Am_Utils */ class Am_Cron { const HOURLY = 1; const DAILY = 2; const WEEKLY = 4; const MONTHLY = 8; const YEARLY = 16; const KEY = 'cron-last-run'; const LOCK = 'am-cron'; static function getLockId() { return 'am-lock-'.md5(ROOT_DIR); } /** @return int */ static function needRun() { // check if another thread is updating time right now if (!Am_Di::getInstance()->db->selectCell("SELECT IS_FREE_LOCK(?)", self::getLockId())) return false; // ok, lets check $last_runned = self::getLastRun(); if (!$last_runned) $last_runned = strtotime('-2 days'); $h_diff = date('dH') - date('dH', $last_runned); $d_diff = date('d') - date('d', $last_runned); $w_diff = date('W') - date('W', $last_runned); $m_diff = date('m') - date('m', $last_runned); $y_diff = date('y') - date('y', $last_runned); return ($h_diff ? self::HOURLY : 0) | ($d_diff ? self::DAILY : 0) | ($w_diff ? self::WEEKLY : 0) | ($m_diff ? self::MONTHLY : 0) | ($y_diff ? self::YEARLY : 0); } static function getLastRun() { return Am_Di::getInstance()->db->selectCell("SELECT `value` FROM ?_store WHERE name=?", self::KEY); } static function setupHook() { Am_Di::getInstance()->hook->add('afterRender', array(__CLASS__, 'inject')); } static function inject(Am_Event_AfterRender $event) { static $runned = 0; if ($runned) return; $url = htmlentities(ROOT_URL . '/cron'); if ($event->replace('|</body>|i', "\n<img src='$url' width='1' height='1'>\$1", 1)) $runned++; } static function checkCron() { if (defined('AM_TEST') && AM_TEST) return; // do not run during unit-testing $needRun = self::needRun(); if (!$needRun) return; // Load all payment plugins here. ccBill plugin require hourly cron to be executed; Am_Di::getInstance()->plugins_payment->loadEnabled()->getAllEnabled(); // get lock if (!Am_Di::getInstance()->db->selectCell("SELECT GET_LOCK(?, 1)", self::getLockId())) { Am_Di::getInstance()->errorLogTable->log("Could not obtain MySQL's GET_LOCK() to update cron run time. Not runned cron"); return; } @ignore_user_abort(true); @set_time_limit(0); @ini_set('memory_limit', '256M'); if (!empty($_GET['log'])) Am_Di::getInstance()->errorLogTable->log("cron.php started"); Am_Di::getInstance()->db->query("REPLACE INTO ?_store (name, `value`) VALUES (?, ?)", self::KEY, time()); Am_Di::getInstance()->db->query("SELECT RELEASE_LOCK(?)", self::getLockId()); $out = ""; if ($needRun & self::HOURLY) { Am_Di::getInstance()->hook->call(Am_Event::HOURLY, array('datetime' => sqlDate('now'))); $out .= "hourly."; } if ($needRun & self::DAILY) { Am_Di::getInstance()->hook->call(Am_Event::DAILY, array('datetime' => sqlDate('now'))); $out .= "daily."; } if ($needRun & self::WEEKLY) { Am_Di::getInstance()->hook->call(Am_Event::WEEKLY, array('datetime' => sqlDate('now'))); $out .= "weekly."; } if ($needRun & self::MONTHLY) { Am_Di::getInstance()->hook->call(Am_Event::MONTHLY, array('datetime' => sqlDate('now'))); $out .= "monthly."; } if ($needRun & self::YEARLY) { Am_Di::getInstance()->hook->call(Am_Event::YEARLY, array('datetime' => sqlDate('now'))); $out .= "yearly."; } if (!empty($_GET['log'])) Am_Di::getInstance()->errorLogTable->log("cron.php finished ($out)"); } } /** * Read and write global application config * @package Am_Utils */ class Am_Config { protected $config = array(); function get($item, $default = null) { $c = & $this->config; foreach (preg_split('/\./', $item) as $s) { $c = & $c[$s]; if (is_null($c) || (is_string($c) && $c == '')) return $default; } return $c; } /** @return Am_Config provides fluent interface */ function set($item, $value) { if (is_null($item)) throw new Exception("Empty value passed as config key to " .__FUNCTION__); $this->setDotValue($item, $value); return $this; } function read() { try { $this->config = (array)unserialize(Am_Di::getInstance()->db->selectCell("SELECT config FROM ?_config WHERE name='default'")); } catch (Am_Exception_Db $e) { amDie("aMember Pro is not configured, or database tables are corrupted - could not read config (sql error #" . $e->getCode()."). You have to remove file [amember/application/configs/config.php] and reinstall aMember, or restore database tables from backup."); } } function save() { Am_Di::getInstance()->db->query("REPLACE INTO ?_config (name, config) VALUES ('default', ?)", serialize($this->config)); } function setArray(array $config) { $this->config = (array)$config; } function getArray() { return (array)$this->config; } protected function setDotValue($item, $value) { $c = & $this->config; $levels = explode('.', $item); $last = array_pop($levels); $passed = array(); foreach ($levels as $s) { $passed[] = $s; if (isset($c[$s]) && !is_array($c[$s])) { trigger_error('Unsafe conversion of scalar config value ['.implode('.',$passed).'] to array in ' . __METHOD__, E_USER_WARNING); $c[$s] = array('_SCALAR_' => $c[$s]); } $c = & $c[$s]; } $c[$last] = $value; return $c; } static function saveValue($k,$v) { $config = new self; $config->read(); $config->set($k, $v); $config->save(); } } /** * Static methods for DbSimple_MyPdo configuration * @package Am_Utils */ class Am_Db /*extends DbSimple_Mypdo */ { /** * @return DbSimple_Mysql */ static function connect($config, $onlyConnect = false) { require_once 'DbSimple/Generic.php'; extract($config); $database = new DbSimple_Mypdo( array('scheme'=>'mysql', 'user'=>@$user, 'pass'=>@$pass, 'host'=>@$host, 'path'=>@$db, 'port'=>@$port, )); if (!$onlyConnect) { $database->setIdentPrefix(@$prefix); $database->setErrorHandler(array(__CLASS__,'defaultDatabaseErrorHandler')); if ($database->_isConnected()) { $database->query("SET NAMES utf8"); $database->query("SET SESSION sql_mode=''"); } } return $database; } static function defaultDatabaseErrorHandler($message, $info) { if (!error_reporting()) return; if (!class_exists('Am_Exception_Db')) require_once dirname(__FILE__) . '/Exception.php'; if ($info['code'] == 1062) $class = 'Am_Exception_Db_NotUnique'; else $class = 'Am_Exception_Db'; $e = new $class("$message({$info['code']}) in query: {$info['query']}", @$info['code']); $e->setDbMessage(preg_replace('/ at.+$/', '', $message)); $e->setLogError(true); // already logged // try to parse table name if (($e instanceof Am_Exception_Db_NotUnique) && preg_match('/insert into (\w+)/i', $info['query'], $regs)) { $prefix = Am_Di::getInstance()->db->getPrefix(); $table = preg_replace('/^'.preg_quote($prefix).'/', '?_', $regs[1]); $e->setTable($table); } throw $e; } static function loggerCallback($db, $sql) { $caller = $db->findLibraryCaller(); if (preg_match('/phpunit/', @$_SERVER['argv'][0]) || empty($_SERVER['REMOTE_ADDR'])) { print_r($sql); print "\n"; } else { $tip = "at ".@$caller['file'].' line '.@$caller['line']; echo "<xmp title=\"$tip\">"; print_r($sql); echo "</xmp>"; } } static function setLogger($db = null) { if ($db === null) $db = Am_Di::getInstance()->db; $db->setLogger(array(__CLASS__, 'loggerCallback')); } static function removeLogger($db = null) { if ($db === null) $db = Am_Di::getInstance()->db; $db->setLogger(null); } } /** * @return <type> Return formatted date string */ function amDate($string) { if ($string == null) return ''; return date(Zend_Registry::get('Am_Locale')->getDateFormat(), amstrtotime($string)); } function amDatetime($string) { if ($string == null) return ''; return date(Zend_Registry::get('Am_Locale')->getDateTimeFormat(), amstrtotime($string)); } function amTime($string) { if ($string == null) return ''; return date(Zend_Registry::get('Am_Locale')->getTimeFormat(), amstrtotime($string)); } function check_demo($msg="Sorry, this function disabled in the demo") { if (APPLICATION_ENV == 'demo') throw new Am_Exception_InputError($msg); } /** * Dump any number of variables, last veriable if exists becomes title */ function print_rr($vars, $title="==DEBUG==") { $args = func_get_args(); $html = !empty($_SERVER['HTTP_CONNECTION']); if ($args == 1) $title = array_pop($args); else $title = '==DEBUG=='; echo $html ? "\n<table><tr><td><pre><b>$title</b>\n" : "\n$title\n"; foreach ($args as $vars) { print_r($vars); print $html ? "<br />\n" : "\n\n"; } if ($html) print "</pre></td></tr></table><br/>\n"; } function print_rre($vars, $title="==DEBUG==") { print_rr($vars, $title); print("\n==<i>exit() called from print_rre</i>==\n"); print_rr(get_backtrace_callers(0), 'print_rre called from '); exit(); } function formatSimpleXml(SimpleXMLElement $xml) { $dom = dom_import_simplexml($xml)->ownerDocument; $dom->formatOutput = true; return $dom->saveXML(); } function print_xml($xml) { if ($xml instanceof SimpleXMLElement) $xml = formatSimpleXml($xml); elseif ($xml instanceof DOMElement) { $xml->formatOutput = true; $xml = $xml->saveXML(); } echo highlight_string($xml, true); } function print_xmle($xml) { print_xml($xml); print("\n==<i>exit() called from print_rre</i>==\n"); print_rr(get_backtrace_callers(0), 'print_xmle called from '); exit(); } function moneyRound($v) { return round($v, 2); } function print_bt($title="==BACKTRACE==") { /** print backtrace **/ print_rr(get_backtrace_callers(1), $title); } /** @return mixed first not-empty argument */ function get_first($arg1, $arg2) { $args = func_get_args(); foreach ($args as $a) if ($a != '') return $a; } if(!function_exists("lcfirst")): function lcfirst($str) { $str[0] = strtolower($str[0]); return $str; } endif; /** * Remove from string all chars except the [a-zA-Z0-9_-] * @param string|null input * @return string|null filtered */ function filterId($string) { if ($string === null) return null; return preg_replace('/[^a-zA-Z0-9_-]/', '', $string); } /** * Transform any date to SQL format yyyy-mm-dd */ function amstrtotime($tm) { if ($tm instanceof DateTime) return $tm->getTimestamp (); if (strlen($tm)==14 && preg_match('/^\d{14}$/', $tm)) return mktime(substr($tm, 8, 2),substr($tm, 10, 2),substr($tm, 12, 2), substr($tm, 4, 2),substr($tm, 6, 2),substr($tm, 0, 4)); elseif (is_numeric($tm)) return (int)$tm; else { $res = strtotime($tm, Am_Di::getInstance()->time); if ($res == -1) trigger_error("Problem with parcing timestamp [".htmlentities($tm)."]", E_USER_NOTICE); return $res; } } function sqlDate($d) { if (!($d instanceof DateTime) && preg_match('/^\d{4}-\d{2}-\d{2}$/', $d)) return $d; else return date('Y-m-d', amstrtotime($d)); } function sqlTime($tm) { if (!($tm instanceof DateTime) && preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/', $tm)) return $tm; else return date('Y-m-d H:i:s', amstrtotime($tm)); } /** * Convert StringOfCamelCase to string_of_camel_case */ function fromCamelCase($string, $separator="_") { return strtolower(preg_replace('/([A-Z])/', $separator.'\1', lcfirst($string))); } /** * Convert string_of_camel_case to StringOfCamelCase * @param <type> $string */ function toCamelCase($string) { return lcfirst(str_replace(' ', '', ucwords(preg_replace('/[_-]+/', ' ', $string)))); } /** * Find all defined not abstract successors of given $className * @param string $className */ function amFindSuccessors($className) { $ret = array(); foreach (get_declared_classes() as $c) { if (is_subclass_of($c, $className)) { $r = new ReflectionClass($c); if ($r->isAbstract()) continue; $ret[] = $c; } } return $ret; } /** translate, sprintf if requested and return string */ function ___($msg) { try { $tr = Zend_Registry::get('Zend_Translate'); } catch (Zend_Exception $e) { //trigger_error("Zend_Translate is not available from registry", E_USER_NOTICE); return $msg; } $args = func_get_args(); $msg = $tr->_(array_shift($args)); return $args ? vsprintf($msg, $args) : $msg; } /** translate and printf format string */ function __e($msg) { $args = func_get_args(); echo call_user_func_array('___', $args); } function is_trial() { return '=-=TRIAL=-=' != ('=-=' . 'TRIAL=-='); } function check_trial($errmsg="Sorry, this function is available in aMember Pro not-trial version only") { if (is_trial()) { throw new Am_Exception_FatalError($errmsg); } } if (PHP_VERSION < '5.1.3') die("This version of aMember Pro requires PHP version 5.1.3 or higher, ".PHP_VERSION." is not supported"); /** * Re-Captcha display and validation class * @package Am_Utils */ class Am_Recaptcha { /** @var string error code returned from previous recaptcha */ protected $error; public function render($theme = 'clean') { if (!$this->isConfigured()) throw new Am_Exception_Configuration("ReCaptcha error - recaptcha is not configured. Please go to aMember Cp -> Setup -> ReCaptcha and enter keys"); $public = Am_Controller::escape(Am_Di::getInstance()->config->get('recaptcha-public-key')); $scheme = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') ? 'https' : 'http'; $error = null; if ($this->error) $error = '&error=' . Am_Controller::escape($this->error); return <<<CUT <script> var RecaptchaOptions = { theme : '$theme' }; </script> <script type="text/javascript" src="$scheme://www.google.com/recaptcha/api/challenge?k=$public$error"> </script> <noscript> <iframe src="$scheme://www.google.com/recaptcha/api/noscript?k=$public$error" height="300" width="500" frameborder="0"></iframe><br> <textarea name="recaptcha_challenge_field" rows="3" cols="40"> </textarea> <input type="hidden" name="recaptcha_response_field" value="manual_challenge"> </noscript> CUT; } /** @return bool true on success, false and set internal error code on failure */ public function validate($challenge, $response) { if (!$this->isConfigured()) throw new Am_Exception_Configuration("Brick: ReCaptcha error - recaptcha is not configured. Please go to aMember Cp -> Setup -> ReCaptcha and enter keys"); $req = new Am_HttpRequest('http://www.google.com/recaptcha/api/verify', Am_HttpRequest::METHOD_POST); $req->addPostParameter('privatekey', Am_Di::getInstance()->config->get('recaptcha-private-key')); $req->addPostParameter('remoteip', $_SERVER['REMOTE_ADDR']); $req->addPostParameter('challenge', $challenge); $req->addPostParameter('response', $response); $response = $req->send(); if ($response->getStatus() != '200') { $this->error = 'recaptcha-not-reachable'; } else { @list($status, $this->error) = explode("\n", $response->getBody()); $status = trim($status) == 'true'; } return $status; } function getPublicKey() { return Am_Di::getInstance()->config->get('recaptcha-public-key'); } function getError() { return $this->error; } public static function isConfigured() { return Am_Di::getInstance()->config->get('recaptcha-public-key') && Am_Di::getInstance()->config->get('recaptcha-private-key'); } } function get_backtrace_callers($skipLevels = 1, $bt=null) { if ($bt === null) $bt = debug_backtrace(); $bt = array_slice($bt, $skipLevels + 1); $ret = array(); foreach ($bt as $b) { $b['line'] = intval(@$b['line']); if (!isset($b['file'])) $b['file'] = null; if (@$b['object'] && $className = (get_class($b['object']))) { $ret[] = $className."->".$b['function']." in line $b[line] ($b[file])"; } elseif (@$b['class']) $ret[] = "$b[class]:$b[function] in line $b[line] ($b[file])"; else $ret[] = "$b[function] in line $b[line] ($b[file])"; } return $ret; } /** * Application bootstrap and common functions * @package Am_Utils */ class Am_App { /** @var Am_Di */ private $di; protected $config; private $initFinished = false; public function __construct($config) { $this->config = is_array($config) ? $config : (require $config); @define('INCLUDED_AMEMBER_CONFIG', 1); if (defined('AM_DEBUG_IP') && AM_DEBUG_IP && (AM_DEBUG_IP == @$_SERVER['REMOTE_ADDR'])) @define('APPLICATION_ENV', 'debug'); // Define application environment defined('APPLICATION_ENV') || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'production')); if (APPLICATION_ENV == 'debug' || APPLICATION_ENV == 'testing') @define('AM_DEBUG', true); if (!defined('APPLICATION_ENV')) define('APPLICATION_ENV', 'production'); } public function bootstrap() { if (defined('APPLICATION_ENV') && (APPLICATION_ENV == 'debug')) { error_reporting(E_ALL | E_RECOVERABLE_ERROR | E_NOTICE | E_DEPRECATED | E_STRICT ); @ini_set('display_errors', true); } else { error_reporting(error_reporting() & ~E_RECOVERABLE_ERROR); // that is really annoying } spl_autoload_register(array(__CLASS__, '__autoload')); $this->di = new Am_Di($this->config); Am_Di::_setInstance($this->di); $this->di->app = $this; set_error_handler(array($this, '__error')); set_exception_handler(array($this, '__exception')); $this->di->init(); try { $this->di->getService('db'); } catch (Am_Exception $e) { if (defined('AM_DEBUG') && AM_DEBUG) amDie($e->getMessage()); else amDie($e->getPublicError()); } $this->di->config; $this->initConstants(); // set memory limit $limit = @ini_get('memory_limit'); if (preg_match('/(\d+)M$/', $limit, $regs) && ($regs[1]<=64)) @ini_set('memory_limit', '64M'); // $this->initModules(); $this->initSession(); Am_Locale::initLocale($this->di); $this->initTranslate(); $this->initFront(); require_once 'Am/License.php'; $this->di->blocks->addDefaultBlocks(); $this->di->hook->call(Am_Event::INIT_FINISHED); $this->initFinished = true; if (file_exists( APPLICATION_PATH . "/configs/site.php")) require_once(APPLICATION_PATH . "/configs/site.php"); } /*** * Fetch updated license from aMember Pro website */ function updateLicense() { if (!$this->di->config->get('license')) return; // empty license. trial? if ($this->di->store->get('app-update-license-checked')) return; try { $req = new Am_HttpRequest('http://update.amember.com/license.php'); $req->setConfig('connect_timeout', 2); $req->setMethod(Am_HttpRequest::METHOD_POST); $req->addPostParameter('license', $this->di->config->get('license')); $req->addPostParameter('root_url', $this->di->config->get('root_url')); $req->addPostParameter('root_surl', $this->di->config->get('root_surl')); $req->addPostParameter('version', AM_VERSION); $this->di->store->set('app-update-license-checked', 1, '+12 hours'); $response = $req->send(); if ($response->getStatus() == '200') { $newLicense = $response->getBody(); if ($newLicense) if (preg_match('/^L[A-Za-z0-9\/=+\n]+X$/', $newLicense)) Am_Config::saveValue('license', $newLicense); else throw new Exception("Wrong License Key Received: [" . $newLicense . "]"); } } catch (Exception $e) { if (APPLICATION_ENV != 'production') throw $e; } } function initTranslate() { /// setup test translation adapter if (defined('AM_DEBUG_TRANSLATE') && AM_DEBUG_TRANSLATE) { require_once ROOT_DIR . '/utils/TranslateTest.php'; Zend_Registry::set('Zend_Translate', new Am_Translate_Test(array('disableNotices' => true,))); return; } // if ($cache = $this->getResource('Cache')) // Zend_Translate::setCache($cache); $locale = Zend_Locale::getDefault(); $locale = key($locale); list($lang, ) = explode('_', $locale); $tr = new Zend_Translate(array( 'adapter' => 'array', 'content' => APPLICATION_PATH . '/default/language/user/'.$lang.'.php', 'locale' => $locale, )); if (preg_match('/\badmin\b/', @$_SERVER['REQUEST_URI'])) { $tr->addTranslation(array( 'content' => APPLICATION_PATH . '/default/language/admin/en.php', 'locale' => $locale, )); if (file_exists(APPLICATION_PATH . '/default/language/admin/'.$lang.'.php')) $tr->addTranslation(array( 'content' => APPLICATION_PATH . '/default/language/admin/'.$lang.'.php', 'locale' => $locale, )); } //overwrite existing translation from file //with custom translation from DB if ($data = $this->di->translationTable->getTranslationData($lang)) $tr->addTranslation( array( 'locale' => $locale, 'content'=> $data, )); Zend_Registry::set('Zend_Translate', $tr); } function addRoutes(Zend_Controller_Router_Abstract $router) { $router->addRoute('user-logout', new Zend_Controller_Router_Route( 'logout/:action', array( 'module' => 'default', 'controller' => 'login', 'action' => 'logout', ) )); $router->addRoute('inside-pages', new Zend_Controller_Router_Route( ':module/:controller/p/:page_id/:action/*', array( ) )); $router->addRoute('admin-setup', new Zend_Controller_Router_Route( 'admin-setup/:page', array( 'module' => 'default', 'controller' => 'admin-setup', 'action' => 'display', ) )); $router->addRoute('payment', new Zend_Controller_Router_Route( 'payment/:plugin_id/:action', array( 'module' => 'default', 'controller' => 'direct', 'action' => 'index', 'type' => 'payment', ) )); $router->addRoute('protect', new Zend_Controller_Router_Route( 'protect/:plugin_id/:action', array( 'module' => 'default', 'controller' => 'direct', 'action' => 'index', 'type' => 'protect', ) )); $router->addRoute('misc', new Zend_Controller_Router_Route( 'misc/:plugin_id/:action', array( 'module' => 'default', 'controller' => 'direct', 'action' => 'index', 'type' => 'misc', ) )); $router->addRoute('storage', new Zend_Controller_Router_Route( 'storage/:plugin_id/:action', array( 'module' => 'default', 'controller' => 'direct', 'action' => 'index', 'type' => 'storage', ) )); $router->addRoute('cron-compat', new Zend_Controller_Router_Route( 'cron.php', array( 'module' => 'default', 'controller' => 'cron', 'action' => 'index', ) )); $router->addRoute('public-upload', new Zend_Controller_Router_Route( 'data/public/:path', array( 'module' => 'default', 'controller' => 'upload', 'action' => 'get' ) )); if($this->di->config->get('am3_urls', false)){ $this->initAm3Routes($router); } } function initAm3Routes(Zend_Controller_Router_Abstract $router){ $router->addRoute('v3_urls', new Zend_Controller_Router_Route_Regex( '(signup|member|login|logout|profile).php', array( 'module' => 'default', 'action' => 'index' ), array( 'controller' => 1) )); $router->addRoute('v3_logout', new Zend_Controller_Router_Route( 'logout.php', array( 'module' => 'default', 'controller' => 'login', 'action' => 'logout', ) )); $router->addRoute('v3_ipn_scripts', new Zend_Controller_Router_Route_Regex( 'plugins/payment/([0-9a-z]+)_?r?/(ipn)r?.php', array( 'module' => 'default', 'controller' => 'direct', 'action' => 'index', 'type' => 'payment', ), array( 'plugin_id' => 1, 'action' => 2 ))); $router->addRoute('v3_affgo', new Zend_Controller_Router_Route( 'go.php', array( 'module' => 'aff', 'controller' => 'go', 'action' => 'am3go', ) )); $router->addRoute('v3_afflinks', new Zend_Controller_Router_Route( 'aff.php', array( 'module' => 'aff', 'controller' => 'aff', ) )); } /** * Fuzzy match 2 domain names (with/without www.) */ protected function _compareHostDomains($d1, $d2) { return strcasecmp( preg_replace('/^www\./i', '', $d1), preg_replace('/^www\./i', '', $d2)); } public function guessBaseUrl() { $scheme = (empty($_SERVER['HTTPS']) || ($_SERVER['HTTPS'] == 'off')) ? 'http' : 'https'; $host = @$_SERVER['HTTP_HOST']; // try to find exact match for domain name foreach (array(ROOT_URL, ROOT_SURL) as $u) { $p = parse_url($u); if (($scheme == $p['scheme'] && $host == $p['host'])) // be careful to change here!! { // full match required, else it is BETTER to configure RewriteBase in .htaccess return @$p['path']; } } // now try fuzzy match domain name foreach (array(ROOT_URL, ROOT_SURL) as $u) { $p = parse_url($u); if (($scheme == $p['scheme'] && !$this->_compareHostDomains($host, $p['host']))) // be careful to change here!! { // full match required, else it is BETTER to configure RewriteBase in .htaccess return @$p['path']; } } } public function initFront() { Zend_Controller_Action_HelperBroker::addPrefix('Am_Controller_Action_Helper'); $front = Zend_Controller_Front::getInstance(); $front->setParam('di', $this->di); $front->setParam('noViewRenderer', true); $front->throwExceptions(true); $front->addModuleDirectory(APPLICATION_PATH); $front->setRequest(new Am_Request); $front->getRequest()->setBaseUrl(); // if baseUrl has not been automatically detected, // try to get it from configured root URLs // it may not help in case of domain name mismatch // then RewriteBase is only the option! if ((null == $front->getRequest()->getBaseUrl())) { if ($u = $this->guessBaseUrl()) $front->getRequest()->setBaseUrl($u); } if (!$front->getPlugin('Am_Controller_Plugin')) $front->registerPlugin(new Am_Controller_Plugin($this->di), 90); if (!defined('REL_ROOT_URL')) { $relRootUrl = $front->getRequest()->getBaseUrl(); // filter it for additional safety $relRootUrl = preg_replace('|[^a-zA-Z0-9.\\/_+-~]|', '', $relRootUrl); define('REL_ROOT_URL', $relRootUrl); } $this->addRoutes($front->getRouter()); Am_License::getInstance()->init($this); } function initModules() { /// add modules inc dir $pathes = array(); foreach ($this->di->modules->getEnabled() as $module) { $dir = APPLICATION_PATH . '/' . $module . '/library/'; if (file_exists($dir)) $pathes[] = $dir; } if ($pathes) set_include_path(get_include_path() . PATH_SEPARATOR . implode(PATH_SEPARATOR, $pathes)); $this->di->modules->loadEnabled()->getAllEnabled(); } public function run() { Zend_Controller_Front::getInstance()->dispatch(); } public function initHooks() { class_exists('Am_Hook', true); /// load plugins $this->di->plugins_protect ->loadEnabled()->getAllEnabled(); $this->di->plugins_payment ->addEnabled('free'); $this->di->plugins_misc ->loadEnabled()->getAllEnabled(); $this->di->plugins_storage ->addEnabled('upload')->addEnabled('disk'); $this->di->hook ->add(Am_Event::HOURLY, array($this->di->app, 'onHourly')) ->add(Am_Event::DAILY, array($this->di->app, 'onDaily')) ->add(Am_Event::INVOICE_AFTER_INSERT, array($this->di->emailTemplateTable, 'onInvoiceAfterInsert')) ->add(Am_Event::INVOICE_STARTED, array('EmailTemplateTable', 'onInvoiceStarted')) ->add(Am_Event::PAYMENT_WITH_ACCESS_AFTER_INSERT, array('EmailTemplateTable', 'onPaymentWithAccessAfterInsert')) ->add(Am_Event::DAILY, array($this->di->savedReportTable, 'sendSavedReports')) ->add(Am_Event::WEEKLY, array($this->di->savedReportTable, 'sendSavedReports')) ->add(Am_Event::MONTHLY, array($this->di->savedReportTable, 'sendSavedReports')) ->add(Am_Event::YEARLY, array($this->di->savedReportTable, 'sendSavedReports')); if (!$this->di->config->get('use_cron') && Am_Cron::needRun()) // we have no remote cron setup Am_Cron::setupHook(); } static function __autoload($className) { $regexes = array( 'Am_Mail_Template' => '$0', 'Am_Mail_TemplateTypes' => '$0', 'Am_Form_Bricked' => '$0', '(Am_Mail)(.+)' => '$1', '(Am_DbSync)(.+)' => '$1', '(Am_Exception)(.+)' => '$1', '(Am_Event)(.+)' => '$1', // '(Am_Form_Brick)(.+)' => '$1', '(Am_Crypt)(.+)' => '$1', 'Am_Table' => 'Am_Record', ); $count = 0; foreach ($regexes as $regex => $replace) { $className = preg_replace('/^'.$regex.'$/', $replace, $className, 1, $count); if ($count) break; } $className = preg_replace('/[^a-zA-Z0-9_]+/', '', $className); $className = str_replace('_', DIRECTORY_SEPARATOR , $className); if (preg_match('/^pear/i', $className)) return; // do not autoload pear classes if (preg_match('/^([a-zA-Z][A-Za-z0-9]+)Table$/', $className, $regs)) $className = $regs[1]; //memUsage('before-'.$className ); include_once $className . '.php'; //tmUsage('after including ' . $className); //memUsage('after-'.$className ); } public function onDaily(Am_Event $event) { $this->di->userTable->checkAllSubscriptions(); $this->di->emailTemplateTable->sendCronExpires(); $this->di->emailTemplateTable->sendCronMailNotCompleted(); $this->di->emailTemplateTable->sendCronAutoresponders(); $this->di->emailTemplateTable->sendCronPendingNotifications(); $this->di->store->cronDeleteExpired(); $this->di->storeRebuild->cronDeleteExpired(); Am_Auth_BruteforceProtector::cleanUp(); if ($this->di->config->get('clear_access_log') && $this->di->config->get('clear_access_log_days') > 0) { $dat = sqlDate($this->di->time - $this->di->config->get('clear_access_log_days') * 3600 * 24); $this->di->accessLogTable->clearOld($dat); } if ($this->di->config->get('clear_inc_payments') && $this->di->config->get('clear_inc_payments_days') > 0) { $dat = sqlDate($this->di->time - $this->di->config->get('clear_inc_payments_days') * 3600 * 24); $this->di->invoiceTable->clearPending($dat); } $this->di->uploadTable->cleanUp(); Am_Mail_Queue::getInstance()->cleanUp(); } public function onHourly() { if ($this->di->config->get('email_queue_enabled')) Am_Mail_Queue::getInstance()->sendFromQueue(); } /** * Generate a string of given length * @param int $len * @param string $acceptedChars ex. "abcdef1234" * @return string */ function generateRandomString($len, $acceptedChars = null) { if (@is_readable('/dev/urandom')) { $f=fopen('/dev/urandom', 'r'); $urandom=fread($f, 8); fclose($f); } if (@$urandom) { mt_srand(crc32($urandom)); } else { $stat = @stat(__FILE__); if (!$stat) $stat = array(php_uname(), __FILE__); mt_srand($x=crc32(microtime(true) . implode('+', $stat))); } // $seed = 8; if (!$acceptedChars) $acceptedChars = 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPLKJHGFDSAZXCVBNM0123456789'; $max = strlen($acceptedChars) - 1; $security_code = ""; for ($i=0; $i < $len; $i++) $security_code .= $acceptedChars{mt_rand(0, $max)}; return $security_code; } public function setSessionCookieDomain() { if (ini_get('session.cookie_domain') != '') return; // already configured $domain = @$_SERVER['HTTP_HOST']; $domain = strtolower(trim(preg_replace('/(\:\d+)$/', '', $domain))); if (!$domain) return; if ($domain == 'localhost') return; if (preg_match('/\.(dev|local)$/', $domain)) { @ini_set('session.cookie_domain', ".$domain"); return; } /* * If domain is valid IP address do not change session.cookie_domain; */ if (filter_var($domain, FILTER_VALIDATE_IP)) return $domain; try { $min = Am_License::getMinDomain($domain); } catch (Exception $e) { return; } @ini_set('session.cookie_domain', ".$min"); } public function initSession() { @ini_set('session.use_trans_sid', false); @ini_set('session.cookie_httponly', true); // lifetime must be bigger than admin and user auth timeout $lifetime = (int)ini_get('session.gc_maxlifetime'); if ($lifetime < ($max = max($this->di->config->get('login_session_lifetime', 120) * 60, 7200))) { @ini_set('session.gc_maxlifetime', $max); } $this->setSessionCookieDomain(); if ('db' == $this->getSessionStorageType()) Zend_Session::setSaveHandler(new Am_Session_SaveHandler($this->di->db)); if(defined('AM_SESSION_NAME') && AM_SESSION_NAME){ Zend_Session::setOptions(array('name' => AM_SESSION_NAME)); } try { Zend_Session::start(); } catch (Zend_Session_Exception $e){ // fix for Error #1009 - Internal error when disable shopping cart module if (strpos($e->getMessage(), "Failed opening 'Am/ShoppingCart.php'") !== false) { Zend_Session::destroy(); header("Location: " . $_SERVER['REQUEST_URI']); exit(); } // process other session issues if (strpos($e->getMessage(), 'This session is not valid according to')===0) { $_SESSION = array(); Zend_Session::regenerateId(); Zend_Session::writeClose(); } if (defined('AM_TEST') && AM_TEST) { // just ignore error } else throw $e; } //disabled as it brokes flash uploads ! //Zend_Session::registerValidator(new Zend_Session_Validator_HttpUserAgent); $this->di->session = new Zend_Session_Namespace('amember'); } public function getSessionStorageType(){ if(ini_get('suhosin.session.encrypt')) return 'php'; else return $this->di->config->get('session_storage', 'db'); } /** * Converts $path to a file located inside aMember folder (!) * to an URL (if possible, relative, if impossible, using ROOT_SURL) * @throws Am_Exception_InternalError * @return string */ function pathToUrl($path) { $p = realpath($path); $r = realpath(ROOT_DIR); if (strpos($p, $r)!==0) throw new Am_Exception_InternalError("File [$p] is not inside application path [$r]"); $rel = substr($p, strlen($r)); return REL_ROOT_URL . str_replace('\\', '/', $rel); } function initConstants() { @ini_set('magic_quotes_runtime', false); @ini_set('magic_quotes_sybase', false); mb_internal_encoding("UTF-8"); if (!defined('ROOT_URL')) define('ROOT_URL', $this->di->config->get('root_url')); if (!defined('ROOT_SURL')) define('ROOT_SURL', $this->di->config->get('root_surl')); if (!defined('AM_WIN')) define('AM_WIN', (bool)preg_match('/Win/i', PHP_OS)); // true if on windows if (!defined('ROOT_DIR')) define('ROOT_DIR', realpath(dirname(dirname(dirname(__FILE__))))); if (!defined('DATA_DIR')) define('DATA_DIR', ROOT_DIR . '/data'); if (!defined('AM_VERSION')) define('AM_VERSION', '4.2.14.3b7ee0a'); } function __exception404(Zend_Controller_Response_Abstract $response) { $response ->setHttpResponseCode(404) ->setBody('HTTP/1.1 404 Not Found') ->setRawHeader('HTTP/1.1 404 Not Found') ->sendResponse(); } function __exception(Exception $e) { if ($e instanceof Zend_Controller_Dispatcher_Exception && (preg_match('/^Invalid controller specified/', $e->getMessage()))) { return $this->__exception404(Zend_Controller_Front::getInstance()->getResponse()); } if ($e->getCode() == 404) { return $this->__exception404(Zend_Controller_Front::getInstance()->getResponse()); } try { static $in_fatal_error; //! $in_fatal_error++; if ($in_fatal_error > 2){ echo(nl2br("<b>\n\n".__METHOD__." called twice\n\n</b>")); exit(); } if (!$this->initFinished) { $isApiError = false; } else { $request = Zend_Controller_Front::getInstance()->getRequest(); $isApiError = (preg_match('#^/api/#', $request->getPathInfo()) && !preg_match('#^/api/admin($|/)#', $request->getPathInfo())); } if (!$isApiError && ((defined('AM_DEBUG') && AM_DEBUG) || (APPLICATION_ENV == 'testing'))){ $display_error = "<pre>".($e).':'.$e->getMessage()."</pre>"; } else { if ($e instanceof Am_Exception){ $display_error = $e->getPublicError(); $display_title = $e->getPublicTitle(); } elseif ($e instanceof Zend_Controller_Dispatcher_Exception) { $display_error = ___("Error 404 - Not Found"); header("HTTP/1.0 404 Not Found"); } else $display_error = ___('An internal error happened in the script, please contact webmaster for details'); } /// special handling for API errors if ($isApiError) { $format = $request->getParam('_format', 'json'); if (!empty($display_title)) $display_error = $display_title . ':' . $display_error; $display_error = trim($display_error, " \t\n\r"); if ($format == 'xml') { $xml = new SimpleXMLElement('<error />'); $xml->ok = 'false'; $xml->message = $display_error; echo (string)$xml; } else { echo json_encode(array('ok' => false , 'error' => true, 'message' => $display_error)); } exit(); } if (!$this->initFinished) amDie($display_error); // fixes http://bt.amember.com/issues/597 if (($router = Zend_Controller_Front::getInstance()->getRouter()) instanceof Zend_Controller_Router_Rewrite) $router->addDefaultRoutes(); // $t = new Am_View; $t->assign('is_html', true); // must be already escaped here! if(isset($display_title)) $t->assign('title', $display_title); $t->assign('error', $display_error); $t->assign('admin_email', $this->di->config->get('admin_email')); if (defined('AM_DEBUG') && AM_DEBUG){ $t->assign('trace', $e->getTraceAsString()); } $t->display("error.phtml"); // log error if (!method_exists($e, 'getLogError') || $e->getLogError()) $this->di->errorLogTable->logException($e); } catch (Exception $e) { echo ($e)." thrown within the exception handler. Message: ".$e->getMessage()." on line ".$e->getLine(); } exit(); } function __error($errno, $errstr, $errfile, $errline) { if (!(error_reporting() & $errno)) return; $ef = (@APPLICATION_ENV != 'debug') ? basename($errfile) : $errfile; switch ($errno) { case E_RECOVERABLE_ERROR: $msg = "<b>RECOVERABLE ERROR:</b> $errstr\nin line $errline of file $errfile"; if (APPLICATION_ENV == 'debug') echo $msg; $this->di->errorLogTable->log($msg); return true; case E_ERROR: case E_PARSE: case E_CORE_ERROR: case E_COMPILE_ERROR: case E_USER_ERROR: $this->di->errorLogTable->log("<b>ERROR:</b> $errstr\nin line $errline of file $errfile"); ob_clean(); amDie("ERROR [$errno] $errstr\nin line $errline of file $ef"); exit(1); case E_USER_WARNING: case E_WARNING: if (!defined('AM_DEBUG') || !AM_DEBUG) return; if (!defined('SILENT_AMEMBER_ERROR_HANDLER') && !(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest')) print("<b>WARNING:</b> $errstr\nin line $errline of file $ef<br />"); $this->di->errorLogTable->log("<b>WARNING:</b> $errstr\nin line $errline of file $errfile"); break; case E_STRICT: case E_USER_NOTICE: case E_NOTICE: if (!defined('AM_DEBUG') || !AM_DEBUG) return; if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') return; print_rr("<b>NOTICE:</b> $errstr\nin line $errline of file $ef<br />"); break; } } function getDefaultLocale($addRegion = false) { @list($found,) = array_keys(Zend_Locale::getDefault()); if (!$found) return 'en_US'; if (!$addRegion) return $found; return (strlen($found)<=4) ? ___('_default_locale') : $found; } /** * Return (generate if necessary) a constant, random site ID * @return string */ function getSiteKey() { static $key; if ($key) return $key; $config = $this->di->config; if ($key = $config->get('random-site-key')) return $key; $key = sha1(mt_rand().@$_SERVER['REMOTE_ADDR'].microtime(true)); Am_Config::saveValue('random-site-key', $key); $config->set('random-site-key', $key); return $key; } /** * Return hash of @link getSiteKey() + $hashString * You may use it to not disclose site key to public * @example Am_App->getSiteHash('backup-cron') * @param type $hashString * @return string [a-zA-Z0-9]{$len} */ function getSiteHash($hashString, $len = 20) { return $this->hash($this->getSiteKey() . $hashString, $len); } /** * Make a site-unique hash of given length * @return string [0-9a-zA-Z] */ function hash($string, $len=20) { if ($len > 20) $len = 20; $chars = "0123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"; $len_chars = strlen($chars); $raw = sha1($string, true); $ret = ""; for ($i=0;$i<$len;$i++) $ret .= $chars[ ord($raw[$i]) % $len_chars ]; return $ret; } function dbSync($reportNoChanges = true, $modules = null) { $nl = empty($_SERVER['REMOTE_ADDR']) ? "\n" : "<br />\n"; $db = new Am_DbSync(); $db->parseTables($this->di->db); $xml = new Am_DbSync(); $xml->parseXml(file_get_contents(APPLICATION_PATH . '/default/db.xml')); if ($modules === null) $modules = $this->di->modules->getEnabled(); foreach ($modules as $module) { if (file_exists($file = APPLICATION_PATH . '/' . $module . "/db.xml")) { print "Parsing XML file: [application/$module/db.xml]$nl"; $xml->parseXml(file_get_contents($file)); } } $this->di->hook->call(Am_Event::DB_SYNC, array( 'dbsync' => $xml, )); $diff = $xml->diff($db); if ($sql = $diff->getSql($this->di->db->getPrefix())) { print "Doing the following database structure changes:$nl"; print $diff->render(); print "$nl"; ob_end_flush(); $diff->apply($this->di->db); print "DONE$nl"; ob_end_flush(); } elseif ($reportNoChanges) { print "No database structure changes required$nl"; } $this->etSync($modules); $this->di->store->set('db_version', AM_VERSION); } function etSync($modules = null) { $etFiles = array(); if ($modules === null) $modules = $this->di->modules->getEnabled(); foreach ($modules as $module) { if (file_exists($file = APPLICATION_PATH . '/' . $module . "/email-templates.xml")) { $etFiles[$module] = $file; } } $nl = empty($_SERVER['REMOTE_ADDR']) ? "\n" : "<br />\n"; $t = $this->di->emailTemplateTable; $t->importXml(file_get_contents(APPLICATION_PATH . '/default/email-templates.xml')); foreach ($etFiles as $module => $file) { print "Parsing XML file: [application/$module/email-templates.xml]$nl"; $t->importXml(file_get_contents($file)); } } function readConfig($fn) { $this->config = require_once $config; return $this; } } function array_remove_value(& $array, $value) { foreach ($array as $k => $v) if ($v === $value) unset($array[$k]); } function filterFilename($fn, $allowDir = false) { $fn = trim($fn); $fn = str_replace(array(chr(0), '..'), array('', ''), $fn); if (!$allowDir) $fn = str_replace(array('/', '\\'), array('', ''), $fn); return $fn; } /** * class to run long operations in portions with respect to time and memory limits * callback function must set $context variable - it will be passed back on next * call, even after page reload. * when operation is finished, callback function must return boolean <b>true</b> * to indicate completion * @package Am_Utils */ class Am_BatchProcessor { protected $callback; protected $tm_started, $tm_finished; protected $max_tm; protected $max_mem; /** * If process was explictly stopped from a function * @var bool */ protected $stopped = false; /** * * @param type $callback Callback function - must return true when processing finished * @param type $max_tm max execution time in seconds * @param type $max_mem memory limit in megabytes */ public function __construct($callback, $max_tm = 20, $max_mem = 64) { if (!is_callable($callback)) throw new Am_Exception_InternalError("Not callable callback passed"); $this->callback = $callback; // get max time $this->max_tm = ini_get('max_execution_time'); if ($this->max_tm <= 0 || $this->max_tm > 20) $this->max_tm = 20; $this->max_tm = min($this->max_tm, $max_tm); // get max memory $max_memory = strtoupper(ini_get('memory_limit')); if ($max_memory != '') { $multi = array('K' => 1024, 'M' => 1024 * 1024, 'G' => 1024 * 1024 * 1024); if (preg_match('/^(\d+)\s*(K|M|G)/', $max_memory, $regs)) $max_memory = $regs[1] * $multi[$regs[2]]; else $max_memory = intval($max_memory); } $this->max_mem = min($max_mem*1024*1024, $max_memory*0.9); } /** * @return true if process finished, false if process was breaked due to limits */ function run( & $context ) { $this->tm_started = time(); $breaked = false; $params = array( & $context, $this ); while (! call_user_func_array($this->callback, $params)) { if ($this->isStopped() || !$this->checkLimits()) { $breaked = true; break; } } $this->tm_finished = time(); return !$breaked; } function stop() { $this->stopped = true; } function isStopped() { return (bool)$this->stopped; } /** * @return bool false if limits are over */ function checkLimits() { $tm_used = time() - $this->tm_started; if ($tm_used >= $this->max_tm) return false; if (memory_get_usage() > $this->max_mem) return false; return true; } function getRunningTime() { $finish = $this->tm_finished ? $this->tm_finished : time(); return $finish - $this->tm_started; } }
Upload Files
Cancel
Upload
Create New
Cancel
Create
Change Permissions
Cancel
Save
Change Date
Cancel
Save
Rename Item
Cancel
Save
Confirm Delete
Are you sure you want to delete the selected items?
Cancel
Delete