function __construct($device = null) { $this->version = intval(Kurogo::getSiteVar('MOBI_SERVICE_VERSION')); $this->userAgent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ''; if ($device && strlen($device)) { Kurogo::log(LOG_DEBUG, "Setting device to {$device} (override)", "deviceDetection"); $this->setDevice($device); // user override of device detection } elseif (isset($_COOKIE[$this->cookieKey()])) { Kurogo::log(LOG_DEBUG, "Setting device to " . $_COOKIE[$this->cookieKey()] . " (cookie)", "deviceDetection"); $this->setDevice($_COOKIE[$this->cookieKey()]); } elseif (isset($_SERVER['HTTP_USER_AGENT'])) { if ($cache = Kurogo::getCache($this->cacheKey($this->userAgent))) { $this->setDevice($cache); return $cache; } if ($data = Kurogo::getSiteVar('MOBI_SERVICE_USE_EXTERNAL') ? $this->detectDeviceExternal($this->userAgent) : $this->detectDeviceInternal($this->userAgent)) { if ($data['pagetype'] == 'tablet' && !Kurogo::getOptionalSiteVar('TABLET_ENABLED', 1)) { $data['pagetype'] = 'compliant'; if ($data['platform'] == 'ipad') { $data['platform'] = 'iphone'; // currently not used but just in case } } $this->pagetype = $data['pagetype']; $this->platform = $data['platform']; $this->certs = $data['supports_certificate']; Kurogo::log(LOG_DEBUG, "Setting device to " . $this->getDevice(), "deviceDetection"); $this->setDeviceCookie(); Kurogo::setCache($this->cacheKey($this->userAgent), $this->getDevice()); } } }
protected function getConfig($area, $type, $opts = 0) { if ($type instanceof Module) { $key = $type->getConfigModule() . '-' . $area; } else { $key = $type . '-' . $area; } if (!isset($this->configs[$key])) { if ($config = Kurogo::getCache("config-" . $key)) { $this->configs[$key] = $config; } else { Kurogo::log(LOG_INFO, "Loading config {$key}", 'config'); $this->configs[$key] = $this->loadConfig($area, $type, $opts); Kurogo::setCache("config-" . $key, $this->configs[$key]); } } return $this->configs[$key]; }
protected function loadFile($_file) { if (empty($_file)) { return false; } $cacheKey = 'configfile-' . md5($_file); if ($cache = Kurogo::getCache($cacheKey)) { // a little sanity in case we update the structure if (isset($cache['vars'], $cache['sectionVars'], $cache['file'])) { $this->addVars($cache['vars']); $this->addSectionVars($cache['sectionVars']); return $cache['file']; } } if (!($file = realpath_exists($_file))) { return false; } $vars = parse_ini_file($file, false); $this->addVars($vars); $sectionVars = parse_ini_file($file, true); $this->addSectionVars($sectionVars); Kurogo::setCache($cacheKey, array('vars' => $vars, 'sectionVars' => $sectionVars, 'file' => $file)); Kurogo::log(LOG_DEBUG, "Loaded config file {$file}", 'config'); return $file; }
/** * Factory method. Used to instantiate a subclass * @param string $id, the module id to load * @param string $type, the type of module to load (web/api) */ public static function factory($id, $type = null) { Kurogo::log(LOG_INFO, "Initializing {$type} module {$id}", 'module'); $configModule = $id; //attempt to load config/$id/module.ini if ($config = ModuleConfigFile::factory($id, 'module', ModuleConfigFile::OPTION_DO_NOT_CREATE)) { //use the ID parameter if it's present, otherwise use the included id $id = $config->getOptionalVar('id', $id); } elseif (!Kurogo::getOptionalSiteVar('CREATE_DEFAULT_CONFIG', false, 'modules')) { Kurogo::log(LOG_ERR, "Module config file not found for module {$id}", 'module'); throw new KurogoModuleNotFound(Kurogo::getLocalizedString('ERROR_MODULE_NOT_FOUND', $id)); } // see if the class location has been cached if ($moduleFile = Kurogo::getCache(self::cacheKey($id, $type))) { $className = basename($moduleFile, '.php'); include_once $moduleFile; $module = new $className(); $module->setConfigModule($configModule); if ($config) { $module->setConfig('module', $config); } return $module; } // when run without a type it will find either $classNames = array('web' => ucfirst($id) . 'WebModule', 'api' => ucfirst($id) . 'APIModule'); // if we specified a type, include only that type in the array if ($type) { if (isset($classNames[$type])) { $classNames = array($classNames[$type]); } else { throw new KurogoException("Invalid module type {$type}"); } } // possible module paths. // 1. Site Folder SiteMODULEIDXXXModule // 2. Site Folder MODULEIDXXXModule // 3. Project folder MODULEIDXXXModule $modulePaths = array(SITE_MODULES_DIR . "/{$id}/Site%s.php" => "Site%s", SITE_MODULES_DIR . "/{$id}/%s.php" => "%s", MODULES_DIR . "/{$id}/%s.php" => "%s"); //cycle module paths foreach ($modulePaths as $path => $className) { //cycle class names to find a valid module foreach ($classNames as $class) { $className = sprintf($className, $class); $path = sprintf($path, $class); Kurogo::log(LOG_DEBUG, "Looking for {$path} for {$id}", 'module'); // see if it exists $moduleFile = realpath_exists($path); if ($moduleFile && (include_once $moduleFile)) { //found it $info = new ReflectionClass($className); if (!$info->isAbstract()) { Kurogo::log(LOG_INFO, "Found {$moduleFile} for {$id}", 'module'); $module = new $className(); $module->setConfigModule($configModule); if ($config) { $module->setConfig('module', $config); } // cache the location of the class (which also includes the classname) Kurogo::setCache(self::cacheKey($id, $type), $moduleFile); return $module; } Kurogo::log(LOG_NOTICE, "{$class} found at {$moduleFile} is abstract and cannot be used for {$id}", 'module'); return false; } } } Kurogo::log(LOG_ERR, "No valid class found for module {$id}", 'module'); throw new KurogoModuleNotFound(Kurogo::getLocalizedString('ERROR_MODULE_NOT_FOUND', $id)); }
/** * Factory method. Used to instantiate a subclass * @param string $id, the module id to load * @param string $type, the type of module to load (web/api) */ public static function factory($id, $type = null) { if ($id == 'kurogo') { set_exception_handler("exceptionHandlerForError"); } if (!self::isValidModuleName($id)) { throw new KurogoException(Kurogo::getLocalizedString('ERROR_INVALID_MODULE')); } Kurogo::log(LOG_INFO, "Initializing {$type} module {$id}", 'module'); $configModule = $id; $configStore = Kurogo::configStore(); //attempt to load config/$id/module.ini if ($moduleData = $configStore->getOptionalSection('module', 'module', $configModule)) { $id = Kurogo::arrayVal($moduleData, 'id', $configModule); } else { throw new KurogoModuleNotFound(Kurogo::getLocalizedString('ERROR_MODULE_NOT_FOUND', $id)); } // see if the class location has been cached if ($moduleFile = Kurogo::getCache(self::cacheKey($id, $type))) { $className = basename($moduleFile, '.php'); include_once $moduleFile; $module = new $className(); if (is_a($module, KurogoWebBridge::STUB_API_CLASS)) { $module->setID($id); } $module->setConfigModule($configModule); Kurogo::addModuleLib($id); return $module; } // when run without a type it will find either $classNames = array('web' => ucfirst($id) . 'WebModule', 'api' => ucfirst($id) . 'APIModule', 'shell' => ucfirst($id) . 'ShellModule'); // if we specified a type, include only that type in the array if ($type) { if (isset($classNames[$type])) { $classNames = array($classNames[$type]); } else { throw new KurogoException("Invalid module type {$type}"); } } // possible module paths. // 1. Site Folder SiteMODULEIDXXXModule // 2. Site Folder MODULEIDXXXModule // 3. Project folder MODULEIDXXXModule // Note: The PHP class name MUST be the basename of the file path. $modulePaths = array(SITE_MODULES_DIR . "/{$id}/Site%s.php", SITE_MODULES_DIR . "/{$id}/%s.php", SHARED_MODULES_DIR . "/{$id}/Site%s.php", SHARED_MODULES_DIR . "/{$id}/%s.php", MODULES_DIR . "/{$id}/%s.php"); if ($type == 'api' && KurogoWebBridge::moduleHasMediaAssets($configModule)) { $modulePaths[] = LIB_DIR . '/' . KurogoWebBridge::STUB_API_CLASS . ".php"; } //cycle module paths foreach ($modulePaths as $path) { $className = basename($path, '.php'); //cycle class names to find a valid module foreach ($classNames as $class) { $className = sprintf($className, $class); $path = sprintf($path, $class); Kurogo::log(LOG_DEBUG, "Looking for {$path} for {$id}", 'module'); // see if it exists $moduleFile = realpath_exists($path); if ($moduleFile && (include_once $moduleFile)) { //found it $info = new ReflectionClass($className); if (!$info->isAbstract()) { Kurogo::log(LOG_INFO, "Found {$moduleFile} for {$id}", 'module'); $module = new $className(); if (is_a($module, KurogoWebBridge::STUB_API_CLASS)) { $module->setID($id); } $module->setConfigModule($configModule); // cache the location of the class (which also includes the classname) Kurogo::setCache(self::cacheKey($id, $type), $moduleFile); Kurogo::addModuleLib($id); return $module; } Kurogo::log(LOG_NOTICE, "{$class} found at {$moduleFile} is abstract and cannot be used for {$id}", 'module'); return false; } } } Kurogo::log(LOG_NOTICE, "No valid {$type} class found for module {$id}", 'module'); throw new KurogoModuleNotFound(Kurogo::getLocalizedString('ERROR_MODULE_NOT_FOUND', $id)); }
public function checkCurrentVersion() { if ($currentVersion = Kurogo::getCache('currentVersion')) { return $currentVersion; } elseif (!Kurogo::getOptionalSiteVar('KUROGO_VERSION_CHECK', 1)) { return null; } try { $cache = new DiskCache(CACHE_DIR . DIRECTORY_SEPARATOR . '/kurogo', 3600, TRUE); } catch (KurogoDataException $e) { $cache = null; } $cacheFilename = 'currentVersion'; if ($cache && $cache->isFresh($cacheFilename)) { $currentVersion = $cache->read($cacheFilename); } else { $url = "http://kurogo.org/checkversion.php?" . http_build_query(array('version' => KUROGO_VERSION, 'base' => FULL_URL_BASE, 'site' => SITE_KEY, 'php' => phpversion(), 'uname' => php_uname("a"))); $context = stream_context_create(array('http' => array('timeout' => 5, 'user_agent' => self::KurogoUserAgent()))); if ($currentVersion = trim(@file_get_contents($url, false, $context))) { if ($cache) { $cache->write($currentVersion, $cacheFilename); } } } if ($currentVersion) { Kurogo::setCache('currentVersion', $currentVersion); } return $currentVersion; }
protected function detectDevice($userAgent) { $classification = $this->unknownClassification(); if ($cachedClassificationString = Kurogo::getCache($this->cacheKey($userAgent))) { // Kurogo cache has device string $classification = $this->classificationForString($cachedClassificationString); } else { if ($data = Kurogo::getSiteVar('MOBI_SERVICE_USE_EXTERNAL') ? $this->detectDeviceExternal($userAgent) : $this->detectDeviceInternal($userAgent)) { // Looked up device data with configured device detection method $classification['pagetype'] = $data['pagetype']; $classification['platform'] = $data['platform']; Kurogo::setCache($this->cacheKey($userAgent), $this->stringForClassification($classification)); } } return $classification; }
public static function getAvailableMediaInfoForModule($id) { $cacheKey = "webbridge-mediainfo-{$id}"; // use memory cache to make this more efficient $info = Kurogo::getCache($cacheKey); if ($info === false) { $files = array_merge((array) glob(WEB_BRIDGE_DIR . "/*/{$id}.zip"), (array) glob(WEB_BRIDGE_DIR . "/*/{$id}-tablet.zip")); $info = array(); foreach ($files as $file) { $name = basename($file, '.zip'); $dir = realpath(dirname($file)); $parts = explode(DIRECTORY_SEPARATOR, $dir); if (!$parts) { continue; } $platform = end($parts); if (!$platform) { continue; } $key = $platform; if ($name == "{$id}-tablet") { $key .= "-tablet"; } $file = realpath_exists($file); if (!$file) { continue; } $info[$key] = array('url' => FULL_URL_PREFIX . "media/web_bridge/{$platform}/{$name}.zip", 'file' => $file, 'mtime' => filemtime($file), 'md5' => md5_file($file)); } Kurogo::setCache($cacheKey, $info); } return $info ? $info : array(); }
private function initSite(&$path) { includePackage('Cache'); includePackage('Config'); $siteConfig = new ConfigGroup(); $saveCache = true; // Load main configuration file $kurogoConfig = ConfigFile::factory('kurogo', 'project', ConfigFile::OPTION_IGNORE_MODE | ConfigFile::OPTION_IGNORE_LOCAL); $siteConfig->addConfig($kurogoConfig); define('CONFIG_MODE', $siteConfig->getVar('CONFIG_MODE', 'kurogo')); Kurogo::log(LOG_DEBUG, "Setting config mode to " . (CONFIG_MODE ? CONFIG_MODE : '<empty>'), 'config'); define('CONFIG_IGNORE_LOCAL', $siteConfig->getVar('CONFIG_IGNORE_LOCAL', 'kurogo')); if ($cacheClass = $siteConfig->getOptionalVar('CACHE_CLASS', '', 'cache')) { $this->cacher = KurogoMemoryCache::factory($cacheClass, $siteConfig->getOptionalSection('cache')); } //multi site currently only works with a url base of root "/" if ($siteConfig->getOptionalVar('MULTI_SITE', false, 'kurogo')) { // in scripts you can pass the site name to Kurogo::initialize() if (PHP_SAPI == 'cli') { $site = strlen($path) > 0 ? $path : $siteConfig->getVar('DEFAULT_SITE'); $siteDir = implode(DIRECTORY_SEPARATOR, array(ROOT_DIR, 'site', $site)); if (!file_exists(realpath($siteDir))) { die("FATAL ERROR: Site Directory {$siteDir} not found for site {$path}"); } } else { $paths = explode("/", $path); // this is url $sites = array(); $siteDir = ''; if (count($paths) > 1) { $site = $paths[1]; if ($sites = $siteConfig->getOptionalVar('ACTIVE_SITES', array(), 'kurogo')) { //see if the site is in the list of available sites if (in_array($site, $sites)) { $testPath = implode(DIRECTORY_SEPARATOR, array(ROOT_DIR, 'site', $site)); if (($siteDir = realpath($testPath)) && file_exists($siteDir)) { $urlBase = '/' . $site . '/'; // this is a url } } } elseif (self::isValidSiteName($site)) { $testPath = implode(DIRECTORY_SEPARATOR, array(ROOT_DIR, 'site', $site)); if (($siteDir = realpath($testPath)) && file_exists($siteDir)) { $urlBase = '/' . $site . '/'; // this is a url } } } if (!$siteDir) { $site = $siteConfig->getVar('DEFAULT_SITE'); array_splice($paths, 1, 1, array($site, $paths[1])); $url = implode("/", $paths); Kurogo::redirectToURL($url, Kurogo::REDIRECT_PERMANENT); } } define('SITE_NAME', $site); } else { //make sure active site is set if (!($site = $siteConfig->getVar('ACTIVE_SITE'))) { die("FATAL ERROR: ACTIVE_SITE not set"); } // make sure site_dir is set and is a valid path // Do not call realpath_exists here because until SITE_DIR define is set // it will not allow files and directories outside ROOT_DIR if (!($siteDir = $siteConfig->getVar('SITE_DIR')) || !(($siteDir = realpath($siteDir)) && file_exists($siteDir))) { die("FATAL ERROR: Site Directory " . $siteConfig->getVar('SITE_DIR') . " not found for site " . $site); } define('SITE_NAME', $site); if (PHP_SAPI != 'cli') { // // Get URL base // if ($urlBase = $siteConfig->getOptionalVar('URL_BASE', '', 'kurogo')) { $urlBase = rtrim($urlBase, '/') . '/'; } elseif ($urlBase = Kurogo::getCache('URL_BASE')) { //@TODO this won't work yet because the cache hasn't initialized $urlBase = rtrim($urlBase, '/') . '/'; $saveCache = false; } else { //extract the path parts from the url $pathParts = array_values(array_filter(explode("/", $_SERVER['REQUEST_URI']))); $testPath = $_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR; $urlBase = '/'; //once the path equals the WEBROOT_DIR we've found the base. This only works with symlinks if (realpath($testPath) != WEBROOT_DIR) { foreach ($pathParts as $dir) { $test = $testPath . $dir . DIRECTORY_SEPARATOR; if (file_exists(realpath($test))) { $testPath = $test; $urlBase .= $dir . '/'; if (realpath($test) == WEBROOT_DIR) { break; } } } } } } } if (PHP_SAPI == 'cli') { define('URL_BASE', null); } else { if (!isset($urlBase)) { throw new KurogoConfigurationException("URL base not set. Please report the configuration to see why this happened"); } define('URL_BASE', $urlBase); if ($saveCache) { Kurogo::setCache('URL_BASE', $urlBase); } Kurogo::log(LOG_DEBUG, "Setting site to {$site} with a base of {$urlBase}", 'kurogo'); // Strips out the leading part of the url for sites where // the base is not located at the document root, ie.. /mobile or /m // Also strips off the leading slash (needed by device debug below) if (isset($path)) { // Strip the URL_BASE off the path $baseLen = strlen(URL_BASE); if ($baseLen && strpos($path, URL_BASE) === 0) { $path = substr($path, $baseLen); } } } // Set up defines relative to SITE_DIR define('SITE_DIR', $siteDir); //already been realpath'd define('SITE_LIB_DIR', SITE_DIR . DIRECTORY_SEPARATOR . 'lib'); define('SITE_APP_DIR', SITE_DIR . DIRECTORY_SEPARATOR . 'app'); define('SITE_MODULES_DIR', SITE_DIR . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'modules'); define('DATA_DIR', SITE_DIR . DIRECTORY_SEPARATOR . 'data'); define('CACHE_DIR', SITE_DIR . DIRECTORY_SEPARATOR . 'cache'); define('LOG_DIR', SITE_DIR . DIRECTORY_SEPARATOR . 'logs'); define('SITE_CONFIG_DIR', SITE_DIR . DIRECTORY_SEPARATOR . 'config'); define('SITE_DISABLED_DIR', SITE_DIR . DIRECTORY_SEPARATOR . 'config_disabled'); //load in the site config file (required); $config = ConfigFile::factory('site', 'site'); $siteConfig->addConfig($config); // attempt to load site key $siteKey = $siteConfig->getOptionalVar('SITE_KEY', md5($siteDir)); define('SITE_KEY', $siteKey); if ($siteConfig->getOptionalVar('SITE_DISABLED')) { die("FATAL ERROR: Site disabled"); } // Set up theme define if (!($theme = $siteConfig->getVar('ACTIVE_THEME'))) { die("FATAL ERROR: ACTIVE_THEME not set"); } Kurogo::log(LOG_DEBUG, "Setting theme to {$theme}", 'kurogo'); define('THEME_DIR', SITE_DIR . DIRECTORY_SEPARATOR . 'themes' . DIRECTORY_SEPARATOR . $theme); $this->siteConfig = $siteConfig; }