/Devblocks.class.php
PHP | 5093 lines | 3748 code | 745 blank | 600 comment | 456 complexity | 4899a3fbd1abe25fcd0f0adcaa994fe3 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- <?php
- include_once(DEVBLOCKS_PATH . "api/Model.php");
- include_once(DEVBLOCKS_PATH . "api/DAO.php");
- include_once(DEVBLOCKS_PATH . "api/Extension.php");
- define('PLATFORM_BUILD',2010120101);
- /**
- * A platform container for plugin/extension registries.
- *
- * @author Jeff Standen <jeff@webgroupmedia.com>
- */
- class DevblocksPlatform extends DevblocksEngine {
- const CACHE_ACL = 'devblocks_acl';
- const CACHE_EVENT_POINTS = 'devblocks_event_points';
- const CACHE_EVENTS = 'devblocks_events';
- const CACHE_EXTENSIONS = 'devblocks_extensions';
- const CACHE_PLUGINS = 'devblocks_plugins';
- const CACHE_POINTS = 'devblocks_points';
- const CACHE_SETTINGS = 'devblocks_settings';
- const CACHE_STORAGE_PROFILES = 'devblocks_storage_profiles';
- const CACHE_TABLES = 'devblocks_tables';
- const CACHE_TAG_TRANSLATIONS = 'devblocks_translations';
-
- static private $extensionDelegate = null;
-
- static private $start_time = 0;
- static private $start_memory = 0;
- static private $start_peak_memory = 0;
-
- static private $locale = 'en_US';
-
- static private $_tmp_files = array();
-
- private function __construct() { return false; }
- /**
- * @param mixed $value
- * @param string $type
- * @param mixed $default
- * @return mixed
- */
- static function importVar($value,$type=null,$default=null) {
- if(is_null($value) && !is_null($default))
- $value = $default;
-
- // Sanitize input
- switch($type) {
- case 'array':
- @settype($value,$type);
- break;
- case 'bit':
- $value = !empty($value) ? 1 : 0;
- break;
- case 'boolean':
- $value = !empty($value) ? true : false;
- break;
- case 'float':
- $value = floatval($value);
- break;
- case 'integer':
- $value = intval($value);
- break;
- case 'string':
- $value = (string) $value;
- break;
- case 'timestamp':
- if(!is_numeric($value)) {
- try {
- $value = strtotime($value);
- } catch(Exception $e) {}
- } else {
- $value = abs(intval($value));
- }
- break;
- default:
- @settype($value,$type);
- break;
- }
-
- return $value;
- }
-
- /**
- * @param mixed $var
- * @param string $cast
- * @param mixed $default
- * @return mixed
- */
- static function importGPC($var,$cast=null,$default=null) {
- if(!is_null($var)) {
- if(is_string($var)) {
- $var = get_magic_quotes_gpc() ? stripslashes($var) : $var;
- } elseif(is_array($var)) {
- foreach($var as $k => $v) {
- $var[$k] = get_magic_quotes_gpc() ? stripslashes($v) : $v;
- }
- }
-
- } elseif (is_null($var) && !is_null($default)) {
- $var = $default;
- }
- if(!is_null($cast))
- $var = self::importVar($var, $cast, $default);
-
- return $var;
- }
- /**
- * Returns a string as a regexp.
- * "*bob" returns "/(.*?)bob/".
- */
- static function parseStringAsRegExp($string) {
- $pattern = str_replace(array('*'),'__any__', $string);
- $pattern = sprintf("/%s/i",str_replace(array('__any__'),'(.*?)', preg_quote($pattern)));
- return $pattern;
- }
-
- /**
- * Returns a formatted string as a number of bytes (e.g. 200M = 209715200)
- *
- * @param string $string
- * @return integer|FALSE
- */
- static function parseBytesString($string) {
- if(is_numeric($string)) {
- return intval($string);
-
- } else {
- $value = intval($string);
- $unit = strtolower(substr($string, -1));
-
- switch($unit) {
- default:
- case 'm':
- return $value * 1048576; // 1024^2
- break;
- case 'g':
- return $value * 1073741824; // 1024^3
- break;
- case 'k':
- return $value * 1024; // 1024^1
- break;
- }
- }
-
- return FALSE;
- }
-
- static function parseCrlfString($string) {
- $parts = preg_split("/[\r\n]/", $string);
-
- // Remove any empty tokens
- foreach($parts as $idx => $part) {
- $parts[$idx] = trim($part);
- if(0 == strlen($parts[$idx]))
- unset($parts[$idx]);
- }
-
- return $parts;
- }
-
- /**
- * Return a string as a regular expression, parsing * into a non-greedy
- * wildcard, etc.
- *
- * @param string $arg
- * @return string
- */
- static function strToRegExp($arg, $is_partial=false) {
- $arg = str_replace(array('*'),array('__WILD__'),$arg);
-
- return sprintf("/%s%s%s/i",
- ($is_partial ? '' : '^'),
- str_replace(array('__WILD__','/'),array('.*?','\/'),preg_quote($arg)),
- ($is_partial ? '' : '$')
- );
- }
-
- /**
- * Return a string with only its alphanumeric characters
- *
- * @param string $arg
- * @return string
- */
- static function strAlphaNum($arg) {
- return preg_replace("/[^A-Z0-9\.]/i","", $arg);
- }
-
- /**
- * Return a string with only its alphanumeric characters or punctuation
- *
- * @param string $arg
- * @return string
- */
- static function strAlphaNumDash($arg) {
- return preg_replace("/[^A-Z0-9_\-\.]/i","", $arg);
- }
- /**
- * Return a string with only its alphanumeric characters or underscore
- *
- * @param string $arg
- * @return string
- */
- static function strAlphaNumUnder($arg) {
- return preg_replace("/[^A-Z0-9_]/i","", $arg);
- }
-
- static function stripHTML($str) {
- // Strip all CRLF and tabs, spacify </TD>
- $str = str_ireplace(
- array("\r","\n","\t","</td>"),
- array('','',' ',' '),
- trim($str)
- );
-
- // Handle XHTML variations
- $str = str_ireplace(
- array("<br />", "<br/>"),
- "<br>",
- $str
- );
-
- // Turn block tags into a linefeed
- $str = str_ireplace(
- array('<BR>','<P>','</P>','<HR>','</TR>','</H1>','</H2>','</H3>','</H4>','</H5>','</H6>','</DIV>'),
- "\n",
- $str
- );
-
- // Strip tags
- $search = array(
- '@<script[^>]*?>.*?</script>@si',
- '@<style[^>]*?>.*?</style>@siU',
- '@<[\/\!]*?[^<>]*?>@si',
- '@<![\s\S]*?--[ \t\n\r]*>@',
- );
- $str = preg_replace($search, '', $str);
-
- // Flatten multiple spaces into a single
- $str = preg_replace('# +#', ' ', $str);
- // Translate HTML entities into text
- $str = html_entity_decode($str, ENT_COMPAT, LANG_CHARSET_CODE);
- // Loop through each line, ltrim, and concat if not empty
- $lines = explode("\n", $str);
- if(is_array($lines)) {
- $str = '';
- $blanks = 0;
- foreach($lines as $idx => $line) {
- $lines[$idx] = ltrim($line);
-
- if(empty($lines[$idx])) {
- if(++$blanks >= 2)
- unset($lines[$idx]);
- //continue; // skip more than 2 blank lines in a row
- } else {
- $blanks = 0;
- }
- }
- $str = implode("\n", $lines);
- }
- unset($lines);
-
- // Clean up bytes (needed after HTML entities)
- $str = mb_convert_encoding($str, LANG_CHARSET_CODE, LANG_CHARSET_CODE);
-
- return $str;
- }
-
- static function parseMarkdown($text) {
- static $parser = null;
-
- if(is_null($parser))
- $parser = new Markdown_Parser();
-
- return $parser->transform($text);
- }
-
- static function parseRss($url) {
- // [TODO] curl | file_get_contents() support
- // [TODO] rss://
-
- if(null == (@$data = file_get_contents($url)))
- return false;
-
- if(null == (@$xml = simplexml_load_string($data)))
- return false;
-
- // [TODO] Better detection of RDF/RSS/Atom + versions
- $root_tag = strtolower(dom_import_simplexml($xml)->tagName);
-
- if('feed'==$root_tag && count($xml->entry)) { // Atom
- $feed = array(
- 'title' => (string) $xml->title,
- 'url' => $url,
- 'items' => array(),
- );
-
- if(!count($xml))
- return $feed;
-
- foreach($xml->entry as $entry) {
- $id = (string) $entry->id;
- $date = (string) $entry->published;
- $title = (string) $entry->title;
- $content = (string) $entry->summary;
- $link = '';
-
- // Link as the <id> element
- if(preg_match("/^(.*)\:\/\/(.*$)/i", $id, $matches)) {
- $link = $id;
- // Link as 'alternative' attrib
- } elseif(count($entry->link)) {
- foreach($entry->link as $link) {
- if(0==strcasecmp('alternate',(string)$link['rel'])) {
- $link = (string) $link['href'];
- break;
- }
- }
- }
-
- $feed['items'][] = array(
- 'date' => strtotime($date),
- 'link' => $link,
- 'title' => $title,
- 'content' => $content,
- );
- }
-
- } elseif('rdf:rdf'==$root_tag && count($xml->item)) { // RDF
- $feed = array(
- 'title' => (string) $xml->channel->title,
- 'url' => $url,
- 'items' => array(),
- );
-
- if(!count($xml))
- return $feed;
-
- foreach($xml->item as $item) {
- $date = (string) $item->pubDate;
- $link = (string) $item->link;
- $title = (string) $item->title;
- $content = (string) $item->description;
-
- $feed['items'][] = array(
- 'date' => strtotime($date),
- 'link' => $link,
- 'title' => $title,
- 'content' => $content,
- );
- }
-
- } elseif('rss'==$root_tag && count($xml->channel->item)) { // RSS
- $feed = array(
- 'title' => (string) $xml->channel->title,
- 'url' => $url,
- 'items' => array(),
- );
-
- if(!count($xml))
- return $feed;
-
- foreach($xml->channel->item as $item) {
- $date = (string) $item->pubDate;
- $link = (string) $item->link;
- $title = (string) $item->title;
- $content = (string) $item->description;
-
- $feed['items'][] = array(
- 'date' => strtotime($date),
- 'link' => $link,
- 'title' => $title,
- 'content' => $content,
- );
- }
- }
- if(empty($feed))
- return false;
-
- return $feed;
- }
-
- /**
- * Returns a string as alphanumerics delimited by underscores.
- * For example: "Devs: 1000 Ways to Improve Sales" becomes
- * "devs_1000_ways_to_improve_sales", which is suitable for
- * displaying in a URL of a blog, faq, etc.
- *
- * @param string $str
- * @return string
- */
- static function getStringAsURI($str) {
- $str = strtolower($str);
-
- // turn non [a-z, 0-9, _] into whitespace
- $str = preg_replace("/[^0-9a-z]/",' ',$str);
-
- // condense whitespace to a single underscore
- $str = preg_replace('/\s\s+/', ' ', $str);
- // replace spaces with underscore
- $str = str_replace(' ','_',$str);
- // remove a leading/trailing underscores
- $str = trim($str, '_');
-
- return $str;
- }
-
- /**
- * Takes a comma-separated value string and returns an array of tokens.
- * [TODO] Move to a FormHelper service?
- *
- * @param string $string
- * @return array
- */
- static function parseCsvString($string) {
- $tokens = explode(',', $string);
- if(!is_array($tokens))
- return array();
-
- foreach($tokens as $k => $v) {
- $tokens[$k] = trim($v);
- if(0==strlen($tokens[$k]))
- unset($tokens[$k]);
- }
-
- return $tokens;
- }
-
- /**
- * Clears any platform-level plugin caches.
- *
- */
- static function clearCache($one_cache=null) {
- $cache = self::getCacheService(); /* @var $cache _DevblocksCacheManager */
- if(!empty($one_cache)) {
- $cache->remove($one_cache);
-
- } else { // All
- $cache->remove(self::CACHE_ACL);
- $cache->remove(self::CACHE_PLUGINS);
- $cache->remove(self::CACHE_EVENT_POINTS);
- $cache->remove(self::CACHE_EVENTS);
- $cache->remove(self::CACHE_EXTENSIONS);
- $cache->remove(self::CACHE_POINTS);
- $cache->remove(self::CACHE_SETTINGS);
- $cache->remove(self::CACHE_TABLES);
- $cache->remove(_DevblocksClassLoadManager::CACHE_CLASS_MAP);
-
- // Clear all locale caches
- $langs = DAO_Translation::getDefinedLangCodes();
- if(is_array($langs) && !empty($langs))
- foreach($langs as $lang_code => $lang_name) {
- $cache->remove(self::CACHE_TAG_TRANSLATIONS . '_' . $lang_code);
- }
- }
- // Cache-specific 'after' actions
- switch($one_cache) {
- case self::CACHE_PLUGINS:
- case self::CACHE_EXTENSIONS:
- case NULL:
- self::getPluginRegistry();
- self::getExtensionRegistry();
- break;
- }
- }
- public static function loadClass($className) {
- $classloader = self::getClassLoaderService();
- return $classloader->loadClass($className);
- }
-
- public static function registerClasses($file,$classes=array()) {
- $classloader = self::getClassLoaderService();
- return $classloader->registerClasses($file,$classes);
- }
-
- public static function getStartTime() {
- return self::$start_time;
- }
-
- public static function getStartMemory() {
- return self::$start_memory;
- }
-
- public static function getStartPeakMemory() {
- return self::$start_peak_memory;
- }
-
- /**
- * @return resource $fp
- */
- public static function getTempFile() {
- // Generate a new temporary file
- $file_name = tempnam(APP_TEMP_PATH, 'tmp');
-
- // Open the file pointer
- $fp = fopen($file_name, "w+b");
-
- // Manually keep track of these temporary files
- self::$_tmp_files[intval($fp)] = $file_name;
- return $fp;
- }
-
- /**
- * @return resource $fp
- */
- public static function getTempFileInfo($fp) {
- // If we're asking about a specific temporary file
- if(!empty($fp)) {
- if(@isset(self::$_tmp_files[intval($fp)]))
- return self::$_tmp_files[intval($fp)];
- return false;
- }
- }
- /**
- * Checks whether the active database has any tables.
- *
- * @return boolean
- */
- static function isDatabaseEmpty() {
- $tables = self::getDatabaseTables();
- return empty($tables);
- }
-
- static function getDatabaseTables() {
- $cache = self::getCacheService();
- $tables = array();
-
- if(null === ($tables = $cache->load(self::CACHE_TABLES))) {
- $db = self::getDatabaseService();
-
- // Make sure the database connection is valid or error out.
- if(is_null($db) || !$db->isConnected())
- return array();
-
- $tables = $db->metaTables();
- $cache->save($tables, self::CACHE_TABLES);
- }
- return $tables;
- }
- /**
- * Checks to see if the application needs to patch
- *
- * @return boolean
- */
- static function versionConsistencyCheck() {
- $cache = DevblocksPlatform::getCacheService(); /* @var _DevblocksCacheManager $cache */
-
- if(null === ($build_cache = $cache->load("devblocks_app_build"))
- || $build_cache != APP_BUILD) {
-
- // If build changed, clear cache regardless of patch status
- // [TODO] We need to find a nicer way to not clear a shared memcached cluster when only one desk needs to
- $cache = DevblocksPlatform::getCacheService(); /* @var $cache _DevblocksCacheManager */
- $cache->clean();
-
- // Re-read manifests
- DevblocksPlatform::readPlugins();
-
- if(self::_needsToPatch()) {
- return false; // the update script will handle new caches
- } else {
- $cache->save(APP_BUILD, "devblocks_app_build");
- DAO_Translation::reloadPluginStrings(); // reload strings even without DB changes
- return true;
- }
- }
-
- return true;
- }
-
- /**
- * Enter description here...
- *
- * @return boolean
- */
- static private function _needsToPatch() {
- $plugins = DevblocksPlatform::getPluginRegistry();
-
- // First install or upgrade
- if(empty($plugins))
- return true;
- foreach($plugins as $plugin) { /* @var $plugin DevblocksPluginManifest */
- if($plugin->enabled) {
- foreach($plugin->getPatches() as $patch) { /* @var $patch DevblocksPatch */
- if(!$patch->hasRun())
- return true;
- }
- }
- }
-
- return false;
- }
-
- /**
- * Returns the list of extensions on a given extension point.
- *
- * @static
- * @param string $point
- * @return DevblocksExtensionManifest[]
- */
- static function getExtensions($point,$as_instances=false, $ignore_acl=false) {
- $results = array();
- $extensions = DevblocksPlatform::getExtensionRegistry($ignore_acl);
- if(is_array($extensions))
- foreach($extensions as $extension) { /* @var $extension DevblocksExtensionManifest */
- if($extension->point == $point) {
- $results[$extension->id] = ($as_instances) ? $extension->createInstance() : $extension;
- }
- }
- return $results;
- }
- /**
- * Returns the manifest of a given extension ID.
- *
- * @static
- * @param string $extension_id
- * @param boolean $as_instance
- * @return DevblocksExtensionManifest
- */
- static function getExtension($extension_id, $as_instance=false, $ignore_acl=false) {
- $result = null;
- $extensions = DevblocksPlatform::getExtensionRegistry($ignore_acl);
- if(is_array($extensions))
- foreach($extensions as $extension) { /* @var $extension DevblocksExtensionManifest */
- if($extension->id == $extension_id) {
- $result = $extension;
- break;
- }
- }
-
- if($as_instance && !is_null($result)) {
- return $result->createInstance();
- }
-
- return $result;
- }
- // static function getExtensionPoints() {
- // $cache = self::getCacheService();
- // if(null !== ($points = $cache->load(self::CACHE_POINTS)))
- // return $points;
- //
- // $extensions = DevblocksPlatform::getExtensionRegistry();
- // foreach($extensions as $extension) { /* @var $extension DevblocksExtensionManifest */
- // $point = $extension->point;
- // if(!isset($points[$point])) {
- // $p = new DevblocksExtensionPoint();
- // $p->id = $point;
- // $points[$point] = $p;
- // }
- //
- // $points[$point]->extensions[$extension->id] = $extension;
- // }
- //
- // $cache->save($points, self::CACHE_POINTS);
- // return $points;
- // }
- /**
- * Returns an array of all contributed extension manifests.
- *
- * @static
- * @return DevblocksExtensionManifest[]
- */
- static function getExtensionRegistry($ignore_acl=false) {
- $cache = self::getCacheService();
- static $acl_extensions = null;
-
- if(null === ($extensions = $cache->load(self::CACHE_EXTENSIONS))) {
- $db = DevblocksPlatform::getDatabaseService();
- if(is_null($db)) return;
-
- $prefix = (APP_DB_PREFIX != '') ? APP_DB_PREFIX.'_' : ''; // [TODO] Cleanup
-
- $sql = sprintf("SELECT e.id , e.plugin_id, e.point, e.pos, e.name , e.file , e.class, e.params ".
- "FROM %sextension e ".
- "INNER JOIN %splugin p ON (e.plugin_id=p.id) ".
- "WHERE p.enabled = 1 ".
- "ORDER BY e.id ASC, e.plugin_id ASC, e.pos ASC",
- $prefix,
- $prefix
- );
- $results = $db->GetArray($sql);
-
- foreach($results as $row) {
- $extension = new DevblocksExtensionManifest();
- $extension->id = $row['id'];
- $extension->plugin_id = $row['plugin_id'];
- $extension->point = $row['point'];
- $extension->name = $row['name'];
- $extension->file = $row['file'];
- $extension->class = $row['class'];
- $extension->params = @unserialize($row['params']);
-
- if(empty($extension->params))
- $extension->params = array();
- $extensions[$extension->id] = $extension;
- }
- $cache->save($extensions, self::CACHE_EXTENSIONS);
- $acl_extensions = null;
- }
-
- if(!$ignore_acl) {
- // If we don't have a cache in this request
- if(null == $acl_extensions) {
- // Check with an extension delegate if we have one
- if(class_exists(self::$extensionDelegate) && method_exists('DevblocksExtensionDelegate','shouldLoadExtension')) {
- if(is_array($extensions))
- foreach($extensions as $id => $extension) {
- // Ask the delegate if we should load the extension
- if(!call_user_func(array(self::$extensionDelegate,'shouldLoadExtension'),$extension))
- unset($extensions[$id]);
- }
- }
- // Cache for duration of request
- $acl_extensions = $extensions;
- } else {
- $extensions = $acl_extensions;
- }
- }
-
- return $extensions;
- }
- /**
- * @return DevblocksEventPoint[]
- */
- static function getEventPointRegistry() {
- $cache = self::getCacheService();
- if(null !== ($events = $cache->load(self::CACHE_EVENT_POINTS)))
- return $events;
- $events = array();
- $plugins = self::getPluginRegistry();
-
- // [JAS]: Event point hashing/caching
- if(is_array($plugins))
- foreach($plugins as $plugin) { /* @var $plugin DevblocksPluginManifest */
- $events = array_merge($events,$plugin->event_points);
- }
-
- $cache->save($events, self::CACHE_EVENT_POINTS);
- return $events;
- }
-
- /**
- * @return DevblocksAclPrivilege[]
- */
- static function getAclRegistry() {
- $cache = self::getCacheService();
- if(null !== ($acl = $cache->load(self::CACHE_ACL)))
- return $acl;
- $acl = array();
- $db = DevblocksPlatform::getDatabaseService();
- if(is_null($db)) return;
- //$plugins = self::getPluginRegistry();
- $prefix = (APP_DB_PREFIX != '') ? APP_DB_PREFIX.'_' : ''; // [TODO] Cleanup
- $sql = sprintf("SELECT a.id, a.plugin_id, a.label ".
- "FROM %sacl a ".
- "INNER JOIN %splugin p ON (a.plugin_id=p.id) ".
- "WHERE p.enabled = 1 ".
- "ORDER BY a.plugin_id, a.id ASC",
- $prefix,
- $prefix
- );
- $results = $db->GetArray($sql);
-
- foreach($results as $row) {
- $priv = new DevblocksAclPrivilege();
- $priv->id = $row['id'];
- $priv->plugin_id = $row['plugin_id'];
- $priv->label = $row['label'];
-
- $acl[$priv->id] = $priv;
- }
-
- $cache->save($acl, self::CACHE_ACL);
- return $acl;
- }
-
- static function getEventRegistry() {
- $cache = self::getCacheService();
- if(null !== ($events = $cache->load(self::CACHE_EVENTS)))
- return $events;
-
- $extensions = self::getExtensions('devblocks.listener.event',false,true);
- $events = array('*');
-
- // [JAS]: Event point hashing/caching
- if(is_array($extensions))
- foreach($extensions as $extension) { /* @var $extension DevblocksExtensionManifest */
- @$evts = $extension->params['events'][0];
-
- // Global listeners (every point)
- if(empty($evts) && !is_array($evts)) {
- $events['*'][] = $extension->id;
- continue;
- }
-
- if(is_array($evts))
- foreach(array_keys($evts) as $evt) {
- $events[$evt][] = $extension->id;
- }
- }
-
- $cache->save($events, self::CACHE_EVENTS);
- return $events;
- }
-
- /**
- * Returns an array of all contributed plugin manifests.
- *
- * @static
- * @return DevblocksPluginManifest[]
- */
- static function getPluginRegistry() {
- $cache = self::getCacheService();
- if(null !== ($plugins = $cache->load(self::CACHE_PLUGINS)))
- return $plugins;
- $db = DevblocksPlatform::getDatabaseService();
- if(is_null($db))
- return;
- $plugins = array();
-
- $prefix = (APP_DB_PREFIX != '') ? APP_DB_PREFIX.'_' : ''; // [TODO] Cleanup
- $sql = sprintf("SELECT p.* ".
- "FROM %splugin p ".
- "ORDER BY p.enabled DESC, p.name ASC ",
- $prefix
- );
- $results = $db->GetArray($sql);
- foreach($results as $row) {
- $plugin = new DevblocksPluginManifest();
- @$plugin->id = $row['id'];
- @$plugin->enabled = intval($row['enabled']);
- @$plugin->name = $row['name'];
- @$plugin->description = $row['description'];
- @$plugin->author = $row['author'];
- @$plugin->revision = intval($row['revision']);
- @$plugin->link = $row['link'];
- @$plugin->dir = $row['dir'];
- // JSON decode
- if(isset($row['manifest_cache_json'])
- && null != ($manifest_cache_json = $row['manifest_cache_json'])) {
- $plugin->manifest_cache = json_decode($manifest_cache_json, true);
- }
- if(file_exists(APP_PATH . DIRECTORY_SEPARATOR . $plugin->dir . DIRECTORY_SEPARATOR . 'plugin.xml'))
- $plugins[$plugin->id] = $plugin;
- }
- $sql = sprintf("SELECT p.id, p.name, p.params, p.plugin_id ".
- "FROM %sevent_point p ",
- $prefix
- );
- $results = $db->GetArray($sql);
- foreach($results as $row) {
- $point = new DevblocksEventPoint();
- $point->id = $row['id'];
- $point->name = $row['name'];
- $point->plugin_id = $row['plugin_id'];
-
- $params = $row['params'];
- $point->params = !empty($params) ? unserialize($params) : array();
- if(isset($plugins[$point->plugin_id])) {
- $plugins[$point->plugin_id]->event_points[$point->id] = $point;
- }
- }
-
- self::_sortPluginsByDependency($plugins);
-
- $cache->save($plugins, self::CACHE_PLUGINS);
- return $plugins;
- }
-
- static private function _sortPluginsByDependency(&$plugins) {
- $dependencies = array();
- $seen = array();
- $order = array();
-
- // Dependencies
- foreach($plugins as $plugin) {
- @$deps = $plugin->manifest_cache['dependencies'];
- $dependencies[$plugin->id] = is_array($deps) ? $deps : array();
- }
-
- foreach($plugins as $plugin)
- self::_recursiveDependency($plugin->id, $dependencies, $seen, $order);
- $original = $plugins;
- $plugins = array();
-
- foreach($order as $order_id) {
- $plugins[$order_id] = $original[$order_id];
- }
- }
- static private function _recursiveDependency($id, $deps, &$seen, &$order, $level=0) {
- if(isset($seen[$id]))
- return true;
-
- if(isset($deps[$id]) && !empty($deps[$id])) {
- foreach($deps[$id] as $dep) {
- if(!self::_recursiveDependency($dep, $deps, $seen, $order, ++$level))
- return false;
- }
- }
-
- if(!isset($seen[$id])) {
- $order[] = $id;
- $seen[$id] = true;
- }
-
- return true;
- }
-
- /**
- * Enter description here...
- *
- * @param string $id
- * @return DevblocksPluginManifest
- */
- static function getPlugin($id) {
- $plugins = DevblocksPlatform::getPluginRegistry();
- if(isset($plugins[$id]))
- return $plugins[$id];
-
- return null;
- }
- /**
- * Reads and caches manifests from the features + plugins directories.
- *
- * @static
- * @return DevblocksPluginManifest[]
- */
- static function readPlugins() {
- $scan_dirs = array(
- 'features',
- 'storage/plugins',
- );
-
- $plugins = array();
- // Devblocks
- if(null !== ($manifest = self::_readPluginManifest('libs/devblocks')))
- $plugin[] = $manifest;
-
- // Application
- if(is_array($scan_dirs))
- foreach($scan_dirs as $scan_dir) {
- $scan_path = APP_PATH . '/' . $scan_dir;
- if (is_dir($scan_path)) {
- if ($dh = opendir($scan_path)) {
- while (($file = readdir($dh)) !== false) {
- if($file=="." || $file == "..")
- continue;
-
- $plugin_path = $scan_path . '/' . $file;
- $rel_path = $scan_dir . '/' . $file;
-
- if(is_dir($plugin_path) && file_exists($plugin_path.'/plugin.xml')) {
- $manifest = self::_readPluginManifest($rel_path); /* @var $manifest DevblocksPluginManifest */
-
- if(null != $manifest) {
- $plugins[$manifest->id] = $manifest;
- }
- }
- }
- closedir($dh);
- }
- }
- }
-
- DevblocksPlatform::clearCache(DevblocksPlatform::CACHE_PLUGINS);
-
- return $plugins;
- }
-
- /**
- * @return _DevblocksPluginSettingsManager
- */
- static function getPluginSettingsService() {
- return _DevblocksPluginSettingsManager::getInstance();
- }
-
- static function getPluginSetting($plugin_id, $key, $default=null) {
- $settings = self::getPluginSettingsService();
- return $settings->get($plugin_id, $key, $default);
- }
-
- static function setPluginSetting($plugin_id, $key, $value) {
- $settings = self::getPluginSettingsService();
- return $settings->set($plugin_id, $key, $value);
- }
- /**
- * @return _DevblocksLogManager
- */
- static function getConsoleLog() {
- return _DevblocksLogManager::getConsoleLog();
- }
-
- /**
- * @return _DevblocksCacheManager
- */
- static function getCacheService() {
- return _DevblocksCacheManager::getInstance();
- }
-
- /**
- * Enter description here...
- *
- * @return _DevblocksDatabaseManager
- */
- static function getDatabaseService() {
- return _DevblocksDatabaseManager::getInstance();
- }
- /**
- * @return _DevblocksUrlManager
- */
- static function getUrlService() {
- return _DevblocksUrlManager::getInstance();
- }
- /**
- * @return _DevblocksEmailManager
- */
- static function getMailService() {
- return _DevblocksEmailManager::getInstance();
- }
- /**
- * @return _DevblocksEventManager
- */
- static function getEventService() {
- return _DevblocksEventManager::getInstance();
- }
-
- /**
- * @return DevblocksProxy
- */
- static function getProxyService() {
- return DevblocksProxy::getProxy();
- }
-
- /**
- * @return _DevblocksClassLoadManager
- */
- static function getClassLoaderService() {
- return _DevblocksClassLoadManager::getInstance();
- }
-
- /**
- * @return _DevblocksSessionManager
- */
- static function getSessionService() {
- return _DevblocksSessionManager::getInstance();
- }
-
- /**
- * @return _DevblocksOpenIDManager
- */
- static function getOpenIDService() {
- return _DevblocksOpenIDManager::getInstance();
- }
-
- /**
- * @return _DevblocksSearchEngineMysqlFulltext
- */
- static function getSearchService() {
- return _DevblocksSearchManager::getInstance();
- }
-
- /**
- * @param $profile_id | $extension_id, $options
- * @return Extension_DevblocksStorageEngine
- */
- static function getStorageService() {
- $args = func_get_args();
- if(empty($args))
- return false;
-
- $profile = $args[0];
- $params = array();
-
- // Handle $profile polymorphism
- if($profile instanceof Model_DevblocksStorageProfile) {
- $extension = $profile->extension_id;
- $params = $profile->params;
- } else if(is_numeric($profile)) {
- $storage_profile = DAO_DevblocksStorageProfile::get($profile);
- $extension = $storage_profile->extension_id;
- $params = $storage_profile->params;
- } else if(is_string($profile)) {
- $extension = $profile;
-
- if(isset($args[1]) && is_array($args[1]))
- $params = $args[1];
- }
-
- return _DevblocksStorageManager::getEngine($extension, $params);
- }
- /**
- * @return Smarty
- */
- static function getTemplateService() {
- return _DevblocksTemplateManager::getInstance();
- }
- /**
- *
- * @param string $set
- * @return DevblocksTemplate[]
- */
- static function getTemplates($set=null) {
- $templates = array();
- $plugins = self::getPluginRegistry();
-
- if(is_array($plugins))
- foreach($plugins as $plugin) {
- if(isset($plugin->manifest_cache['templates']) && is_array($plugin->manifest_cache['templates']))
- foreach($plugin->manifest_cache['templates'] as $tpl) {
- if(null === $set || 0 == strcasecmp($set, $tpl['set'])) {
- $template = new DevblocksTemplate();
- $template->plugin_id = $tpl['plugin_id'];
- $template->set = $tpl['set'];
- $template->path = $tpl['path'];
- $templates[] = $template;
- }
- }
- }
-
- return $templates;
- }
-
- /**
- * @return _DevblocksTemplateBuilder
- */
- static function getTemplateBuilder() {
- return _DevblocksTemplateBuilder::getInstance();
- }
- /**
- * @return _DevblocksDateManager
- */
- static function getDateService($datestamp=null) {
- return _DevblocksDateManager::getInstance();
- }
-
- static function setLocale($locale) {
- @setlocale(LC_ALL, $locale);
- self::$locale = $locale;
- }
-
- static function getLocale() {
- if(!empty(self::$locale))
- return self::$locale;
-
- return 'en_US';
- }
-
- /**
- * @return _DevblocksTranslationManager
- */
- static function getTranslationService() {
- static $languages = array();
- $locale = DevblocksPlatform::getLocale();
- // Registry
- if(isset($languages[$locale])) {
- return $languages[$locale];
- }
-
- $cache = self::getCacheService();
-
- if(null === ($map = $cache->load(self::CACHE_TAG_TRANSLATIONS.'_'.$locale))) { /* @var $cache _DevblocksCacheManager */
- $map = array();
- $map_en = DAO_Translation::getMapByLang('en_US');
- if(0 != strcasecmp('en_US', $locale))
- $map_loc = DAO_Translation::getMapByLang($locale);
-
- // Loop through the English string objects
- if(is_array($map_en))
- foreach($map_en as $string_id => $obj_string_en) {
- $string = '';
-
- // If we have a locale to check
- if(isset($map_loc) && is_array($map_loc)) {
- @$obj_string_loc = $map_loc[$string_id];
- @$string =
- (!empty($obj_string_loc->string_override))
- ? $obj_string_loc->string_override
- : $obj_string_loc->string_default;
- }
-
- // If we didn't hit, load the English default
- if(empty($string))
- @$string =
- (!empty($obj_string_en->string_override))
- ? $obj_string_en->string_override
- : $obj_string_en->string_default;
-
- // If we found any match
- if(!empty($string))
- $map[$string_id] = $string;
- }
- unset($obj_string_en);
- unset($obj_string_loc);
- unset($map_en);
- unset($map_loc);
-
- // Cache with tag (tag allows easy clean for multiple langs at once)
- $cache->save($map,self::CACHE_TAG_TRANSLATIONS.'_'.$locale);
- }
-
- $translate = _DevblocksTranslationManager::getInstance();
- $translate->addLocale($locale, $map);
- $translate->setLocale($locale);
-
- $languages[$locale] = $translate;
- return $translate;
- }
- /**
- * Enter description here...
- *
- * @return DevblocksHttpRequest
- */
- static function getHttpRequest() {
- return self::$request;
- }
- /**
- * @param DevblocksHttpRequest $request
- */
- static function setHttpRequest(DevblocksHttpRequest $request) {
- self::$request = $request;
- }
- /**
- * Enter description here...
- *
- * @return DevblocksHttpRequest
- */
- static function getHttpResponse() {
- return self::$response;
- }
- /**
- * @param DevblocksHttpResponse $response
- */
- static function setHttpResponse(DevblocksHttpResponse $response) {
- self::$response = $response;
- }
- /**
- * Initializes the plugin platform (paths, etc).
- *
- * @static
- * @return void
- */
- static function init() {
- self::$start_time = microtime(true);
- if(function_exists('memory_get_usage') && function_exists('memory_get_peak_usage')) {
- self::$start_memory = memory_get_usage();
- self::$start_peak_memory = memory_get_peak_usage();
- }
-
- // Encoding (mbstring)
- mb_internal_encoding(LANG_CHARSET_CODE);
-
- // [JAS] [MDF]: Automatically determine the relative webpath to Devblocks files
- @$proxyhost = $_SERVER['HTTP_DEVBLOCKSPROXYHOST'];
- @$proxybase = $_SERVER['HTTP_DEVBLOCKSPROXYBASE'];
-
- // App path (always backend)
-
- $app_self = $_SERVER["SCRIPT_NAME"];
-
- if(DEVBLOCKS_REWRITE) {
- $pos = strrpos($app_self,'/');
- $app_self = substr($app_self,0,$pos) . '/';
- } else {
- $pos = strrpos($app_self,'index.php');
- if(false === $pos) $pos = strrpos($app_self,'ajax.php');
- $app_self = substr($app_self,0,$pos);
- }
-
- // Context path (abstracted: proxies or backend)
-
- if(!empty($proxybase)) { // proxy
- $context_self = $proxybase . '/';
- } else { // non-proxy
- $context_self = $app_self;
- }
-
- @define('DEVBLOCKS_WEBPATH',$context_self);
- @define('DEVBLOCKS_APP_WEBPATH',$app_self);
-
- // Register shutdown function
- register_shutdown_function(array('DevblocksPlatform','shutdown'));
- }
-
- static function shutdown() {
- // Clean up any temporary files
- while(null != ($tmpfile = array_pop(self::$_tmp_files))) {
- @unlink($tmpfile);
- }
- }
- static function setExtensionDelegate($class) {
- if(!empty($class) && class_exists($class, true))
- self::$extensionDelegate = $class;
- }
-
- static function redirect(DevblocksHttpIO $httpIO) {
- $url_service = self::getUrlService();
- session_write_close();
- $url = $url_service->writeDevblocksHttpIO($httpIO, true);
- header('Location: '.$url);
- exit;
- }
- };
- abstract class DevblocksEngine {
- protected static $request = null;
- protected static $response = null;
-
- /**
- * Reads and caches a single manifest from a given plugin directory.
- *
- * @static
- * @private
- * @param string $dir
- * @return DevblocksPluginManifest
- */
- static protected function _readPluginManifest($rel_dir, $persist=true) {
- $manifest_file = APP_PATH . '/' . $rel_dir . '/plugin.xml';
-
- if(!file_exists($manifest_file))
- return NULL;
-
- $plugin = simplexml_load_file($manifest_file);
- $prefix = (APP_DB_PREFIX != '') ? APP_DB_PREFIX.'_' : ''; // [TODO] Cleanup
-
- $manifest = new DevblocksPluginManifest();
- $manifest->id = (string) $plugin->id;
- $manifest->dir = $rel_dir;
- $manifest->description = (string) $plugin->description;
- $manifest->author = (string) $plugin->author;
- $manifest->revision = (integer) $plugin->revision;
- $manifest->link = (string) $plugin->link;
- $manifest->name = (string) $plugin->name;
-
- // Dependencies
- if(isset($plugin->dependencies)) {
- if(isset($plugin->dependencies->require))
- foreach($plugin->dependencies->require as $eDependency) {
- $depends_on = (string) $eDependency['plugin_id'];
- $manifest->manifest_cache['dependencies'][] = $depends_on;
- }
- }
-
- // Patches
- if(isset($plugin->patches)) {
- if(isset($plugin->patches->patch))
- foreach($plugin->patches->patch as $ePatch) {
- $patch_version = (string) $ePatch['version'];
- $patch_revision = (string) $ePatch['revision'];
- $patch_file = (string) $ePatch['file'];
- $manifest->manifest_cache['patches'][] = array(
- 'version' => $patch_version,
- 'revision' => $patch_revision,
- 'file' => $patch_file,
- );
- }
- }
-
- // Templates
- if(isset($plugin->templates)) {
- foreach($plugin->templates as $eTemplates) {
- $template_set = (string) $eTemplates['set'];
-
- if(isset($eTemplates->template))
- foreach($eTemplates->template as $eTemplate) {
- $manifest->manifest_cache['templates'][] = array(
- 'plugin_id' => $manifest->id,
- 'set' => $template_set,
- 'path' => (string) $eTemplate['path'],
- );
- }
- }
- }
-
- // Image
- if(isset($plugin->image)) {
- $manifest->manifest_cache['plugin_image'] = (string) $plugin->image;
- }
-
- if(!$persist)
- return $manifest;
-
- $db = DevblocksPlatform::getDatabaseService();
- if(is_null($db))
- return;
-
- // Persist manifest
- if($db->GetOne(sprintf("SELECT id FROM ${prefix}plugin WHERE id = %s", $db->qstr($manifest->id)))) { // update
- $db->Execute(sprintf(
- "UPDATE ${prefix}plugin ".
- "SET name=%s,description=%s,author=%s,revision=%s,link=%s,dir=%s,manifest_cache_json=%s ".
- "WHERE id=%s",
- $db->qstr($manifest->name),
- $db->qstr($manifest->description),
- $db->qstr($manifest->author),
- $db->qstr($manifest->revision),
- $db->qstr($manifest->link),
- $db->qstr($manifest->dir),
- $db->qstr(json_encode($manifest->manifest_cache)),
- $db->qstr($manifest->id)
- ));
-
- } else { // insert
- $enabled = ('devblocks.core'==$manifest->id) ? 1 : 0;
- $db->Execute(sprintf(
- "INSERT INTO ${prefix}plugin (id,enabled,name,description,author,revision,link,dir,manifest_cache_json) ".
- "VALUES (%s,%d,%s,%s,%s,%s,%s,%s,%s)",
- $db->qstr($manifest->id),
- $enabled,
- $db->qstr($manifest->name),
- $db->qstr($manifest->description),
- $db->qstr($manifest->author),
- $db->qstr($manifest->revision),
- $db->qstr($manifest->link),
- $db->qstr($manifest->dir),
- $db->qstr(json_encode($manifest->manifest_cache))
- ));
- }
-
- // Class Loader
- if(isset($plugin->class_loader->file)) {
- foreach($plugin->class_loader->file as $eFile) {
- @$sFilePath = (string) $eFile['path'];
- $manifest->class_loader[$sFilePath] = array();
-
- if(isset($eFile->class))
- foreach($eFile->class as $eClass) {
- @$sClassName = (string) $eClass['name'];
- $manifest->class_loader[$sFilePath][] = $sClassName;
- }
- }
- }
-
- // Routing
- if(isset($plugin->uri_routing->uri)) {
- foreach($plugin->uri_routing->uri as $eUri) {
- @$sUriName = (string) $eUri['name'];
- @$sController = (string) $eUri['controller'];
- $manifest->uri_routing[$sUriName] = $sController;
- }
- }
-
- // ACL
- if(isset($plugin->acl->priv)) {
- foreach($plugin->acl->priv as $ePriv) {
- @$sId = (string) $ePriv['id'];
- @$sLabel = (string) $ePriv['label'];
-
- if(empty($sId) || empty($sLabel))
- continue;
-
- $priv = new DevblocksAclPrivilege();
- $priv->id = $sId;
- $priv->plugin_id = $manifest->id;
- $priv->label = $sLabel;
-
- $manifest->acl_privs[$priv->id] = $priv;
- }
- asort($manifest->acl_privs);
- }
-
- // Event points
- if(isset($plugin->event_points->event)) {
- foreach($plugin->event_points->event as $eEvent) {
- $sId = (string) $eEvent['id'];
- $sName = (string) $eEvent->name;
-
- if(empty($sId) || empty($sName))
- continue;
-
- $point = new DevblocksEventPoint();
- $point->id = $sId;
- $point->plugin_id = $plugin->id;
- $point->name = $sName;
- $point->params = array();
-
- if(isset($eEvent->param)) {
- foreach($eEvent->param as $eParam) {
- $key = (string) $eParam['key'];
- $val = (string) $eParam['value'];
- $point->param[$key] = $val;
- }
- }
-
- $manifest->event_points[] = $point;
- }
- }
-
- // Extensions
- if(isset($plugin->extensions->extension)) {
- foreach($plugin->extensions->extension as $eExtension) {
- $sId = (string) $eExtension->id;
- $sName = (string) $eExtension->name;
-
- if(empty($sId) || empty($sName))
- continue;
-
- $extension = new DevblocksExtensionManifest();
-
- $extension->id = $sId;
- $extension->plugin_id = $manifest->id;
- $extension->point = (string) $eExtension['point'];
- $extension->name = $sName;
- $extension->file = (string) $eExtension->class->file;
- $extension->class = (string) $eExtension->class->name;
-
- if(isset($eExtension->params->param)) {
- foreach($eExtension->params->param as $eParam) {
- $key = (string) $eParam['key'];
- if(isset($eParam->value)) {
- // [JSJ]: If there is a child of the param tag named value, then this
- // param has multiple values and thus we need to grab them all.
- foreach($eParam->value as $eValue) {
- // [JSJ]: If there is a child named data, then this is a complex structure
- if(isset($eValue->data)) {
- $value = array();
- foreach($eValue->data as $eData) {
- $key2 = (string) $eData['key'];
- if(isset($eData['value'])) {
- $value[$key2] = (string) $eData['value'];
- } else {
- $value[$key2] = (string) $eData;
- }
- }
- }
- else {
- // [JSJ]: Else, just grab the value and use it
- $value = (string) $eValue;
- }
- $extension->params[$key][] = $value;
- unset($value); // Just to be extra safe
- }
- }
- else {
- // [JSJ]: Otherwise, we grab the single value from the params value attribute.
- $extension->params[$key] = (string) $eParam['value'];
- }
- }
- }
-
- $manifest->extensions[] = $extension;
- }
- }
- // [JAS]: Extension caching
- $new_extensions = array();
- if(is_array($manifest->extensions))
- foreach($manifest->extensions as $pos => $extension) { /* @var $extension DevblocksExtensionManifest */
- $db->Execute(sprintf(
- "REPLACE INTO ${prefix}extension (id,plugin_id,point,pos,name,file,class,params) ".
- "VALUES (%s,%s,%s,%d,%s,%s,%s,%s)",
- $db->qstr($extension->id),
- $db->qstr($extension->plugin_id),
- $db->qstr($extension->point),
- $pos,
- $db->qstr($extension->name),
- $db->qstr($extension->file),
- $db->qstr($extension->class),
- $db->qstr(serialize($extension->params))
- ));
-
- $new_extensions[$extension->id] = true;
- }
-
- /*
- * Compare our loaded XML manifest to the DB manifest cache and invalidate
- * the cache for extensions that are no longer in the XML.
- */
- $sql = sprintf("SELECT id FROM %sextension WHERE plugin_id = %s",
- $prefix,
- $db->qstr($plugin->id)
- );
- $results = $db->GetArray($sql);
- foreach($results as $row) {
- $plugin_ext_id = $row['id'];
- if(!isset($new_extensions[$plugin_ext_id]))
- DAO_Platform::deleteExtension($plugin_ext_id);
- }
-
- // Class loader cache
- $db->Execute(sprintf("DELETE FROM %sclass_loader WHERE plugin_id = %s",$prefix,$db->qstr($plugin->id)));
- if(is_array($manifest->class_loader))
- foreach($manifest->class_loader as $file_path => $classes) {
- if(is_array($classes) && !empty($classes))
- foreach($classes as $class)
- $db->Execute(sprintf(
- "REPLACE INTO ${prefix}class_loader (class,plugin_id,rel_path) ".
- "VALUES (%s,%s,%s)",
- $db->qstr($class),
- $db->qstr($manifest->id),
- $db->qstr($file_path)
- ));
- }
-
- // URI routing cache
- $db->Execute(sprintf("DELETE FROM %suri_routing WHERE plugin_id = %s",$prefix,$db->qstr($plugin->id)));
- if(is_array($manifest->uri_routing))
- foreach($manifest->uri_routing as $uri => $controller_id) {
- $db->Execute(sprintf(
- "REPLACE INTO ${prefix}uri_routing (uri,plugin_id,controller_id) ".
- "VALUES (%s,%s,%s)",
- $db->qstr($uri),
- $db->qstr($manifest->id),
- $db->qstr($controller_id)
- ));
- }
- // ACL caching
- $db->Execute(sprintf("DELETE FROM %sacl WHERE plugin_id = %s",$prefix,$db->qstr($plugin->id)));
- if(is_array($manifest->acl_privs))
- foreach($manifest->acl_privs as $priv) { /* @var $priv DevblocksAclPrivilege */
- $db->Execute(sprintf(
- "REPLACE INTO ${prefix}acl (id,plugin_id,label) ".
- "VALUES (%s,%s,%s)",
- $db->qstr($priv->id),
- $db->qstr($priv->plugin_id),
- $db->qstr($priv->label)
- ));
- }
-
- // [JAS]: Event point caching
- if(is_array($manifest->event_points))
- foreach($manifest->event_points as $event) { /* @var $event DevblocksEventPoint */
- $db->Execute(sprintf(
- "REPLACE INTO ${prefix}event_point (id,plugin_id,name,params) ".
- "VALUES (%s,%s,%s,%s)",
- $db->qstr($event->id),
- $db->qstr($event->plugin_id),
- $db->qstr($event->name),
- $db->qstr(serialize($event->params))
- ));
- }
-
- return $manifest;
- }
-
- static function getWebPath() {
- $location = "";
-
- // Read the relative URL into an array
- if(isset($_SERVER['HTTP_X_REWRITE_URL'])) { // IIS Rewrite
- $location = $_SERVER['HTTP_X_REWRITE_URL'];
- } elseif(isset($_SERVER['REQUEST_URI'])) { // Apache
- $location = $_SERVER['REQUEST_URI'];
- } elseif(isset($_SERVER['REDIRECT_URL'])) { // Apache mod_rewrite (breaks on CGI)
- $location = $_SERVER['REDIRECT_URL'];
- } elseif(isset($_SERVER['ORIG_PATH_INFO'])) { // IIS + CGI
- $location = $_SERVER['ORIG_PATH_INFO'];
- }
-
- return $location;
- }
-
- /**
- * Reads the HTTP Request object.
- *
- * @return DevblocksHttpRequest
- */
- static function readRequest() {
- $url = DevblocksPlatform::getUrlService();
- $location = self::getWebPath();
-
- $parts = $url->parseURL($location);
-
- // Add any query string arguments (?arg=value&arg=value)
- @$query = $_SERVER['QUERY_STRING'];
- $queryArgs = $url->parseQueryString($query);
-
- if(empty($parts)) {
- // Overrides (Form POST, etc.)
- // Controller (GET has precedence over POST)
- if(isset($_GET['c'])) {
- @$uri = DevblocksPlatform::importGPC($_GET['c']); // extension
- } elseif (isset($_POST['c'])) {
- @$uri = DevblocksPlatform::importGPC($_POST['c']); // extension
- }
- if(!empty($uri)) $parts[] = DevblocksPlatform::strAlphaNum($uri);
- // Action (GET has precedence over POST)
- if(isset($_GET['a'])) {
- @$listener = DevblocksPlatform::importGPC($_GET['a']); // listener
- } elseif (isset($_POST['a'])) {
- @$listener = DevblocksPlatform::importGPC($_POST['a']); // listener
- }
- if(!empty($listener)) $parts[] = DevblocksPlatform::strAlphaNum($listener);
- }
-
- // Controller XSS security (alphanum only)
- if(isset($parts[0])) {
- $parts[0] = DevblocksPlatform::strAlphaNum($parts[0]);
- }
-
- // Resource / Proxy
- /*
- * [TODO] Run this code through another audit. Is it worth a tiny hit per resource
- * to verify the plugin matches exactly in the DB? If so, make sure we cache the
- * resulting file.
- *
- * [TODO] Make this a controller
- */
- $path = $parts;
- switch(array_shift($path)) {
- case "resource":
- $plugin_id = array_shift($path);
- if(null == ($plugin = DevblocksPlatform::getPlugin($plugin_id)))
- break;
-
- $file = implode(DIRECTORY_SEPARATOR, $path); // combine path
- $dir = APP_PATH . '/' . $plugin->dir . '/' . 'resources';
- if(!is_dir($dir)) die(""); // basedir Security
- $resource = $dir . '/' . $file;
- if(0 != strstr($dir,$resource)) die("");
- $ext = @array_pop(explode('.', $resource));
- if(!is_file($resource) || 'php' == $ext) die(""); // extension security
- // Caching
- switch($ext) {
- case 'css':
- case 'gif':
- case 'jpg':
- case 'js':
- case 'png':
- header('Cache-control: max-age=604800', true); // 1 wk // , must-revalidate
- header('Expires: ' . gmdate('D, d M Y H:i:s',time()+604800) . ' GMT'); // 1 wk
- break;
- }
-
- switch($ext) {
- case 'css':
- header('Content-type: text/css;');
- break;
- case 'gif':
- header('Content-type: image/gif;');
- break;
- case 'jpeg':
- case 'jpg':
- header('Content-type: image/jpeg;');
- break;
- case 'js':
- header('Content-type: text/javascript;');
- break;
- case 'png':
- header('Content-type: image/png;');
- break;
- case 'xml':
- header('Content-type: text/xml;');
- break;
- }
-
- $out = file_get_contents($resource, false);
-
- // Pass through
- if($out) {
- header('Content-Length: '. strlen($out));
- echo $out;
- }
-
- exit;
- break;
-
- default:
- break;
- …
Large files files are truncated, but you can click here to view the full file