OSDN Git Service

translated by kitsune.info
[nucleus-jp/nucleus-jp-ancient.git] / euc / nucleus / libs / globalfunctions.php
1 <?php\r
2 \r
3 /**\r
4   * Nucleus: PHP/MySQL Weblog CMS (http://nucleuscms.org/)\r
5   * Copyright (C) 2002-2004 The Nucleus Group\r
6   *\r
7   * This program is free software; you can redistribute it and/or\r
8   * modify it under the terms of the GNU General Public License\r
9   * as published by the Free Software Foundation; either version 2\r
10   * of the License, or (at your option) any later version.\r
11   * (see nucleus/documentation/index.html#license for more info)\r
12   *\r
13   */\r
14 \r
15 // needed if we include globalfunctions from install.php\r
16 global $nucleus, $CONF, $DIR_LIBS, $DIR_LANG, $manager, $member; \r
17 \r
18 \r
19 checkVars(array('nucleus', 'CONF', 'DIR_LIBS', 'MYSQL_HOST', 'MYSQL_USER', 'MYSQL_PASSWORD', 'MYSQL_DATABASE', 'DIR_LANG', 'DIR_PLUGINS'));\r
20 \r
21 $CONF['debug'] = 0;\r
22 \r
23 $nucleus['version'] = 'v3.15';\r
24 if (getNucleusPatchLevel() > 0)\r
25 {\r
26         $nucleus['version'] .= '/' . getNucleusPatchLevel();\r
27 }\r
28 \r
29 /*\r
30         Indicates when Nucleus should display startup errors. Set to 1 if you want\r
31         the error enabled (default), false otherwise\r
32 \r
33         alertOnHeadersSent\r
34                 Displays an error when visiting a public Nucleus page and headers have\r
35                 been sent out to early. This usually indicates an error in either a\r
36                 configuration file or a language file, and could cause Nucleus to\r
37                 malfunction\r
38         alertOnSecurityRisk\r
39                 Displays an error only when visiting the admin area, and when one or\r
40                 more of the installation files (install.php, install.sql, upgrades/\r
41                 directory) are still on the server.\r
42 */\r
43 $CONF['alertOnHeadersSent'] = 1;\r
44 $CONF['alertOnSecurityRisk'] = 1;\r
45 \r
46 /**\r
47   * returns the currently used version (100 = 1.00, 101 = 1.01, etc...)\r
48   */\r
49 function getNucleusVersion() {\r
50         return 315;\r
51 }\r
52 \r
53 /**\r
54  * power users can install patches in between nucleus releases. These patches\r
55  * usually add new functionality in the plugin API and allow those to\r
56  * be tested without having to install CVS.\r
57  */\r
58 function getNucleusPatchLevel() {\r
59         return 0;\r
60 }\r
61 \r
62 \r
63 if ($CONF['debug']) {\r
64         error_reporting(E_ALL & ~E_NOTICE);     // report almost all errors!\r
65                                                                                 // (no uninitialized vars and such)\r
66 } else {\r
67         error_reporting(E_ERROR | E_WARNING | E_PARSE);\r
68 }\r
69 \r
70 // we will use postVar, getVar, ... methods instead of HTTP_GET_VARS or _GET\r
71 if ($CONF['installscript']!=1){ // vars were already included in install.php\r
72   if (phpversion() >= '4.1.0')\r
73           include_once($DIR_LIBS . 'vars4.1.0.php');\r
74   else\r
75           include_once($DIR_LIBS . 'vars4.0.6.php');\r
76 }\r
77 \r
78 function intPostVar($name) { return intval(postVar($name));}\r
79 function intGetVar($name) { return intval(getVar($name));}\r
80 function intRequestVar($name) { return intval(requestVar($name)); }\r
81 function intCookieVar($name) { return intval(cookieVar($name)); }\r
82 \r
83 // get all variables that can come from the request and put them in the global scope\r
84 $blogid                 = requestVar('blogid');\r
85 $itemid                 = intRequestVar('itemid');\r
86 $catid                  = intRequestVar('catid');\r
87 $skinid                 = requestVar('skinid');\r
88 $memberid               = requestVar('memberid');\r
89 $archivelist    = requestVar('archivelist');\r
90 $imagepopup             = requestVar('imagepopup');\r
91 $archive                = requestVar('archive');\r
92 $query                  = requestVar('query');\r
93 $highlight              = requestVar('highlight');\r
94 $amount                 = requestVar('amount');\r
95 $action                 = requestVar('action');\r
96 $nextaction             = requestVar('nextaction');\r
97 $maxresults     = requestVar('maxresults');\r
98 $startpos       = intRequestVar('startpos');\r
99 $errormessage   = '';\r
100 $error                  = '';\r
101 \r
102 if (!headers_sent())\r
103         header('Generator: Nucleus ' . $nucleus['version']);\r
104 \r
105 // include core classes that are needed for login & plugin handling\r
106 include($DIR_LIBS . 'MEMBER.php');\r
107 include($DIR_LIBS . 'ACTIONLOG.php');\r
108 include($DIR_LIBS . 'MANAGER.php');\r
109 include($DIR_LIBS . 'PLUGIN.php');\r
110 \r
111 $manager =& MANAGER::instance();\r
112 \r
113 // make sure there's no unnecessary escaping:\r
114 set_magic_quotes_runtime(0);\r
115 \r
116 // only needed when updating logs\r
117 if ($CONF['UsingAdminArea']) {\r
118         include($DIR_LIBS . 'xmlrpc.inc.php');  // XML-RPC client classes\r
119         include_once($DIR_LIBS . 'ADMIN.php');\r
120 }\r
121 \r
122 \r
123 // connect to sql\r
124 sql_connect();\r
125 \r
126 // makes sure database connection gets closed on script termination\r
127 register_shutdown_function('sql_disconnect');\r
128 \r
129 // read config\r
130 getConfig();\r
131 \r
132 // automatically use simpler toolbar for mozilla\r
133 if (($CONF['DisableJsTools'] == 0) && strstr(serverVar('HTTP_USER_AGENT'),'Mozilla/5.0') && strstr(serverVar('HTTP_USER_AGENT'),'Gecko'))\r
134         $CONF['DisableJsTools'] = 2;\r
135 \r
136 // login if cookies set\r
137 \r
138 $member = new MEMBER();\r
139 \r
140 // login/logout when required or renew cookies\r
141 if ($action == 'login') {\r
142         // Form Authentication\r
143         $login  = postVar('login');\r
144         $pw     = postVar('password');\r
145         $shared = intPostVar('shared'); // shared computer or not\r
146 \r
147         if ($member->login($login,$pw)) {\r
148 \r
149                 $member->newCookieKey();\r
150                 $member->setCookies($shared);\r
151 \r
152                 // allows direct access to parts of the admin area after logging in\r
153                 if ($nextaction)\r
154                         $action = $nextaction;\r
155 \r
156                 $manager->notify('LoginSuccess',array('member' => &$member));\r
157                 ACTIONLOG::add(INFO, "Login successful for $login (sharedpc=$shared)");\r
158         } else {\r
159                 $manager->notify('LoginFailed',array('username' => $login));\r
160                 ACTIONLOG::add(INFO, 'Login failed for ' . $login);\r
161         }\r
162 /*\r
163 \r
164 Backed out for now: See http://forum.nucleuscms.org/viewtopic.php?t=3684 for details\r
165 \r
166 } elseif (serverVar('PHP_AUTH_USER') && serverVar('PHP_AUTH_PW')) {\r
167         // HTTP Authentication\r
168        $login  = serverVar('PHP_AUTH_USER');\r
169        $pw     = serverVar('PHP_AUTH_PW');\r
170 \r
171        if ($member->login($login,$pw)) {\r
172                $manager->notify('LoginSuccess',array('member' => &$member));\r
173                ACTIONLOG::add(INFO, "HTTP authentication successful for $login");\r
174        } else {\r
175                $manager->notify('LoginFailed',array('username' => $login));\r
176                ACTIONLOG::add(INFO, 'HTTP authentication failed for ' . $login);\r
177 \r
178                //Since bad credentials, generate an apropriate error page\r
179                header("WWW-Authenticate: Basic realm=\"Nucleus {$nucleus['version']}\"");\r
180                header('HTTP/1.0 401 Unauthorized');\r
181                echo 'Invalid username or password';\r
182                exit;\r
183        }\r
184 */\r
185 \r
186 } elseif (($action == 'logout') && (!headers_sent()) && cookieVar('user')){\r
187         // remove cookies on logout\r
188         setcookie('user','',(time()-2592000),$CONF['CookiePath'],$CONF['CookieDomain'],$CONF['CookieSecure']);\r
189         setcookie('loginkey','',(time()-2592000),$CONF['CookiePath'],$CONF['CookieDomain'],$CONF['CookieSecure']);\r
190         $manager->notify('Logout',array('username' => cookieVar('user')));\r
191 } elseif (cookieVar('user')) {\r
192         // Cookie Authentication\r
193         $res = $member->cookielogin(cookieVar('user'), cookieVar('loginkey'));\r
194 \r
195         // renew cookies when not on a shared computer\r
196         if ($res && (cookieVar('sharedpc') != 1) && (!headers_sent()))\r
197                 $member->setCookies();\r
198 }\r
199 \r
200 // login completed\r
201 $manager->notify('PostAuthentication',array('loggedIn' => $member->isLoggedIn()));\r
202 \r
203 // load other classes\r
204 include($DIR_LIBS . 'PARSER.php');\r
205 include($DIR_LIBS . 'SKIN.php');\r
206 include($DIR_LIBS . 'TEMPLATE.php');\r
207 include($DIR_LIBS . 'BLOG.php');\r
208 include($DIR_LIBS . 'COMMENTS.php');\r
209 include($DIR_LIBS . 'COMMENT.php');\r
210 //include($DIR_LIBS . 'ITEM.php');\r
211 include($DIR_LIBS . 'NOTIFICATION.php');\r
212 include($DIR_LIBS . 'BAN.php');\r
213 include($DIR_LIBS . 'PAGEFACTORY.php');\r
214 include($DIR_LIBS . 'SEARCH.php');\r
215 \r
216 \r
217 // set lastVisit cookie (if allowed)\r
218 if (!headers_sent()) {\r
219         if ($CONF['LastVisit'])\r
220                 setcookie('lastVisit',time(),time()+2592000,$CONF['CookiePath'],$CONF['CookieDomain'],$CONF['CookieSecure']);\r
221         else\r
222                 setcookie('lastVisit','',(time()-2592000),$CONF['CookiePath'],$CONF['CookieDomain'],$CONF['CookieSecure']);\r
223 }\r
224 \r
225 // read language file, only after user has been initialized\r
226 $language = getLanguageName();\r
227 include($DIR_LANG . ereg_replace( '[\\|/]', '', $language) . '.php');\r
228 \r
229 /*\r
230         Backed out for now: See http://forum.nucleuscms.org/viewtopic.php?t=3684 for details\r
231         \r
232 // To remove after v2.5 is released and language files have been updated. \r
233 // Including this makes sure that language files for v2.5beta can still be used for v2.5final\r
234 // without having weird _SETTINGS_EXTAUTH string showing up in the admin area.\r
235 if (!defined('_MEMBERS_BYPASS'))\r
236 {\r
237         define('_SETTINGS_EXTAUTH',                     'Enable External Authentication');\r
238         define('_WARNING_EXTAUTH',                      'Warning: Enable only if needed.');\r
239         define('_MEMBERS_BYPASS',                       'Use External Authentication');\r
240 }\r
241 \r
242 */\r
243 \r
244 // decode path_info\r
245 if ($CONF['URLMode'] == 'pathinfo') {\r
246         $data = explode("/",serverVar('PATH_INFO'));\r
247         for ($i=0;$i<sizeof($data);$i++) {\r
248                 switch ($data[$i]) {\r
249                         case 'item':                    // item/1 (blogid)\r
250                                 $i++;\r
251                                 if ($i<sizeof($data)) $itemid = intval($data[$i]);\r
252                                 break;\r
253                         case 'archives':                // archives/1 (blogid)\r
254                                 $i++;\r
255                                 if ($i<sizeof($data)) $archivelist = intval($data[$i]);\r
256                                 break;\r
257                         case 'archive':                 // two possibilities: archive/yyyy-mm or archive/1/yyyy-mm (with blogid)\r
258                                 if ((($i+1)<sizeof($data)) && (!strstr($data[$i+1],'-')) ){\r
259                                         $blogid = intval($data[++$i]);\r
260                                 }\r
261                                 $i++;\r
262                                 if ($i<sizeof($data)) $archive = $data[$i];\r
263                                 break;\r
264                         case 'blogid':                  // blogid/1\r
265                         case 'blog':                    // blog/1\r
266                                 $i++;\r
267                                 if ($i<sizeof($data)) $blogid = intval($data[$i]);\r
268                                 break;\r
269                         case 'category':                // category/1 (catid)\r
270                         case 'catid':\r
271                                 $i++;\r
272                                 if ($i<sizeof($data)) $catid = intval($data[$i]);\r
273                                 break;\r
274                         case 'member':\r
275                                 $i++;\r
276                                 if ($i<sizeof($data)) $memberid = intval($data[$i]);\r
277                                 break;\r
278                         default:\r
279                                 // skip...\r
280                 }\r
281         }\r
282 }\r
283 \r
284 /**\r
285   * Connects to mysql server\r
286   */\r
287 function sql_connect() {\r
288         global $MYSQL_HOST, $MYSQL_USER, $MYSQL_PASSWORD, $MYSQL_DATABASE;\r
289 \r
290         $connection = @mysql_connect($MYSQL_HOST, $MYSQL_USER, $MYSQL_PASSWORD) or startUpError('<p>Could not connect to MySQL database.</p>','Connect Error');\r
291         mysql_select_db($MYSQL_DATABASE) or startUpError('<p>Could not select database: '. mysql_error().'</p>', 'Connect Error');\r
292 \r
293         return $connection;\r
294 }\r
295 \r
296 /**\r
297  * returns a prefixed nucleus table name\r
298  */\r
299 function sql_table($name)\r
300 {\r
301         global $MYSQL_PREFIX;\r
302 \r
303         if ($MYSQL_PREFIX)\r
304                 return $MYSQL_PREFIX . 'nucleus_' . $name;\r
305         else\r
306                 return 'nucleus_' . $name;\r
307 }\r
308 \r
309 function sendContentType($contenttype, $pagetype = '', $charset = _CHARSET) {\r
310         global $manager, $CONF;\r
311         \r
312         if (!headers_sent()) {\r
313                 // if content type is application/xhtml+xml, only send it to browsers\r
314                 // that can handle it (IE6 cannot). Otherwise, send text/html\r
315                 \r
316                 // v2.5: For admin area pages, keep sending text/html (unless it's a debug version)\r
317                 //       application/xhtml+xml still causes too much problems with the javascript implementations\r
318                 if (\r
319                                 ($contenttype == 'application/xhtml+xml')\r
320                         &&      (($CONF['UsingAdminArea'] && !$CONF['debug']) || !stristr(serverVar('HTTP_ACCEPT'),'application/xhtml+xml'))\r
321                         )\r
322                 {\r
323                         $contenttype = 'text/html';\r
324                 }\r
325                         \r
326                 $manager->notify(\r
327                         'PreSendContentType',\r
328                         array(\r
329                                 'contentType' => &$contenttype,\r
330                                 'charset' => &$charset,\r
331                                 'pageType' => $pagetype\r
332                         )\r
333                 );\r
334                 \r
335                 // strip strange characters\r
336                 $contenttype = preg_replace('|[^a-z0-9-+./]|i', '', $contenttype);\r
337                 $charset = preg_replace('|[^a-z0-9-_]|i', '', $charset);\r
338                 \r
339                 header('Content-Type: ' . $contenttype . '; charset=' . $charset);                      \r
340         }\r
341         \r
342         \r
343 \r
344         \r
345 }\r
346 \r
347 /**\r
348  * Errors before the database connection has been made\r
349  */\r
350 function startUpError($msg, $title) {\r
351         ?>\r
352         <html xmlns="http://www.w3.org/1999/xhtml">\r
353                 <head><meta http-equiv="Content-Type" content="text/html; charset=EUC-JP" /><title><?php echo htmlspecialchars($title)?></title></head>\r
354                 <body>\r
355                         <h1><?php echo htmlspecialchars($title)?></h1>\r
356                         <?php echo $msg?>\r
357                 </body>\r
358         </html>\r
359         <?php   exit;\r
360 }\r
361 \r
362 /**\r
363   * disconnects from SQL server\r
364   */\r
365 function sql_disconnect() {\r
366         @mysql_close();\r
367 }\r
368 \r
369 /**\r
370   * executes an SQL query\r
371   */\r
372 function sql_query($query) {\r
373         $res = mysql_query($query) or print("mySQL error with query $query: " . mysql_error() . '<p />');\r
374         return $res;\r
375 }\r
376 \r
377 \r
378 /**\r
379  * Highlights a specific query in a given HTML text (not within HTML tags) and returns it\r
380  *\r
381  * @param $text\r
382  *              text to be highlighted\r
383  * @param $expression\r
384  *              regular expression to be matched (can be an array of expressions as well)\r
385  * @param $highlight\r
386  *              highlight to be used (use \\0 to indicate the matched expression)\r
387  *\r
388  */\r
389 function highlight($text, $expression, $highlight) {\r
390         if (!$highlight || !$expression) return $text;\r
391         if (is_array($expression) && (count($expression) == 0))\r
392                 return $text;\r
393 \r
394         // add a tag in front (is needed for preg_match_all to work correct)\r
395         $text = '<!--h-->'.$text;\r
396 \r
397         // split the HTML up so we have HTML tags\r
398         // $matches[0][i] = HTML + text\r
399         // $matches[1][i] = HTML\r
400         // $matches[2][i] = text\r
401         preg_match_all('/(<[^>]+>)([^<>]*)/', $text, $matches);\r
402 \r
403         // throw it all together again while applying the highlight to the text pieces\r
404         $result = '';\r
405         for ($i = 0; $i < sizeof($matches[2]); $i++) {\r
406                 if ($i != 0) $result .= $matches[1][$i];\r
407 \r
408                 if (is_array($expression)) {\r
409                         foreach ($expression as $regex)\r
410                                 if ($regex)\r
411                                         $matches[2][$i] = @eregi_replace($regex,$highlight,$matches[2][$i]);\r
412                         $result .= $matches[2][$i];\r
413                 } else {\r
414                         $result .= @eregi_replace($expression,$highlight,$matches[2][$i]);\r
415                 }\r
416         }\r
417 \r
418         return $result;\r
419 }\r
420 \r
421 /**\r
422  * Parses a query into an array of expressions that can be passed on to the highlight method\r
423  */\r
424 function parseHighlight($query) {\r
425         // TODO: add more intelligent splitting logic\r
426 \r
427         // get rid of quotes\r
428         $query = preg_replace('/\'|"/','',$query);\r
429 \r
430         if (!query) return array();\r
431 \r
432         $aHighlight = explode(' ', $query);\r
433 \r
434         for ($i = 0; $i<count($aHighlight); $i++) {\r
435                 $aHighlight[$i] = trim($aHighlight[$i]);\r
436                 if (strlen($aHighlight[$i]) < 3)\r
437                         unset($aHighlight[$i]);\r
438         }\r
439 \r
440         if (count($aHighlight) == 1)\r
441                 return $aHighlight[0];\r
442         else\r
443                 return $aHighlight;\r
444 }\r
445 \r
446 /**\r
447   * Checks if email address is valid\r
448   */\r
449 function isValidMailAddress($address) {\r
450         if (preg_match('/^[a-zA-Z0-9\._-]+@[a-zA-Z0-9\._-]+\.[A-Za-z]{2,5}$/', $address))\r
451                 return 1;\r
452         else\r
453                 return 0;\r
454 }\r
455 \r
456 \r
457 // some helper functions\r
458 function getBlogIDFromName($name) {\r
459         return quickQuery('SELECT bnumber as result FROM '.sql_table('blog').' WHERE bshortname="'.addslashes($name).'"');\r
460 }\r
461 function getBlogNameFromID($id) {\r
462         return quickQuery('SELECT bname as result FROM '.sql_table('blog').' WHERE bnumber='.intval($id));\r
463 }\r
464 function getBlogIDFromItemID($itemid) {\r
465         return quickQuery('SELECT iblog as result FROM '.sql_table('item').' WHERE inumber='.intval($itemid));\r
466 }\r
467 function getBlogIDFromCommentID($commentid) {\r
468         return quickQuery('SELECT cblog as result FROM '.sql_table('comment').' WHERE cnumber='.intval($commentid));\r
469 }\r
470 function getBlogIDFromCatID($catid) {\r
471         return quickQuery('SELECT cblog as result FROM '.sql_table('category').' WHERE catid='.intval($catid));\r
472 }\r
473 function getCatIDFromName($name) {\r
474         return quickQuery('SELECT catid as result FROM '.sql_table('category').' WHERE cname="'.addslashes($name).'"');\r
475 }\r
476 function quickQuery($q) {\r
477         $res = sql_query($q);\r
478         $obj = mysql_fetch_object($res);\r
479         return $obj->result;\r
480 }\r
481 \r
482 function getPluginNameFromPid($pid) {\r
483         $obj = mysql_fetch_object(sql_query('SELECT pfile FROM '.sql_table('plugin').' WHERE pid='.intval($pid)));\r
484         return $obj->pfile;\r
485 }\r
486 \r
487 function selector() {\r
488         global $itemid, $blogid, $memberid, $query, $amount, $archivelist, $maxresults;\r
489         global $archive, $skinid, $blog, $memberinfo, $CONF, $member;\r
490         global $imagepopup, $catid;\r
491         global $manager;\r
492 \r
493         // first, let's see if the site is disabled or not\r
494         if ($CONF['DisableSite'] && !$member->isAdmin()) {\r
495                 redirect($CONF['DisableSiteURL']);\r
496                 exit;\r
497         }\r
498 \r
499 \r
500         // show error when headers already sent out\r
501         if (headers_sent() && $CONF['alertOnHeadersSent']) {\r
502 \r
503                 // try to get line number/filename (extra headers_sent params only exists in PHP 4.3+)\r
504                 if (function_exists('version_compare') && version_compare('4.3.0', phpversion(), '<=')) {\r
505                         headers_sent($hsFile, $hsLine);\r
506                         $extraInfo = ' in <code>'.$hsFile.'</code> line <code>'.$hsLine.'</code>';\r
507                 } else {\r
508                         $extraInfo = '';\r
509                 }\r
510 \r
511 \r
512                 startUpError(\r
513                         '<p>The page headers have already been sent out'.$extraInfo.'. This could cause Nucleus not to work in the expected way.</p><p>Usually, this is caused by spaces or newlines at the end of the <code>config.php</code> file, at the end of the language file or at the end of a plugin file. Please check this and try again.</p><p>If you don\'t want to see this error message again, without solving the problem, set <code>$CONF[\'alertOnHeadersSent\']</code> in <code>globalfunctions.php</code> to <code>0</code></p>',\r
514                         'Page headers already sent'\r
515                 );\r
516                 exit;\r
517         }\r
518 \r
519         // make is so ?archivelist without blogname or blogid shows the archivelist\r
520         // for the default weblog\r
521         if (serverVar('QUERY_STRING') == 'archivelist')\r
522                 $archivelist = $CONF['DefaultBlog'];\r
523 \r
524         // now decide which type of skin we need\r
525         if ($itemid) {\r
526                 // itemid given -> only show that item\r
527                 $type = 'item';\r
528                 if (!$manager->existsItem($itemid,0,0))\r
529                         doError(_ERROR_NOSUCHITEM);\r
530 \r
531 \r
532                 global $itemidprev, $itemidnext, $catid, $itemtitlenext, $itemtitleprev;\r
533 \r
534                 // 1. get timestamp and blogid for item\r
535                 $query = 'SELECT itime, iblog FROM '.sql_table('item').' WHERE inumber=' . intval($itemid);\r
536                 $res = sql_query($query);\r
537                 $obj = mysql_fetch_object($res);\r
538 \r
539                 // if a different blog id has been set through the request or selectBlog(),\r
540                 // deny access\r
541                 if ($blogid && (intval($blogid) != $obj->iblog))\r
542                         doError(_ERROR_NOSUCHITEM);\r
543 \r
544                 $blogid = $obj->iblog;\r
545                 $timestamp = strtotime($obj->itime);\r
546 \r
547                 $b =& $manager->getBlog($blogid);\r
548                 if ($b->isValidCategory($catid))\r
549                         $catextra = ' and icat=' . $catid;\r
550 \r
551                 // get previous itemid and title\r
552                 $query = 'SELECT inumber, ititle FROM '.sql_table('item').' WHERE itime<' . mysqldate($timestamp) . ' and idraft=0 and iblog=' . $blogid . $catextra . ' ORDER BY itime DESC LIMIT 1';\r
553                 $res = sql_query($query);\r
554 \r
555                 $obj = mysql_fetch_object($res);\r
556                 if ($obj) {\r
557                         $itemidprev = $obj->inumber;\r
558                         $itemtitleprev = $obj->ititle;\r
559         }\r
560 \r
561                 // get next itemid and title\r
562                 $query = 'SELECT inumber, ititle FROM '.sql_table('item').' WHERE itime>' . mysqldate($timestamp) . ' and itime <= ' . mysqldate(time()) . ' and idraft=0 and iblog=' . $blogid . $catextra . ' ORDER BY itime ASC LIMIT 1';\r
563                 $res = sql_query($query);\r
564 \r
565                 $obj = mysql_fetch_object($res);\r
566                 if ($obj) {\r
567                         $itemidnext = $obj->inumber;\r
568                         $itemtitlenext = $obj->ititle;\r
569                 }\r
570 \r
571         } elseif ($archive) {\r
572                 // show archive\r
573                 $type = 'archive';\r
574 \r
575                 // get next and prev month links\r
576                 global $archivenext, $archiveprev, $archivetype;\r
577 \r
578                 sscanf($archive,'%d-%d-%d',$y,$m,$d);\r
579                 if ($d != 0) {\r
580                         $archivetype = _ARCHIVETYPE_DAY;\r
581                         $t = mktime(0,0,0,$m,$d,$y);\r
582                         $archiveprev = strftime('%Y-%m-%d',$t - (24*60*60));\r
583                         $archivenext = strftime('%Y-%m-%d',$t + (24*60*60));\r
584 \r
585                 } else {\r
586                         $archivetype = _ARCHIVETYPE_MONTH;\r
587                         $t = mktime(0,0,0,$m,1,$y);\r
588                         $archiveprev = strftime('%Y-%m',$t - (1*24*60*60));\r
589                         $archivenext = strftime('%Y-%m',$t + (32*24*60*60));\r
590                 }\r
591 \r
592 \r
593         } elseif ($archivelist) {\r
594                 $type = 'archivelist';\r
595                 if (intval($archivelist) != 0)\r
596                         $blogid = $archivelist;\r
597                 else\r
598                         $blogid = getBlogIDFromName($archivelist);\r
599                 if (!$blogid) doError(_ERROR_NOSUCHBLOG);\r
600         } elseif ($query) {\r
601             global $startpos;\r
602                 $type = 'search';\r
603                 $query = stripslashes($query);\r
604                 if(preg_match("/^(\xA1{2}|\xe3\x80{2}|\x20)+$/",$query)){\r
605                                         $type = 'index';\r
606                 }\r
607                 $order = (_CHARSET == 'EUC-JP') ? 'EUC-JP, UTF-8,' : 'UTF-8, EUC-JP,';\r
608                 $query = mb_convert_encoding($query, _CHARSET, $order.' JIS, SJIS, ASCII');\r
609                 if (intval($blogid)==0)\r
610                         $blogid = getBlogIDFromName($blogid);\r
611                 if (!$blogid) doError(_ERROR_NOSUCHBLOG);\r
612         } elseif ($memberid) {\r
613                 $type = 'member';\r
614                 if (!MEMBER::existsID($memberid))\r
615                         doError(_ERROR_NOSUCHMEMBER);\r
616                 $memberinfo = MEMBER::createFromID($memberid);\r
617 \r
618         } elseif ($imagepopup) {\r
619                 // media object (images etc.)\r
620                 $type = 'imagepopup';\r
621 \r
622                 // TODO: check if media-object exists\r
623                 // TODO: set some vars?\r
624         } else {\r
625                 // show regular index page\r
626             global $startpos;\r
627                 $type = 'index';\r
628         }\r
629 \r
630         // decide which blog should be displayed\r
631         if (!$blogid)\r
632                 $blogid = $CONF['DefaultBlog'];\r
633 \r
634         $b =& $manager->getBlog($blogid);\r
635         $blog = $b;     // references can't be placed in global variables?\r
636         if (!$blog->isValid)\r
637                 doError(_ERROR_NOSUCHBLOG);\r
638 \r
639         // set catid if necessary\r
640         if ($catid)\r
641                 $blog->setSelectedCategory($catid);\r
642 \r
643         // decide which skin should be used\r
644         if ($skinid != '' && ($skinid == 0))\r
645                 selectSkin($skinid);\r
646         if (!$skinid)\r
647                 $skinid = $blog->getDefaultSkin();\r
648 \r
649         \r
650         $skin = new SKIN($skinid);\r
651         if (!$skin->isValid)\r
652                 doError(_ERROR_NOSUCHSKIN);\r
653 \r
654         // parse the skin\r
655         $skin->parse($type);\r
656 }\r
657 \r
658 /**\r
659   * Show error skin with given message. An optional skin-object to use can be given\r
660   */\r
661 function doError($msg, $skin = '') {\r
662         global $errormessage, $CONF, $skinid, $blogid, $manager;\r
663 \r
664         if ($skin == '') {\r
665                 if (SKIN::existsID($skinid)) {\r
666                         $skin = new SKIN($skinid);\r
667                 } elseif ($manager->existsBlogID($blogid)) {\r
668                         $blog =& $manager->getBlog($blogid);\r
669                         $skin = new SKIN($blog->getDefaultSkin());\r
670                 } elseif ($CONF['DefaultBlog']) {\r
671                         $blog =& $manager->getBlog($CONF['DefaultBlog']);\r
672                         $skin = new SKIN($blog->getDefaultSkin());\r
673                 } else {\r
674                         // this statement should actually never be executed\r
675                         $skin = new SKIN($CONF['BaseSkin']);\r
676                 }\r
677         }\r
678 \r
679         $errormessage = $msg;\r
680         $skin->parse('error');\r
681         exit;\r
682 }\r
683 \r
684 function getConfig() {\r
685         global $CONF;\r
686 \r
687         $query = 'SELECT * FROM '.sql_table('config');\r
688         $res = sql_query($query);\r
689         while ($obj = mysql_fetch_object($res)) {\r
690                 $CONF[$obj->name] = $obj->value;\r
691         }\r
692 }\r
693 \r
694 // some checks for names of blogs, categories, templates, members, ...\r
695 function isValidShortName($name) {              return eregi('^[a-z0-9]+$', $name); }\r
696 function isValidDisplayName($name) {    return eregi('^[a-z0-9]+[a-z0-9 ]*[a-z0-9]+$', $name); }\r
697 function isValidCategoryName($name) {   return 1; } \r
698 function isValidTemplateName($name) {   return eregi('^[a-z0-9/]+$', $name); }\r
699 function isValidSkinName($name) {               return eregi('^[a-z0-9/]+$', $name); }\r
700 \r
701 // add and remove linebreaks\r
702 function addBreaks($var) {                              return nl2br($var); }\r
703 function removeBreaks($var) {                   return preg_replace("/<br \/>([\r\n])/","$1",$var); }\r
704 \r
705 /**\r
706   * Generate a 'pronouncable' password\r
707   * (http://www.zend.com/codex.php?id=215&single=1)\r
708   */\r
709 function genPassword($length){\r
710 \r
711     srand((double)microtime()*1000000);\r
712 \r
713     $vowels = array('a', 'e', 'i', 'o', 'u');\r
714     $cons = array('b', 'c', 'd', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'r', 's', 't', 'u', 'v', 'w', 'tr',\r
715     'cr', 'br', 'fr', 'th', 'dr', 'ch', 'ph', 'wr', 'st', 'sp', 'sw', 'pr', 'sl', 'cl');\r
716 \r
717     $num_vowels = count($vowels);\r
718     $num_cons = count($cons);\r
719 \r
720     for($i = 0; $i < $length; $i++){\r
721         $password .= $cons[rand(0, $num_cons - 1)] . $vowels[rand(0, $num_vowels - 1)];\r
722     }\r
723 \r
724     return substr($password, 0, $length);\r
725 }\r
726 \r
727 // shortens a text string to maxlength ($toadd) is what needs to be added\r
728 // at the end (end length is <= $maxlength)\r
729 function shorten($text, $maxlength, $toadd) {\r
730         // 1. remove entities...\r
731         $trans = get_html_translation_table(HTML_ENTITIES);\r
732         $trans = array_flip($trans);\r
733         $text = strtr($text, $trans);\r
734         // 2. the actual shortening\r
735         if (strlen($text) > $maxlength)\r
736                 $text = mb_strimwidth($text, 0, $maxlength, $toadd, _CHARSET);\r
737         return $text;\r
738 }\r
739 \r
740 /**\r
741   * Converts a unix timestamp to a mysql DATETIME format, and places\r
742   * quotes around it.\r
743   */\r
744 function mysqldate($timestamp) {\r
745         return '"' . date('Y-m-d H:i:s',$timestamp) . '"';\r
746 }\r
747 \r
748 /**\r
749   * functions for use in index.php\r
750   */\r
751 function selectBlog($shortname) {\r
752         global $blogid, $archivelist;\r
753         $blogid = getBlogIDFromName($shortname);\r
754 \r
755         // also force archivelist variable, if it is set\r
756         if ($archivelist)\r
757                 $archivelist = $blogid;\r
758 }\r
759 \r
760 function selectSkin($skinname) {\r
761         global $skinid;\r
762         $skinid = SKIN::getIdFromName($skinname);\r
763 }\r
764 \r
765 /**\r
766  * Can take either a category ID or a category name (be aware that\r
767  * multiple categories can have the same name)\r
768  */\r
769 function selectCategory($cat) {\r
770         global $catid;\r
771         if (is_numeric($cat))\r
772                 $catid = intval($cat);\r
773         else\r
774                 $catid = getCatIDFromName($cat);\r
775 }\r
776 \r
777 function selectItem($id){\r
778         global $itemid;\r
779         $itemid = intval($id);\r
780 }\r
781 \r
782 // force the use of a language file (warning: can cause warnings)\r
783 function selectLanguage($language) {\r
784         global $DIR_LANG;\r
785         include($DIR_LANG . ereg_replace( '[\\|/]', '', $language) . '.php');\r
786 }\r
787 \r
788 function parseFile($filename) {\r
789         $handler = new ACTIONS('fileparser');\r
790         $parser = new PARSER(SKIN::getAllowedActionsForType('fileparser'), $handler);\r
791         $handler->parser =& $parser;\r
792 \r
793         if (!file_exists($filename)) doError('A file is missing');\r
794 \r
795         $fsize = filesize($filename);\r
796         if ($fsize <= 0)\r
797                 return;\r
798 \r
799         // read file\r
800         $fd = fopen ($filename, 'r');\r
801         $contents = fread ($fd, $fsize);\r
802         fclose ($fd);\r
803 \r
804         // parse file contents\r
805         $parser->parse($contents);\r
806 }\r
807 \r
808 /**\r
809   * Outputs a debug message\r
810   */\r
811 function debug($msg) {\r
812         echo '<p><b>' . $msg . "</b></p>\n";\r
813 }\r
814 \r
815 // shortcut\r
816 function addToLog($level, $msg) { ACTIONLOG::add($level, $msg); }\r
817 \r
818 // shows a link to help file\r
819 function help($id) {\r
820         echo helpHtml($id);\r
821 }\r
822 \r
823 function helpHtml($id) {\r
824         return helplink($id) . '<img src="documentation/icon-help.gif" width="15" height="15" alt="'._HELP_TT.'" /></a>';\r
825 }\r
826 \r
827 function helplink($id) {\r
828         return '<a href="documentation/help.html#'. $id . '" onclick="if (event &amp;&amp; event.preventDefault) event.preventDefault(); return help(this.href);">';\r
829 }\r
830 \r
831 function getMailFooter() {\r
832         $message = "\n\n-----------------------------";\r
833         $message .=  "\n   Powered by Nucleus CMS";\r
834         $message .=  "\n(http://www.nucleuscms.org/)";\r
835         return $message;\r
836 }\r
837 \r
838 /**\r
839   * Returns the name of the language to use\r
840   * preference priority: member - site\r
841   * defaults to english when no good language found\r
842   *\r
843   * checks if file exists, etc...\r
844   */\r
845 function getLanguageName() {\r
846         global $CONF, $member;\r
847 \r
848         if ($member) {\r
849                 // try to use members language\r
850                 $memlang = $member->getLanguage();\r
851 \r
852                 if (($memlang != '') && (checkLanguage($memlang)))\r
853                         return $memlang;\r
854         }\r
855 \r
856         // use default language\r
857         if (checkLanguage($CONF['Language']))\r
858                 return $CONF['Language'];\r
859         else\r
860                 return 'english';\r
861 }\r
862 \r
863 /**\r
864   * Includes a PHP file. This method can be called while parsing templates and skins\r
865   */\r
866 function includephp($filename) {\r
867         // make predefined variables global, so most simple scripts can be used here\r
868 \r
869         // apache (names taken from PHP doc)\r
870         global $GATEWAY_INTERFACE, $SERVER_NAME, $SERVER_SOFTWARE, $SERVER_PROTOCOL;\r
871         global $REQUEST_METHOD, $QUERY_STRING, $DOCUMENT_ROOT, $HTTP_ACCEPT;\r
872         global $HTTP_ACCEPT_CHARSET, $HTTP_ACCEPT_ENCODING, $HTTP_ACCEPT_LANGUAGE;\r
873         global $HTTP_CONNECTION, $HTTP_HOST, $HTTP_REFERER, $HTTP_USER_AGENT;\r
874         global $REMOTE_ADDR, $REMOTE_PORT, $SCRIPT_FILENAME, $SERVER_ADMIN;\r
875         global $SERVER_PORT, $SERVER_SIGNATURE, $PATH_TRANSLATED, $SCRIPT_NAME;\r
876         global $REQUEST_URI;\r
877 \r
878         // php (taken from PHP doc)\r
879         global $argv, $argc, $PHP_SELF, $HTTP_COOKIE_VARS, $HTTP_GET_VARS, $HTTP_POST_VARS;\r
880         global $HTTP_POST_FILES, $HTTP_ENV_VARS, $HTTP_SERVER_VARS, $HTTP_SESSION_VARS;\r
881 \r
882         // other\r
883         global $PATH_INFO, $HTTPS, $HTTP_RAW_POST_DATA, $HTTP_X_FORWARDED_FOR;\r
884 \r
885         if (@file_exists($filename)) include($filename);\r
886 }\r
887 \r
888 /**\r
889   * Checks if a certain language/plugin exists\r
890   */\r
891 function checkLanguage($lang) {\r
892         global $DIR_LANG ;\r
893         return file_exists($DIR_LANG . ereg_replace( '[\\|/]', '', $lang) . '.php');\r
894 }\r
895 function checkPlugin($plug) {\r
896         global $DIR_PLUGINS;\r
897         return file_exists($DIR_PLUGINS . ereg_replace( '[\\|/]', '', $plug) . '.php');\r
898 }\r
899 \r
900 \r
901 $CONF['ItemURL'] = $CONF['Self'];\r
902 $CONF['ArchiveURL'] = $CONF['Self'];\r
903 $CONF['ArchiveListURL'] = $CONF['Self'];\r
904 $CONF['MemberURL'] = $CONF['Self'];\r
905 $CONF['SearchURL'] = $CONF['Self'];\r
906 $CONF['BlogURL'] = $CONF['Self'];\r
907 $CONF['CategoryURL'] = $CONF['Self'];\r
908 \r
909 // switch URLMode back to normal when $CONF['Self'] ends in .php\r
910 // this avoids urls like index.php/item/13/index.php/item/15\r
911 if (    ($CONF['URLMode'] == 'pathinfo')\r
912         &&      (substr($CONF['Self'], strlen($CONF['Self']) - 4) == '.php')\r
913         ) {\r
914         $CONF['URLMode'] = 'normal';\r
915 }\r
916 \r
917 /**\r
918   * Centralisation of the functions that generate links\r
919   */\r
920 function createItemLink($itemid, $extra = '') {\r
921         global $CONF;\r
922         if ($CONF['URLMode'] == 'pathinfo')\r
923                 $link = $CONF['ItemURL'] . '/item/' . $itemid;\r
924         else\r
925                 $link = $CONF['ItemURL'] . '?itemid=' . $itemid;\r
926         return addLinkParams($link, $extra);\r
927 }\r
928 function createMemberLink($memberid, $extra = '') {\r
929         global $CONF;\r
930         if ($CONF['URLMode'] == 'pathinfo')\r
931                 $link = $CONF['MemberURL'] . '/member/' . $memberid;\r
932         else\r
933                 $link = $CONF['MemberURL'] . '?memberid=' . $memberid;\r
934         return addLinkParams($link, $extra);\r
935 }\r
936 function createCategoryLink($catid, $extra = '') {\r
937         global $CONF;\r
938         if ($CONF['URLMode'] == 'pathinfo')\r
939                 $link = $CONF['CategoryURL'] . '/category/' . $catid;\r
940         else\r
941                 $link = $CONF['CategoryURL'] . '?catid=' . $catid;\r
942         return addLinkParams($link, $extra);\r
943 }\r
944 function createArchiveListLink($blogid = '', $extra = '') {\r
945         global $CONF;\r
946         if (!$blogid)\r
947                 $blogid = $CONF['DefaultBlog'];\r
948         if ($CONF['URLMode'] == 'pathinfo')\r
949                 $link = $CONF['ArchiveListURL'] . '/archives/' . $blogid;\r
950         else\r
951                 $link = $CONF['ArchiveListURL'] . '?archivelist=' . $blogid;\r
952         return addLinkParams($link, $extra);\r
953 }\r
954 function createArchiveLink($blogid, $archive, $extra = '') {\r
955         global $CONF;\r
956         if ($CONF['URLMode'] == 'pathinfo')\r
957                 $link = $CONF['ArchiveURL'] . '/archive/'.$blogid.'/' . $archive;\r
958         else\r
959                 $link = $CONF['ArchiveURL'] . '?blogid='.$blogid.'&amp;archive=' . $archive;\r
960         return addLinkParams($link, $extra);\r
961 }\r
962 function createBlogLink($url, $params) {\r
963         return addLinkParams($url . '?', $params);\r
964 }\r
965 function createBlogidLink($blogid, $params = '') {\r
966         global $CONF;\r
967         if ($CONF['URLMode'] == 'pathinfo')\r
968                 $link = $CONF['BlogURL'] . '/blog/' . $blogid;\r
969         else\r
970                 $link = $CONF['BlogURL'] . '?blogid=' . $blogid;\r
971         return addLinkParams($link, $params);\r
972 }\r
973 \r
974 \r
975 function addLinkParams($link, $params) {\r
976         global $CONF;\r
977         if (is_array($params)) {\r
978                 if ($CONF['URLMode'] == 'pathinfo')     {\r
979                         foreach ($params as $param => $value) {\r
980                                 $link .= '/' . $param . '/' . urlencode($value);\r
981                         }\r
982                 } else {\r
983                         foreach ($params as $param => $value) {\r
984                                 $link .= '&amp;' . $param . '=' . urlencode($value);\r
985                         }\r
986                 }\r
987         }\r
988         return $link;\r
989 }\r
990 \r
991 /**\r
992  * @param $querystr\r
993  *              querystring to alter (e.g. foo=1&bar=2&x=y)\r
994  * @param $param\r
995  *              name of parameter to change (e.g. 'foo')\r
996  * @param $value\r
997  *              New value for that parameter (e.g. 3)\r
998  * @result \r
999  *              altered query string (for the examples above: foo=3&bar=2&x=y)\r
1000  */\r
1001 function alterQueryStr($querystr, $param, $value) {\r
1002     $vars = explode("&", $querystr);\r
1003     $set  = false;\r
1004     for ($i=0;$i<count($vars);$i++) {\r
1005         $v = explode('=',$vars[$i]);\r
1006         if ($v[0] == $param) {\r
1007             $v[1]     = $value;\r
1008             $vars[$i] = implode('=', $v);\r
1009             $set      = true;\r
1010             break;\r
1011         }\r
1012     }\r
1013     if (!$set) {$vars[] = $param . '=' . $value;}\r
1014     return ltrim(implode('&', $vars), '&');\r
1015 }\r
1016 \r
1017 // passes one variable as hidden input field (multiple fields for arrays)\r
1018 // @see passRequestVars in varsx.x.x.php\r
1019 function passVar($key, $value) {\r
1020         // array ?\r
1021         if (is_array($value)) {\r
1022                 for ($i=0;$i<sizeof($value);$i++)\r
1023                         passVar($key.'['.$i.']',$value[$i]);\r
1024                         return;\r
1025         }\r
1026 \r
1027         // other values: do stripslashes if needed\r
1028         ?><input type="hidden" name="<?php echo htmlspecialchars($key)?>" value="<?php echo htmlspecialchars(undoMagic($value))?>" /><?php\r
1029 }\r
1030 \r
1031 /*\r
1032         Date format functions (to be used from [%date(..)%] skinvars\r
1033 */\r
1034 function formatDate($format, $timestamp, $defaultFormat) {\r
1035         if ($format == 'rfc822') { \r
1036                 return date('r', $timestamp); \r
1037         } else if ($format == 'rfc822GMT') { \r
1038                 return gmdate('r', $timestamp); \r
1039         } else if ($format == 'utc') { \r
1040                 return gmdate('Y-m-d\TH:i:s\Z', $timestamp); \r
1041         } else if ($format == 'iso8601') {\r
1042         $tz = date('O', $timestamp);\r
1043         $tz = substr($tz, 0, 3) . ':' . substr($tz, 3, 2);      \r
1044                 return gmdate('Y-m-d\TH:i:s', $timestamp) . $tz;\r
1045         } else {  \r
1046                 return strftime($format ? $format : $defaultFormat,$timestamp); \r
1047         }  \r
1048 \r
1049 }\r
1050 \r
1051 function checkVars($aVars)\r
1052 {\r
1053         global $HTTP_GET_VARS, $HTTP_POST_VARS, $HTTP_COOKIE_VARS, $HTTP_ENV_VARS, $HTTP_POST_FILES, $HTTP_SESSION_VARS;\r
1054         foreach ($aVars as $varName)\r
1055         {\r
1056                 if (phpversion() >= '4.1.0')\r
1057                 {\r
1058                         if (   isset($_GET[$varName]) \r
1059                                 || isset($_POST[$varName]) \r
1060                                 || isset($_COOKIE[$varName])\r
1061                                 || isset($_ENV[$varName])\r
1062                                 || isset($_SESSION[$varName])\r
1063                                 || isset($_FILES[$varName])\r
1064                         ){\r
1065                                 die('Sorry. An error occurred.');\r
1066                         }\r
1067                 } else {\r
1068                         if (   isset($HTTP_GET_VARS[$varName]) \r
1069                                 || isset($HTTP_POST_VARS[$varName]) \r
1070                                 || isset($HTTP_COOKIE_VARS[$varName])\r
1071                                 || isset($HTTP_ENV_VARS[$varName])\r
1072                                 || isset($HTTP_SESSION_VARS[$varName])\r
1073                                 || isset($HTTP_POST_FILES[$varName])\r
1074                         ){\r
1075                                 die('Sorry. An error occurred.');\r
1076                         }\r
1077                 }\r
1078         }\r
1079 }\r
1080 \r
1081 /** \r
1082  * Stops processing the request and redirects to the given URL.\r
1083  * - no actual contents should have been sent to the output yet\r
1084  * - the URL will be stripped of illegal or dangerous characters\r
1085  */\r
1086 function redirect($url)\r
1087 {\r
1088         $url = preg_replace('|[^a-z0-9-~+_.?#=&;,/:@%]|i', '', $url);\r
1089         header('Location: ' . $url);\r
1090         exit;\r
1091 }\r
1092 \r
1093 ?>\r