00001 <?php 00002 /* 00003 * Nucleus: PHP/MySQL Weblog CMS (http://nucleuscms.org/) 00004 * Copyright (C) 2002-2007 The Nucleus Group 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * (see nucleus/documentation/index.html#license for more info) 00011 */ 00026 class MANAGER { 00027 00036 var $items; 00037 var $blogs; 00038 var $plugins; 00039 var $karma; 00040 var $templates; 00041 var $members; 00042 00049 var $cachedInfo; 00050 00058 var $subscriptions; 00059 00066 function &instance() { 00067 static $instance = array(); 00068 if (empty($instance)) { 00069 $instance[0] =& new MANAGER(); 00070 } 00071 return $instance[0]; 00072 } 00073 00077 function MANAGER() { 00078 $this->items = array(); 00079 $this->blogs = array(); 00080 $this->plugins = array(); 00081 $this->karma = array(); 00082 $this->parserPrefs = array(); 00083 $this->cachedInfo = array(); 00084 } 00085 00091 function &getItem($itemid, $allowdraft, $allowfuture) { 00092 $item =& $this->items[$itemid]; 00093 00094 // check the draft and future rules if the item was already cached 00095 if ($item) { 00096 if ((!$allowdraft) && ($item['draft'])) 00097 return 0; 00098 00099 $blog =& $this->getBlog(getBlogIDFromItemID($itemid)); 00100 if ((!$allowfuture) && ($item['timestamp'] > $blog->getCorrectTime())) 00101 return 0; 00102 } 00103 if (!$item) { 00104 // load class if needed 00105 $this->loadClass('ITEM'); 00106 // load item object 00107 $item = ITEM::getitem($itemid, $allowdraft, $allowfuture); 00108 $this->items[$itemid] = $item; 00109 } 00110 return $item; 00111 } 00112 00116 function loadClass($name) { 00117 $this->_loadClass($name, $name . '.php'); 00118 } 00119 00123 function existsItem($id,$future,$draft) { 00124 $this->_loadClass('ITEM','ITEM.php'); 00125 return ITEM::exists($id,$future,$draft); 00126 } 00127 00131 function existsCategory($id) { 00132 return (quickQuery('SELECT COUNT(*) as result FROM '.sql_table('category').' WHERE catid='.intval($id)) > 0); 00133 } 00134 00135 function &getBlog($blogid) { 00136 $blog =& $this->blogs[$blogid]; 00137 00138 if (!$blog) { 00139 // load class if needed 00140 $this->_loadClass('BLOG','BLOG.php'); 00141 // load blog object 00142 $blog =& new BLOG($blogid); 00143 $this->blogs[$blogid] =& $blog; 00144 } 00145 return $blog; 00146 } 00147 00148 function existsBlog($name) { 00149 $this->_loadClass('BLOG','BLOG.php'); 00150 return BLOG::exists($name); 00151 } 00152 00153 function existsBlogID($id) { 00154 $this->_loadClass('BLOG','BLOG.php'); 00155 return BLOG::existsID($id); 00156 } 00157 00161 function &getTemplate($templateName) { 00162 $template =& $this->templates[$templateName]; 00163 00164 if (!$template) { 00165 $template = TEMPLATE::read($templateName); 00166 $this->templates[$templateName] =& $template; 00167 } 00168 return $template; 00169 } 00170 00174 function &getKarma($itemid) { 00175 $karma =& $this->karma[$itemid]; 00176 00177 if (!$karma) { 00178 // load class if needed 00179 $this->_loadClass('KARMA','KARMA.php'); 00180 // create KARMA object 00181 $karma =& new KARMA($itemid); 00182 $this->karma[$itemid] =& $karma; 00183 } 00184 return $karma; 00185 } 00186 00190 function &getMember($memberid) { 00191 $mem =& $this->members[$memberid]; 00192 00193 if (!$mem) { 00194 // load class if needed 00195 $this->_loadClass('MEMBER','MEMBER.php'); 00196 // create MEMBER object 00197 $mem =& MEMBER::createFromID($memberid); 00198 $this->members[$memberid] =& $mem; 00199 } 00200 return $mem; 00201 } 00202 00206 function setParserProperty($name, $value) { 00207 $this->parserPrefs[$name] = $value; 00208 } 00209 function getParserProperty($name) { 00210 return $this->parserPrefs[$name]; 00211 } 00212 00216 function _loadClass($name, $filename) { 00217 if (!class_exists($name)) { 00218 global $DIR_LIBS; 00219 include($DIR_LIBS . $filename); 00220 } 00221 } 00222 00223 function _loadPlugin($name) { 00224 if (!class_exists($name)) { 00225 global $DIR_PLUGINS; 00226 00227 $fileName = $DIR_PLUGINS . $name . '.php'; 00228 00229 if (!file_exists($fileName)) 00230 { 00231 ACTIONLOG::add(WARNING, 'Plugin ' . $name . ' was not loaded (File not found)'); 00232 return 0; 00233 } 00234 00235 // load plugin 00236 include($fileName); 00237 00238 // check if class exists (avoid errors in eval'd code) 00239 if (!class_exists($name)) 00240 { 00241 ACTIONLOG::add(WARNING, 'Plugin ' . $name . ' was not loaded (Class not found in file, possible parse error)'); 00242 return 0; 00243 } 00244 00245 // add to plugin array 00246 eval('$this->plugins[$name] =& new ' . $name . '();'); 00247 00248 // get plugid 00249 $this->plugins[$name]->plugid = $this->getPidFromName($name); 00250 00251 // unload plugin if a prefix is used and the plugin cannot handle this^ 00252 global $MYSQL_PREFIX; 00253 if (($MYSQL_PREFIX != '') && !$this->plugins[$name]->supportsFeature('SqlTablePrefix')) 00254 { 00255 unset($this->plugins[$name]); 00256 ACTIONLOG::add(WARNING, 'Plugin ' . $name . ' was not loaded (does not support SqlTablePrefix)'); 00257 return 0; 00258 } 00259 00260 // call init method 00261 $this->plugins[$name]->init(); 00262 00263 } 00264 } 00265 00266 function &getPlugin($name) { 00267 $plugin =& $this->plugins[$name]; 00268 00269 if (!$plugin) { 00270 // load class if needed 00271 $this->_loadPlugin($name); 00272 $plugin =& $this->plugins[$name]; 00273 } 00274 return $plugin; 00275 } 00276 00280 function &pluginLoaded($name) { 00281 $plugin =& $this->plugins[$name]; 00282 return $plugin; 00283 } 00284 function &pidLoaded($pid) { 00285 $plugin=false; 00286 reset($this->plugins); 00287 while (list($name) = each($this->plugins)) { 00288 if ($pid!=$this->plugins[$name]->getId()) continue; 00289 $plugin= & $this->plugins[$name]; 00290 break; 00291 } 00292 return $plugin; 00293 } 00294 00298 function pluginInstalled($name) { 00299 $this->_initCacheInfo('installedPlugins'); 00300 return ($this->getPidFromName($name) != -1); 00301 } 00302 function pidInstalled($pid) { 00303 $this->_initCacheInfo('installedPlugins'); 00304 return ($this->cachedInfo['installedPlugins'][$pid] != ''); 00305 } 00306 function getPidFromName($name) { 00307 $this->_initCacheInfo('installedPlugins'); 00308 foreach ($this->cachedInfo['installedPlugins'] as $pid => $pfile) 00309 { 00310 if ($pfile == $name) 00311 return $pid; 00312 } 00313 return -1; 00314 } 00315 function clearCachedInfo($what) { 00316 unset($this->cachedInfo[$what]); 00317 } 00318 00322 function _initCacheInfo($what) 00323 { 00324 if (isset($this->cachedInfo[$what]) && is_array($this->cachedInfo[$what])) 00325 return; 00326 switch ($what) 00327 { 00328 // 'installedPlugins' = array ($pid => $name) 00329 case 'installedPlugins': 00330 $this->cachedInfo['installedPlugins'] = array(); 00331 $res = sql_query('SELECT pid, pfile FROM ' . sql_table('plugin')); 00332 while ($o = mysql_fetch_object($res)) 00333 { 00334 $this->cachedInfo['installedPlugins'][$o->pid] = $o->pfile; 00335 } 00336 break; 00337 } 00338 } 00339 00352 function notify($eventName, $data) { 00353 // load subscription list if needed 00354 if (!is_array($this->subscriptions)) 00355 $this->_loadSubscriptions(); 00356 00357 00358 // get listening objects 00359 $listeners = false; 00360 if (isset($this->subscriptions[$eventName])) { 00361 $listeners = $this->subscriptions[$eventName]; 00362 } 00363 00364 // notify all of them 00365 if (is_array($listeners)) { 00366 foreach($listeners as $listener) { 00367 // load class if needed 00368 $this->_loadPlugin($listener); 00369 // do notify (if method exists) 00370 if (method_exists($this->plugins[$listener], 'event_' . $eventName)) 00371 call_user_func(array(&$this->plugins[$listener],'event_' . $eventName), $data); 00372 } 00373 } 00374 00375 } 00376 00380 function _loadSubscriptions() { 00381 // initialize as array 00382 $this->subscriptions = array(); 00383 00384 $res = sql_query('SELECT p.pfile as pfile, e.event as event FROM '.sql_table('plugin_event').' as e, '.sql_table('plugin').' as p WHERE e.pid=p.pid ORDER BY p.porder ASC'); 00385 while ($o = mysql_fetch_object($res)) { 00386 $pluginName = $o->pfile; 00387 $eventName = $o->event; 00388 $this->subscriptions[$eventName][] = $pluginName; 00389 } 00390 00391 } 00392 00393 /* 00394 Ticket functions. These are uses by the admin area to make it impossible to simulate certain GET/POST 00395 requests. tickets are user specific 00396 */ 00397 00398 var $currentRequestTicket = ''; 00399 00403 function addTicketToUrl($url) 00404 { 00405 $ticketCode = 'ticket=' . $this->_generateTicket(); 00406 if (strstr($url, '?')) 00407 return $url . '&' . $ticketCode; 00408 else 00409 return $url . '?' . $ticketCode; 00410 } 00411 00415 function addTicketHidden() 00416 { 00417 $ticket = $this->_generateTicket(); 00418 00419 echo '<input type="hidden" name="ticket" value="', htmlspecialchars($ticket), '" />'; 00420 } 00421 00426 function getNewTicket() 00427 { 00428 $this->currentRequestTicket = ''; 00429 return $this->_generateTicket(); 00430 } 00431 00435 function checkTicket() 00436 { 00437 global $member; 00438 00439 // get ticket from request 00440 $ticket = requestVar('ticket'); 00441 00442 // no ticket -> don't allow 00443 if ($ticket == '') 00444 return false; 00445 00446 // remove expired tickets first 00447 $this->_cleanUpExpiredTickets(); 00448 00449 // get member id 00450 if (!$member->isLoggedIn()) 00451 $memberId = -1; 00452 else 00453 $memberId = $member->getID(); 00454 00455 // check if ticket is a valid one 00456 $query = 'SELECT COUNT(*) as result FROM ' . sql_table('tickets') . ' WHERE member=' . intval($memberId). ' and ticket=\''.addslashes($ticket).'\''; 00457 if (quickQuery($query) == 1) 00458 { 00459 // [in the original implementation, the checked ticket was deleted. This would lead to invalid 00460 // tickets when using the browsers back button and clicking another link/form 00461 // leaving the keys in the database is not a real problem, since they're member-specific and 00462 // only valid for a period of one hour 00463 // ] 00464 // sql_query('DELETE FROM '.sql_table('tickets').' WHERE member=' . intval($memberId). ' and ticket=\''.addslashes($ticket).'\''); 00465 return true; 00466 } else { 00467 // not a valid ticket 00468 return false; 00469 } 00470 00471 } 00472 00476 function _cleanUpExpiredTickets() 00477 { 00478 // remove tickets older than 1 hour 00479 $oldTime = time() - 60 * 60; 00480 $query = 'DELETE FROM ' . sql_table('tickets'). ' WHERE ctime < \'' . date('Y-m-d H:i:s',$oldTime) .'\''; 00481 sql_query($query); 00482 } 00483 00487 function _generateTicket() 00488 { 00489 if ($this->currentRequestTicket == '') 00490 { 00491 // generate new ticket (only one ticket will be generated per page request) 00492 // and store in database 00493 global $member; 00494 // get member id 00495 if (!$member->isLoggedIn()) 00496 $memberId = -1; 00497 else 00498 $memberId = $member->getID(); 00499 00500 $ok = false; 00501 while (!$ok) 00502 { 00503 // generate a random token 00504 srand((double)microtime()*1000000); 00505 $ticket = md5(uniqid(rand(), true)); 00506 00507 // add in database as non-active 00508 $query = 'INSERT INTO ' . sql_table('tickets') . ' (ticket, member, ctime) '; 00509 $query .= 'VALUES (\'' . addslashes($ticket). '\', \'' . intval($memberId). '\', \'' . date('Y-m-d H:i:s',time()) . '\')'; 00510 if (sql_query($query)) 00511 $ok = true; 00512 } 00513 00514 $this->currentRequestTicket = $ticket; 00515 } 00516 return $this->currentRequestTicket; 00517 } 00518 00519 } 00520 00521 ?>