OSDN Git Service

Merge branch 'skinnable-master'
[nucleus-jp/nucleus-next.git] / nucleus / libs / globalfunctions.php
1 <<<<<<< HEAD
2 <?php\r
3 \r
4 /*\r
5  * Nucleus: PHP/MySQL Weblog CMS (http://nucleuscms.org/)\r
6  * Copyright (C) 2002-2009 The Nucleus Group\r
7  *\r
8  * This program is free software; you can redistribute it and/or\r
9  * modify it under the terms of the GNU General Public License\r
10  * as published by the Free Software Foundation; either version 2\r
11  * of the License, or (at your option) any later version.\r
12  * (see nucleus/documentation/index.html#license for more info)\r
13  */\r
14 /**\r
15  * @license http://nucleuscms.org/license.txt GNU General Public License\r
16  * @copyright Copyright (C) 2002-2009 The Nucleus Group\r
17  * @version $Id: globalfunctions.php 1856 2012-05-18 09:30:16Z sakamocchi $
18  */\r
19 \r
20 /* needed if we include globalfunctions from install.php */\r
21 global $nucleus, $CONF, $DIR_LIBS, $DIR_LOCALES, $manager, $member, $MYSQL_HANDLER, $StartTime;
22
23 /* just for benchmark tag */
24 $StartTime = microtime(TRUE);
25 \r
26 $nucleus['version'] = 'v4.00 SVN';\r
27 $nucleus['codename'] = '';\r
28 \r
29 /*\r
30  * make sure there's no unnecessary escaping:\r
31  * set_magic_quotes_runtime(0);\r
32  */\r
33 if ( version_compare(PHP_VERSION, '5.3.0', '<') )\r
34 {\r
35         ini_set('magic_quotes_runtime', '0');\r
36 }\r
37 \r
38 /* check and die if someone is trying to override internal globals (when register_globals turn on) */\r
39 checkVars(array('nucleus', 'CONF', 'DIR_LIBS',
40 'MYSQL_HOST', 'MYSQL_USER', 'MYSQL_PASSWORD', 'MYSQL_DATABASE',
41 'DIR_LOCALES', 'DIR_PLUGINS',
42 'HTTP_GET_VARS', 'HTTP_POST_VARS', 'HTTP_COOKIE_VARS', 'HTTP_ENV_VARS',
43 'HTTP_SESSION_VARS', 'HTTP_POST_FILES', 'HTTP_SERVER_VARS',
44 'GLOBALS', 'argv', 'argc', '_GET', '_POST', '_COOKIE', '_ENV', '_SESSION', '_SERVER', '_FILES'));
45 \r
46 if ( !isset($CONF) )\r
47 {\r
48         $CONF = array();\r
49 }\r
50 \r
51 /* debug mode */\r
52 if ( array_key_exists('debug', $CONF) && $CONF['debug'] )\r
53 {\r
54         /* report all errors! */\r
55         error_reporting(E_ALL);\r
56 }\r
57 else\r
58 {\r
59         ini_set('display_errors','0');\r
60         error_reporting(E_ERROR | E_WARNING | E_PARSE);\r
61 }\r
62 \r
63 /*\r
64  * alertOnHeadersSent\r
65  *  Displays an error when visiting a public Nucleus page and headers have\r
66  *  been sent out to early. This usually indicates an error in either a\r
67  *  configuration file or a translation file, and could cause Nucleus to\r
68  *  malfunction\r
69  */\r
70 if ( !array_key_exists('alertOnHeadersSent', $CONF) )\r
71 {\r
72         $CONF['alertOnHeadersSent'] = 1;\r
73 }\r
74 \r
75 /*\r
76  * alertOnSecurityRisk\r
77  * Displays an error only when visiting the admin area, and when one or\r
78  *  more of the installation files (install.php, install.sql, upgrades/\r
79  *  directory) are still on the server.\r
80  */\r
81 if ( !array_key_exists('alertOnSecurityRisk', $CONF) )\r
82 {\r
83         $CONF['alertOnSecurityRisk'] = 1;\r
84 }\r
85 \r
86 /*\r
87  * Set these to 1 to allow viewing of future items or draft items\r
88  * Should really never do this, but can be useful for some plugins that might need to\r
89  * Could cause some other issues if you use future posts otr drafts\r
90  * So use with care\r
91  */\r
92 $CONF['allowDrafts'] = 0;\r
93 $CONF['allowFuture'] = 0;\r
94 \r
95 if ( getNucleusPatchLevel() > 0 )\r
96 {\r
97         $nucleus['version'] .= '/' . getNucleusPatchLevel();\r
98 }\r
99 \r
100 /* Avoid notices */\r
101 if ( !array_key_exists('installscript', $CONF) || empty($CONF['installscript']) )\r
102 {\r
103         $CONF['installscript'] = 0;\r
104 }\r
105 if ( !array_key_exists('UsingAdminArea', $CONF) )\r
106 {\r
107         $CONF['UsingAdminArea'] = 0;\r
108 }\r
109 \r
110 if ( !headers_sent() )\r
111 {\r
112         header('Generator: Nucleus CMS ' . $nucleus['version']);\r
113 }\r
114 \r
115 \r
116 /* TODO: This is for compatibility since 4.0, should be obsoleted at future release. */\r
117 if ( !isset($DIR_LOCALES) )\r
118 {\r
119         $DIR_LOCALES = $DIR_NUCLEUS . 'locales/';\r
120 }\r
121 global $DIR_LANG;\r
122 if ( !isset($DIR_LANG) )\r
123 {\r
124         $DIR_LANG = $DIR_LOCALES;\r
125 }\r
126 \r
127 /* load and initialize i18n class */\r
128 if (!class_exists('i18n', FALSE))\r
129 {\r
130         include($DIR_LIBS . 'i18n.php');\r
131 }\r
132 if ( !i18n::init('UTF-8', $DIR_LOCALES) )\r
133 {\r
134         exit('Fail to initialize i18n class.');\r
135 }\r
136 \r
137 /* TODO: This is just for compatibility since 4.0, should be obsoleted at future release. */\r
138 define('_CHARSET', i18n::get_current_charset());\r
139 \r
140 \r
141 /*\r
142  * NOTE: Since 4.0 release, Entity class becomes to be important class\r
143  *  with some wrapper functions for htmlspechalchars/htmlentity PHP's built-in function\r
144  */\r
145 include($DIR_LIBS . 'ENTITY.php');\r
146 \r
147 /* we will use postVar, getVar, ... methods instead of $_GET, $_POST ... */\r
148 if ( $CONF['installscript'] != 1 )\r
149 {\r
150         /* vars were already included in install.php */\r
151         include_once($DIR_LIBS . 'vars4.1.0.php');\r
152         \r
153         /* added for 4.0 DB::* wrapper and compatibility sql_* */\r
154         include_once($DIR_LIBS . 'sql/sql.php');\r
155 }\r
156 \r
157 /* include core classes that are needed for login & plugin handling */\r
158 include($DIR_LIBS . 'MEMBER.php');\r
159 include($DIR_LIBS . 'ACTIONLOG.php');\r
160 include($DIR_LIBS . 'MANAGER.php');\r
161 include($DIR_LIBS . 'PLUGIN.php');\r
162 \r
163 $manager =& MANAGER::instance();\r
164 \r
165 /* only needed when updating logs */\r
166 if ( $CONF['UsingAdminArea'] )\r
167 {\r
168         /* XML-RPC client classes */\r
169         include($DIR_LIBS . 'xmlrpc.inc.php');\r
170         include($DIR_LIBS . 'ADMIN.php');\r
171 }\r
172 \r
173 \r
174 /* connect to database */\r
175 if ( !isset($MYSQL_HANDLER) )\r
176 {\r
177         $MYSQL_HANDLER = array('mysql','');\r
178 }\r
179 if ( $MYSQL_HANDLER[0] == '' )\r
180 {\r
181         $MYSQL_HANDLER[0] = 'mysql';\r
182 }\r
183 DB::setConnectionInfo($MYSQL_HANDLER[1], $MYSQL_HOST, $MYSQL_USER, $MYSQL_PASSWORD, $MYSQL_DATABASE);\r
184 \r
185 \r
186 /* force locale or charset */\r
187 $locale = '';\r
188 $charset = i18n::get_current_charset();\r
189 \r
190 $data = array(\r
191         'locale'        => &$locale,\r
192         'charset'       => &$charset\r
193 );\r
194 $manager->notify('ForceLocale', $data);\r
195 \r
196 if ( $data['locale'] !== '' )\r
197 {\r
198         i18n::set_forced_locale($data['locale']);\r
199 }\r
200 if ( $data['charset'] !== '' )\r
201 {\r
202         i18n::set_forced_charset($data['charset']);\r
203 }\r
204 unset($locale);\r
205 unset($charset);\r
206 \r
207 \r
208 /* convert forced charset to current charset */\r
209 if ( i18n::get_forced_charset() != i18n::get_current_charset() )\r
210 {\r
211         $_POST          = i18n::convert_array($_POST, i18n::get_forced_charset());\r
212         $_GET           = i18n::convert_array($_GET, i18n::get_forced_charset());\r
213         $_REQUEST       = i18n::convert_array($_REQUEST, i18n::get_forced_charset());\r
214         $_COOKIE        = i18n::convert_array($_COOKIE, i18n::get_forced_charset());\r
215         $_FILES         = i18n::convert_array($_FILES, i18n::get_forced_charset());\r
216         \r
217         if ( session_id() !== '' )\r
218         {\r
219                 $_SESSION = i18n::convert_array($_SESSION, i18n::get_forced_charset());\r
220         }\r
221 }\r
222 \r
223 \r
224 /* sanitize option */\r
225 $bLoggingSanitizedResult = 0;\r
226 $bSanitizeAndContinue = 0;\r
227 $orgRequestURI = serverVar('REQUEST_URI');\r
228 sanitizeParams();\r
229 \r
230 /* logs sanitized result if need */\r
231 if ( $orgRequestURI !== serverVar('REQUEST_URI') )\r
232 {\r
233         $msg = "Sanitized [" . serverVar('REMOTE_ADDR') . "] ";\r
234         $msg .= $orgRequestURI . " -> " . serverVar('REQUEST_URI');\r
235         if ( $bLoggingSanitizedResult )\r
236         {\r
237                 addToLog(WARNING, $msg);\r
238         }\r
239         if ( !$bSanitizeAndContinue )\r
240         {\r
241                 die("");\r
242         }\r
243 }\r
244 \r
245 /* get all variables that can come from the request and put them in the global scope */\r
246 $blogid         = requestVar('blogid');\r
247 $itemid         = intRequestVar('itemid');\r
248 $catid          = intRequestVar('catid');\r
249 $skinid         = requestVar('skinid');\r
250 $memberid       = requestVar('memberid');\r
251 $archivelist = requestVar('archivelist');\r
252 $imagepopup     = requestVar('imagepopup');\r
253 $archive        = requestVar('archive');\r
254 $query          = requestVar('query');\r
255 $highlight      = requestVar('highlight');\r
256 $amount         = requestVar('amount');\r
257 $action         = requestVar('action');\r
258 $nextaction     = requestVar('nextaction');\r
259 $maxresults     = requestVar('maxresults');\r
260 $startpos       = intRequestVar('startpos');\r
261 $errormessage = '';\r
262 $error          = '';\r
263 $special        = requestVar('special');\r
264 \r
265 \r
266 /* read config */\r
267 getConfig();\r
268 \r
269 \r
270 /* Properly set $CONF['Self'] and others if it's not set...\r
271  * usually when we are access from admin menu\r
272  */\r
273 if ( !array_key_exists('Self', $CONF) )\r
274 {\r
275         $CONF['Self'] = $CONF['IndexURL'];\r
276         /* strip trailing */\r
277         if ( $CONF['Self'][i18n::strlen($CONF['Self']) -1] == "/" )\r
278         {\r
279                 $CONF['Self'] = i18n::substr($CONF['Self'], 0, i18n::strlen($CONF['Self']) -1);\r
280         }\r
281 }\r
282 \r
283 $CONF['ItemURL']                = $CONF['Self'];\r
284 $CONF['ArchiveURL']             = $CONF['Self'];\r
285 $CONF['ArchiveListURL'] = $CONF['Self'];\r
286 $CONF['MemberURL']              = $CONF['Self'];\r
287 $CONF['SearchURL']              = $CONF['Self'];\r
288 $CONF['BlogURL']                = $CONF['Self'];\r
289 $CONF['CategoryURL']    = $CONF['Self'];\r
290 \r
291 /* automatically use simpler toolbar for mozilla */\r
292 if ( ($CONF['DisableJsTools'] == 0)\r
293    && i18n::strpos(serverVar('HTTP_USER_AGENT'), 'Mozilla/5.0') !== FALSE\r
294    && i18n::strpos(serverVar('HTTP_USER_AGENT'), 'Gecko') !== FALSE )\r
295 {\r
296         $CONF['DisableJsTools'] = 2;\r
297 }\r
298 \r
299 /* login processing */
300 $member = new Member();\r
301 \r
302 if ( $action == 'login' )\r
303 {\r
304         $login = postVar('login');\r
305         $password = postVar('password');\r
306         $shared = intPostVar('shared');\r
307         $member->login($login, $password, $shared);\r
308 }\r
309 elseif ( ($action == 'logout') )\r
310 {\r
311         $member->logout();\r
312 }\r
313 else\r
314 {\r
315         $member->cookielogin();\r
316 }\r
317 \r
318 \r
319 /* TODO: This is for backward compatibility, should be obsoleted near future. */\r
320 if ( !preg_match('#^(.+)_(.+)_(.+)$#', $CONF['Locale'])\r
321   && ($CONF['Locale'] = i18n::convert_old_language_file_name_to_locale($CONF['Locale'])) === FALSE )\r
322 {\r
323         $CONF['Locale'] = 'en_Latn_US';\r
324 }\r
325 if ( !array_key_exists('Language', $CONF) )\r
326 {\r
327         $CONF['Language'] = i18n::convert_locale_to_old_language_file_name($CONF['Locale']);\r
328 }\r
329 $locale = $CONF['Locale'];\r
330 \r
331 \r
332 /* NOTE: include translation file and set locale */\r
333 if ( $member->isLoggedIn() )\r
334 {\r
335         if ( $member->getLocale() )\r
336         {\r
337                 $locale = $member->getLocale();\r
338         }\r
339 }\r
340 else\r
341 {\r
342         if ( i18n::get_forced_locale() !== '' )\r
343         {\r
344                 $locale = i18n::get_forced_locale();\r
345         }\r
346 }\r
347 include_translation($locale);\r
348 i18n::set_current_locale($locale);\r
349 \r
350 \r
351 /* login completed */\r
352 $manager->notify('PostAuthentication', array('loggedIn' => $member->isLoggedIn() ) );\r
353 \r
354 /* next action */\r
355 if ( $member->isLoggedIn() && $nextaction )\r
356 {\r
357         $action = $nextaction;\r
358 }\r
359 \r
360 /* first, let's see if the site is disabled or not. always allow admin area access. */\r
361 if ( $CONF['DisableSite'] && !$member->isAdmin() && !$CONF['UsingAdminArea'] )\r
362 {\r
363         redirect($CONF['DisableSiteURL']);\r
364         exit;\r
365 }\r
366 \r
367 /* load other classes */\r
368 include($DIR_LIBS . 'PARSER.php');\r
369 include($DIR_LIBS . 'SKIN.php');\r
370 include($DIR_LIBS . 'TEMPLATE.php');\r
371 include($DIR_LIBS . 'BLOG.php');\r
372 include($DIR_LIBS . 'BODYACTIONS.php');\r
373 include($DIR_LIBS . 'COMMENTS.php');\r
374 include($DIR_LIBS . 'COMMENT.php');\r
375 include($DIR_LIBS . 'NOTIFICATION.php');\r
376 include($DIR_LIBS . 'BAN.php');\r
377 include($DIR_LIBS . 'PAGEFACTORY.php');\r
378 include($DIR_LIBS . 'SEARCH.php');\r
379 include($DIR_LIBS . 'LINK.php');\r
380 \r
381 /* set lastVisit cookie (if allowed) */\r
382 if ( !headers_sent() )\r
383 {\r
384         if ( $CONF['LastVisit'] )\r
385         {\r
386                 setcookie($CONF['CookiePrefix'] . 'lastVisit', time(), time() + 2592000, $CONF['CookiePath'], $CONF['CookieDomain'], $CONF['CookieSecure']);\r
387         }\r
388         else\r
389         {\r
390                 setcookie($CONF['CookiePrefix'] . 'lastVisit', '', (time() - 2592000), $CONF['CookiePath'], $CONF['CookieDomain'], $CONF['CookieSecure']);\r
391         }\r
392 }\r
393 \r
394 if ( !defined('_ARCHIVETYPE_MONTH') )\r
395 {\r
396         define('_ARCHIVETYPE_DAY', 'day');\r
397         define('_ARCHIVETYPE_MONTH', 'month');\r
398         define('_ARCHIVETYPE_YEAR', 'year');\r
399 }\r
400 \r
401 /* for path resolving */
402 $virtualpath = getVar('virtualpath');
403 if ( getVar('virtualpath') == '' )
404                                         {\r
405         $virtualpath = serverVar('PATH_INFO');
406                                         }\r
407                                 \r
408 /*
409  * switch URLMode back to normal when $CONF['Self'] ends in .php
410  * this avoids urls like index.php/item/13/index.php/item/15
411  */
412 if ( !array_key_exists('URLMode', $CONF) || ($CONF['URLMode'] != 'pathinfo') )
413                                         {\r
414         $CONF['URLMode'] = 'normal';
415                                         }\r
416 else
417                                         {\r
418         if ( i18n::substr($CONF['Self'], i18n::strlen($CONF['Self']) - 4) != '.php' )
419                                         {\r
420                 decodePathInfo($virtualpath);
421         }\r
422 }\r
423 \r
424 /*\r
425  * PostParseURL is a place to cleanup any of the path-related global variables before the selector function is run.\r
426  * It has 2 values in the data in case the original virtualpath is needed, but most the use will be in tweaking\r
427  * global variables to clean up (scrub out catid or add catid) or to set someother global variable based on\r
428  * the values of something like catid or itemid\r
429  * New in 3.60\r
430  */\r
431 $data = array(\r
432         'type' => basename(serverVar('SCRIPT_NAME')),\r
433         'info' => $virtualpath\r
434 );\r
435 $manager->notify('PostParseURL', $data);\r
436 \r
437 /*\r
438  * NOTE: Here is the end of initialization\r
439  */\r
440 \r
441 /**\r
442  * include_libs()\r
443  * This function includes or requires the specified library file\r
444  * \r
445  * @param       string  $file\r
446  * @param       boolean $once use the _once() version\r
447  * @param       boolean $require use require() instead of include()\r
448  * @return      void\r
449  */\r
450 function include_libs($file, $once = TRUE, $require = TRUE)\r
451 {\r
452         global $DIR_LIBS;\r
453         \r
454         // $DIR_LIBS isn't a directory\r
455         if ( !is_dir($DIR_LIBS) )\r
456         {\r
457                 exit;\r
458         }\r
459         \r
460         $lib_path = $DIR_LIBS . $file;\r
461         \r
462         if ( $once && $require )\r
463         {\r
464                 require_once($lib_path);\r
465         }\r
466         else if ( $once && !$require )\r
467         {\r
468                 include_once($lib_path);\r
469         }\r
470         else if ( $require )\r
471         {\r
472                 require($lib_path);\r
473         }\r
474         else\r
475         {\r
476                 include($lib_path);\r
477         }\r
478         return;\r
479 }\r
480 \r
481 /**\r
482  * include_plugins()\r
483  * This function includes or requires the specified plugin file\r
484  * \r
485  * @param       string  $file\r
486  * @param       boolean $once use the _once() version\r
487  * @param       boolean $require use require() instead of include()\r
488  * @return      \r
489  */\r
490 function include_plugins($file, $once = TRUE, $require = TRUE)\r
491 {\r
492         global $DIR_PLUGINS;\r
493         \r
494         // begin if: $DIR_LIBS isn't a directory\r
495         if ( !is_dir($DIR_PLUGINS) )\r
496         {\r
497                 exit;\r
498         }\r
499         \r
500         $plugin_path = $DIR_PLUGINS . $file;\r
501         \r
502         // begin if: \r
503         if ( $once && $require )\r
504         {\r
505                 require_once($plugin_path);\r
506         }\r
507         else if ( $once && !$require )\r
508         {\r
509                 include_once($plugin_path);\r
510         }\r
511         elseif ( $require )\r
512         {\r
513                 require($plugin_path);\r
514         }\r
515         else\r
516         {\r
517                 include($plugin_path);\r
518         }\r
519         return;\r
520 }\r
521 \r
522 /**\r
523  * include_translation()\r
524  * This function decide which locale is used and include translation\r
525  * \r
526  * @param       string  &$locale        locale name referring to 'language tags' defined in RFC 5646\r
527  * @return      void\r
528  */\r
529 function include_translation(&$locale)\r
530 {\r
531         global $DIR_LOCALES;\r
532         \r
533         $translation_file = $DIR_LOCALES . $locale . '.' . i18n::get_current_charset() . '.php';\r
534         if ( !file_exists($translation_file) )\r
535         {\r
536                 $locale = 'en_Latn_US';\r
537                 $translation_file = $DIR_LOCALES . 'en_Latn_US.ISO-8859-1.php';\r
538         }\r
539         include($translation_file);\r
540         return;\r
541 }\r
542 \r
543 /**\r
544  * intPostVar()\r
545  * This function returns the integer value of $_POST for the variable $name\r
546  * \r
547  * @param       string  $name   field to get the integer value of\r
548  * @return      integer\r
549  */\r
550 function intPostVar($name)\r
551 {\r
552         return (integer) postVar($name);\r
553 }\r
554 \r
555 \r
556 /**\r
557  * intGetVar()\r
558  * This function returns the integer value of $_GET for the variable $name\r
559  * \r
560  * @param       string  $name   field to get the integer value of\r
561  * @return      integer\r
562  */\r
563 function intGetVar($name)\r
564 {\r
565         return (integer) getVar($name);\r
566 }\r
567 \r
568 \r
569 /**\r
570  * intRequestVar()\r
571  * This function returns the integer value of $_REQUEST for the variable $name. Also checks $_GET and $_POST if not found in $_REQUEST\r
572  * \r
573  * @param string $name field to get the integer value of\r
574  * @return int\r
575  */\r
576 function intRequestVar($name)\r
577 {\r
578         return (integer) requestVar($name);\r
579 }\r
580 \r
581 \r
582 /**\r
583  * intCookieVar()\r
584  * This function returns the integer value of $_COOKIE for the variable $name\r
585  * \r
586  * @param       string  $name   field to get the integer value of\r
587  * @return      integer\r
588  */\r
589 function intCookieVar($name)\r
590 {\r
591         return (integer) cookieVar($name);\r
592 }\r
593 \r
594 /**\r
595  * getNucleusVersion()\r
596  * This function returns the current Nucleus version (100 = 1.00, 101 = 1.01, etc...)\r
597  * \r
598  * @param       void\r
599  * @return      integer\r
600  */\r
601 function getNucleusVersion()\r
602 {\r
603         return 400;\r
604 }\r
605 \r
606 /**\r
607  * getNucleusPatchLevel()\r
608  * TODO: Better description of this function.\r
609  *\r
610  * Power users can install patches in between nucleus releases. These patches\r
611  * usually add new functionality in the plugin API and allow those to\r
612  * be tested without having to install CVS.\r
613  *\r
614  *@param        void\r
615  * @return      integer\r
616  */\r
617 function getNucleusPatchLevel()\r
618 {\r
619         return 0;\r
620 }\r
621 \r
622 /**\r
623  * getLatestVersion()\r
624  * This function returns the latest Nucleus version available for download from nucleuscms.org or FALSE if unable to attain data\r
625  * Format will be major.minor/patachlevel e.g. 3.41 or 3.41/02\r
626  * \r
627  * @param       void\r
628  * @return      mixed\r
629  */\r
630 function getLatestVersion()\r
631 {\r
632         // begin if: cURL is not available in this PHP installation\r
633         if ( !function_exists('curl_init') )\r
634         {\r
635                 return FALSE;\r
636         }\r
637         \r
638         $curl = curl_init();\r
639         $timeout = 5;\r
640         \r
641         curl_setopt ($curl, CURLOPT_URL, 'http://nucleuscms.org/version_check.php');\r
642         curl_setopt ($curl, CURLOPT_RETURNTRANSFER, 1);\r
643         curl_setopt ($curl, CURLOPT_CONNECTTIMEOUT, $timeout);\r
644         \r
645         $return = curl_exec($curl);\r
646         \r
647         curl_close($curl);\r
648         \r
649         return $return;\r
650 }\r
651 \r
652 /**\r
653  * sql_table()\r
654  * This function returns a Nucleus table name with the appropriate prefix\r
655  * @param string $name\r
656  * @return string\r
657  */\r
658 function sql_table($name)\r
659 {\r
660         global $MYSQL_PREFIX;\r
661         \r
662         // begin if: no MySQL prefix\r
663         if ( empty($MYSQL_PREFIX) )\r
664         {\r
665                 return 'nucleus_' . $name;\r
666         }\r
667         // else: use MySQL prefix\r
668         else\r
669         {\r
670                 return $MYSQL_PREFIX . 'nucleus_' . $name;\r
671         }\r
672         return;\r
673 }\r
674 \r
675 /**\r
676  * sendContentType()\r
677  * This function sends the Content-Type header if headers have not already been sent\r
678  * It also determines if the browser can accept application/xhtml+xml and sends it only to those that can.\r
679  * \r
680  * if content type is application/xhtml+xml, only send it to browsers\r
681  * that can handle it (IE6 cannot). Otherwise, send text/html\r
682  *\r
683  * v2.5:\r
684  * For admin area pages, keep sending text/html (unless it's a debug version)\r
685  * application/xhtml+xml still causes too much problems with the javascript implementations\r
686  *\r
687  * v3.3:\r
688  * ($CONF['UsingAdminArea'] && !$CONF['debug']) gets removed,\r
689  * application/xhtml+xml seems to be working, so we're going to use it if we can.\r
690  * \r
691  * @param       string  $content_type   MIME media type registered to IANA, http://www.iana.org/assignments/media-types/index.html\r
692  * @param       string  $page_type              \r
693  * @param       string  $charset                Deprecated. This has no meaning.\r
694  * @return      void\r
695  * \r
696  */\r
697 function sendContentType($content_type, $page_type = '', $charset = '')\r
698 {\r
699         global $manager, $CONF;\r
700         \r
701         if ( headers_sent() )\r
702         {\r
703                 return;\r
704         }\r
705         \r
706         /* NOTE: MIME Media Type */\r
707         if ( ($content_type == 'application/xhtml+xml')\r
708                 && (!stristr(serverVar('HTTP_ACCEPT'), 'application/xhtml+xml') ) )\r
709         {\r
710                 $content_type = 'text/html';\r
711         }\r
712         \r
713         /* NOTE: generate event */\r
714         $data = array(\r
715                 'pageType'              =>  $page_type,\r
716                 'contentType'   => &$content_type\r
717         );\r
718         $manager->notify('PreSendContentType', $data);\r
719         \r
720         /* NOTE: confirm MIME Media Type */\r
721         $content_type = preg_replace('#[^a-zA-Z0-9-+./]#', '', $content_type);\r
722         \r
723         /* NOTE: confirm character set */\r
724         $charset = i18n::get_current_charset();\r
725         if ( i18n::get_forced_charset() !== '' )\r
726         {\r
727                 $charset = i18n::get_forced_charset();\r
728         }\r
729         \r
730         /* NOTE: send HTTP 1.1 header */\r
731         header("Content-Type: {$content_type}; charset={$charset}");\r
732         \r
733         /* NOTE: set handler for translating character set */\r
734         if ( $charset != i18n::get_current_charset() )\r
735         {\r
736                 ob_start(array('i18n', 'convert_handler'));\r
737         }\r
738         \r
739         return;\r
740 }\r
741 \r
742 /**\r
743  * parseHighlight()\r
744  * This function parses a query into an array of expressions that can be passed on to the highlight method\r
745  * @param       string  $query\r
746  * @return      void\r
747  */\r
748 function parseHighlight($query)\r
749 {\r
750         // TODO: add more intelligent splitting logic\r
751         \r
752         // get rid of quotes\r
753         $query = preg_replace('/\'|"/', '', $query);\r
754         \r
755         if ( !$query )\r
756         {\r
757                 return array();\r
758         }\r
759         \r
760         $aHighlight = preg_split('# #', $query);\r
761         \r
762         for ( $i = 0; $i < count($aHighlight); $i++ )\r
763         {\r
764                 $aHighlight[$i] = trim($aHighlight[$i]);\r
765                 \r
766                 if ( i18n::strlen($aHighlight[$i]) < 3 )\r
767                 {\r
768                         unset($aHighlight[$i]);\r
769                 }\r
770         }\r
771         \r
772         if ( count($aHighlight) == 1 )\r
773         {\r
774                 return $aHighlight[0];\r
775         }\r
776         else\r
777         {\r
778                 return $aHighlight;\r
779         }\r
780         return;\r
781 }\r
782 \r
783 /**\r
784  * getConfig()\r
785  * \r
786  * @param       void\r
787  * @return      void\r
788  */\r
789 function getConfig()\r
790 {\r
791         global $CONF;\r
792         \r
793         $query = sprintf('SELECT * FROM %s', sql_table('config'));\r
794         $res = DB::getResult($query);\r
795         \r
796         foreach ( $res as $row )\r
797         {\r
798                 $CONF[$row['name']] = $row['value'];\r
799         }\r
800         return;\r
801 }\r
802 \r
803 /**\r
804  * This function gets the blog ID from the blog name\r
805  * @param string $name\r
806  * @return\r
807  */\r
808 function getBlogIDFromName($name)\r
809 {\r
810         $query = sprintf('SELECT bnumber AS result FROM %s WHERE bshortname=%s', sql_table('blog'), DB::quoteValue($name));\r
811         return DB::getValue($query);\r
812 }\r
813 \r
814 /**\r
815  * This function gets the blog name from the blog ID\r
816  * @param int $id\r
817  * @return object\r
818  */\r
819 function getBlogNameFromID($id)\r
820 {\r
821         $query = sprintf('SELECT bname AS result FROM %s WHERE bnumber=%d', sql_table('blog'), intval($id));\r
822         return DB::getValue($query);\r
823 }\r
824 \r
825 /**\r
826  * This function gets the blog ID from the item ID\r
827  * @param int $item_id\r
828  * @return object\r
829  */\r
830 function getBlogIDFromItemID($item_id)\r
831 {\r
832         $query = sprintf('SELECT iblog AS result FROM %s WHERE inumber=%d', sql_table('item'), intval($item_id));\r
833         return DB::getValue($query);\r
834 }\r
835 \r
836 /**\r
837  * This function gets the blog ID from the comment ID\r
838  * @param int $comment_id\r
839  * @return object\r
840  */\r
841 function getBlogIDFromCommentID($comment_id)\r
842 {\r
843         $query = sprintf('SELECT cblog AS result FROM %s WHERE cnumber=%d', sql_table('comment'), intval($comment_id));\r
844         return DB::getValue($query);\r
845 }\r
846 \r
847 /**\r
848  * This function gets the blog ID from the category ID\r
849  * @param int $category_id\r
850  * @return object\r
851  */\r
852 function getBlogIDFromCatID($category_id)\r
853 {\r
854         $query = sprintf('SELECT cblog AS result FROM %s WHERE catid=%d', sql_table('category'), intval($category_id));\r
855         return DB::getValue($query);\r
856 }\r
857 \r
858 /**\r
859  * This function gets the category ID from the category name\r
860  * @param int $name\r
861  * @return object\r
862  */\r
863 function getCatIDFromName($name)\r
864 {\r
865         $query = sprintf('SELECT catid AS result FROM %s WHERE cname=%s', sql_table('category'), DB::quoteValue($name));\r
866         return DB::getValue($query);\r
867 }\r
868 \r
869 \r
870 /**\r
871  * functions to be used in index.php to select something\r
872  */\r
873 function selectBlog($shortname)\r
874 {\r
875         global $blogid, $archivelist;\r
876         $blogid = getBlogIDFromName($shortname);\r
877         \r
878         // also force archivelist variable, if it is set\r
879         if ( $archivelist )\r
880         {\r
881                 $archivelist = $blogid;\r
882         }\r
883         return;\r
884 }\r
885 function selectSkin($skinname)\r
886 {\r
887         global $skinid;\r
888         $skinid = SKIN::getIdFromName($skinname);\r
889         return;\r
890 }\r
891 function selectCategory($cat)\r
892 {\r
893         global $catid;\r
894         if ( is_numeric($cat) )\r
895         {\r
896                 $catid = (integer) $cat;\r
897         }\r
898         else\r
899         {\r
900                 $catid = getCatIDFromName($cat);\r
901         }\r
902         return;\r
903 }\r
904 function selectItem($id)\r
905 {\r
906         global $itemid;\r
907         $itemid = (integer) $id;\r
908         return;\r
909 }\r
910 function selectSpecialSkinType($id)\r
911 {\r
912         global $special;\r
913         $special = strtolower($id);\r
914         return;\r
915 }\r
916 function selector()\r
917 {\r
918         global $archive, $archivelist, $archivenext, $archivenextexists, $archiveprev, $archiveprevexists, $archivetype;\r
919         global $blog, $blogid;\r
920         global $catid;\r
921         global $itemid, $itemidnext, $itemidprev, $itemtitlenext, $itemtitleprev;\r
922         global $CONF, $DIR_LIBS, $amount, $errormessage, $imagepopup;\r
923         global $manager, $maxresults, $query;\r
924         global $member, $memberid, $memberinfo;\r
925         global $skinid, $skinpart, $special;\r
926         \r
927         $actionNames = array('addcomment', 'sendmessage', 'createaccount', 'forgotpassword', 'votepositive', 'votenegative', 'plugin');\r
928         $action = requestVar('action');\r
929         \r
930         if ( in_array($action, $actionNames) )\r
931         {\r
932                 include_once($DIR_LIBS . 'ACTION.php');\r
933                 $a = new Action();\r
934                 $errorInfo = $a->doAction($action);\r
935                 \r
936                 if ( $errorInfo )\r
937                 {\r
938                         $errormessage = $errorInfo['message'];\r
939                 }\r
940         }\r
941         \r
942         // show error when headers already sent out\r
943         if ( headers_sent() && $CONF['alertOnHeadersSent'] )\r
944         {\r
945                 // try to get line number/filename (extra headers_sent params only exists in PHP 4.3+)\r
946                 if ( function_exists('version_compare') && version_compare('4.3.0', phpversion(), '<=') )\r
947                 {\r
948                         headers_sent($hsFile, $hsLine);\r
949                         $extraInfo = ' in <code>' . $hsFile . '</code> line <code>' . $hsLine . '</code>';\r
950                 }\r
951                 else\r
952                 {\r
953                         $extraInfo = '';\r
954                 }\r
955                 \r
956                 startUpError(\r
957                    "<p>The page headers have already been sent out{$extraInfo}. This could cause Nucleus not to work in the expected way.</p>"\r
958                  . "<p>Usually, this is caused by spaces or newlines at the end of the <code>config.php</code> file, "\r
959                  . "at the end of the translation file or at the end of a plugin file.</p>"\r
960                  . "<p>Please check this and try again.</p>"\r
961                  . "<p>If you don't want to see this error message again, without solving the problem, "\r
962                  . "set <code>{$CONF['alertOnHeadersSent']}</code> in <code>globalfunctions.php</code> to <code>0</code></p>"\r
963                  . "Page headers already sent"\r
964                 );\r
965                 exit;\r
966         }\r
967         \r
968         // make is so ?archivelist without blogname or blogid shows the archivelist\r
969         // for the default weblog\r
970         if ( serverVar('QUERY_STRING') == 'archivelist' )\r
971         {\r
972                 $archivelist = $CONF['DefaultBlog'];\r
973         }\r
974         \r
975         // now decide which type of skin we need\r
976         if ( $itemid )\r
977         {\r
978                 // itemid given -> only show that item\r
979                 $type = 'item';\r
980                 \r
981                 if ( !$manager->existsItem($itemid,intval($CONF['allowFuture']),intval($CONF['allowDrafts'])) )\r
982                 {\r
983                         doError(_ERROR_NOSUCHITEM);\r
984                 }\r
985                 \r
986                 // 1. get timestamp, blogid and catid for item\r
987                 $query = 'SELECT itime, iblog, icat FROM %s WHERE inumber=%d';\r
988                 $query = sprintf($query, sql_table('item'), intval($itemid));\r
989                 $row = DB::getRow($query);\r
990                 \r
991                 // if a different blog id has been set through the request or selectBlog(),\r
992                 // deny access\r
993                 \r
994                 if ( $blogid && (intval($blogid) != $row['iblog']) )\r
995                 {\r
996                         doError(_ERROR_NOSUCHITEM);\r
997                 }\r
998                 \r
999                 // if a category has been selected which doesn't match the item, ignore the\r
1000                 // category. #85\r
1001                 if ( ($catid != 0) && ($catid != $row['icat']) )\r
1002                 {\r
1003                         $catid = 0;\r
1004                 }\r
1005                 \r
1006                 $blogid = $row['iblog'];\r
1007                 $timestamp = strtotime($row['itime']);\r
1008                 \r
1009                 $b =& $manager->getBlog($blogid);\r
1010                 \r
1011                 if ( !$b->isValidCategory($catid) )\r
1012                 {\r
1013                         $query = "SELECT inumber, ititle FROM %s WHERE itime<%s AND idraft=0 AND iblog=%d ORDER BY itime DESC LIMIT 1";\r
1014                         $query = sprintf($query, sql_table('item'), DB::formatDateTime($timestamp), intval($blogid));\r
1015                 }\r
1016                 else\r
1017                 {\r
1018                         $query = "SELECT inumber, ititle FROM %s WHERE itime<%s AND idraft=0 AND iblog=%d AND icat=%d ORDER BY itime DESC LIMIT 1";\r
1019                         $query = sprintf($query, sql_table('item'), DB::formatDateTime($timestamp), intval($blogid), intval($catid));\r
1020                 }\r
1021                 $row = DB::getRow($query);\r
1022                 \r
1023                 if ( $row )\r
1024                 {\r
1025                         $itemidprev = $row['inumber'];\r
1026                         $itemtitleprev = $row['ititle'];\r
1027                 }\r
1028                 \r
1029                 // get next itemid and title\r
1030                 if ( !$b->isValidCategory($catid) )\r
1031                 {\r
1032                         $query = "SELECT inumber, ititle FROM %s WHERE itime>%s AND itime<=%s AND idraft=0 AND iblog=%d ORDER BY itime ASC LIMIT 1";\r
1033                         $query = sprintf($query, sql_table('item'), DB::formatDateTime($timestamp), DB::formatDateTime($b->getCorrectTime()), intval($blogid));\r
1034                 }\r
1035                 else\r
1036                 {\r
1037                         $query = "SELECT inumber, ititle FROM %s WHERE itime>%s AND itime<=%s AND idraft=0 AND iblog=%d AND icat=%d ORDER BY itime ASC LIMIT 1";\r
1038                         $query = sprintf($query, sql_table('item'), DB::formatDateTime($timestamp), DB::formatDateTime($b->getCorrectTime()), intval($blogid), intval($catid));\r
1039                 }\r
1040                 $row = DB::getRow($query);\r
1041                 \r
1042                 if ( $row )\r
1043                 {\r
1044                         $itemidnext = $row['inumber'];\r
1045                         $itemtitlenext = $row['ititle'];\r
1046                 }\r
1047         }\r
1048         elseif ( $archive )\r
1049         {\r
1050                 // show archive\r
1051                 $type = 'archive';\r
1052                 \r
1053                 // sql queries for the timestamp of the first and the last published item\r
1054                 $query = sprintf('SELECT UNIX_TIMESTAMP(itime) as result FROM %s WHERE idraft=0 ORDER BY itime ASC', sql_table('item'));\r
1055                 $first_timestamp = DB::getValue($query);\r
1056                 $query = sprintf('SELECT UNIX_TIMESTAMP(itime) as result FROM %s WHERE idraft=0 ORDER BY itime DESC', sql_table('item'));\r
1057                 $last_timestamp = DB::getValue($query);\r
1058                 \r
1059                 sscanf($archive, '%d-%d-%d', $y, $m, $d);\r
1060                 \r
1061                 if ( $d != 0 )\r
1062                 {\r
1063                         $archivetype = _ARCHIVETYPE_DAY;\r
1064                         $t = mktime(0, 0, 0, $m, $d, $y);\r
1065                         // one day has 24 * 60 * 60 = 86400 seconds\r
1066                         $archiveprev = i18n::formatted_datetime('%Y-%m-%d', $t - 86400 );\r
1067                         // check for published items\r
1068                         if ( $t > $first_timestamp )\r
1069                         {\r
1070                                 $archiveprevexists = true;\r
1071                         }\r
1072                         else\r
1073                         {\r
1074                                 $archiveprevexists = false;\r
1075                         }\r
1076                         \r
1077                         // one day later\r
1078                         $t += 86400;\r
1079                         $archivenext = i18n::formatted_datetime('%Y-%m-%d', $t);\r
1080                         if ( $t < $last_timestamp )\r
1081                         {\r
1082                                 $archivenextexists = true;\r
1083                         }\r
1084                         else\r
1085                         {\r
1086                                 $archivenextexists = false;\r
1087                         }\r
1088                 }\r
1089                 elseif ( $m == 0 )\r
1090                 {\r
1091                         $archivetype = _ARCHIVETYPE_YEAR;\r
1092                         $t = mktime(0, 0, 0, 12, 31, $y - 1);\r
1093                         // one day before is in the previous year\r
1094                         $archiveprev = i18n::formatted_datetime('%Y', $t);\r
1095                         if ( $t > $first_timestamp )\r
1096                         {\r
1097                                 $archiveprevexists = true;\r
1098                         }\r
1099                         else\r
1100                         {\r
1101                                 $archiveprevexists = false;\r
1102                         }\r
1103 \r
1104                         // timestamp for the next year\r
1105                         $t = mktime(0, 0, 0, 1, 1, $y + 1);\r
1106                         $archivenext = i18n::formatted_datetime('%Y', $t);\r
1107                         if ( $t < $last_timestamp )\r
1108                         {\r
1109                                 $archivenextexists = true;\r
1110                         }\r
1111                         else\r
1112                         {\r
1113                                 $archivenextexists = false;\r
1114                         }\r
1115                 }\r
1116                 else\r
1117                 {\r
1118                         $archivetype = _ARCHIVETYPE_MONTH;\r
1119                         $t = mktime(0, 0, 0, $m, 1, $y);\r
1120                         // one day before is in the previous month\r
1121                         $archiveprev = i18n::formatted_datetime('%Y-%m', $t - 86400);\r
1122                         if ( $t > $first_timestamp )\r
1123                         {\r
1124                                 $archiveprevexists = true;\r
1125                         }\r
1126                         else\r
1127                         {\r
1128                                 $archiveprevexists = false;\r
1129                         }\r
1130                         \r
1131                         // timestamp for the next month\r
1132                         $t = mktime(0, 0, 0, $m+1, 1, $y);\r
1133                         $archivenext = i18n::formatted_datetime('%Y-%m', $t);\r
1134                         if ( $t < $last_timestamp )\r
1135                         {\r
1136                                 $archivenextexists = true;\r
1137                         }\r
1138                         else\r
1139                         {\r
1140                                 $archivenextexists = false;\r
1141                         }\r
1142                 }\r
1143         }\r
1144         elseif ( $archivelist )\r
1145         {\r
1146                 $type = 'archivelist';\r
1147                 \r
1148                 if ( is_numeric($archivelist) )\r
1149                 {\r
1150                         $blogid = intVal($archivelist);\r
1151                 }\r
1152                 else\r
1153                 {\r
1154                         $blogid = getBlogIDFromName($archivelist);\r
1155                 }\r
1156         \r
1157                 if ( !$blogid )\r
1158                 {\r
1159                         doError(_ERROR_NOSUCHBLOG);\r
1160                 }\r
1161         }\r
1162         elseif ( $query )\r
1163         {\r
1164                 global $startpos;\r
1165                 $type = 'search';\r
1166                 $query = stripslashes($query);\r
1167                 \r
1168                 if ( is_numeric($blogid) )\r
1169                 {\r
1170                         $blogid = intVal($blogid);\r
1171                 }\r
1172                 else\r
1173                 {\r
1174                         $blogid = getBlogIDFromName($blogid);\r
1175                 }\r
1176                 \r
1177                 if ( !$blogid )\r
1178                 {\r
1179                         doError(_ERROR_NOSUCHBLOG);\r
1180                 }\r
1181         }\r
1182         elseif ( $memberid )\r
1183         {\r
1184                 $type = 'member';\r
1185                 \r
1186                 if ( !Member::existsID($memberid) )\r
1187                 {\r
1188                         doError(_ERROR_NOSUCHMEMBER);\r
1189                 }\r
1190                 $memberinfo = $manager->getMember($memberid);\r
1191         }\r
1192         elseif ( $imagepopup )\r
1193         {\r
1194                 // media object (images etc.)\r
1195                 $type = 'imagepopup';\r
1196                 \r
1197                 // TODO: check if media-object exists\r
1198                 // TODO: set some vars?\r
1199         }\r
1200         else\r
1201         {\r
1202                 // show regular index page\r
1203                 global $startpos;\r
1204                 $type = 'index';\r
1205         }\r
1206         \r
1207         // any type of skin with catid\r
1208         if ( $catid && !$blogid )\r
1209         {\r
1210                 $blogid = getBlogIDFromCatID($catid);\r
1211         }\r
1212         \r
1213         // decide which blog should be displayed\r
1214         if ( !$blogid )\r
1215         {\r
1216                 $blogid = $CONF['DefaultBlog'];\r
1217         }\r
1218         \r
1219         $b =& $manager->getBlog($blogid);\r
1220         $blog = $b; // references can't be placed in global variables?\r
1221         \r
1222         if ( !$blog->isValid )\r
1223         {\r
1224                 doError(_ERROR_NOSUCHBLOG);\r
1225         }\r
1226         \r
1227         // set catid if necessary\r
1228         if ( $catid )\r
1229         {\r
1230                 // check if the category is valid\r
1231                 if ( !$blog->isValidCategory($catid) )\r
1232                 {\r
1233                         doError(_ERROR_NOSUCHCATEGORY);\r
1234                 }\r
1235                 else\r
1236                 {\r
1237                         $blog->setSelectedCategory($catid);\r
1238                 }\r
1239         }\r
1240         \r
1241         if ( !$skinid )\r
1242         {\r
1243                 $skinid = $blog->getDefaultSkin();\r
1244         }\r
1245         \r
1246         if ( !empty($special) && isValidShortName($special) )\r
1247         {\r
1248                 $type = strtolower($special);\r
1249         }\r
1250         \r
1251         $skin = new SKIN($skinid);\r
1252         \r
1253         if ( !$skin->isValid() )\r
1254         {\r
1255                 doError(_ERROR_NOSUCHSKIN);\r
1256         }\r
1257         \r
1258         // set global skinpart variable so can determine quickly what is being parsed from any plugin or phpinclude\r
1259         $skinpart = $type;\r
1260         \r
1261         // parse the skin\r
1262         $skin->parse($type);\r
1263         \r
1264         // check to see we should throw JustPosted event\r
1265         $blog->checkJustPosted();\r
1266         return;\r
1267 }\r
1268 \r
1269 /**\r
1270  * doError()\r
1271  * Show error skin with given message. An optional skin-object to use can be given\r
1272  * \r
1273  * @param       string  $msg\r
1274  * @param       string  $skin\r
1275  * @return      void\r
1276  */\r
1277 function doError($msg, $skin = '')\r
1278 {\r
1279         global $errormessage, $CONF, $skinid, $blogid, $manager;\r
1280         \r
1281         if ( $skin == '' )\r
1282         {\r
1283                 if ( Skin::existsID($skinid) )\r
1284                 {\r
1285                         $id = $skinid;\r
1286                 }\r
1287                 elseif ( $manager->existsBlogID($blogid) )\r
1288                 {\r
1289                         $blog =& $manager->getBlog($blogid);\r
1290                         $id = $blog->getDefaultSkin();\r
1291                 }\r
1292                 elseif ($CONF['DefaultBlog'] )\r
1293                 {\r
1294                         $blog =& $manager->getBlog($CONF['DefaultBlog']);\r
1295                         $id = $blog->getDefaultSkin();\r
1296                 }\r
1297                 else\r
1298                 {\r
1299                         // this statement should actually never be executed\r
1300                         $id = $CONF['BaseSkin'];\r
1301                 }\r
1302                 $skin = new Skin($id);\r
1303         }\r
1304         \r
1305         $errormessage = $msg;\r
1306         $skin->parse('error');\r
1307         return;
1308 }\r
1309 \r
1310 /**\r
1311  * Errors before the database connection has been made\r
1312  * \r
1313  * @param       string  $msg    message to notify\r
1314  * @param       string  $title  page title\r
1315  * @return      void\r
1316  */\r
1317 function startUpError($msg, $title)\r
1318 {\r
1319         header('Content-Type: text/xml; charset=' . i18n::get_current_charset());\r
1320         echo "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n";\r
1321         echo "<head>\n";\r
1322         echo "<title>{$title}</title></head>\n";\r
1323         echo "<body>\n";\r
1324         echo "<h1>{$title}</h1>\n";\r
1325         echo $msg;\r
1326         echo "</body>\n";\r
1327         echo "</html>\n";\r
1328         exit;\r
1329 }\r
1330 \r
1331 function isValidShortName($name)\r
1332 {\r
1333         return preg_match('#^[a-z0-9]+$#i', $name);\r
1334 }\r
1335 function isValidDisplayName($name)\r
1336 {\r
1337         return preg_match('#^[a-z0-9]+[a-z0-9 ]*[a-z0-9]+$#i', $name);\r
1338 }\r
1339 function isValidCategoryName($name)\r
1340 {\r
1341         return 1;\r
1342 }\r
1343 function isValidTemplateName($name)\r
1344 {\r
1345         return preg_match('#^[a-z0-9/_\-]+$#i', $name);\r
1346 }\r
1347 function isValidSkinName($name)\r
1348 {\r
1349         return preg_match('#^[a-z0-9/_\-]+$#i', $name);\r
1350 }\r
1351 \r
1352 // add and remove linebreaks\r
1353 function addBreaks($var)\r
1354 {\r
1355         return nl2br($var);\r
1356 }\r
1357 function removeBreaks($var)\r
1358 {\r
1359         return preg_replace("/<br \/>([\r\n])/", "$1", $var);\r
1360 }\r
1361 \r
1362 /**\r
1363  * parseFile()\r
1364  * \r
1365  * @param       string  $filename\r
1366  * @param       string  $includeMode\r
1367  * @param       string  $includePrefix\r
1368  * @return      void\r
1369  */\r
1370 function parseFile($filename, $includeMode = 'normal', $includePrefix = '')\r
1371 {\r
1372         global $skinid;\r
1373         \r
1374         if ( !$skinid || !existsID($skinid) )\r
1375         {\r
1376                 $skin = new Skin($CONF['BaseSkin']);\r
1377         }\r
1378         else\r
1379         {\r
1380                 $skin = new Skin($skinid);\r
1381         }\r
1382         \r
1383         $oldIncludeMode = Parser::getProperty('IncludeMode');\r
1384         $oldIncludePrefix = Parser::getProperty('IncludePrefix');\r
1385         \r
1386         $skin->parse('fileparse', $filename);\r
1387         \r
1388         Parser::setProperty('IncludeMode', $oldIncludeMode);\r
1389         Parser::setProperty('IncludePrefix', $oldIncludePrefix);\r
1390         \r
1391         return;\r
1392 }\r
1393 \r
1394 /**\r
1395  * debug()\r
1396  * Outputs a debug message\r
1397  * \r
1398  * @param       string  $msg\r
1399  * @return      void\r
1400  */\r
1401 function debug($msg)\r
1402 {\r
1403         echo '<p><b>' . $msg . "</b></p>\n";\r
1404         return;\r
1405 }\r
1406 \r
1407 // shows a link to help file\r
1408 function help($id)\r
1409 {\r
1410         echo helpHtml($id);\r
1411         return;\r
1412 }\r
1413 function helpHtml($id)\r
1414 {\r
1415         global $CONF;\r
1416         return helplink($id) . '<img src="' . $CONF['AdminURL'] . 'documentation/icon-help.gif" width="15" height="15" alt="' . _HELP_TT . '" title="' . _HELP_TT . '" /></a>';\r
1417 }\r
1418 function helplink($id)\r
1419 {\r
1420         global $CONF;\r
1421         return '<a href="' . $CONF['AdminURL'] . 'documentation/help.html#'. $id . '" onclick="if (event &amp;&amp; event.preventDefault) event.preventDefault(); return help(this.href);">';\r
1422 }\r
1423 \r
1424 /**\r
1425  * includephp()\r
1426  * Includes a PHP file. This method can be called while parsing templates and skins\r
1427  * \r
1428  * @param       string  $filename       name of file to parse\r
1429  * @return      void\r
1430  */\r
1431 function includephp($filename)\r
1432 {\r
1433         // make predefined variables global, so most simple scripts can be used here\r
1434         \r
1435         // apache (names taken from PHP doc)\r
1436         global $GATEWAY_INTERFACE, $SERVER_NAME, $SERVER_SOFTWARE, $SERVER_PROTOCOL;\r
1437         global $REQUEST_METHOD, $QUERY_STRING, $DOCUMENT_ROOT, $HTTP_ACCEPT;\r
1438         global $HTTP_ACCEPT_CHARSET, $HTTP_ACCEPT_ENCODING, $HTTP_ACCEPT_LANGUAGE;\r
1439         global $HTTP_CONNECTION, $HTTP_HOST, $HTTP_REFERER, $HTTP_USER_AGENT;\r
1440         global $REMOTE_ADDR, $REMOTE_PORT, $SCRIPT_FILENAME, $SERVER_ADMIN;\r
1441         global $SERVER_PORT, $SERVER_SIGNATURE, $PATH_TRANSLATED, $SCRIPT_NAME;\r
1442         global $REQUEST_URI;\r
1443         \r
1444         // php (taken from PHP doc)\r
1445         global $argv, $argc, $PHP_SELF, $HTTP_COOKIE_VARS, $HTTP_GET_VARS, $HTTP_POST_VARS;\r
1446         global $HTTP_POST_FILES, $HTTP_ENV_VARS, $HTTP_SERVER_VARS, $HTTP_SESSION_VARS;\r
1447         \r
1448         // other\r
1449         global $PATH_INFO, $HTTPS, $HTTP_RAW_POST_DATA, $HTTP_X_FORWARDED_FOR;\r
1450         \r
1451         if ( @file_exists($filename) )\r
1452         {\r
1453                 include($filename);\r
1454         }\r
1455         return;\r
1456 }\r
1457 \r
1458 /**\r
1459  * Checks if a certain plugin exists\r
1460  * @param       string  $plug   name of plugin\r
1461  * @return      boolean exists or not\r
1462  */\r
1463 function checkPlugin($name)\r
1464 {\r
1465         global $DIR_PLUGINS;\r
1466         return file_exists($DIR_PLUGINS . preg_replace('#[\\\\|/]#', '', $name) . '.php');\r
1467 }\r
1468 \r
1469 /**\r
1470  * alterQueryStr()\r
1471  * \r
1472  * @param       string  $querystr       querystring to alter (e.g. foo=1&bar=2&x=y)\r
1473  * @param       string  $param  name of parameter to change (e.g. 'foo')\r
1474  * @param       string  $value  New value for that parameter (e.g. 3)\r
1475  * @return      string  altered query string (for the examples above: foo=3&bar=2&x=y)\r
1476  */\r
1477 function alterQueryStr($querystr, $param, $value)\r
1478 {\r
1479         $vars = preg_split('#&#', $querystr);\r
1480         $set = FALSE;\r
1481         \r
1482         for ( $i = 0; $i < count($vars); $i++ )\r
1483         {\r
1484                 $v = preg_split('#=#', $vars[$i]);\r
1485                 \r
1486                 if ( $v[0] == $param )\r
1487                 {\r
1488                         $v[1] = $value;\r
1489                         $vars[$i] = implode('=', $v);\r
1490                         $set = true;\r
1491                         break;\r
1492                 }\r
1493         }\r
1494         if ( !$set )\r
1495         {\r
1496                 $vars[] = "{$param}={$value}";\r
1497         }\r
1498         return ltrim(implode('&', $vars), '&');\r
1499 }\r
1500 \r
1501 /**\r
1502  * passVar()\r
1503  * passes one variable as hidden input field (multiple fields for arrays)\r
1504  * @see passRequestVars in varsx.x.x.php\r
1505  * \r
1506  * @param       string  $key\r
1507  * @param       string  $value\r
1508  * @return      void\r
1509  */\r
1510 function passVar($key, $value)\r
1511 {\r
1512         // array ?\r
1513         if ( is_array($value) )\r
1514         {\r
1515                 for ( $i = 0; $i < sizeof($value); $i++ )\r
1516                 {\r
1517                         passVar($key . '[' . $i . ']', $value[$i]);\r
1518                 }\r
1519                 return;\r
1520         }\r
1521         \r
1522         // other values: do stripslashes if needed\r
1523         echo '<input type="hidden" name="' . Entity::hsc($key) . '" value="' . Entity::hsc(undoMagic($value)) . '" />' . "\n";\r
1524         return;\r
1525 }\r
1526 \r
1527 /**\r
1528  * checkVars()\r
1529  * \r
1530  * @param       string  $variables\r
1531  * @return      void\r
1532  */\r
1533 function checkVars($variables)\r
1534 {\r
1535         foreach ( $variables as $variable )\r
1536         {\r
1537                 if ( array_key_exists($variable, $_GET)\r
1538                   || array_key_exists($variable, $_POST)\r
1539                   || array_key_exists($variable, $_COOKIE)\r
1540                   || array_key_exists($variable, $_ENV)\r
1541                   || (session_id() !== '' && array_key_exists($variable, $_SESSION))\r
1542                   || array_key_exists($variable, $_FILES) )\r
1543                 {\r
1544                         die('Sorry. An error occurred.');\r
1545                 }\r
1546         }\r
1547         return;\r
1548 }\r
1549 \r
1550 /**\r
1551  * sanitizeParams()\r
1552  * Sanitize parameters such as $_GET and $_SERVER['REQUEST_URI'] etc.\r
1553  * to avoid XSS.\r
1554  * \r
1555  * @param       void\r
1556  * @return      void\r
1557  */\r
1558 function sanitizeParams()\r
1559 {\r
1560         $array = array();\r
1561         $str = '';\r
1562         $frontParam = '';\r
1563         \r
1564         // REQUEST_URI of $_SERVER\r
1565         $str =& $_SERVER["REQUEST_URI"];\r
1566         serverStringToArray($str, $array, $frontParam);\r
1567         sanitizeArray($array);\r
1568         arrayToServerString($array, $frontParam, $str);\r
1569         \r
1570         // QUERY_STRING of $_SERVER\r
1571         $str =& $_SERVER["QUERY_STRING"];\r
1572         serverStringToArray($str, $array, $frontParam);\r
1573         sanitizeArray($array);\r
1574         arrayToServerString($array, $frontParam, $str);\r
1575         \r
1576         // $_GET\r
1577         convArrayForSanitizing($_GET, $array);\r
1578         sanitizeArray($array);\r
1579         revertArrayForSanitizing($array, $_GET);\r
1580         \r
1581         // $_REQUEST (only GET param)\r
1582         convArrayForSanitizing($_REQUEST, $array);\r
1583         sanitizeArray($array);\r
1584         revertArrayForSanitizing($array, $_REQUEST);\r
1585         \r
1586         return;\r
1587 }\r
1588 \r
1589 function _addInputTags(&$keys,$prefix='')\r
1590 {\r
1591         foreach ( $keys as $key=>$value )\r
1592         {\r
1593                 if ( $prefix )\r
1594                 {\r
1595                         $key=$prefix.'['.$key.']';\r
1596                 }\r
1597                 if ( is_array($value) )\r
1598                 {\r
1599                         _addInputTags($value,$key);\r
1600                 }\r
1601                 else\r
1602                 {\r
1603                         if ( get_magic_quotes_gpc() )\r
1604                                 {$value=stripslashes($value);\r
1605                         }\r
1606                         if ( $key == 'ticket' )\r
1607                         {\r
1608                                 continue;\r
1609                         }\r
1610                         echo '<input type="hidden" name="'.Entity::hsc($key).\r
1611                              '" value="'.Entity::hsc($value).'" />'."\n";\r
1612                 }\r
1613         }\r
1614         return;\r
1615 }\r
1616 \r
1617 /**\r
1618  * serverStringToArray()\r
1619  * Convert the server string such as $_SERVER['REQUEST_URI']\r
1620  * to arry like arry['blogid']=1 and array['page']=2 etc.\r
1621  * \r
1622  * @param       string   $uri                           string\r
1623  * @param       string  &$query_elements        elements of query according to application/x-www-form-urlencoded\r
1624  * @param       string  &$hier_part                     hierarchical part includes path\r
1625  * \r
1626  * NOTE:\r
1627  * RFC 3986: Uniform Resource Identifiers (URI): Generic Syntax\r
1628  * 3.  Syntax Components\r
1629  * http://www.ietf.org/rfc/rfc3986.txt\r
1630  * \r
1631  * Hypertext Markup Language - 2.0\r
1632  * 8.2.1. The form-urlencoded Media Type\r
1633  * http://tools.ietf.org/html/rfc1866#section-8.2.1\r
1634  * \r
1635  * $_SERVER > Language Reference > Predefined Variables > PHP Manual\r
1636  * http://www.php.net/manual/en/reserved.variables.server.php\r
1637  */\r
1638 function serverStringToArray($uri, &$query_elements, &$hier_part)\r
1639 {\r
1640         // init param\r
1641         $query_elements = array();\r
1642         $hier_part = "";\r
1643         \r
1644         // split hierarchical part, e.g. /index.php, query and fragment, e.g. blogid=1&page=2#section1\r
1645         if ( i18n::strpos($uri, "?") > 0 )\r
1646         {\r
1647                 list($hier_part, $query_and_fragment) = preg_split("#\?#", $uri, 2);\r
1648         }\r
1649         else\r
1650         {\r
1651                 $query_and_fragment = $uri;\r
1652                 $hier_part = '';\r
1653         }\r
1654         \r
1655         // If there is no query like blogid=1&page=2, return\r
1656         if ( i18n::strpos($uri, "=") == FALSE && !i18n::strlen($hier_part) )\r
1657         {\r
1658                 $hier_part = $uri;\r
1659                 return;\r
1660         }\r
1661         \r
1662         $query_elements = preg_split("#&#", $query_and_fragment);\r
1663         return;\r
1664 }\r
1665 \r
1666 /**\r
1667  * arrayToServerString()\r
1668  * Convert array like array['blogid'] to server string\r
1669  * such as $_SERVER['REQUEST_URI']\r
1670  * \r
1671  * @param       array    $query_elements        elements of query according to application/x-www-form-urlencoded\r
1672  * @param       string   $hier_part                     hier-part defined in RFC3986\r
1673  * @param       string  &$uri                           return value\r
1674  * @return      void\r
1675  * \r
1676  * NOTE:\r
1677  * RFC 3986: Uniform Resource Identifiers (URI): Generic Syntax\r
1678  * 3.  Syntax Components\r
1679  * http://www.ietf.org/rfc/rfc3986.txt\r
1680  * \r
1681  * Hypertext Markup Language - 2.0\r
1682  * 8.2.1. The form-urlencoded Media Type\r
1683  * http://tools.ietf.org/html/rfc1866#section-8.2.1\r
1684  * \r
1685  * $_SERVER > Language Reference > Predefined Variables > PHP Manual\r
1686  * http://www.php.net/manual/en/reserved.variables.server.php\r
1687  */\r
1688 function arrayToServerString($query_elements, $hier_part, &$uri)\r
1689 {\r
1690         if ( i18n::strpos($uri, "?") !== FALSE )\r
1691         {\r
1692                 $uri = $hier_part . "?";\r
1693         }\r
1694         else\r
1695         {\r
1696                 $uri = $hier_part;\r
1697         }\r
1698         if ( count($query_elements) > 0 )\r
1699         {\r
1700                 $uri .= implode("&", $query_elements);\r
1701         }\r
1702         return;\r
1703 }\r
1704 \r
1705 /**\r
1706  * sanitizeArray()\r
1707  * Sanitize array parameters.\r
1708  * This function checks both key and value.\r
1709  * - check key if it inclues " (double quote),  remove from array\r
1710  * - check value if it includes \ (escape sequece), remove remaining string\r
1711  * \r
1712  * @param       array   &$array elements of query according to application/x-www-form-urlencoded\r
1713  * @return      void\r
1714  */\r
1715 function sanitizeArray(&$array)\r
1716 {\r
1717         $excludeListForSanitization = array('query');\r
1718         \r
1719         foreach ( $array as $k => $v )\r
1720         {\r
1721                 // split to key and value\r
1722                 list($key, $val) = preg_split("#=#", $v, 2);\r
1723                 if ( !isset($val) )\r
1724                 {\r
1725                         continue;\r
1726                 }\r
1727                 \r
1728                 // when magic quotes is on, need to use stripslashes,\r
1729                 // and then addslashes\r
1730                 if ( get_magic_quotes_gpc() )\r
1731                 {\r
1732                         $val = stripslashes($val);\r
1733                 }\r
1734                 \r
1735                 // note that we must use addslashes here because this function is called before the db connection is made\r
1736                 // and sql_real_escape_string needs a db connection\r
1737                 $val = addslashes($val);\r
1738                 \r
1739                 // if $key is included in exclude list, skip this param\r
1740                 if ( !in_array($key, $excludeListForSanitization) )\r
1741                 {\r
1742                         // check value\r
1743                         if ( i18n::strpos($val, '\\') > 0 )\r
1744                         {\r
1745                                 list($val, $tmp) = preg_split('#\\\\#', $val);\r
1746                         }\r
1747                         \r
1748                         // remove control code etc.\r
1749                         $val = strtr($val, "\0\r\n<>'\"", "       ");\r
1750                         \r
1751                         // check key\r
1752                         if ( preg_match('#\"#', $key) > 0 )\r
1753                         {\r
1754                                 unset($array[$k]);\r
1755                                 continue;\r
1756                         }\r
1757                         \r
1758                         // set sanitized info\r
1759                         $array[$k] = sprintf("%s=%s", $key, $val);\r
1760                 }\r
1761         }\r
1762         return;\r
1763 }\r
1764 \r
1765 /**\r
1766  * convArrayForSanitizing()\r
1767  * Convert array for sanitizeArray function\r
1768  * \r
1769  * @param       string  $src    array to be sanitized\r
1770  * @param       array   &$array array to be temporarily stored\r
1771  * @return      void\r
1772  */\r
1773 function convArrayForSanitizing($src, &$array)\r
1774 {\r
1775         $array = array();\r
1776         foreach ( $src as $key => $val )\r
1777         {\r
1778                 if ( !key_exists($key, $_GET) )\r
1779                 {\r
1780                         continue;\r
1781                 }\r
1782                 $array[] = sprintf("%s=%s", $key, $val);\r
1783                 continue;\r
1784         }\r
1785         return;\r
1786 }\r
1787 \r
1788 /**\r
1789  * revertArrayForSanitizing()\r
1790  * Revert array after sanitizeArray function\r
1791  * \r
1792  * @param       array   $array  element of query according to application/x-www-form-urlencoded\r
1793  * @param       array   &$dst   combination of key and value\r
1794  * @return      void\r
1795  */\r
1796 function revertArrayForSanitizing($array, &$dst)\r
1797 {\r
1798         foreach ( $array as $v )\r
1799         {\r
1800                 list($key, $val) = preg_split("#=#", $v, 2);\r
1801                 $dst[$key] = $val;\r
1802                 continue;\r
1803         }\r
1804         return;\r
1805 }\r
1806 \r
1807 /**\r
1808 =======
1809 <?php
1810
1811 /*
1812  * Nucleus: PHP/MySQL Weblog CMS (http://nucleuscms.org/)
1813  * Copyright (C) 2002-2009 The Nucleus Group
1814  *
1815  * This program is free software; you can redistribute it and/or
1816  * modify it under the terms of the GNU General Public License
1817  * as published by the Free Software Foundation; either version 2
1818  * of the License, or (at your option) any later version.
1819  * (see nucleus/documentation/index.html#license for more info)
1820  */
1821 /**
1822  * @license http://nucleuscms.org/license.txt GNU General Public License
1823  * @copyright Copyright (C) 2002-2009 The Nucleus Group
1824  * @version $Id: globalfunctions.php 1886 2012-06-17 08:27:27Z sakamocchi $
1825  */
1826
1827 /* needed if we include globalfunctions from install.php */
1828 global $nucleus, $CONF, $DIR_LIBS, $DIR_LOCALES, $manager, $member, $MYSQL_HANDLER, $StartTime;
1829
1830 /* just for benchmark tag */
1831 $StartTime = microtime(TRUE);
1832
1833 $nucleus['version'] = 'v4.00 SVN';
1834 $nucleus['codename'] = '';
1835
1836 /*
1837  * make sure there's no unnecessary escaping:
1838  * set_magic_quotes_runtime(0);
1839  */
1840 if ( version_compare(PHP_VERSION, '5.3.0', '<') )
1841 {
1842         ini_set('magic_quotes_runtime', '0');
1843 }
1844
1845 /* check and die if someone is trying to override internal globals (when register_globals turn on) */
1846 checkVars(array('nucleus', 'CONF', 'DIR_LIBS',
1847 'MYSQL_HOST', 'MYSQL_USER', 'MYSQL_PASSWORD', 'MYSQL_DATABASE',
1848 'DIR_LOCALES', 'DIR_PLUGINS',
1849 'HTTP_GET_VARS', 'HTTP_POST_VARS', 'HTTP_COOKIE_VARS', 'HTTP_ENV_VARS',
1850 'HTTP_SESSION_VARS', 'HTTP_POST_FILES', 'HTTP_SERVER_VARS',
1851 'GLOBALS', 'argv', 'argc', '_GET', '_POST', '_COOKIE', '_ENV', '_SESSION', '_SERVER', '_FILES'));
1852
1853 if ( !isset($CONF) )
1854 {
1855         $CONF = array();
1856 }
1857
1858 /* debug mode */
1859 if ( array_key_exists('debug', $CONF) && $CONF['debug'] )
1860 {
1861         /* report all errors! */
1862         error_reporting(E_ALL | E_STRICT);
1863 }
1864 else
1865 {
1866         ini_set('display_errors','0');
1867         error_reporting(E_ERROR | E_WARNING | E_PARSE);
1868 }
1869
1870 /*
1871  * alertOnHeadersSent
1872  *  Displays an error when visiting a public Nucleus page and headers have
1873  *  been sent out to early. This usually indicates an error in either a
1874  *  configuration file or a translation file, and could cause Nucleus to
1875  *  malfunction
1876  */
1877 if ( !array_key_exists('alertOnHeadersSent', $CONF) )
1878 {
1879         $CONF['alertOnHeadersSent'] = 1;
1880 }
1881 /*
1882  * alertOnSecurityRisk
1883  * Displays an error only when visiting the admin area, and when one or
1884  *  more of the installation files (install.php, install.sql, upgrades/
1885  *  directory) are still on the server.
1886  */
1887 if ( !array_key_exists('alertOnSecurityRisk', $CONF) )
1888 {
1889         $CONF['alertOnSecurityRisk'] = 1;
1890 }
1891 /*
1892  * Set these to 1 to allow viewing of future items or draft items
1893  * Should really never do this, but can be useful for some plugins that might need to
1894  * Could cause some other issues if you use future posts otr drafts
1895  * So use with care
1896  */
1897 $CONF['allowDrafts'] = 0;
1898 $CONF['allowFuture'] = 0;
1899
1900 if ( getNucleusPatchLevel() > 0 )
1901 {
1902         $nucleus['version'] .= '/' . getNucleusPatchLevel();
1903 }
1904
1905 /* Avoid notices */
1906 if ( !array_key_exists('installscript', $CONF) || empty($CONF['installscript']) )
1907 {
1908         $CONF['installscript'] = 0;
1909 }
1910 if ( !array_key_exists('UsingAdminArea', $CONF) )
1911 {
1912         $CONF['UsingAdminArea'] = 0;
1913 }
1914
1915 if ( !headers_sent() )
1916 {
1917         header('Generator: Nucleus CMS ' . $nucleus['version']);
1918 }
1919
1920
1921 /* TODO: This is for compatibility since 4.0, should be obsoleted at future release. */
1922 if ( !isset($DIR_LOCALES) )
1923 {
1924         $DIR_LOCALES = $DIR_NUCLEUS . 'locales/';
1925 }
1926 global $DIR_LANG;
1927 if ( !isset($DIR_LANG) )
1928 {
1929         $DIR_LANG = $DIR_LOCALES;
1930 }
1931
1932 /* load and initialize i18n class */
1933 if (!class_exists('i18n', FALSE))
1934 {
1935         include($DIR_LIBS . 'i18n.php');
1936 }
1937 if ( !i18n::init('UTF-8', $DIR_LOCALES) )
1938 {
1939         exit('Fail to initialize i18n class.');
1940 }
1941
1942 /* TODO: This is just for compatibility since 4.0, should be obsoleted at future release. */
1943 define('_CHARSET', i18n::get_current_charset());
1944
1945
1946 /*
1947  * NOTE: Since 4.0 release, Entity class becomes to be important class
1948  *  with some wrapper functions for htmlspechalchars/htmlentity PHP's built-in function
1949  */
1950 include($DIR_LIBS . 'ENTITY.php');
1951
1952 /* we will use postVar, getVar, ... methods instead of $_GET, $_POST ... */
1953 if ( $CONF['installscript'] != 1 )
1954 {
1955         /* vars were already included in install.php */
1956         include_once($DIR_LIBS . 'vars4.1.0.php');
1957         
1958         /* added for 4.0 DB::* wrapper and compatibility sql_* */
1959         include_once($DIR_LIBS . 'sql/sql.php');
1960 }
1961
1962 /* include core classes that are needed for login & plugin handling */
1963 include($DIR_LIBS . 'MEMBER.php');
1964 include($DIR_LIBS . 'ACTIONLOG.php');
1965 include($DIR_LIBS . 'MANAGER.php');
1966 include($DIR_LIBS . 'PLUGIN.php');
1967
1968 $manager =& MANAGER::instance();
1969
1970 /* only needed when updating logs */
1971 if ( $CONF['UsingAdminArea'] )
1972 {
1973         /* XML-RPC client classes */
1974         include($DIR_LIBS . 'xmlrpc.inc.php');
1975         include($DIR_LIBS . 'ADMIN.php');
1976 }
1977
1978
1979 /* connect to database */
1980 if ( !isset($MYSQL_HANDLER) )
1981 {
1982         $MYSQL_HANDLER = array('mysql','');
1983 }
1984 if ( $MYSQL_HANDLER[0] == '' )
1985 {
1986         $MYSQL_HANDLER[0] = 'mysql';
1987 }
1988 DB::setConnectionInfo($MYSQL_HANDLER[1], $MYSQL_HOST, $MYSQL_USER, $MYSQL_PASSWORD, $MYSQL_DATABASE);
1989
1990
1991 /* force locale or charset */
1992 $locale = '';
1993 $charset = i18n::get_current_charset();
1994
1995 $data = array(
1996         'locale'        => &$locale,
1997         'charset'       => &$charset
1998 );
1999 $manager->notify('ForceLocale', $data);
2000
2001 if ( $data['locale'] !== '' )
2002 {
2003         i18n::set_forced_locale($data['locale']);
2004 }
2005 if ( $data['charset'] !== '' )
2006 {
2007         i18n::set_forced_charset($data['charset']);
2008 }
2009 unset($locale);
2010 unset($charset);
2011
2012
2013 /* convert forced charset to current charset */
2014 if ( i18n::get_forced_charset() != i18n::get_current_charset() )
2015 {
2016         $_POST          = i18n::convert_array($_POST, i18n::get_forced_charset());
2017         $_GET           = i18n::convert_array($_GET, i18n::get_forced_charset());
2018         $_REQUEST       = i18n::convert_array($_REQUEST, i18n::get_forced_charset());
2019         $_COOKIE        = i18n::convert_array($_COOKIE, i18n::get_forced_charset());
2020         $_FILES         = i18n::convert_array($_FILES, i18n::get_forced_charset());
2021         
2022         if ( session_id() !== '' )
2023         {
2024                 $_SESSION = i18n::convert_array($_SESSION, i18n::get_forced_charset());
2025         }
2026 }
2027
2028
2029 /* sanitize option */
2030 $bLoggingSanitizedResult = 0;
2031 $bSanitizeAndContinue = 0;
2032 $orgRequestURI = serverVar('REQUEST_URI');
2033 sanitizeParams();
2034
2035 /* logs sanitized result if need */
2036 if ( $orgRequestURI !== serverVar('REQUEST_URI') )
2037 {
2038         $msg = "Sanitized [" . serverVar('REMOTE_ADDR') . "] ";
2039         $msg .= $orgRequestURI . " -> " . serverVar('REQUEST_URI');
2040         if ( $bLoggingSanitizedResult )
2041         {
2042                 addToLog(WARNING, $msg);
2043         }
2044         if ( !$bSanitizeAndContinue )
2045         {
2046                 die("");
2047         }
2048 }
2049
2050 /* get all variables that can come from the request and put them in the global scope */
2051 $blogid         = requestVar('blogid');
2052 $itemid         = intRequestVar('itemid');
2053 $catid          = intRequestVar('catid');
2054 $skinid         = requestVar('skinid');
2055 $memberid       = requestVar('memberid');
2056 $archivelist = requestVar('archivelist');
2057 $imagepopup     = requestVar('imagepopup');
2058 $archive        = requestVar('archive');
2059 $query          = requestVar('query');
2060 $highlight      = requestVar('highlight');
2061 $amount         = requestVar('amount');
2062 $action         = requestVar('action');
2063 $nextaction     = requestVar('nextaction');
2064 $maxresults     = requestVar('maxresults');
2065 $startpos       = intRequestVar('startpos');
2066 $errormessage = '';
2067 $error          = '';
2068 $special        = requestVar('special');
2069
2070
2071 /* read config */
2072 getConfig();
2073
2074
2075 /* Properly set $CONF['Self'] and others if it's not set...
2076  * usually when we are access from admin menu
2077  */
2078 if ( !array_key_exists('Self', $CONF) )
2079 {
2080         $CONF['Self'] = $CONF['IndexURL'];
2081         /* strip trailing */
2082         if ( $CONF['Self'][i18n::strlen($CONF['Self']) -1] == "/" )
2083         {
2084                 $CONF['Self'] = i18n::substr($CONF['Self'], 0, i18n::strlen($CONF['Self']) -1);
2085         }
2086 }
2087
2088 $CONF['ItemURL']                = $CONF['Self'];
2089 $CONF['ArchiveURL']             = $CONF['Self'];
2090 $CONF['ArchiveListURL'] = $CONF['Self'];
2091 $CONF['MemberURL']              = $CONF['Self'];
2092 $CONF['SearchURL']              = $CONF['Self'];
2093 $CONF['BlogURL']                = $CONF['Self'];
2094 $CONF['CategoryURL']    = $CONF['Self'];
2095
2096 /* automatically use simpler toolbar for mozilla */
2097 if ( ($CONF['DisableJsTools'] == 0)
2098    && i18n::strpos(serverVar('HTTP_USER_AGENT'), 'Mozilla/5.0') !== FALSE
2099    && i18n::strpos(serverVar('HTTP_USER_AGENT'), 'Gecko') !== FALSE )
2100 {
2101         $CONF['DisableJsTools'] = 2;
2102 }
2103
2104 /* login processing */
2105 $member = new Member();
2106 if ( $action == 'login' )
2107 {
2108         $login = postVar('login');
2109         $password = postVar('password');
2110         $shared = intPostVar('shared');
2111         $member->login($login, $password, $shared);
2112 }
2113 elseif ( ($action == 'logout') )
2114 {
2115         $member->logout();
2116 }
2117 else
2118 {
2119         $member->cookielogin();
2120 }
2121
2122 /* TODO: This is for backward compatibility, should be obsoleted near future. */
2123 if ( !preg_match('#^(.+)_(.+)_(.+)$#', $CONF['Locale'])
2124   && ($CONF['Locale'] = i18n::convert_old_language_file_name_to_locale($CONF['Locale'])) === FALSE )
2125 {
2126         $CONF['Locale'] = 'en_Latn_US';
2127 }
2128 if ( !array_key_exists('Language', $CONF) )
2129 {
2130         $CONF['Language'] = i18n::convert_locale_to_old_language_file_name($CONF['Locale']);
2131 }
2132 $locale = $CONF['Locale'];
2133
2134
2135 /* NOTE: include translation file and set locale */
2136 if ( $member->isLoggedIn() )
2137 {
2138         if ( $member->getLocale() )
2139         {
2140                 $locale = $member->getLocale();
2141         }
2142 }
2143 else
2144 {
2145         if ( i18n::get_forced_locale() !== '' )
2146         {
2147                 $locale = i18n::get_forced_locale();
2148         }
2149 }
2150 include_translation($locale);
2151 i18n::set_current_locale($locale);
2152
2153
2154 /* login completed */
2155 $data = array('loggedIn' => $member->isLoggedIn());
2156 $manager->notify('PostAuthentication', $data);
2157
2158 /* next action */
2159 if ( $member->isLoggedIn() && $nextaction )
2160 {
2161         $action = $nextaction;
2162 }
2163
2164 /* first, let's see if the site is disabled or not. always allow admin area access. */
2165 if ( $CONF['DisableSite'] && !$member->isAdmin() && !$CONF['UsingAdminArea'] )
2166 {
2167         redirect($CONF['DisableSiteURL']);
2168         exit;
2169 }
2170
2171 /* load other classes */
2172 include($DIR_LIBS . 'PARSER.php');
2173 include($DIR_LIBS . 'SKIN.php');
2174 include($DIR_LIBS . 'TEMPLATE.php');
2175 include($DIR_LIBS . 'BLOG.php');
2176 include($DIR_LIBS . 'BODYACTIONS.php');
2177 include($DIR_LIBS . 'COMMENTS.php');
2178 include($DIR_LIBS . 'COMMENT.php');
2179 include($DIR_LIBS . 'NOTIFICATION.php');
2180 include($DIR_LIBS . 'BAN.php');
2181 include($DIR_LIBS . 'SEARCH.php');
2182 include($DIR_LIBS . 'LINK.php');
2183
2184 /* set lastVisit cookie (if allowed) */
2185 if ( !headers_sent() )
2186 {
2187         if ( $CONF['LastVisit'] )
2188         {
2189                 setcookie($CONF['CookiePrefix'] . 'lastVisit', time(), time() + 2592000, $CONF['CookiePath'], $CONF['CookieDomain'], $CONF['CookieSecure']);
2190         }
2191         else
2192         {
2193                 setcookie($CONF['CookiePrefix'] . 'lastVisit', '', (time() - 2592000), $CONF['CookiePath'], $CONF['CookieDomain'], $CONF['CookieSecure']);
2194         }
2195 }
2196
2197 /* for path resolving */
2198 $virtualpath = getVar('virtualpath');
2199 if ( getVar('virtualpath') == '' )
2200 {
2201         $virtualpath = serverVar('PATH_INFO');
2202 }
2203
2204 /*
2205  * switch URLMode back to normal when $CONF['Self'] ends in .php
2206  * this avoids urls like index.php/item/13/index.php/item/15
2207  */
2208 if ( !array_key_exists('URLMode', $CONF) || ($CONF['URLMode'] != 'pathinfo') )
2209 {
2210         $CONF['URLMode'] = 'normal';
2211 }
2212 else
2213 {
2214         if ( i18n::substr($CONF['Self'], i18n::strlen($CONF['Self']) - 4) != '.php' )
2215         {
2216                 decodePathInfo($virtualpath);
2217         }
2218 }
2219
2220 /*
2221  * PostParseURL is a place to cleanup any of the path-related global variables before the selector function is run.
2222  * It has 2 values in the data in case the original virtualpath is needed, but most the use will be in tweaking
2223  * global variables to clean up (scrub out catid or add catid) or to set someother global variable based on
2224  * the values of something like catid or itemid
2225  * New in 3.60
2226  */
2227 $data = array(
2228         'type' => basename(serverVar('SCRIPT_NAME')),
2229         'info' => $virtualpath
2230 );
2231 $manager->notify('PostParseURL', $data);
2232
2233 /*
2234  * NOTE: Here is the end of initialization
2235  */
2236
2237 /**
2238  * include_libs()
2239  * This function includes or requires the specified library file
2240  * 
2241  * @param       string  $file
2242  * @param       boolean $once use the _once() version
2243  * @param       boolean $require use require() instead of include()
2244  * @return      void
2245  */
2246 function include_libs($file, $once = TRUE, $require = TRUE)
2247 {
2248         global $DIR_LIBS;
2249         
2250         // $DIR_LIBS isn't a directory
2251         if ( !is_dir($DIR_LIBS) )
2252         {
2253                 exit;
2254         }
2255         
2256         $lib_path = $DIR_LIBS . $file;
2257         
2258         if ( $once && $require )
2259         {
2260                 require_once($lib_path);
2261         }
2262         else if ( $once && !$require )
2263         {
2264                 include_once($lib_path);
2265         }
2266         else if ( $require )
2267         {
2268                 require($lib_path);
2269         }
2270         else
2271         {
2272                 include($lib_path);
2273         }
2274         return;
2275 }
2276
2277 /**
2278  * include_plugins()
2279  * This function includes or requires the specified plugin file
2280  * 
2281  * @param       string  $file
2282  * @param       boolean $once use the _once() version
2283  * @param       boolean $require use require() instead of include()
2284  * @return      
2285  */
2286 function include_plugins($file, $once = TRUE, $require = TRUE)
2287 {
2288         global $DIR_PLUGINS;
2289         
2290         // begin if: $DIR_LIBS isn't a directory
2291         if ( !is_dir($DIR_PLUGINS) )
2292         {
2293                 exit;
2294         }
2295         
2296         $plugin_path = $DIR_PLUGINS . $file;
2297         
2298         // begin if: 
2299         if ( $once && $require )
2300         {
2301                 require_once($plugin_path);
2302         }
2303         else if ( $once && !$require )
2304         {
2305                 include_once($plugin_path);
2306         }
2307         elseif ( $require )
2308         {
2309                 require($plugin_path);
2310         }
2311         else
2312         {
2313                 include($plugin_path);
2314         }
2315         return;
2316 }
2317
2318 /**
2319  * include_translation()
2320  * This function decide which locale is used and include translation
2321  * 
2322  * @param       string  &$locale        locale name referring to 'language tags' defined in RFC 5646
2323  * @return      void
2324  */
2325 function include_translation(&$locale)
2326 {
2327         global $DIR_LOCALES;
2328         
2329         $translation_file = $DIR_LOCALES . $locale . '.' . i18n::get_current_charset() . '.php';
2330         if ( !file_exists($translation_file) )
2331         {
2332                 $locale = 'en_Latn_US';
2333                 $translation_file = $DIR_LOCALES . 'en_Latn_US.ISO-8859-1.php';
2334         }
2335         include($translation_file);
2336         
2337         /*
2338          * NOTE:
2339          * PHP is written by C and utilize C library, whose APIs are defined in POSIX.
2340          * 
2341          * setlocale() is one of APIs of C library.
2342          * but the argument value for setlocale() depends on each implements
2343          * 
2344          * The latest POSIX standard:
2345          * The Open Group Base Specifications Issue 7
2346          * IEEE Std 1003.1™-2008
2347          * http://pubs.opengroup.org/onlinepubs/9699919799/mindex.html
2348          * 
2349          * Microsoft's operating system uses their own implementation
2350          *  Language Strings
2351          *   http://msdn.microsoft.com/en-us/library/39cwe7zf%28v=vs.110%29.aspx
2352          *  Country/Region Strings
2353          *   http://msdn.microsoft.com/en-us/library/cdax410z%28v=vs.110%29.aspx
2354          * 
2355          * Linux and Unix (in this meaning, Apple's OS X derives from UNIX) uses ISO standard.
2356          *  two characters language tag (ISO 639-1)
2357          *  two characters region and country lag (ISO 3166-1 alpha-1)
2358          * 
2359          */
2360         if ( PHP_OS == "WIN32" || PHP_OS == "WINNT" )
2361         {
2362                 /* LOCALE_IN_WINDOWS is defined in each translation files */
2363                 setlocale(LC_ALL, _LOCALE_IN_WINDOWS);
2364         }
2365         else
2366         {
2367                 setlocale(LC_ALL, preg_replace('#(.+)_(.+)_(.+)#', '$1-$3', $locale));
2368         }
2369         return;
2370 }
2371
2372 /**
2373  * intPostVar()
2374  * This function returns the integer value of $_POST for the variable $name
2375  * 
2376  * @param       string  $name   field to get the integer value of
2377  * @return      integer
2378  */
2379 function intPostVar($name)
2380 {
2381         return (integer) postVar($name);
2382 }
2383
2384
2385 /**
2386  * intGetVar()
2387  * This function returns the integer value of $_GET for the variable $name
2388  * 
2389  * @param       string  $name   field to get the integer value of
2390  * @return      integer
2391  */
2392 function intGetVar($name)
2393 {
2394         return (integer) getVar($name);
2395 }
2396
2397
2398 /**
2399  * intRequestVar()
2400  * This function returns the integer value of $_REQUEST for the variable $name. Also checks $_GET and $_POST if not found in $_REQUEST
2401  * 
2402  * @param string $name field to get the integer value of
2403  * @return int
2404  */
2405 function intRequestVar($name)
2406 {
2407         return (integer) requestVar($name);
2408 }
2409
2410
2411 /**
2412  * intCookieVar()
2413  * This function returns the integer value of $_COOKIE for the variable $name
2414  * 
2415  * @param       string  $name   field to get the integer value of
2416  * @return      integer
2417  */
2418 function intCookieVar($name)
2419 {
2420         return (integer) cookieVar($name);
2421 }
2422
2423 /**
2424  * getNucleusVersion()
2425  * This function returns the current Nucleus version (100 = 1.00, 101 = 1.01, etc...)
2426  * 
2427  * @param       void
2428  * @return      integer
2429  */
2430 function getNucleusVersion()
2431 {
2432         return 400;
2433 }
2434
2435 /**
2436  * getNucleusPatchLevel()
2437  * TODO: Better description of this function.
2438  *
2439  * Power users can install patches in between nucleus releases. These patches
2440  * usually add new functionality in the plugin API and allow those to
2441  * be tested without having to install CVS.
2442  *
2443  *@param        void
2444  * @return      integer
2445  */
2446 function getNucleusPatchLevel()
2447 {
2448         return 0;
2449 }
2450
2451 /**
2452  * getLatestVersion()
2453  * This function returns the latest Nucleus version available for download from nucleuscms.org or FALSE if unable to attain data
2454  * Format will be major.minor/patachlevel e.g. 3.41 or 3.41/02
2455  * 
2456  * @param       void
2457  * @return      mixed
2458  */
2459 function getLatestVersion()
2460 {
2461         // begin if: cURL is not available in this PHP installation
2462         if ( !function_exists('curl_init') )
2463         {
2464                 return FALSE;
2465         }
2466         
2467         $curl = curl_init();
2468         $timeout = 5;
2469         
2470         curl_setopt ($curl, CURLOPT_URL, 'http://nucleuscms.org/version_check.php');
2471         curl_setopt ($curl, CURLOPT_RETURNTRANSFER, 1);
2472         curl_setopt ($curl, CURLOPT_CONNECTTIMEOUT, $timeout);
2473         
2474         $return = curl_exec($curl);
2475         
2476         curl_close($curl);
2477         
2478         return $return;
2479 }
2480
2481 /**
2482  * sql_table()
2483  * This function returns a Nucleus table name with the appropriate prefix
2484  * @param string $name
2485  * @return string
2486  */
2487 function sql_table($name)
2488 {
2489         global $MYSQL_PREFIX;
2490         
2491         // begin if: no MySQL prefix
2492         if ( empty($MYSQL_PREFIX) )
2493         {
2494                 return 'nucleus_' . $name;
2495         }
2496         // else: use MySQL prefix
2497         else
2498         {
2499                 return $MYSQL_PREFIX . 'nucleus_' . $name;
2500         }
2501         return;
2502 }
2503
2504 /**
2505  * sendContentType()
2506  * This function sends the Content-Type header if headers have not already been sent
2507  * It also determines if the browser can accept application/xhtml+xml and sends it only to those that can.
2508  * 
2509  * if content type is application/xhtml+xml, only send it to browsers
2510  * that can handle it (IE6 cannot). Otherwise, send text/html
2511  *
2512  * v2.5:
2513  * For admin area pages, keep sending text/html (unless it's a debug version)
2514  * application/xhtml+xml still causes too much problems with the javascript implementations
2515  *
2516  * v3.3:
2517  * ($CONF['UsingAdminArea'] && !$CONF['debug']) gets removed,
2518  * application/xhtml+xml seems to be working, so we're going to use it if we can.
2519  * 
2520  * @param       string  $content_type   MIME media type registered to IANA, http://www.iana.org/assignments/media-types/index.html
2521  * @param       string  $page_type              
2522  * @param       string  $charset                Deprecated. This has no meaning.
2523  * @return      void
2524  * 
2525  */
2526 function sendContentType($content_type, $page_type = '', $charset = '')
2527 {
2528         global $manager, $CONF;
2529         
2530         if ( headers_sent() )
2531         {
2532                 return;
2533         }
2534         
2535         /* NOTE: MIME Media Type */
2536         if ( ($content_type == 'application/xhtml+xml')
2537                 && (!stristr(serverVar('HTTP_ACCEPT'), 'application/xhtml+xml') ) )
2538         {
2539                 $content_type = 'text/html';
2540         }
2541         
2542         /* NOTE: generate event */
2543         $data = array(
2544                 'pageType'              =>  $page_type,
2545                 'contentType'   => &$content_type
2546         );
2547         $manager->notify('PreSendContentType', $data);
2548         
2549         /* NOTE: confirm MIME Media Type */
2550         $content_type = preg_replace('#[^a-zA-Z0-9-+./]#', '', $content_type);
2551         
2552         /* NOTE: confirm character set */
2553         $charset = i18n::get_current_charset();
2554         if ( i18n::get_forced_charset() !== '' )
2555         {
2556                 $charset = i18n::get_forced_charset();
2557         }
2558         
2559         /* NOTE: send HTTP 1.1 header */
2560         header("Content-Type: {$content_type}; charset={$charset}");
2561         
2562         /* NOTE: set handler for translating character set */
2563         if ( $charset != i18n::get_current_charset() )
2564         {
2565                 ob_start(array('i18n', 'convert_handler'));
2566         }
2567         
2568         return;
2569 }
2570
2571 /**
2572  * parseHighlight()
2573  * This function parses a query into an array of expressions that can be passed on to the highlight method
2574  * @param       string  $query
2575  * @return      void
2576  */
2577 function parseHighlight($query)
2578 {
2579         // TODO: add more intelligent splitting logic
2580         
2581         // get rid of quotes
2582         $query = preg_replace('/\'|"/', '', $query);
2583         
2584         if ( !$query )
2585         {
2586                 return array();
2587         }
2588         
2589         $aHighlight = preg_split('# #', $query);
2590         
2591         for ( $i = 0; $i < count($aHighlight); $i++ )
2592         {
2593                 $aHighlight[$i] = trim($aHighlight[$i]);
2594                 
2595                 if ( i18n::strlen($aHighlight[$i]) < 3 )
2596                 {
2597                         unset($aHighlight[$i]);
2598                 }
2599         }
2600         
2601         if ( count($aHighlight) == 1 )
2602         {
2603                 return $aHighlight[0];
2604         }
2605         else
2606         {
2607                 return $aHighlight;
2608         }
2609         return;
2610 }
2611
2612 /**
2613  * getConfig()
2614  * 
2615  * @param       void
2616  * @return      void
2617  */
2618 function getConfig()
2619 {
2620         global $CONF;
2621         
2622         $query = sprintf('SELECT * FROM %s', sql_table('config'));
2623         $res = DB::getResult($query);
2624         
2625         foreach ( $res as $row )
2626         {
2627                 $CONF[$row['name']] = $row['value'];
2628         }
2629         return;
2630 }
2631
2632 /**
2633  * This function gets the blog ID from the blog name
2634  * @param string $name
2635  * @return
2636  */
2637 function getBlogIDFromName($name)
2638 {
2639         $query = sprintf('SELECT bnumber AS result FROM %s WHERE bshortname=%s', sql_table('blog'), DB::quoteValue($name));
2640         return DB::getValue($query);
2641 }
2642
2643 /**
2644  * This function gets the blog name from the blog ID
2645  * @param int $id
2646  * @return object
2647  */
2648 function getBlogNameFromID($id)
2649 {
2650         $query = sprintf('SELECT bname AS result FROM %s WHERE bnumber=%d', sql_table('blog'), intval($id));
2651         return DB::getValue($query);
2652 }
2653
2654 /**
2655  * This function gets the blog ID from the item ID
2656  * @param int $item_id
2657  * @return object
2658  */
2659 function getBlogIDFromItemID($item_id)
2660 {
2661         $query = sprintf('SELECT iblog AS result FROM %s WHERE inumber=%d', sql_table('item'), intval($item_id));
2662         return DB::getValue($query);
2663 }
2664
2665 /**
2666  * This function gets the blog ID from the comment ID
2667  * @param int $comment_id
2668  * @return object
2669  */
2670 function getBlogIDFromCommentID($comment_id)
2671 {
2672         $query = sprintf('SELECT cblog AS result FROM %s WHERE cnumber=%d', sql_table('comment'), intval($comment_id));
2673         return DB::getValue($query);
2674 }
2675
2676 /**
2677  * This function gets the blog ID from the category ID
2678  * @param int $category_id
2679  * @return object
2680  */
2681 function getBlogIDFromCatID($category_id)
2682 {
2683         $query = sprintf('SELECT cblog AS result FROM %s WHERE catid=%d', sql_table('category'), intval($category_id));
2684         return DB::getValue($query);
2685 }
2686
2687 /**
2688  * This function gets the category ID from the category name
2689  * @param int $name
2690  * @return object
2691  */
2692 function getCatIDFromName($name)
2693 {
2694         $query = sprintf('SELECT catid AS result FROM %s WHERE cname=%s', sql_table('category'), DB::quoteValue($name));
2695         return DB::getValue($query);
2696 }
2697
2698
2699 /**
2700  * functions to be used in index.php to select something
2701  */
2702 function selectBlog($shortname)
2703 {
2704         global $blogid, $archivelist;
2705         $blogid = getBlogIDFromName($shortname);
2706         
2707         // also force archivelist variable, if it is set
2708         if ( $archivelist )
2709         {
2710                 $archivelist = $blogid;
2711         }
2712         return;
2713 }
2714 function selectSkin($skinname)
2715 {
2716         global $skinid;
2717         $skinid = SKIN::getIdFromName($skinname);
2718         return;
2719 }
2720 function selectCategory($cat)
2721 {
2722         global $catid;
2723         if ( is_numeric($cat) )
2724         {
2725                 $catid = (integer) $cat;
2726         }
2727         else
2728         {
2729                 $catid = getCatIDFromName($cat);
2730         }
2731         return;
2732 }
2733 function selectItem($id)
2734 {
2735         global $itemid;
2736         $itemid = (integer) $id;
2737         return;
2738 }
2739 function selectSpecialSkinType($id)
2740 {
2741         global $special;
2742         $special = strtolower($id);
2743         return;
2744 }
2745 function selector()
2746 {
2747         global $archive, $archivelist, $archivenext, $archivenextexists, $archiveprev, $archiveprevexists, $archivetype;
2748         global $blog, $blogid;
2749         global $catid;
2750         global $itemid, $itemidnext, $itemidprev, $itemtitlenext, $itemtitleprev;
2751         global $CONF, $DIR_LIBS, $amount, $errormessage, $imagepopup;
2752         global $manager, $maxresults, $query;
2753         global $member, $memberid, $memberinfo;
2754         global $skinid, $skinpart, $special;
2755         
2756         $actionNames = array('addcomment', 'sendmessage', 'createaccount', 'forgotpassword', 'votepositive', 'votenegative', 'plugin');
2757         $action = requestVar('action');
2758         
2759         if ( in_array($action, $actionNames) )
2760         {
2761                 include_once($DIR_LIBS . 'ACTION.php');
2762                 $a = new Action();
2763                 $errorInfo = $a->doAction($action);
2764                 
2765                 if ( $errorInfo )
2766                 {
2767                         $errormessage = $errorInfo['message'];
2768                 }
2769         }
2770         
2771         // show error when headers already sent out
2772         if ( headers_sent() && $CONF['alertOnHeadersSent'] )
2773         {
2774                 // try to get line number/filename (extra headers_sent params only exists in PHP 4.3+)
2775                 if ( function_exists('version_compare') && version_compare('4.3.0', phpversion(), '<=') )
2776                 {
2777                         headers_sent($hsFile, $hsLine);
2778                         $extraInfo = ' in <code>' . $hsFile . '</code> line <code>' . $hsLine . '</code>';
2779                 }
2780                 else
2781                 {
2782                         $extraInfo = '';
2783                 }
2784                 
2785                 startUpError(
2786                    "<p>The page headers have already been sent out{$extraInfo}. This could cause Nucleus not to work in the expected way.</p>"
2787                  . "<p>Usually, this is caused by spaces or newlines at the end of the <code>config.php</code> file, "
2788                  . "at the end of the translation file or at the end of a plugin file.</p>"
2789                  . "<p>Please check this and try again.</p>"
2790                  . "<p>If you don't want to see this error message again, without solving the problem, "
2791                  . "set <code>{$CONF['alertOnHeadersSent']}</code> in <code>globalfunctions.php</code> to <code>0</code></p>"
2792                  . "Page headers already sent"
2793                 );
2794                 exit;
2795         }
2796         
2797         // make is so ?archivelist without blogname or blogid shows the archivelist
2798         // for the default weblog
2799         if ( serverVar('QUERY_STRING') == 'archivelist' )
2800         {
2801                 $archivelist = $CONF['DefaultBlog'];
2802         }
2803         
2804         // now decide which type of skin we need
2805         if ( $itemid )
2806         {
2807                 // itemid given -> only show that item
2808                 $type = 'item';
2809                 
2810                 if ( !$manager->existsItem($itemid,intval($CONF['allowFuture']),intval($CONF['allowDrafts'])) )
2811                 {
2812                         doError(_ERROR_NOSUCHITEM);
2813                         return;
2814                 }
2815                 
2816                 // 1. get timestamp, blogid and catid for item
2817                 $query = 'SELECT itime, iblog, icat FROM %s WHERE inumber=%d';
2818                 $query = sprintf($query, sql_table('item'), intval($itemid));
2819                 $row = DB::getRow($query);
2820                 
2821                 // if a different blog id has been set through the request or selectBlog(),
2822                 // deny access
2823                 
2824                 if ( $blogid && (intval($blogid) != $row['iblog']) )
2825                 {
2826                         doError(_ERROR_NOSUCHITEM);
2827                         return;
2828                 }
2829                 
2830                 // if a category has been selected which doesn't match the item, ignore the
2831                 // category. #85
2832                 if ( ($catid != 0) && ($catid != $row['icat']) )
2833                 {
2834                         $catid = 0;
2835                 }
2836                 
2837                 $blogid = $row['iblog'];
2838                 $timestamp = strtotime($row['itime']);
2839                 
2840                 $b =& $manager->getBlog($blogid);
2841                 
2842                 if ( !$b->isValidCategory($catid) )
2843                 {
2844                         $query = "SELECT inumber, ititle FROM %s WHERE itime<%s AND idraft=0 AND iblog=%d ORDER BY itime DESC LIMIT 1";
2845                         $query = sprintf($query, sql_table('item'), DB::formatDateTime($timestamp), intval($blogid));
2846                 }
2847                 else
2848                 {
2849                         $query = "SELECT inumber, ititle FROM %s WHERE itime<%s AND idraft=0 AND iblog=%d AND icat=%d ORDER BY itime DESC LIMIT 1";
2850                         $query = sprintf($query, sql_table('item'), DB::formatDateTime($timestamp), intval($blogid), intval($catid));
2851                 }
2852                 $row = DB::getRow($query);
2853                 
2854                 if ( $row )
2855                 {
2856                         $itemidprev = $row['inumber'];
2857                         $itemtitleprev = $row['ititle'];
2858                 }
2859                 
2860                 // get next itemid and title
2861                 if ( !$b->isValidCategory($catid) )
2862                 {
2863                         $query = "SELECT inumber, ititle FROM %s WHERE itime>%s AND itime<=%s AND idraft=0 AND iblog=%d ORDER BY itime ASC LIMIT 1";
2864                         $query = sprintf($query, sql_table('item'), DB::formatDateTime($timestamp), DB::formatDateTime($b->getCorrectTime()), intval($blogid));
2865                 }
2866                 else
2867                 {
2868                         $query = "SELECT inumber, ititle FROM %s WHERE itime>%s AND itime<=%s AND idraft=0 AND iblog=%d AND icat=%d ORDER BY itime ASC LIMIT 1";
2869                         $query = sprintf($query, sql_table('item'), DB::formatDateTime($timestamp), DB::formatDateTime($b->getCorrectTime()), intval($blogid), intval($catid));
2870                 }
2871                 $row = DB::getRow($query);
2872                 
2873                 if ( $row )
2874                 {
2875                         $itemidnext = $row['inumber'];
2876                         $itemtitlenext = $row['ititle'];
2877                 }
2878         }
2879         elseif ( $archive )
2880         {
2881                 // show archive
2882                 $type = 'archive';
2883                 
2884                 // sql queries for the timestamp of the first and the last published item
2885                 $query = sprintf('SELECT UNIX_TIMESTAMP(itime) as result FROM %s WHERE idraft=0 ORDER BY itime ASC', sql_table('item'));
2886                 $first_timestamp = DB::getValue($query);
2887                 $query = sprintf('SELECT UNIX_TIMESTAMP(itime) as result FROM %s WHERE idraft=0 ORDER BY itime DESC', sql_table('item'));
2888                 $last_timestamp = DB::getValue($query);
2889                 
2890                 sscanf($archive, '%d-%d-%d', $y, $m, $d);
2891                 
2892                 if ( $d != 0 )
2893                 {
2894                         $archivetype = _LABEL_DAY_UNIT;
2895                         $t = mktime(0, 0, 0, $m, $d, $y);
2896                         // one day has 24 * 60 * 60 = 86400 seconds
2897                         $archiveprev = i18n::formatted_datetime('%Y-%m-%d', $t - 86400 );
2898                         // check for published items
2899                         if ( $t > $first_timestamp )
2900                         {
2901                                 $archiveprevexists = true;
2902                         }
2903                         else
2904                         {
2905                                 $archiveprevexists = false;
2906                         }
2907                         
2908                         // one day later
2909                         $t += 86400;
2910                         $archivenext = i18n::formatted_datetime('%Y-%m-%d', $t);
2911                         if ( $t < $last_timestamp )
2912                         {
2913                                 $archivenextexists = true;
2914                         }
2915                         else
2916                         {
2917                                 $archivenextexists = false;
2918                         }
2919                 }
2920                 elseif ( $m == 0 )
2921                 {
2922                         $archivetype = _LABEL_YEAR_UNIT;
2923                         $t = mktime(0, 0, 0, 12, 31, $y - 1);
2924                         // one day before is in the previous year
2925                         $archiveprev = i18n::formatted_datetime('%Y', $t);
2926                         if ( $t > $first_timestamp )
2927                         {
2928                                 $archiveprevexists = true;
2929                         }
2930                         else
2931                         {
2932                                 $archiveprevexists = false;
2933                         }
2934
2935                         // timestamp for the next year
2936                         $t = mktime(0, 0, 0, 1, 1, $y + 1);
2937                         $archivenext = i18n::formatted_datetime('%Y', $t);
2938                         if ( $t < $last_timestamp )
2939                         {
2940                                 $archivenextexists = true;
2941                         }
2942                         else
2943                         {
2944                                 $archivenextexists = false;
2945                         }
2946                 }
2947                 else
2948                 {
2949                         $archivetype = _LABEL_MONTH_UNIT;
2950                         $t = mktime(0, 0, 0, $m, 1, $y);
2951                         // one day before is in the previous month
2952                         $archiveprev = i18n::formatted_datetime('%Y-%m', $t - 86400);
2953                         if ( $t > $first_timestamp )
2954                         {
2955                                 $archiveprevexists = true;
2956                         }
2957                         else
2958                         {
2959                                 $archiveprevexists = false;
2960                         }
2961                         
2962                         // timestamp for the next month
2963                         $t = mktime(0, 0, 0, $m+1, 1, $y);
2964                         $archivenext = i18n::formatted_datetime('%Y-%m', $t);
2965                         if ( $t < $last_timestamp )
2966                         {
2967                                 $archivenextexists = true;
2968                         }
2969                         else
2970                         {
2971                                 $archivenextexists = false;
2972                         }
2973                 }
2974         }
2975         elseif ( $archivelist )
2976         {
2977                 $type = 'archivelist';
2978                 
2979                 if ( is_numeric($archivelist) )
2980                 {
2981                         $blogid = intVal($archivelist);
2982                 }
2983                 else
2984                 {
2985                         $blogid = getBlogIDFromName($archivelist);
2986                 }
2987         
2988                 if ( !$blogid )
2989                 {
2990                         doError(_ERROR_NOSUCHBLOG);
2991                         return;
2992                 }
2993         }
2994         elseif ( $query )
2995         {
2996                 global $startpos;
2997                 $type = 'search';
2998                 $query = stripslashes($query);
2999                 
3000                 if ( is_numeric($blogid) )
3001                 {
3002                         $blogid = intVal($blogid);
3003                 }
3004                 else
3005                 {
3006                         $blogid = getBlogIDFromName($blogid);
3007                 }
3008                 
3009                 if ( !$blogid )
3010                 {
3011                         doError(_ERROR_NOSUCHBLOG);
3012                         return;
3013                 }
3014         }
3015         elseif ( $memberid )
3016         {
3017                 $type = 'member';
3018                 
3019                 if ( !Member::existsID($memberid) )
3020                 {
3021                         doError(_ERROR_NOSUCHMEMBER);
3022                         return;
3023                 }
3024                 $memberinfo = $manager->getMember($memberid);
3025         }
3026         elseif ( $imagepopup )
3027         {
3028                 // media object (images etc.)
3029                 $type = 'imagepopup';
3030                 
3031                 // TODO: check if media-object exists
3032                 // TODO: set some vars?
3033         }
3034         else
3035         {
3036                 // show regular index page
3037                 global $startpos;
3038                 $type = 'index';
3039         }
3040         
3041         // any type of skin with catid
3042         if ( $catid && !$blogid )
3043         {
3044                 $blogid = getBlogIDFromCatID($catid);
3045         }
3046         
3047         // decide which blog should be displayed
3048         if ( !$blogid )
3049         {
3050                 $blogid = $CONF['DefaultBlog'];
3051         }
3052         
3053         $b =& $manager->getBlog($blogid);
3054         $blog = $b; // references can't be placed in global variables?
3055         
3056         if ( !$blog->isValid )
3057         {
3058                 doError(_ERROR_NOSUCHBLOG);
3059                 return;
3060         }
3061         
3062         // set catid if necessary
3063         if ( $catid )
3064         {
3065                 // check if the category is valid
3066                 if ( !$blog->isValidCategory($catid) )
3067                 {
3068                         doError(_ERROR_NOSUCHCATEGORY);
3069                         return;
3070                 }
3071                 else
3072                 {
3073                         $blog->setSelectedCategory($catid);
3074                 }
3075         }
3076         
3077         if ( !$skinid )
3078         {
3079                 $skinid = $blog->getDefaultSkin();
3080         }
3081         
3082         if ( !empty($special) && isValidShortName($special) )
3083         {
3084                 $type = strtolower($special);
3085         }
3086         
3087         $skin =& $manager->getSkin($skinid);
3088         
3089         if ( !$skin->isValid() )
3090         {
3091                 doError(_ERROR_NOSUCHSKIN);
3092                 return;
3093         }
3094         
3095         // set global skinpart variable so can determine quickly what is being parsed from any plugin or phpinclude
3096         $skinpart = $type;
3097         
3098         // parse the skin
3099         $skin->parse($type);
3100         
3101         // check to see we should throw JustPosted event
3102         $blog->checkJustPosted();
3103         return;
3104 }
3105
3106 /**
3107  * doError()
3108  * Show error skin with given message. An optional skin-object to use can be given
3109  * 
3110  * @param       string  $msg
3111  * @param       string  $skin
3112  * @return      void
3113  */
3114 function doError($msg, $skin = '')
3115 {
3116         global $errormessage, $CONF, $skinid, $blogid, $manager;
3117         
3118         if ( $skin == '' )
3119         {
3120                 if ( Skin::existsID($skinid) )
3121                 {
3122                         $id = $skinid;
3123                 }
3124                 elseif ( $manager->existsBlogID($blogid) )
3125                 {
3126                         $blog =& $manager->getBlog($blogid);
3127                         $id = $blog->getDefaultSkin();
3128                 }
3129                 elseif ($CONF['DefaultBlog'] )
3130                 {
3131                         $blog =& $manager->getBlog($CONF['DefaultBlog']);
3132                         $id = $blog->getDefaultSkin();
3133                 }
3134                 else
3135                 {
3136                         // this statement should actually never be executed
3137                         $id = $CONF['BaseSkin'];
3138                 }
3139                 $skin =& $manager->getSkin($id);
3140         }
3141         
3142         $errormessage = $msg;
3143         $skin->parse('error');
3144         return;
3145 }
3146
3147 /**
3148  * Errors before the database connection has been made
3149  * 
3150  * @param       string  $msg    message to notify
3151  * @param       string  $title  page title
3152  * @return      void
3153  */
3154 function startUpError($msg, $title)
3155 {
3156         header('Content-Type: text/xml; charset=' . i18n::get_current_charset());
3157         echo "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n";
3158         echo "<head>\n";
3159         echo "<title>{$title}</title></head>\n";
3160         echo "<body>\n";
3161         echo "<h1>{$title}</h1>\n";
3162         echo $msg;
3163         echo "</body>\n";
3164         echo "</html>\n";
3165         exit;
3166 }
3167
3168 function isValidShortName($name)
3169 {
3170         return preg_match('#^[a-z0-9]+$#i', $name);
3171 }
3172 function isValidDisplayName($name)
3173 {
3174         return preg_match('#^[a-z0-9]+[a-z0-9 ]*[a-z0-9]+$#i', $name);
3175 }
3176 function isValidCategoryName($name)
3177 {
3178         return 1;
3179 }
3180 function isValidTemplateName($name)
3181 {
3182         return preg_match('#^[a-z0-9/_\-]+$#i', $name);
3183 }
3184 function isValidSkinName($name)
3185 {
3186         return preg_match('#^[a-z0-9/_\-]+$#i', $name);
3187 }
3188
3189 // add and remove linebreaks
3190 function addBreaks($var)
3191 {
3192         return nl2br($var);
3193 }
3194 function removeBreaks($var)
3195 {
3196         return preg_replace("/<br \/>([\r\n])/", "$1", $var);
3197 }
3198
3199 /**
3200  * parseFile()
3201  * 
3202  * @param       string  $filename
3203  * @param       string  $includeMode
3204  * @param       string  $includePrefix
3205  * @return      void
3206  */
3207 function parseFile($filename, $includeMode = 'normal', $includePrefix = '')
3208 {
3209         global $manager, $skinid;
3210         
3211         if ( !$skinid || !existsID($skinid) )
3212         {
3213                 $skin =& $manager->getSkin($CONF['BaseSkin']);
3214         }
3215         else
3216         {
3217                 $skin =& $manager->getSkin($skinid);
3218         }
3219         
3220         $oldIncludeMode = Parser::getProperty('IncludeMode');
3221         $oldIncludePrefix = Parser::getProperty('IncludePrefix');
3222         
3223         $skin->parse('fileparse', $filename);
3224         
3225         Parser::setProperty('IncludeMode', $oldIncludeMode);
3226         Parser::setProperty('IncludePrefix', $oldIncludePrefix);
3227         
3228         return;
3229 }
3230
3231 /**
3232  * debug()
3233  * Outputs a debug message
3234  * 
3235  * @param       string  $msg
3236  * @return      void
3237  */
3238 function debug($msg)
3239 {
3240         echo '<p><b>' . $msg . "</b></p>\n";
3241         return;
3242 }
3243
3244 // shows a link to help file
3245 function help($id)
3246 {
3247         echo helpHtml($id);
3248         return;
3249 }
3250 function helpHtml($id)
3251 {
3252         global $CONF;
3253         return helplink($id) . '<img src="' . $CONF['AdminURL'] . 'documentation/icon-help.gif" width="15" height="15" alt="' . _HELP_TT . '" title="' . _HELP_TT . '" /></a>';
3254 }
3255 function helplink($id)
3256 {
3257         global $CONF;
3258         return '<a href="' . $CONF['AdminURL'] . 'documentation/help.html#'. $id . '" onclick="if (event &amp;&amp; event.preventDefault) event.preventDefault(); return help(this.href);">';
3259 }
3260
3261 /**
3262  * includephp()
3263  * Includes a PHP file. This method can be called while parsing templates and skins
3264  * 
3265  * @param       string  $filename       name of file to parse
3266  * @return      void
3267  */
3268 function includephp($filename)
3269 {
3270         // make predefined variables global, so most simple scripts can be used here
3271         
3272         // apache (names taken from PHP doc)
3273         global $GATEWAY_INTERFACE, $SERVER_NAME, $SERVER_SOFTWARE, $SERVER_PROTOCOL;
3274         global $REQUEST_METHOD, $QUERY_STRING, $DOCUMENT_ROOT, $HTTP_ACCEPT;
3275         global $HTTP_ACCEPT_CHARSET, $HTTP_ACCEPT_ENCODING, $HTTP_ACCEPT_LANGUAGE;
3276         global $HTTP_CONNECTION, $HTTP_HOST, $HTTP_REFERER, $HTTP_USER_AGENT;
3277         global $REMOTE_ADDR, $REMOTE_PORT, $SCRIPT_FILENAME, $SERVER_ADMIN;
3278         global $SERVER_PORT, $SERVER_SIGNATURE, $PATH_TRANSLATED, $SCRIPT_NAME;
3279         global $REQUEST_URI;
3280         
3281         // php (taken from PHP doc)
3282         global $argv, $argc, $PHP_SELF, $HTTP_COOKIE_VARS, $HTTP_GET_VARS, $HTTP_POST_VARS;
3283         global $HTTP_POST_FILES, $HTTP_ENV_VARS, $HTTP_SERVER_VARS, $HTTP_SESSION_VARS;
3284         
3285         // other
3286         global $PATH_INFO, $HTTPS, $HTTP_RAW_POST_DATA, $HTTP_X_FORWARDED_FOR;
3287         
3288         if ( @file_exists($filename) )
3289         {
3290                 include($filename);
3291         }
3292         return;
3293 }
3294
3295 /**
3296  * Checks if a certain plugin exists
3297  * @param       string  $plug   name of plugin
3298  * @return      boolean exists or not
3299  */
3300 function checkPlugin($name)
3301 {
3302         global $DIR_PLUGINS;
3303         return file_exists($DIR_PLUGINS . preg_replace('#[\\\\|/]#', '', $name) . '.php');
3304 }
3305
3306 /**
3307  * alterQueryStr()
3308  * 
3309  * @param       string  $querystr       querystring to alter (e.g. foo=1&bar=2&x=y)
3310  * @param       string  $param  name of parameter to change (e.g. 'foo')
3311  * @param       string  $value  New value for that parameter (e.g. 3)
3312  * @return      string  altered query string (for the examples above: foo=3&bar=2&x=y)
3313  */
3314 function alterQueryStr($querystr, $param, $value)
3315 {
3316         $vars = preg_split('#&#', $querystr);
3317         $set = FALSE;
3318         
3319         for ( $i = 0; $i < count($vars); $i++ )
3320         {
3321                 $v = preg_split('#=#', $vars[$i]);
3322                 
3323                 if ( $v[0] == $param )
3324                 {
3325                         $v[1] = $value;
3326                         $vars[$i] = implode('=', $v);
3327                         $set = true;
3328                         break;
3329                 }
3330         }
3331         if ( !$set )
3332         {
3333                 $vars[] = "{$param}={$value}";
3334         }
3335         return ltrim(implode('&', $vars), '&');
3336 }
3337
3338 /**
3339  * passVar()
3340  * passes one variable as hidden input field (multiple fields for arrays)
3341  * @see passRequestVars in varsx.x.x.php
3342  * 
3343  * @param       string  $key
3344  * @param       string  $value
3345  * @return      void
3346  */
3347 function passVar($key, $value)
3348 {
3349         // array ?
3350         if ( is_array($value) )
3351         {
3352                 for ( $i = 0; $i < sizeof($value); $i++ )
3353                 {
3354                         passVar($key . '[' . $i . ']', $value[$i]);
3355                 }
3356                 return;
3357         }
3358         
3359         // other values: do stripslashes if needed
3360         echo '<input type="hidden" name="' . Entity::hsc($key) . '" value="' . Entity::hsc(undoMagic($value)) . '" />' . "\n";
3361         return;
3362 }
3363
3364 /**
3365  * checkVars()
3366  * 
3367  * @param       string  $variables
3368  * @return      void
3369  */
3370 function checkVars($variables)
3371 {
3372         foreach ( $variables as $variable )
3373         {
3374                 if ( array_key_exists($variable, $_GET)
3375                   || array_key_exists($variable, $_POST)
3376                   || array_key_exists($variable, $_COOKIE)
3377                   || array_key_exists($variable, $_ENV)
3378                   || (session_id() !== '' && array_key_exists($variable, $_SESSION))
3379                   || array_key_exists($variable, $_FILES) )
3380                 {
3381                         die('Sorry. An error occurred.');
3382                 }
3383         }
3384         return;
3385 }
3386
3387 /**
3388  * sanitizeParams()
3389  * Sanitize parameters such as $_GET and $_SERVER['REQUEST_URI'] etc.
3390  * to avoid XSS.
3391  * 
3392  * @param       void
3393  * @return      void
3394  */
3395 function sanitizeParams()
3396 {
3397         $array = array();
3398         $str = '';
3399         $frontParam = '';
3400         
3401         // REQUEST_URI of $_SERVER
3402         $str =& $_SERVER["REQUEST_URI"];
3403         serverStringToArray($str, $array, $frontParam);
3404         sanitizeArray($array);
3405         arrayToServerString($array, $frontParam, $str);
3406         
3407         // QUERY_STRING of $_SERVER
3408         $str =& $_SERVER["QUERY_STRING"];
3409         serverStringToArray($str, $array, $frontParam);
3410         sanitizeArray($array);
3411         arrayToServerString($array, $frontParam, $str);
3412         
3413         // $_GET
3414         convArrayForSanitizing($_GET, $array);
3415         sanitizeArray($array);
3416         revertArrayForSanitizing($array, $_GET);
3417         
3418         // $_REQUEST (only GET param)
3419         convArrayForSanitizing($_REQUEST, $array);
3420         sanitizeArray($array);
3421         revertArrayForSanitizing($array, $_REQUEST);
3422         
3423         return;
3424 }
3425
3426 function _addInputTags(&$keys,$prefix='')
3427 {
3428         foreach ( $keys as $key=>$value )
3429         {
3430                 if ( $prefix )
3431                 {
3432                         $key=$prefix.'['.$key.']';
3433                 }
3434                 if ( is_array($value) )
3435                 {
3436                         _addInputTags($value,$key);
3437                 }
3438                 else
3439                 {
3440                         if ( get_magic_quotes_gpc() )
3441                                 {$value=stripslashes($value);
3442                         }
3443                         if ( $key == 'ticket' )
3444                         {
3445                                 continue;
3446                         }
3447                         echo '<input type="hidden" name="'.Entity::hsc($key).
3448                              '" value="'.Entity::hsc($value).'" />'."\n";
3449                 }
3450         }
3451         return;
3452 }
3453
3454 /**
3455  * serverStringToArray()
3456  * Convert the server string such as $_SERVER['REQUEST_URI']
3457  * to arry like arry['blogid']=1 and array['page']=2 etc.
3458  * 
3459  * @param       string   $uri                           string
3460  * @param       string  &$query_elements        elements of query according to application/x-www-form-urlencoded
3461  * @param       string  &$hier_part                     hierarchical part includes path
3462  * 
3463  * NOTE:
3464  * RFC 3986: Uniform Resource Identifiers (URI): Generic Syntax
3465  * 3.  Syntax Components
3466  * http://www.ietf.org/rfc/rfc3986.txt
3467  * 
3468  * Hypertext Markup Language - 2.0
3469  * 8.2.1. The form-urlencoded Media Type
3470  * http://tools.ietf.org/html/rfc1866#section-8.2.1
3471  * 
3472  * $_SERVER > Language Reference > Predefined Variables > PHP Manual
3473  * http://www.php.net/manual/en/reserved.variables.server.php
3474  */
3475 function serverStringToArray($uri, &$query_elements, &$hier_part)
3476 {
3477         // init param
3478         $query_elements = array();
3479         $hier_part = "";
3480         
3481         // split hierarchical part, e.g. /index.php, query and fragment, e.g. blogid=1&page=2#section1
3482         if ( i18n::strpos($uri, "?") > 0 )
3483         {
3484                 list($hier_part, $query_and_fragment) = preg_split("#\?#", $uri, 2);
3485         }
3486         else
3487         {
3488                 $query_and_fragment = $uri;
3489                 $hier_part = '';
3490         }
3491         
3492         // If there is no query like blogid=1&page=2, return
3493         if ( i18n::strpos($uri, "=") == FALSE && !i18n::strlen($hier_part) )
3494         {
3495                 $hier_part = $uri;
3496                 return;
3497         }
3498         
3499         $query_elements = preg_split("#&#", $query_and_fragment);
3500         return;
3501 }
3502
3503 /**
3504  * arrayToServerString()
3505  * Convert array like array['blogid'] to server string
3506  * such as $_SERVER['REQUEST_URI']
3507  * 
3508  * @param       array    $query_elements        elements of query according to application/x-www-form-urlencoded
3509  * @param       string   $hier_part                     hier-part defined in RFC3986
3510  * @param       string  &$uri                           return value
3511  * @return      void
3512  * 
3513  * NOTE:
3514  * RFC 3986: Uniform Resource Identifiers (URI): Generic Syntax
3515  * 3.  Syntax Components
3516  * http://www.ietf.org/rfc/rfc3986.txt
3517  * 
3518  * Hypertext Markup Language - 2.0
3519  * 8.2.1. The form-urlencoded Media Type
3520  * http://tools.ietf.org/html/rfc1866#section-8.2.1
3521  * 
3522  * $_SERVER > Language Reference > Predefined Variables > PHP Manual
3523  * http://www.php.net/manual/en/reserved.variables.server.php
3524  */
3525 function arrayToServerString($query_elements, $hier_part, &$uri)
3526 {
3527         if ( i18n::strpos($uri, "?") !== FALSE )
3528         {
3529                 $uri = $hier_part . "?";
3530         }
3531         else
3532         {
3533                 $uri = $hier_part;
3534         }
3535         if ( count($query_elements) > 0 )
3536         {
3537                 $uri .= implode("&", $query_elements);
3538         }
3539         return;
3540 }
3541
3542 /**
3543  * sanitizeArray()
3544  * Sanitize array parameters.
3545  * This function checks both key and value.
3546  * - check key if it inclues " (double quote),  remove from array
3547  * - check value if it includes \ (escape sequece), remove remaining string
3548  * 
3549  * @param       array   &$array elements of query according to application/x-www-form-urlencoded
3550  * @return      void
3551  */
3552 function sanitizeArray(&$array)
3553 {
3554         $excludeListForSanitization = array('query');
3555         
3556         foreach ( $array as $k => $v )
3557         {
3558                 // split to key and value
3559                 list($key, $val) = preg_split("#=#", $v, 2);
3560                 if ( !isset($val) )
3561                 {
3562                         continue;
3563                 }
3564                 
3565                 // when magic quotes is on, need to use stripslashes,
3566                 // and then addslashes
3567                 if ( get_magic_quotes_gpc() )
3568                 {
3569                         $val = stripslashes($val);
3570                 }
3571                 
3572                 // note that we must use addslashes here because this function is called before the db connection is made
3573                 // and sql_real_escape_string needs a db connection
3574                 $val = addslashes($val);
3575                 
3576                 // if $key is included in exclude list, skip this param
3577                 if ( !in_array($key, $excludeListForSanitization) )
3578                 {
3579                         // check value
3580                         if ( i18n::strpos($val, '\\') > 0 )
3581                         {
3582                                 list($val, $tmp) = preg_split('#\\\\#', $val);
3583                         }
3584                         
3585                         // remove control code etc.
3586                         $val = strtr($val, "\0\r\n<>'\"", "       ");
3587                         
3588                         // check key
3589                         if ( preg_match('#\"#', $key) > 0 )
3590                         {
3591                                 unset($array[$k]);
3592                                 continue;
3593                         }
3594                         
3595                         // set sanitized info
3596                         $array[$k] = sprintf("%s=%s", $key, $val);
3597                 }
3598         }
3599         return;
3600 }
3601
3602 /**
3603  * convArrayForSanitizing()
3604  * Convert array for sanitizeArray function
3605  * 
3606  * @param       string  $src    array to be sanitized
3607  * @param       array   &$array array to be temporarily stored
3608  * @return      void
3609  */
3610 function convArrayForSanitizing($src, &$array)
3611 {
3612         $array = array();
3613         foreach ( $src as $key => $val )
3614         {
3615                 if ( !key_exists($key, $_GET) )
3616                 {
3617                         continue;
3618                 }
3619                 $array[] = sprintf("%s=%s", $key, $val);
3620                 continue;
3621         }
3622         return;
3623 }
3624
3625 /**
3626  * revertArrayForSanitizing()
3627  * Revert array after sanitizeArray function
3628  * 
3629  * @param       array   $array  element of query according to application/x-www-form-urlencoded
3630  * @param       array   &$dst   combination of key and value
3631  * @return      void
3632  */
3633 function revertArrayForSanitizing($array, &$dst)
3634 {
3635         foreach ( $array as $v )
3636         {
3637                 list($key, $val) = preg_split("#=#", $v, 2);
3638                 $dst[$key] = $val;
3639                 continue;
3640         }
3641         return;
3642 }
3643
3644 /**
3645 >>>>>>> skinnable-master
3646  * decodePathInfo()
3647  * 
3648  * @param       string  $virtualpath
3649  * @return      void
3650  */
3651 function decodePathInfo($virtualpath)
3652 {
3653         global $CONF, $manager, $archive, $blog, $catid, $memberid, $special;
3654         
3655         /* initialize keywords if this hasn't been done before */
3656         if ( !isset($CONF['ItemKey']) || empty($CONF['ItemKey']) )
3657         {
3658                 $CONF['ItemKey'] = 'item';
3659         }
3660         
3661         if ( !isset($CONF['ArchiveKey']) || empty($CONF['ArchiveKey']) )
3662         {
3663                 $CONF['ArchiveKey'] = 'archive';
3664         }
3665         
3666         if ( !isset($CONF['ArchivesKey']) || empty($CONF['ArchivesKey']) )
3667         {
3668                 $CONF['ArchivesKey'] = 'archives';
3669         }
3670         
3671         if ( !isset($CONF['MemberKey']) || empty($CONF['MemberKey']) )
3672         {
3673                 $CONF['MemberKey'] = 'member';
3674         }
3675         
3676         if ( !isset($CONF['BlogKey']) || empty($CONF['BlogKey']) )
3677         {
3678                 $CONF['BlogKey'] = 'blog';
3679         }
3680         
3681         if ( !isset($CONF['CategoryKey']) || empty($CONF['CategoryKey']) )
3682         {
3683                 $CONF['CategoryKey'] = 'category';
3684         }
3685         
3686         if ( !isset($CONF['SpecialskinKey']) || empty($CONF['SpecialskinKey']) )
3687         {
3688                 $CONF['SpecialskinKey'] = 'special';
3689         }
3690         
3691         $parsed = FALSE;
3692         $data = array(
3693                 'type'          =>  basename(serverVar('SCRIPT_NAME') ),
3694                 'info'          =>  $virtualpath,
3695                 'complete'      => &$parsed
3696         );
3697         $manager->notify('ParseURL', $data);
3698         
3699         /* already parsed by the other subsystem */
3700         if ( $parsed )
3701         {
3702                 return;
3703         }
3704         /* default implementation */
3705         $data = preg_split("#/#", $virtualpath);
3706         for ( $i = 0; $i < sizeof($data); $i++ )
3707         {
3708                 switch ( $data[$i] )
3709                 {
3710                         /* item/1 (blogid) */
3711                         case $CONF['ItemKey']:
3712                                 $i++;
3713                                 
3714                                 if ( $i < sizeof($data) )
3715                                 {
3716                                         $itemid = (integer) $data[$i];
3717                                 }
3718                                 break;
3719                         
3720                         /* archives/1 (blogid) */
3721                         case $CONF['ArchivesKey']:
3722                                         $i++;
3723                                         if ( $i < sizeof($data) )
3724                                         {
3725                                                 $archivelist = (integer) $data[$i];
3726                                         }
3727                                         break;
3728                                 
3729                         /* two possibilities: archive/yyyy-mm or archive/1/yyyy-mm (with blogid) */
3730                         case $CONF['ArchiveKey']:
3731                                 if ( (($i + 1) < sizeof($data) ) && (i18n::strpos($data[$i + 1], '-') === FALSE ) )
3732                                 {
3733                                         $blogid = (integer) $data[++$i];
3734                                 }
3735                                 $i++;
3736                                 if ( $i < sizeof($data) )
3737                                 {
3738                                         $archive = $data[$i];
3739                                 }
3740                                 break;
3741                                 
3742                         /* blogid/1 */
3743                         case 'blogid':
3744                         /* blog/1 */
3745                         case $CONF['BlogKey']:
3746                                 $i++;
3747                                 if ( $i < sizeof($data) )
3748                                 {
3749                                         $blogid = intval($data[$i]);
3750                                 }
3751                                 break;
3752                         
3753                         /* category/1 (catid) */
3754                         case $CONF['CategoryKey']:
3755                         case 'catid':
3756                                 $i++;
3757                                 if ( $i < sizeof($data) )
3758                                 {
3759                                         $catid = intval($data[$i]);
3760                                 }
3761                                 break;
3762                         
3763                         case $CONF['MemberKey']:
3764                                 $i++;
3765                                 if ( $i < sizeof($data) )
3766                                 {
3767                                         $memberid = intval($data[$i]);
3768                                 }
3769                                 break;
3770                         
3771                         case $CONF['SpecialskinKey']:
3772                                 $i++;
3773                                 if ( $i < sizeof($data) )
3774                                 {
3775                                         $special = $data[$i];
3776                                 }
3777                                 break;
3778                         
3779                         default:
3780                                 /* do nothing */
3781                                 break;
3782                 }
3783         }
3784         
3785         return;
3786 }
3787
3788
3789 /**
3790 <<<<<<< HEAD
3791  * redirect()\r
3792  * Stops processing the request and redirects to the given URL.\r
3793  * - no actual contents should have been sent to the output yet\r
3794  * - the URL will be stripped of illegal or dangerous characters\r
3795  * \r
3796  * @param       string  $uri\r
3797  * @return      void\r
3798  */\r
3799 function redirect($url)\r
3800 {\r
3801         $url = preg_replace('#[^a-z0-9-~+_.?\#=&;,/:@%*]#i', '', $url);\r
3802         header('Location: ' . $url);\r
3803         exit;\r
3804 }\r
3805 \r
3806 /**\r
3807  * getBookmarklet()\r
3808  * Returns the Javascript code for a bookmarklet that works on most modern browsers\r
3809  * \r
3810  * @param       integer $blogid ID for weblog\r
3811  * @return      script to call Bookmarklet\r
3812  */\r
3813 function getBookmarklet($blogid, $width=600,  $height=500)\r
3814 {\r
3815         global $CONF;\r
3816         \r
3817         $script = "Q='';"\r
3818                 . "x=document;"\r
3819                 . "y=window;"\r
3820                 . "if ( x.selection )"\r
3821                 . "{"\r
3822                 . " Q=x.selection.createRange().text;"\r
3823                 . "}"\r
3824                 . "else if ( y.getSelection )"\r
3825                 . "{"\r
3826                 . " Q=y.getSelection();"\r
3827                 . "}"\r
3828                 . "else if ( x.getSelection )"\r
3829                 . "{"\r
3830                 . " Q=x.getSelection();"\r
3831                 . "}"\r
3832                 . "wingm = window.open('{$CONF['AdminURL']}bookmarklet.php?blogid={$blogid}"\r
3833                 . " &logtext=' + encodeURIComponent(Q) +"\r
3834                 . " '&loglink=' + encodeURIComponent(x.location.href) +"\r
3835                 . " '&loglinktitle=' + encodeURIComponent(x.title),"\r
3836                 . " 'nucleusbm',"\r
3837                 . " 'scrollbars=yes,width={$width},height={$height},left=10,top=10,status=yes,resizable=yes');"\r
3838                 . "wingm.focus();";\r
3839         \r
3840         return $script;\r
3841 }\r
3842 \r
3843 /**\r
3844  * cleanFileName()\r
3845  * cleans filename of uploaded file for writing to file system\r
3846  *\r
3847  * @param       string  $str\r
3848  * @return      string  $cleaned filename ready for use\r
3849  */\r
3850 function cleanFileName($str)\r
3851 {\r
3852         $str = strtolower($str);\r
3853         $ext_point = i18n::strrpos($str,".");\r
3854         if ( $ext_point === FALSE )\r
3855         {\r
3856                 return FALSE;\r
3857         }\r
3858         $ext = i18n::substr($str,$ext_point,i18n::strlen($str));\r
3859         $str = i18n::substr($str,0,$ext_point);\r
3860         \r
3861         return preg_replace("#[^a-z0-9-]#", "_", $str) . $ext;\r
3862 }\r
3863 \r
3864 /**\r
3865  * use Notification class instead of this\r
3866  * Deprecated since 4.0:\r
3867  */\r
3868 function getMailFooter()\r
3869 {\r
3870         NOTIFICATION::get_mail_footer();\r
3871 }\r
3872 function isValidMailAddress($address)\r
3873 {\r
3874         return NOTIFICATION::address_validation($address);\r
3875 }\r
3876 /**\r
3877  * use Entity class instead of this\r
3878  * Deprecated since 4.0:\r
3879  */\r
3880 function highlight($text, $expression, $highlight)\r
3881 {\r
3882         return Entity::highlight($text, $expression, $highlight);\r
3883 }\r
3884 function shorten($string, $maxlength, $suffix)\r
3885 {\r
3886         return Entity::shorten($string, $maxlength, $suffix);\r
3887 }\r
3888 function stringStripTags ($string)\r
3889 {\r
3890         return Entity::strip_tags($string);\r
3891 }\r
3892 function toAscii($string)\r
3893 {\r
3894         return Entity::anchor_footnoting($string);\r
3895 }\r
3896 function stringToAttribute ($string)\r
3897 {\r
3898         return Entity::hsc($string);\r
3899 }\r
3900 function stringToXML ($string)\r
3901 {\r
3902         return Entity::hen($string);\r
3903 }\r
3904 function encode_desc($data)\r
3905 {\r
3906         return Entity::hen($data);\r
3907 }\r
3908 /**\r
3909  * Centralisation of the functions that deals with locales\r
3910  * This functions is based on the old way to deal with languages\r
3911  * Deprecated since 4.0:\r
3912  */\r
3913 function getLanguageName()\r
3914 {\r
3915         if( ($language = i18n::convert_locale_to_old_language_file_name(i18n::get_current_locale())) === FALSE )\r
3916         {\r
3917                 $language ='english';\r
3918         }\r
3919         return $language;\r
3920 }\r
3921 function selectLanguage($language)\r
3922 {\r
3923         global $DIR_LANG;\r
3924         include($DIR_LANG . preg_replace('#[\\\\|/]#', '', $language) . '.php');\r
3925         return;\r
3926 }\r
3927 /**\r
3928  * use i18n class instead of these\r
3929  * Deprecated since 4.0\r
3930  */\r
3931 function checkLanguage($lang)\r
3932 {\r
3933         return ( preg_match('#^(.+)_(.+)_(.+)$#', $lang)\r
3934           || i18n::convert_old_language_file_name_to_locale($lang) );\r
3935 }\r
3936 function formatDate($format, $timestamp, $default_format, &$blog)\r
3937 {\r
3938         $offset = date('Z', $timestamp);\r
3939         if ( $blog )\r
3940         {\r
3941                 $offset += $blog->getTimeOffset() * 3600;\r
3942         }\r
3943         return i18n::formatted_datetime($format, $timestamp, $offset, $default_format);\r
3944 }\r
3945 \r
3946 /**\r
3947  * use DB class instead of these\r
3948  * Deprecated since 4.0\r
3949  */\r
3950 function quickQuery($query)\r
3951 {\r
3952         $row = DB::getRow($query);\r
3953         return $row['result'];\r
3954 }\r
3955 function mysqldate($timestamp)\r
3956 {\r
3957         return DB::formatDateTime($timestamp);\r
3958  }\r
3959 /**\r
3960  * Centralisation of the functions that generate links\r
3961  * Deprecated since 4.0:\r
3962  * Please use Link::FunctionName(...) instead\r
3963  */\r
3964 function createItemLink($itemid, $extra = '')\r
3965 {\r
3966         return Link::create_item_link($itemid, $extra);\r
3967 }\r
3968 function createMemberLink($memberid, $extra = '')\r
3969 {\r
3970         return Link::create_member_link($memberid, $extra);\r
3971 }\r
3972 function createCategoryLink($catid, $extra = '')\r
3973 {\r
3974         return Link::create_category_link($catid, $extra);\r
3975 }\r
3976 function createArchiveListLink($blogid = '', $extra = '')\r
3977 {\r
3978         return Link::create_archivelist_link($blogid, $extra);\r
3979 }\r
3980 function createArchiveLink($blogid, $archive, $extra = '')\r
3981 {\r
3982         return Link::create_archive_link($blogid, $archive, $extra);\r
3983 }\r
3984 function createBlogidLink($blogid, $params = '')\r
3985 {\r
3986         return Link::create_blogid_link($blogid, $params = '');\r
3987 }\r
3988 function createLink($type, $params)\r
3989 {\r
3990         return Link::create_link($type, $params);\r
3991 }\r
3992 function createBlogLink($url, $params)\r
3993 {\r
3994         return Link::create_blog_link($url, $params);\r
3995 }\r
3996 /**\r
3997  * use ActionLog class instead of this\r
3998  * Deprecated since 4.0\r
3999  */\r
4000 function addToLog($level, $msg)\r
4001 {\r
4002         ActionLog::add($level, $msg);\r
4003 }\r
4004 /**\r
4005  * use PHP's implement\r
4006  * Deprecated since 4.0\r
4007  */\r
4008 function ifset(&$var)\r
4009 {\r
4010         if ( isset($var) )\r
4011         {\r
4012                 return $var;\r
4013         }\r
4014         \r
4015         return NULL;\r
4016 }\r
4017 /**\r
4018  * use Manager::getPluginNameFromPid() instead of this\r
4019  * Deprecated since 4.0\r
4020  */\r
4021 function getPluginNameFromPid($pid)\r
4022 {\r
4023         global $manager;\r
4024         return $manager->getPluginNameFromPid($pid);\r
4025 }\r
4026 /**\r
4027  * use Manager::numberOfEventSubscribers() instead of this\r
4028  * Deprecated since 4.0\r
4029  */\r
4030 function numberOfEventSubscribers($event)\r
4031 {\r
4032         global $manager;\r
4033         return $manager->getNumberOfSubscribers($event);\r
4034 }\r
4035 \r
4036 /**\r
4037  * PluginAdmin has already the alternative implement\r
4038  * Deprecated since 4.0\r
4039  */\r
4040 function ticketForPlugin()\r
4041 {\r
4042         global $CONF, $DIR_LIBS, $DIR_LOCALES, $DIR_PLUGINS, $manager, $member, $ticketforplugin;\r
4043         \r
4044         /* initialize */\r
4045         $ticketforplugin = array();\r
4046         $ticketforplugin['ticket'] = FALSE;\r
4047         \r
4048         /* Check if using plugin's php file. */\r
4049         $p_translated = serverVar('SCRIPT_FILENAME');\r
4050         \r
4051         if (!file_exists($p_translated) )\r
4052         {\r
4053                 header("HTTP/1.0 404 Not Found");\r
4054                 exit('');\r
4055         }\r
4056         \r
4057         // check whether this is plugin or not\r
4058         $p_translated = str_replace('\\', '/', $p_translated);\r
4059         $d_plugins = str_replace('\\', '/', $DIR_PLUGINS);\r
4060         if ( i18n::strpos($p_translated, $d_plugins) !== 0 )\r
4061         {\r
4062                 return;\r
4063         }\r
4064         \r
4065         // Solve the plugin php file or admin directory\r
4066         $phppath = i18n::substr($p_translated, i18n::strlen($d_plugins) );\r
4067         // Remove the first "/" if exists.\r
4068         $phppath = preg_replace('#^/#', '', $phppath);\r
4069         // Remove the first "NP_" and the last ".php" if exists.\r
4070         $path = preg_replace('#^NP_(.*)\.php$#', '$1', $phppath);\r
4071         // Remove the "/" and beyond.\r
4072         $path = preg_replace('#^([^/]*)/(.*)$#', '$1', $path);\r
4073         \r
4074         // Solve the plugin name.\r
4075         $plugins = array();\r
4076         $query = sprintf('SELECT pfile FROM %s;', sql_table('plugin'));\r
4077         $res = DB::getResult($query);\r
4078         \r
4079         foreach ( $res as $row )\r
4080         {\r
4081                 $name = i18n::substr($row['pfile'], 3);\r
4082                 $plugins[strtolower($name)] = $name;\r
4083         }\r
4084         \r
4085         $res->closeCursor();\r
4086         \r
4087         if ( !array_key_exists($path, $plugins) )\r
4088         {\r
4089                 header("HTTP/1.0 404 Not Found");\r
4090                 exit('');\r
4091         }\r
4092         else\r
4093         {\r
4094                 $plugin_name = $plugins[$path];\r
4095         }\r
4096         \r
4097         /* Return if not index.php */\r
4098         if ( ($phppath != strtolower($plugin_name) . '/')\r
4099           && ($phppath != strtolower($plugin_name) . '/index.php') )\r
4100         {\r
4101                 return;\r
4102         }\r
4103         \r
4104         /* Exit if not logged in. */\r
4105         if ( !$member->isLoggedIn() )\r
4106         {\r
4107                 exit('You aren\'t logged in.');\r
4108         }\r
4109         \r
4110         /* Check if this feature is needed (ie, if "$manager->checkTicket()" is not included in the script). */\r
4111         if ( $file = @file($p_translated) )\r
4112         {\r
4113                 $prevline = '';\r
4114                 \r
4115                 foreach($file as $line)\r
4116                 {\r
4117                         if (preg_match('#[\$]manager([\s]*)[\-]>([\s]*)checkTicket([\s]*)[\(]#i', $prevline . $line) )\r
4118                         {\r
4119                                 return;\r
4120                         }\r
4121                         \r
4122                         $prevline = $line;\r
4123                 }\r
4124         }\r
4125         \r
4126         /* Show a form if not valid ticket */\r
4127         if ( (i18n::strpos(serverVar('REQUEST_URI'), '?') !== FALSE\r
4128           || serverVar('QUERY_STRING')\r
4129           || strtoupper(serverVar('REQUEST_METHOD') ) == 'POST')\r
4130           && !$manager->checkTicket() )\r
4131         {\r
4132                 $oPluginAdmin = new PluginAdmin($plugin_name);\r
4133                 $oPluginAdmin->start();\r
4134                 \r
4135                 echo '<p>' . _ERROR_BADTICKET . "</p>\n";\r
4136                 \r
4137                 // Resolve URI and QUERY_STRING\r
4138                 if ($uri = serverVar('REQUEST_URI') )\r
4139                 {\r
4140                         list($uri, $qstring) = preg_split('#\?#', $uri);\r
4141                 }\r
4142                 else\r
4143                 {\r
4144                         if ( !($uri = serverVar('PHP_SELF') ) )\r
4145                         {\r
4146                                 $uri = serverVar('SCRIPT_NAME');\r
4147                         }\r
4148                         $qstring = serverVar('QUERY_STRING');\r
4149                 }\r
4150                 if ($qstring)\r
4151                 {\r
4152                         $qstring = '?' . $qstring;\r
4153                 }\r
4154                 \r
4155                 echo '<p>' . _SETTINGS_UPDATE . ' : ' . _QMENU_PLUGINS . ' <span style="color:red;">' . Entity::hsc($plugin_name) . "</span> ?</p>\n";\r
4156                 \r
4157                 switch(strtoupper(serverVar('REQUEST_METHOD') ) )\r
4158                 {\r
4159                         case 'POST':\r
4160                                 echo '<form method="POST" action="'.Entity::hsc($uri.$qstring).'">';\r
4161                                 $manager->addTicketHidden();\r
4162                                 _addInputTags($_POST);\r
4163                                 break;\r
4164                         \r
4165                         case 'GET':\r
4166                                 echo '<form method="GET" action="'.Entity::hsc($uri).'">';\r
4167                                 $manager->addTicketHidden();\r
4168                                 _addInputTags($_GET);\r
4169                         \r
4170                         default:\r
4171                                 break;\r
4172                 }\r
4173                 \r
4174                 echo '<input type="submit" value="' . _YES . '" />&nbsp;&nbsp;&nbsp;&nbsp;';\r
4175                 echo '<input type="button" value="' . _NO . '" onclick="history.back(); return false;" />';\r
4176                 echo "</form>\n";\r
4177                 \r
4178                 $oPluginAdmin->end();\r
4179                 exit;\r
4180         }\r
4181         \r
4182         /* Create new ticket */\r
4183         $ticket=$manager->addTicketToUrl('');\r
4184         $ticketforplugin['ticket'] = preg_split($ticket, i18n::strpos($ticket, 'ticket=') + 7);\r
4185         return;\r
4186 }\r
4187 =======
4188  * redirect()
4189  * Stops processing the request and redirects to the given URL.
4190  * - no actual contents should have been sent to the output yet
4191  * - the URL will be stripped of illegal or dangerous characters
4192  * 
4193  * @param       string  $uri
4194  * @return      void
4195  */
4196 function redirect($url)
4197 {
4198         $url = preg_replace('#[^a-z0-9-~+_.?\#=&;,/:@%*]#i', '', $url);
4199         header('Location: ' . $url);
4200         exit;
4201 }
4202
4203 /**
4204  * getBookmarklet()
4205  * Returns the Javascript code for a bookmarklet that works on most modern browsers
4206  * 
4207  * @param       integer $blogid ID for weblog
4208  * @return      script to call Bookmarklet
4209  */
4210 function getBookmarklet($blogid, $width=600,  $height=500)
4211 {
4212         global $CONF;
4213         
4214         $script = "Q='';"
4215                 . "x=document;"
4216                 . "y=window;"
4217                 . "if ( x.selection )"
4218                 . "{"
4219                 . " Q=x.selection.createRange().text;"
4220                 . "}"
4221                 . "else if ( y.getSelection )"
4222                 . "{"
4223                 . " Q=y.getSelection();"
4224                 . "}"
4225                 . "else if ( x.getSelection )"
4226                 . "{"
4227                 . " Q=x.getSelection();"
4228                 . "}"
4229                 . "wingm = window.open('{$CONF['AdminURL']}bookmarklet.php?blogid={$blogid}"
4230                 . " &logtext=' + encodeURIComponent(Q) +"
4231                 . " '&loglink=' + encodeURIComponent(x.location.href) +"
4232                 . " '&loglinktitle=' + encodeURIComponent(x.title),"
4233                 . " 'nucleusbm',"
4234                 . " 'scrollbars=yes,width={$width},height={$height},left=10,top=10,status=yes,resizable=yes');"
4235                 . "wingm.focus();";
4236         
4237         return $script;
4238 }
4239
4240 /**
4241  * cleanFileName()
4242  * cleans filename of uploaded file for writing to file system
4243  *
4244  * @param       string  $str
4245  * @return      string  $cleaned filename ready for use
4246  */
4247 function cleanFileName($str)
4248 {
4249         $str = strtolower($str);
4250         $ext_point = i18n::strrpos($str,".");
4251         if ( $ext_point === FALSE )
4252         {
4253                 return FALSE;
4254         }
4255         $ext = i18n::substr($str,$ext_point,i18n::strlen($str));
4256         $str = i18n::substr($str,0,$ext_point);
4257         
4258         return preg_replace("#[^a-z0-9-]#", "_", $str) . $ext;
4259 }
4260
4261 /**
4262  * use Notification class instead of this
4263  * Deprecated since 4.0:
4264  */
4265 function getMailFooter()
4266 {
4267         NOTIFICATION::get_mail_footer();
4268 }
4269 function isValidMailAddress($address)
4270 {
4271         return NOTIFICATION::address_validation($address);
4272 }
4273 /**
4274  * use Entity class instead of this
4275  * Deprecated since 4.0:
4276  */
4277 function highlight($text, $expression, $highlight)
4278 {
4279         return Entity::highlight($text, $expression, $highlight);
4280 }
4281 function shorten($string, $maxlength, $suffix)
4282 {
4283         return Entity::shorten($string, $maxlength, $suffix);
4284 }
4285 function stringStripTags ($string)
4286 {
4287         return Entity::strip_tags($string);
4288 }
4289 function toAscii($string)
4290 {
4291         return Entity::anchor_footnoting($string);
4292 }
4293 function stringToAttribute ($string)
4294 {
4295         return Entity::hsc($string);
4296 }
4297 function stringToXML ($string)
4298 {
4299         return Entity::hen($string);
4300 }
4301 function encode_desc($data)
4302 {
4303         return Entity::hen($data);
4304 }
4305 /**
4306  * Centralisation of the functions that deals with locales
4307  * This functions is based on the old way to deal with languages
4308  * Deprecated since 4.0:
4309  */
4310 function getLanguageName()
4311 {
4312         if( ($language = i18n::convert_locale_to_old_language_file_name(i18n::get_current_locale())) === FALSE )
4313         {
4314                 $language ='english';
4315         }
4316         return $language;
4317 }
4318 function selectLanguage($language)
4319 {
4320         global $DIR_LANG;
4321         include($DIR_LANG . preg_replace('#[\\\\|/]#', '', $language) . '.php');
4322         return;
4323 }
4324 /**
4325  * use i18n class instead of these
4326  * Deprecated since 4.0
4327  */
4328 function checkLanguage($lang)
4329 {
4330         return ( preg_match('#^(.+)_(.+)_(.+)$#', $lang)
4331           || i18n::convert_old_language_file_name_to_locale($lang) );
4332 }
4333 function formatDate($format, $timestamp, $default_format, &$blog)
4334 {
4335         $offset = date('Z', $timestamp);
4336         if ( $blog )
4337         {
4338                 $offset += $blog->getTimeOffset() * 3600;
4339         }
4340         return i18n::formatted_datetime($format, $timestamp, $offset, $default_format);
4341 }
4342
4343 /**
4344  * use DB class instead of these
4345  * Deprecated since 4.0
4346  */
4347 function quickQuery($query)
4348 {
4349         $row = DB::getRow($query);
4350         return $row['result'];
4351 }
4352 function mysqldate($timestamp)
4353 {
4354         return DB::formatDateTime($timestamp);
4355  }
4356 /**
4357  * Centralisation of the functions that generate links
4358  * Deprecated since 4.0:
4359  * Please use Link::FunctionName(...) instead
4360  */
4361 function createItemLink($itemid, $extra = '')
4362 {
4363         return Link::create_item_link($itemid, $extra);
4364 }
4365 function createMemberLink($memberid, $extra = '')
4366 {
4367         return Link::create_member_link($memberid, $extra);
4368 }
4369 function createCategoryLink($catid, $extra = '')
4370 {
4371         return Link::create_category_link($catid, $extra);
4372 }
4373 function createArchiveListLink($blogid = '', $extra = '')
4374 {
4375         return Link::create_archivelist_link($blogid, $extra);
4376 }
4377 function createArchiveLink($blogid, $archive, $extra = '')
4378 {
4379         return Link::create_archive_link($blogid, $archive, $extra);
4380 }
4381 function createBlogidLink($blogid, $params = '')
4382 {
4383         return Link::create_blogid_link($blogid, $params = '');
4384 }
4385 function createLink($type, $params)
4386 {
4387         return Link::create_link($type, $params);
4388 }
4389 function createBlogLink($url, $params)
4390 {
4391         return Link::create_blog_link($url, $params);
4392 }
4393 /**
4394  * use ActionLog class instead of this
4395  * Deprecated since 4.0
4396  */
4397 function addToLog($level, $msg)
4398 {
4399         ActionLog::add($level, $msg);
4400 }
4401 /**
4402  * use PHP's implement
4403  * Deprecated since 4.0
4404  */
4405 function ifset(&$var)
4406 {
4407         if ( isset($var) )
4408         {
4409                 return $var;
4410         }
4411         
4412         return NULL;
4413 }
4414 /**
4415  * use Manager::getPluginNameFromPid() instead of this
4416  * Deprecated since 4.0
4417  */
4418 function getPluginNameFromPid($pid)
4419 {
4420         global $manager;
4421         return $manager->getPluginNameFromPid($pid);
4422 }
4423 /**
4424  * use Manager::numberOfEventSubscribers() instead of this
4425  * Deprecated since 4.0
4426  */
4427 function numberOfEventSubscribers($event)
4428 {
4429         global $manager;
4430         return $manager->getNumberOfSubscribers($event);
4431 }
4432
4433 /**
4434  * PluginAdmin has already the alternative implement
4435  * Deprecated since 4.0
4436  */
4437 function ticketForPlugin()
4438 {
4439         global $CONF, $DIR_LIBS, $DIR_LOCALES, $DIR_PLUGINS, $manager, $member, $ticketforplugin;
4440         
4441         /* initialize */
4442         $ticketforplugin = array();
4443         $ticketforplugin['ticket'] = FALSE;
4444         
4445         /* Check if using plugin's php file. */
4446         $p_translated = serverVar('SCRIPT_FILENAME');
4447         
4448         if (!file_exists($p_translated) )
4449         {
4450                 header("HTTP/1.0 404 Not Found");
4451                 exit('');
4452         }
4453         
4454         // check whether this is plugin or not
4455         $p_translated = str_replace('\\', '/', $p_translated);
4456         $d_plugins = str_replace('\\', '/', $DIR_PLUGINS);
4457         if ( i18n::strpos($p_translated, $d_plugins) !== 0 )
4458         {
4459                 return;
4460         }
4461         
4462         // Solve the plugin php file or admin directory
4463         $phppath = i18n::substr($p_translated, i18n::strlen($d_plugins) );
4464         // Remove the first "/" if exists.
4465         $phppath = preg_replace('#^/#', '', $phppath);
4466         // Remove the first "NP_" and the last ".php" if exists.
4467         $path = preg_replace('#^NP_(.*)\.php$#', '$1', $phppath);
4468         // Remove the "/" and beyond.
4469         $path = preg_replace('#^([^/]*)/(.*)$#', '$1', $path);
4470         
4471         // Solve the plugin name.
4472         $plugins = array();
4473         $query = sprintf('SELECT pfile FROM %s;', sql_table('plugin'));
4474         $res = DB::getResult($query);
4475         
4476         foreach ( $res as $row )
4477         {
4478                 $name = i18n::substr($row['pfile'], 3);
4479                 $plugins[strtolower($name)] = $name;
4480         }
4481         
4482         $res->closeCursor();
4483         
4484         if ( !array_key_exists($path, $plugins) )
4485         {
4486                 header("HTTP/1.0 404 Not Found");
4487                 exit('');
4488         }
4489         else
4490         {
4491                 $plugin_name = $plugins[$path];
4492         }
4493         
4494         /* Return if not index.php */
4495         if ( ($phppath != strtolower($plugin_name) . '/')
4496           && ($phppath != strtolower($plugin_name) . '/index.php') )
4497         {
4498                 return;
4499         }
4500         
4501         /* Exit if not logged in. */
4502         if ( !$member->isLoggedIn() )
4503         {
4504                 exit('You aren\'t logged in.');
4505         }
4506         
4507         /* Check if this feature is needed (ie, if "$manager->checkTicket()" is not included in the script). */
4508         if ( $file = @file($p_translated) )
4509         {
4510                 $prevline = '';
4511                 
4512                 foreach($file as $line)
4513                 {
4514                         if (preg_match('#[\$]manager([\s]*)[\-]>([\s]*)checkTicket([\s]*)[\(]#i', $prevline . $line) )
4515                         {
4516                                 return;
4517                         }
4518                         
4519                         $prevline = $line;
4520                 }
4521         }
4522         
4523         /* Show a form if not valid ticket */
4524         if ( (i18n::strpos(serverVar('REQUEST_URI'), '?') !== FALSE
4525           || serverVar('QUERY_STRING')
4526           || strtoupper(serverVar('REQUEST_METHOD') ) == 'POST')
4527           && !$manager->checkTicket() )
4528         {
4529                 $oPluginAdmin = new PluginAdmin($plugin_name);
4530                 $oPluginAdmin->start();
4531                 
4532                 echo '<p>' . _ERROR_BADTICKET . "</p>\n";
4533                 
4534                 // Resolve URI and QUERY_STRING
4535                 if ($uri = serverVar('REQUEST_URI') )
4536                 {
4537                         list($uri, $qstring) = preg_split('#\?#', $uri);
4538                 }
4539                 else
4540                 {
4541                         if ( !($uri = serverVar('PHP_SELF') ) )
4542                         {
4543                                 $uri = serverVar('SCRIPT_NAME');
4544                         }
4545                         $qstring = serverVar('QUERY_STRING');
4546                 }
4547                 if ($qstring)
4548                 {
4549                         $qstring = '?' . $qstring;
4550                 }
4551                 
4552                 echo '<p>' . _SETTINGS_UPDATE . ' : ' . _QMENU_PLUGINS . ' <span style="color:red;">' . Entity::hsc($plugin_name) . "</span> ?</p>\n";
4553                 
4554                 switch(strtoupper(serverVar('REQUEST_METHOD') ) )
4555                 {
4556                         case 'POST':
4557                                 echo '<form method="POST" action="'.Entity::hsc($uri.$qstring).'">';
4558                                 $manager->addTicketHidden();
4559                                 _addInputTags($_POST);
4560                                 break;
4561                         
4562                         case 'GET':
4563                                 echo '<form method="GET" action="'.Entity::hsc($uri).'">';
4564                                 $manager->addTicketHidden();
4565                                 _addInputTags($_GET);
4566                         
4567                         default:
4568                                 break;
4569                 }
4570                 
4571                 echo '<input type="submit" value="' . _YES . '" />&nbsp;&nbsp;&nbsp;&nbsp;';
4572                 echo '<input type="button" value="' . _NO . '" onclick="history.back(); return false;" />';
4573                 echo "</form>\n";
4574                 
4575                 $oPluginAdmin->end();
4576                 exit;
4577         }
4578         
4579         /* Create new ticket */
4580         $ticket=$manager->addTicketToUrl('');
4581         $ticketforplugin['ticket'] = preg_split($ticket, i18n::strpos($ticket, 'ticket=') + 7);
4582         return;
4583 }
4584 >>>>>>> skinnable-master