OSDN Git Service

420f1c13d9d326263da2889efdee0eceefa9cded
[nucleus-jp/nucleus-next.git] / nucleus / libs / globalfunctions.php
1 <?php\r
2 \r
3 /*\r
4  * Nucleus: PHP/MySQL Weblog CMS (http://nucleuscms.org/)\r
5  * Copyright (C) 2002-2009 The Nucleus Group\r
6  *\r
7  * This program is free software; you can redistribute it and/or\r
8  * modify it under the terms of the GNU General Public License\r
9  * as published by the Free Software Foundation; either version 2\r
10  * of the License, or (at your option) any later version.\r
11  * (see nucleus/documentation/index.html#license for more info)\r
12  */\r
13 /**\r
14  * @license http://nucleuscms.org/license.txt GNU General Public License\r
15  * @copyright Copyright (C) 2002-2009 The Nucleus Group\r
16  * @version $Id: globalfunctions.php 1856 2012-05-18 09:30:16Z sakamocchi $
17  */\r
18 \r
19 /* needed if we include globalfunctions from install.php */\r
20 global $nucleus, $CONF, $DIR_LIBS, $DIR_LOCALES, $manager, $member, $MYSQL_HANDLER, $StartTime;
21
22 /* just for benchmark tag */
23 $StartTime = microtime(TRUE);
24 \r
25 $nucleus['version'] = 'v4.00 SVN';\r
26 $nucleus['codename'] = '';\r
27 \r
28 /*\r
29  * make sure there's no unnecessary escaping:\r
30  * set_magic_quotes_runtime(0);\r
31  */\r
32 if ( version_compare(PHP_VERSION, '5.3.0', '<') )\r
33 {\r
34         ini_set('magic_quotes_runtime', '0');\r
35 }\r
36 \r
37 /* check and die if someone is trying to override internal globals (when register_globals turn on) */\r
38 checkVars(array('nucleus', 'CONF', 'DIR_LIBS',
39 'MYSQL_HOST', 'MYSQL_USER', 'MYSQL_PASSWORD', 'MYSQL_DATABASE',
40 'DIR_LOCALES', 'DIR_PLUGINS',
41 'HTTP_GET_VARS', 'HTTP_POST_VARS', 'HTTP_COOKIE_VARS', 'HTTP_ENV_VARS',
42 'HTTP_SESSION_VARS', 'HTTP_POST_FILES', 'HTTP_SERVER_VARS',
43 'GLOBALS', 'argv', 'argc', '_GET', '_POST', '_COOKIE', '_ENV', '_SESSION', '_SERVER', '_FILES'));
44 \r
45 if ( !isset($CONF) )\r
46 {\r
47         $CONF = array();\r
48 }\r
49 \r
50 /* debug mode */\r
51 if ( array_key_exists('debug', $CONF) && $CONF['debug'] )\r
52 {\r
53         /* report all errors! */\r
54         error_reporting(E_ALL);\r
55 }\r
56 else\r
57 {\r
58         ini_set('display_errors','0');\r
59         error_reporting(E_ERROR | E_WARNING | E_PARSE);\r
60 }\r
61 \r
62 /*\r
63  * alertOnHeadersSent\r
64  *  Displays an error when visiting a public Nucleus page and headers have\r
65  *  been sent out to early. This usually indicates an error in either a\r
66  *  configuration file or a translation file, and could cause Nucleus to\r
67  *  malfunction\r
68  */\r
69 if ( !array_key_exists('alertOnHeadersSent', $CONF) )\r
70 {\r
71         $CONF['alertOnHeadersSent'] = 1;\r
72 }\r
73 \r
74 /*\r
75  * alertOnSecurityRisk\r
76  * Displays an error only when visiting the admin area, and when one or\r
77  *  more of the installation files (install.php, install.sql, upgrades/\r
78  *  directory) are still on the server.\r
79  */\r
80 if ( !array_key_exists('alertOnSecurityRisk', $CONF) )\r
81 {\r
82         $CONF['alertOnSecurityRisk'] = 1;\r
83 }\r
84 \r
85 /*\r
86  * Set these to 1 to allow viewing of future items or draft items\r
87  * Should really never do this, but can be useful for some plugins that might need to\r
88  * Could cause some other issues if you use future posts otr drafts\r
89  * So use with care\r
90  */\r
91 $CONF['allowDrafts'] = 0;\r
92 $CONF['allowFuture'] = 0;\r
93 \r
94 if ( getNucleusPatchLevel() > 0 )\r
95 {\r
96         $nucleus['version'] .= '/' . getNucleusPatchLevel();\r
97 }\r
98 \r
99 /* Avoid notices */\r
100 if ( !array_key_exists('installscript', $CONF) || empty($CONF['installscript']) )\r
101 {\r
102         $CONF['installscript'] = 0;\r
103 }\r
104 if ( !array_key_exists('UsingAdminArea', $CONF) )\r
105 {\r
106         $CONF['UsingAdminArea'] = 0;\r
107 }\r
108 \r
109 if ( !headers_sent() )\r
110 {\r
111         header('Generator: Nucleus CMS ' . $nucleus['version']);\r
112 }\r
113 \r
114 \r
115 /* TODO: This is for compatibility since 4.0, should be obsoleted at future release. */\r
116 if ( !isset($DIR_LOCALES) )\r
117 {\r
118         $DIR_LOCALES = $DIR_NUCLEUS . 'locales/';\r
119 }\r
120 global $DIR_LANG;\r
121 if ( !isset($DIR_LANG) )\r
122 {\r
123         $DIR_LANG = $DIR_LOCALES;\r
124 }\r
125 \r
126 /* load and initialize i18n class */\r
127 if (!class_exists('i18n', FALSE))\r
128 {\r
129         include($DIR_LIBS . 'i18n.php');\r
130 }\r
131 if ( !i18n::init('UTF-8', $DIR_LOCALES) )\r
132 {\r
133         exit('Fail to initialize i18n class.');\r
134 }\r
135 \r
136 /* TODO: This is just for compatibility since 4.0, should be obsoleted at future release. */\r
137 define('_CHARSET', i18n::get_current_charset());\r
138 \r
139 \r
140 /*\r
141  * NOTE: Since 4.0 release, Entity class becomes to be important class\r
142  *  with some wrapper functions for htmlspechalchars/htmlentity PHP's built-in function\r
143  */\r
144 include($DIR_LIBS . 'ENTITY.php');\r
145 \r
146 /* we will use postVar, getVar, ... methods instead of $_GET, $_POST ... */\r
147 if ( $CONF['installscript'] != 1 )\r
148 {\r
149         /* vars were already included in install.php */\r
150         include_once($DIR_LIBS . 'vars4.1.0.php');\r
151         \r
152         /* added for 4.0 DB::* wrapper and compatibility sql_* */\r
153         include_once($DIR_LIBS . 'sql/sql.php');\r
154 }\r
155 \r
156 /* include core classes that are needed for login & plugin handling */\r
157 include($DIR_LIBS . 'MEMBER.php');\r
158 include($DIR_LIBS . 'ACTIONLOG.php');\r
159 include($DIR_LIBS . 'MANAGER.php');\r
160 include($DIR_LIBS . 'PLUGIN.php');\r
161 \r
162 $manager =& MANAGER::instance();\r
163 \r
164 /* only needed when updating logs */\r
165 if ( $CONF['UsingAdminArea'] )\r
166 {\r
167         /* XML-RPC client classes */\r
168         include($DIR_LIBS . 'xmlrpc.inc.php');\r
169         include($DIR_LIBS . 'ADMIN.php');\r
170 }\r
171 \r
172 \r
173 /* connect to database */\r
174 if ( !isset($MYSQL_HANDLER) )\r
175 {\r
176         $MYSQL_HANDLER = array('mysql','');\r
177 }\r
178 if ( $MYSQL_HANDLER[0] == '' )\r
179 {\r
180         $MYSQL_HANDLER[0] = 'mysql';\r
181 }\r
182 DB::setConnectionInfo($MYSQL_HANDLER[1], $MYSQL_HOST, $MYSQL_USER, $MYSQL_PASSWORD, $MYSQL_DATABASE);\r
183 \r
184 \r
185 /* force locale or charset */\r
186 $locale = '';\r
187 $charset = i18n::get_current_charset();\r
188 \r
189 $data = array(\r
190         'locale'        => &$locale,\r
191         'charset'       => &$charset\r
192 );\r
193 $manager->notify('ForceLocale', $data);\r
194 \r
195 if ( $data['locale'] !== '' )\r
196 {\r
197         i18n::set_forced_locale($data['locale']);\r
198 }\r
199 if ( $data['charset'] !== '' )\r
200 {\r
201         i18n::set_forced_charset($data['charset']);\r
202 }\r
203 unset($locale);\r
204 unset($charset);\r
205 \r
206 \r
207 /* convert forced charset to current charset */\r
208 if ( i18n::get_forced_charset() != i18n::get_current_charset() )\r
209 {\r
210         $_POST          = i18n::convert_array($_POST, i18n::get_forced_charset());\r
211         $_GET           = i18n::convert_array($_GET, i18n::get_forced_charset());\r
212         $_REQUEST       = i18n::convert_array($_REQUEST, i18n::get_forced_charset());\r
213         $_COOKIE        = i18n::convert_array($_COOKIE, i18n::get_forced_charset());\r
214         $_FILES         = i18n::convert_array($_FILES, i18n::get_forced_charset());\r
215         \r
216         if ( session_id() !== '' )\r
217         {\r
218                 $_SESSION = i18n::convert_array($_SESSION, i18n::get_forced_charset());\r
219         }\r
220 }\r
221 \r
222 \r
223 /* sanitize option */\r
224 $bLoggingSanitizedResult = 0;\r
225 $bSanitizeAndContinue = 0;\r
226 $orgRequestURI = serverVar('REQUEST_URI');\r
227 sanitizeParams();\r
228 \r
229 /* logs sanitized result if need */\r
230 if ( $orgRequestURI !== serverVar('REQUEST_URI') )\r
231 {\r
232         $msg = "Sanitized [" . serverVar('REMOTE_ADDR') . "] ";\r
233         $msg .= $orgRequestURI . " -> " . serverVar('REQUEST_URI');\r
234         if ( $bLoggingSanitizedResult )\r
235         {\r
236                 addToLog(WARNING, $msg);\r
237         }\r
238         if ( !$bSanitizeAndContinue )\r
239         {\r
240                 die("");\r
241         }\r
242 }\r
243 \r
244 /* get all variables that can come from the request and put them in the global scope */\r
245 $blogid         = requestVar('blogid');\r
246 $itemid         = intRequestVar('itemid');\r
247 $catid          = intRequestVar('catid');\r
248 $skinid         = requestVar('skinid');\r
249 $memberid       = requestVar('memberid');\r
250 $archivelist = requestVar('archivelist');\r
251 $imagepopup     = requestVar('imagepopup');\r
252 $archive        = requestVar('archive');\r
253 $query          = requestVar('query');\r
254 $highlight      = requestVar('highlight');\r
255 $amount         = requestVar('amount');\r
256 $action         = requestVar('action');\r
257 $nextaction     = requestVar('nextaction');\r
258 $maxresults     = requestVar('maxresults');\r
259 $startpos       = intRequestVar('startpos');\r
260 $errormessage = '';\r
261 $error          = '';\r
262 $special        = requestVar('special');\r
263 \r
264 \r
265 /* read config */\r
266 getConfig();\r
267 \r
268 \r
269 /* Properly set $CONF['Self'] and others if it's not set...\r
270  * usually when we are access from admin menu\r
271  */\r
272 if ( !array_key_exists('Self', $CONF) )\r
273 {\r
274         $CONF['Self'] = $CONF['IndexURL'];\r
275         /* strip trailing */\r
276         if ( $CONF['Self'][i18n::strlen($CONF['Self']) -1] == "/" )\r
277         {\r
278                 $CONF['Self'] = i18n::substr($CONF['Self'], 0, i18n::strlen($CONF['Self']) -1);\r
279         }\r
280 }\r
281 \r
282 $CONF['ItemURL']                = $CONF['Self'];\r
283 $CONF['ArchiveURL']             = $CONF['Self'];\r
284 $CONF['ArchiveListURL'] = $CONF['Self'];\r
285 $CONF['MemberURL']              = $CONF['Self'];\r
286 $CONF['SearchURL']              = $CONF['Self'];\r
287 $CONF['BlogURL']                = $CONF['Self'];\r
288 $CONF['CategoryURL']    = $CONF['Self'];\r
289 \r
290 /* automatically use simpler toolbar for mozilla */\r
291 if ( ($CONF['DisableJsTools'] == 0)\r
292    && i18n::strpos(serverVar('HTTP_USER_AGENT'), 'Mozilla/5.0') !== FALSE\r
293    && i18n::strpos(serverVar('HTTP_USER_AGENT'), 'Gecko') !== FALSE )\r
294 {\r
295         $CONF['DisableJsTools'] = 2;\r
296 }\r
297 \r
298 /* login processing */
299 $member = new Member();\r
300 \r
301 if ( $action == 'login' )\r
302 {\r
303         $login = postVar('login');\r
304         $password = postVar('password');\r
305         $shared = intPostVar('shared');\r
306         $member->login($login, $password, $shared);\r
307 }\r
308 elseif ( ($action == 'logout') )\r
309 {\r
310         $member->logout();\r
311 }\r
312 else\r
313 {\r
314         $member->cookielogin();\r
315 }\r
316 \r
317 \r
318 /* TODO: This is for backward compatibility, should be obsoleted near future. */\r
319 if ( !preg_match('#^(.+)_(.+)_(.+)$#', $CONF['Locale'])\r
320   && ($CONF['Locale'] = i18n::convert_old_language_file_name_to_locale($CONF['Locale'])) === FALSE )\r
321 {\r
322         $CONF['Locale'] = 'en_Latn_US';\r
323 }\r
324 if ( !array_key_exists('Language', $CONF) )\r
325 {\r
326         $CONF['Language'] = i18n::convert_locale_to_old_language_file_name($CONF['Locale']);\r
327 }\r
328 $locale = $CONF['Locale'];\r
329 \r
330 \r
331 /* NOTE: include translation file and set locale */\r
332 if ( $member->isLoggedIn() )\r
333 {\r
334         if ( $member->getLocale() )\r
335         {\r
336                 $locale = $member->getLocale();\r
337         }\r
338 }\r
339 else\r
340 {\r
341         if ( i18n::get_forced_locale() !== '' )\r
342         {\r
343                 $locale = i18n::get_forced_locale();\r
344         }\r
345 }\r
346 include_translation($locale);\r
347 i18n::set_current_locale($locale);\r
348 \r
349 \r
350 /* login completed */\r
351 $manager->notify('PostAuthentication', array('loggedIn' => $member->isLoggedIn() ) );\r
352 \r
353 /* next action */\r
354 if ( $member->isLoggedIn() && $nextaction )\r
355 {\r
356         $action = $nextaction;\r
357 }\r
358 \r
359 /* first, let's see if the site is disabled or not. always allow admin area access. */\r
360 if ( $CONF['DisableSite'] && !$member->isAdmin() && !$CONF['UsingAdminArea'] )\r
361 {\r
362         redirect($CONF['DisableSiteURL']);\r
363         exit;\r
364 }\r
365 \r
366 /* load other classes */\r
367 include($DIR_LIBS . 'PARSER.php');\r
368 include($DIR_LIBS . 'SKIN.php');\r
369 include($DIR_LIBS . 'TEMPLATE.php');\r
370 include($DIR_LIBS . 'BLOG.php');\r
371 include($DIR_LIBS . 'BODYACTIONS.php');\r
372 include($DIR_LIBS . 'COMMENTS.php');\r
373 include($DIR_LIBS . 'COMMENT.php');\r
374 include($DIR_LIBS . 'NOTIFICATION.php');\r
375 include($DIR_LIBS . 'BAN.php');\r
376 include($DIR_LIBS . 'SEARCH.php');\r
377 include($DIR_LIBS . 'LINK.php');\r
378 \r
379 /* set lastVisit cookie (if allowed) */\r
380 if ( !headers_sent() )\r
381 {\r
382         if ( $CONF['LastVisit'] )\r
383         {\r
384                 setcookie($CONF['CookiePrefix'] . 'lastVisit', time(), time() + 2592000, $CONF['CookiePath'], $CONF['CookieDomain'], $CONF['CookieSecure']);\r
385         }\r
386         else\r
387         {\r
388                 setcookie($CONF['CookiePrefix'] . 'lastVisit', '', (time() - 2592000), $CONF['CookiePath'], $CONF['CookieDomain'], $CONF['CookieSecure']);\r
389         }\r
390 }\r
391 \r
392 if ( !defined('_ARCHIVETYPE_MONTH') )\r
393 {\r
394         define('_ARCHIVETYPE_DAY', 'day');\r
395         define('_ARCHIVETYPE_MONTH', 'month');\r
396         define('_ARCHIVETYPE_YEAR', 'year');\r
397 }\r
398 \r
399 /* for path resolving */
400 $virtualpath = getVar('virtualpath');
401 if ( getVar('virtualpath') == '' )
402                                         {\r
403         $virtualpath = serverVar('PATH_INFO');
404                                         }\r
405                                 \r
406 /*
407  * switch URLMode back to normal when $CONF['Self'] ends in .php
408  * this avoids urls like index.php/item/13/index.php/item/15
409  */
410 if ( !array_key_exists('URLMode', $CONF) || ($CONF['URLMode'] != 'pathinfo') )
411                                         {\r
412         $CONF['URLMode'] = 'normal';
413                                         }\r
414 else
415                                         {\r
416         if ( i18n::substr($CONF['Self'], i18n::strlen($CONF['Self']) - 4) != '.php' )
417                                         {\r
418                 decodePathInfo($virtualpath);
419         }\r
420 }\r
421 \r
422 /*\r
423  * PostParseURL is a place to cleanup any of the path-related global variables before the selector function is run.\r
424  * It has 2 values in the data in case the original virtualpath is needed, but most the use will be in tweaking\r
425  * global variables to clean up (scrub out catid or add catid) or to set someother global variable based on\r
426  * the values of something like catid or itemid\r
427  * New in 3.60\r
428  */\r
429 $data = array(\r
430         'type' => basename(serverVar('SCRIPT_NAME')),\r
431         'info' => $virtualpath\r
432 );\r
433 $manager->notify('PostParseURL', $data);\r
434 \r
435 /*\r
436  * NOTE: Here is the end of initialization\r
437  */\r
438 \r
439 /**\r
440  * include_libs()\r
441  * This function includes or requires the specified library file\r
442  * \r
443  * @param       string  $file\r
444  * @param       boolean $once use the _once() version\r
445  * @param       boolean $require use require() instead of include()\r
446  * @return      void\r
447  */\r
448 function include_libs($file, $once = TRUE, $require = TRUE)\r
449 {\r
450         global $DIR_LIBS;\r
451         \r
452         // $DIR_LIBS isn't a directory\r
453         if ( !is_dir($DIR_LIBS) )\r
454         {\r
455                 exit;\r
456         }\r
457         \r
458         $lib_path = $DIR_LIBS . $file;\r
459         \r
460         if ( $once && $require )\r
461         {\r
462                 require_once($lib_path);\r
463         }\r
464         else if ( $once && !$require )\r
465         {\r
466                 include_once($lib_path);\r
467         }\r
468         else if ( $require )\r
469         {\r
470                 require($lib_path);\r
471         }\r
472         else\r
473         {\r
474                 include($lib_path);\r
475         }\r
476         return;\r
477 }\r
478 \r
479 /**\r
480  * include_plugins()\r
481  * This function includes or requires the specified plugin file\r
482  * \r
483  * @param       string  $file\r
484  * @param       boolean $once use the _once() version\r
485  * @param       boolean $require use require() instead of include()\r
486  * @return      \r
487  */\r
488 function include_plugins($file, $once = TRUE, $require = TRUE)\r
489 {\r
490         global $DIR_PLUGINS;\r
491         \r
492         // begin if: $DIR_LIBS isn't a directory\r
493         if ( !is_dir($DIR_PLUGINS) )\r
494         {\r
495                 exit;\r
496         }\r
497         \r
498         $plugin_path = $DIR_PLUGINS . $file;\r
499         \r
500         // begin if: \r
501         if ( $once && $require )\r
502         {\r
503                 require_once($plugin_path);\r
504         }\r
505         else if ( $once && !$require )\r
506         {\r
507                 include_once($plugin_path);\r
508         }\r
509         elseif ( $require )\r
510         {\r
511                 require($plugin_path);\r
512         }\r
513         else\r
514         {\r
515                 include($plugin_path);\r
516         }\r
517         return;\r
518 }\r
519 \r
520 /**\r
521  * include_translation()\r
522  * This function decide which locale is used and include translation\r
523  * \r
524  * @param       string  &$locale        locale name referring to 'language tags' defined in RFC 5646\r
525  * @return      void\r
526  */\r
527 function include_translation(&$locale)\r
528 {\r
529         global $DIR_LOCALES;\r
530         \r
531         $translation_file = $DIR_LOCALES . $locale . '.' . i18n::get_current_charset() . '.php';\r
532         if ( !file_exists($translation_file) )\r
533         {\r
534                 $locale = 'en_Latn_US';\r
535                 $translation_file = $DIR_LOCALES . 'en_Latn_US.ISO-8859-1.php';\r
536         }\r
537         include($translation_file);\r
538         return;\r
539 }\r
540 \r
541 /**\r
542  * intPostVar()\r
543  * This function returns the integer value of $_POST for the variable $name\r
544  * \r
545  * @param       string  $name   field to get the integer value of\r
546  * @return      integer\r
547  */\r
548 function intPostVar($name)\r
549 {\r
550         return (integer) postVar($name);\r
551 }\r
552 \r
553 \r
554 /**\r
555  * intGetVar()\r
556  * This function returns the integer value of $_GET for the variable $name\r
557  * \r
558  * @param       string  $name   field to get the integer value of\r
559  * @return      integer\r
560  */\r
561 function intGetVar($name)\r
562 {\r
563         return (integer) getVar($name);\r
564 }\r
565 \r
566 \r
567 /**\r
568  * intRequestVar()\r
569  * This function returns the integer value of $_REQUEST for the variable $name. Also checks $_GET and $_POST if not found in $_REQUEST\r
570  * \r
571  * @param string $name field to get the integer value of\r
572  * @return int\r
573  */\r
574 function intRequestVar($name)\r
575 {\r
576         return (integer) requestVar($name);\r
577 }\r
578 \r
579 \r
580 /**\r
581  * intCookieVar()\r
582  * This function returns the integer value of $_COOKIE for the variable $name\r
583  * \r
584  * @param       string  $name   field to get the integer value of\r
585  * @return      integer\r
586  */\r
587 function intCookieVar($name)\r
588 {\r
589         return (integer) cookieVar($name);\r
590 }\r
591 \r
592 /**\r
593  * getNucleusVersion()\r
594  * This function returns the current Nucleus version (100 = 1.00, 101 = 1.01, etc...)\r
595  * \r
596  * @param       void\r
597  * @return      integer\r
598  */\r
599 function getNucleusVersion()\r
600 {\r
601         return 400;\r
602 }\r
603 \r
604 /**\r
605  * getNucleusPatchLevel()\r
606  * TODO: Better description of this function.\r
607  *\r
608  * Power users can install patches in between nucleus releases. These patches\r
609  * usually add new functionality in the plugin API and allow those to\r
610  * be tested without having to install CVS.\r
611  *\r
612  *@param        void\r
613  * @return      integer\r
614  */\r
615 function getNucleusPatchLevel()\r
616 {\r
617         return 0;\r
618 }\r
619 \r
620 /**\r
621  * getLatestVersion()\r
622  * This function returns the latest Nucleus version available for download from nucleuscms.org or FALSE if unable to attain data\r
623  * Format will be major.minor/patachlevel e.g. 3.41 or 3.41/02\r
624  * \r
625  * @param       void\r
626  * @return      mixed\r
627  */\r
628 function getLatestVersion()\r
629 {\r
630         // begin if: cURL is not available in this PHP installation\r
631         if ( !function_exists('curl_init') )\r
632         {\r
633                 return FALSE;\r
634         }\r
635         \r
636         $curl = curl_init();\r
637         $timeout = 5;\r
638         \r
639         curl_setopt ($curl, CURLOPT_URL, 'http://nucleuscms.org/version_check.php');\r
640         curl_setopt ($curl, CURLOPT_RETURNTRANSFER, 1);\r
641         curl_setopt ($curl, CURLOPT_CONNECTTIMEOUT, $timeout);\r
642         \r
643         $return = curl_exec($curl);\r
644         \r
645         curl_close($curl);\r
646         \r
647         return $return;\r
648 }\r
649 \r
650 /**\r
651  * sql_table()\r
652  * This function returns a Nucleus table name with the appropriate prefix\r
653  * @param string $name\r
654  * @return string\r
655  */\r
656 function sql_table($name)\r
657 {\r
658         global $MYSQL_PREFIX;\r
659         \r
660         // begin if: no MySQL prefix\r
661         if ( empty($MYSQL_PREFIX) )\r
662         {\r
663                 return 'nucleus_' . $name;\r
664         }\r
665         // else: use MySQL prefix\r
666         else\r
667         {\r
668                 return $MYSQL_PREFIX . 'nucleus_' . $name;\r
669         }\r
670         return;\r
671 }\r
672 \r
673 /**\r
674  * sendContentType()\r
675  * This function sends the Content-Type header if headers have not already been sent\r
676  * It also determines if the browser can accept application/xhtml+xml and sends it only to those that can.\r
677  * \r
678  * if content type is application/xhtml+xml, only send it to browsers\r
679  * that can handle it (IE6 cannot). Otherwise, send text/html\r
680  *\r
681  * v2.5:\r
682  * For admin area pages, keep sending text/html (unless it's a debug version)\r
683  * application/xhtml+xml still causes too much problems with the javascript implementations\r
684  *\r
685  * v3.3:\r
686  * ($CONF['UsingAdminArea'] && !$CONF['debug']) gets removed,\r
687  * application/xhtml+xml seems to be working, so we're going to use it if we can.\r
688  * \r
689  * @param       string  $content_type   MIME media type registered to IANA, http://www.iana.org/assignments/media-types/index.html\r
690  * @param       string  $page_type              \r
691  * @param       string  $charset                Deprecated. This has no meaning.\r
692  * @return      void\r
693  * \r
694  */\r
695 function sendContentType($content_type, $page_type = '', $charset = '')\r
696 {\r
697         global $manager, $CONF;\r
698         \r
699         if ( headers_sent() )\r
700         {\r
701                 return;\r
702         }\r
703         \r
704         /* NOTE: MIME Media Type */\r
705         if ( ($content_type == 'application/xhtml+xml')\r
706                 && (!stristr(serverVar('HTTP_ACCEPT'), 'application/xhtml+xml') ) )\r
707         {\r
708                 $content_type = 'text/html';\r
709         }\r
710         \r
711         /* NOTE: generate event */\r
712         $data = array(\r
713                 'pageType'              =>  $page_type,\r
714                 'contentType'   => &$content_type\r
715         );\r
716         $manager->notify('PreSendContentType', $data);\r
717         \r
718         /* NOTE: confirm MIME Media Type */\r
719         $content_type = preg_replace('#[^a-zA-Z0-9-+./]#', '', $content_type);\r
720         \r
721         /* NOTE: confirm character set */\r
722         $charset = i18n::get_current_charset();\r
723         if ( i18n::get_forced_charset() !== '' )\r
724         {\r
725                 $charset = i18n::get_forced_charset();\r
726         }\r
727         \r
728         /* NOTE: send HTTP 1.1 header */\r
729         header("Content-Type: {$content_type}; charset={$charset}");\r
730         \r
731         /* NOTE: set handler for translating character set */\r
732         if ( $charset != i18n::get_current_charset() )\r
733         {\r
734                 ob_start(array('i18n', 'convert_handler'));\r
735         }\r
736         \r
737         return;\r
738 }\r
739 \r
740 /**\r
741  * parseHighlight()\r
742  * This function parses a query into an array of expressions that can be passed on to the highlight method\r
743  * @param       string  $query\r
744  * @return      void\r
745  */\r
746 function parseHighlight($query)\r
747 {\r
748         // TODO: add more intelligent splitting logic\r
749         \r
750         // get rid of quotes\r
751         $query = preg_replace('/\'|"/', '', $query);\r
752         \r
753         if ( !$query )\r
754         {\r
755                 return array();\r
756         }\r
757         \r
758         $aHighlight = preg_split('# #', $query);\r
759         \r
760         for ( $i = 0; $i < count($aHighlight); $i++ )\r
761         {\r
762                 $aHighlight[$i] = trim($aHighlight[$i]);\r
763                 \r
764                 if ( i18n::strlen($aHighlight[$i]) < 3 )\r
765                 {\r
766                         unset($aHighlight[$i]);\r
767                 }\r
768         }\r
769         \r
770         if ( count($aHighlight) == 1 )\r
771         {\r
772                 return $aHighlight[0];\r
773         }\r
774         else\r
775         {\r
776                 return $aHighlight;\r
777         }\r
778         return;\r
779 }\r
780 \r
781 /**\r
782  * getConfig()\r
783  * \r
784  * @param       void\r
785  * @return      void\r
786  */\r
787 function getConfig()\r
788 {\r
789         global $CONF;\r
790         \r
791         $query = sprintf('SELECT * FROM %s', sql_table('config'));\r
792         $res = DB::getResult($query);\r
793         \r
794         foreach ( $res as $row )\r
795         {\r
796                 $CONF[$row['name']] = $row['value'];\r
797         }\r
798         return;\r
799 }\r
800 \r
801 /**\r
802  * This function gets the blog ID from the blog name\r
803  * @param string $name\r
804  * @return\r
805  */\r
806 function getBlogIDFromName($name)\r
807 {\r
808         $query = sprintf('SELECT bnumber AS result FROM %s WHERE bshortname=%s', sql_table('blog'), DB::quoteValue($name));\r
809         return DB::getValue($query);\r
810 }\r
811 \r
812 /**\r
813  * This function gets the blog name from the blog ID\r
814  * @param int $id\r
815  * @return object\r
816  */\r
817 function getBlogNameFromID($id)\r
818 {\r
819         $query = sprintf('SELECT bname AS result FROM %s WHERE bnumber=%d', sql_table('blog'), intval($id));\r
820         return DB::getValue($query);\r
821 }\r
822 \r
823 /**\r
824  * This function gets the blog ID from the item ID\r
825  * @param int $item_id\r
826  * @return object\r
827  */\r
828 function getBlogIDFromItemID($item_id)\r
829 {\r
830         $query = sprintf('SELECT iblog AS result FROM %s WHERE inumber=%d', sql_table('item'), intval($item_id));\r
831         return DB::getValue($query);\r
832 }\r
833 \r
834 /**\r
835  * This function gets the blog ID from the comment ID\r
836  * @param int $comment_id\r
837  * @return object\r
838  */\r
839 function getBlogIDFromCommentID($comment_id)\r
840 {\r
841         $query = sprintf('SELECT cblog AS result FROM %s WHERE cnumber=%d', sql_table('comment'), intval($comment_id));\r
842         return DB::getValue($query);\r
843 }\r
844 \r
845 /**\r
846  * This function gets the blog ID from the category ID\r
847  * @param int $category_id\r
848  * @return object\r
849  */\r
850 function getBlogIDFromCatID($category_id)\r
851 {\r
852         $query = sprintf('SELECT cblog AS result FROM %s WHERE catid=%d', sql_table('category'), intval($category_id));\r
853         return DB::getValue($query);\r
854 }\r
855 \r
856 /**\r
857  * This function gets the category ID from the category name\r
858  * @param int $name\r
859  * @return object\r
860  */\r
861 function getCatIDFromName($name)\r
862 {\r
863         $query = sprintf('SELECT catid AS result FROM %s WHERE cname=%s', sql_table('category'), DB::quoteValue($name));\r
864         return DB::getValue($query);\r
865 }\r
866 \r
867 \r
868 /**\r
869  * functions to be used in index.php to select something\r
870  */\r
871 function selectBlog($shortname)\r
872 {\r
873         global $blogid, $archivelist;\r
874         $blogid = getBlogIDFromName($shortname);\r
875         \r
876         // also force archivelist variable, if it is set\r
877         if ( $archivelist )\r
878         {\r
879                 $archivelist = $blogid;\r
880         }\r
881         return;\r
882 }\r
883 function selectSkin($skinname)\r
884 {\r
885         global $skinid;\r
886         $skinid = SKIN::getIdFromName($skinname);\r
887         return;\r
888 }\r
889 function selectCategory($cat)\r
890 {\r
891         global $catid;\r
892         if ( is_numeric($cat) )\r
893         {\r
894                 $catid = (integer) $cat;\r
895         }\r
896         else\r
897         {\r
898                 $catid = getCatIDFromName($cat);\r
899         }\r
900         return;\r
901 }\r
902 function selectItem($id)\r
903 {\r
904         global $itemid;\r
905         $itemid = (integer) $id;\r
906         return;\r
907 }\r
908 function selectSpecialSkinType($id)\r
909 {\r
910         global $special;\r
911         $special = strtolower($id);\r
912         return;\r
913 }\r
914 function selector()\r
915 {\r
916         global $archive, $archivelist, $archivenext, $archivenextexists, $archiveprev, $archiveprevexists, $archivetype;\r
917         global $blog, $blogid;\r
918         global $catid;\r
919         global $itemid, $itemidnext, $itemidprev, $itemtitlenext, $itemtitleprev;\r
920         global $CONF, $DIR_LIBS, $amount, $errormessage, $imagepopup;\r
921         global $manager, $maxresults, $query;\r
922         global $member, $memberid, $memberinfo;\r
923         global $skinid, $skinpart, $special;\r
924         \r
925         $actionNames = array('addcomment', 'sendmessage', 'createaccount', 'forgotpassword', 'votepositive', 'votenegative', 'plugin');\r
926         $action = requestVar('action');\r
927         \r
928         if ( in_array($action, $actionNames) )\r
929         {\r
930                 include_once($DIR_LIBS . 'ACTION.php');\r
931                 $a = new Action();\r
932                 $errorInfo = $a->doAction($action);\r
933                 \r
934                 if ( $errorInfo )\r
935                 {\r
936                         $errormessage = $errorInfo['message'];\r
937                 }\r
938         }\r
939         \r
940         // show error when headers already sent out\r
941         if ( headers_sent() && $CONF['alertOnHeadersSent'] )\r
942         {\r
943                 // try to get line number/filename (extra headers_sent params only exists in PHP 4.3+)\r
944                 if ( function_exists('version_compare') && version_compare('4.3.0', phpversion(), '<=') )\r
945                 {\r
946                         headers_sent($hsFile, $hsLine);\r
947                         $extraInfo = ' in <code>' . $hsFile . '</code> line <code>' . $hsLine . '</code>';\r
948                 }\r
949                 else\r
950                 {\r
951                         $extraInfo = '';\r
952                 }\r
953                 \r
954                 startUpError(\r
955                    "<p>The page headers have already been sent out{$extraInfo}. This could cause Nucleus not to work in the expected way.</p>"\r
956                  . "<p>Usually, this is caused by spaces or newlines at the end of the <code>config.php</code> file, "\r
957                  . "at the end of the translation file or at the end of a plugin file.</p>"\r
958                  . "<p>Please check this and try again.</p>"\r
959                  . "<p>If you don't want to see this error message again, without solving the problem, "\r
960                  . "set <code>{$CONF['alertOnHeadersSent']}</code> in <code>globalfunctions.php</code> to <code>0</code></p>"\r
961                  . "Page headers already sent"\r
962                 );\r
963                 exit;\r
964         }\r
965         \r
966         // make is so ?archivelist without blogname or blogid shows the archivelist\r
967         // for the default weblog\r
968         if ( serverVar('QUERY_STRING') == 'archivelist' )\r
969         {\r
970                 $archivelist = $CONF['DefaultBlog'];\r
971         }\r
972         \r
973         // now decide which type of skin we need\r
974         if ( $itemid )\r
975         {\r
976                 // itemid given -> only show that item\r
977                 $type = 'item';\r
978                 \r
979                 if ( !$manager->existsItem($itemid,intval($CONF['allowFuture']),intval($CONF['allowDrafts'])) )\r
980                 {\r
981                         doError(_ERROR_NOSUCHITEM);\r
982                 }\r
983                 \r
984                 // 1. get timestamp, blogid and catid for item\r
985                 $query = 'SELECT itime, iblog, icat FROM %s WHERE inumber=%d';\r
986                 $query = sprintf($query, sql_table('item'), intval($itemid));\r
987                 $row = DB::getRow($query);\r
988                 \r
989                 // if a different blog id has been set through the request or selectBlog(),\r
990                 // deny access\r
991                 \r
992                 if ( $blogid && (intval($blogid) != $row['iblog']) )\r
993                 {\r
994                         doError(_ERROR_NOSUCHITEM);\r
995                 }\r
996                 \r
997                 // if a category has been selected which doesn't match the item, ignore the\r
998                 // category. #85\r
999                 if ( ($catid != 0) && ($catid != $row['icat']) )\r
1000                 {\r
1001                         $catid = 0;\r
1002                 }\r
1003                 \r
1004                 $blogid = $row['iblog'];\r
1005                 $timestamp = strtotime($row['itime']);\r
1006                 \r
1007                 $b =& $manager->getBlog($blogid);\r
1008                 \r
1009                 if ( !$b->isValidCategory($catid) )\r
1010                 {\r
1011                         $query = "SELECT inumber, ititle FROM %s WHERE itime<%s AND idraft=0 AND iblog=%d ORDER BY itime DESC LIMIT 1";\r
1012                         $query = sprintf($query, sql_table('item'), DB::formatDateTime($timestamp), intval($blogid));\r
1013                 }\r
1014                 else\r
1015                 {\r
1016                         $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
1017                         $query = sprintf($query, sql_table('item'), DB::formatDateTime($timestamp), intval($blogid), intval($catid));\r
1018                 }\r
1019                 $row = DB::getRow($query);\r
1020                 \r
1021                 if ( $row )\r
1022                 {\r
1023                         $itemidprev = $row['inumber'];\r
1024                         $itemtitleprev = $row['ititle'];\r
1025                 }\r
1026                 \r
1027                 // get next itemid and title\r
1028                 if ( !$b->isValidCategory($catid) )\r
1029                 {\r
1030                         $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
1031                         $query = sprintf($query, sql_table('item'), DB::formatDateTime($timestamp), DB::formatDateTime($b->getCorrectTime()), intval($blogid));\r
1032                 }\r
1033                 else\r
1034                 {\r
1035                         $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
1036                         $query = sprintf($query, sql_table('item'), DB::formatDateTime($timestamp), DB::formatDateTime($b->getCorrectTime()), intval($blogid), intval($catid));\r
1037                 }\r
1038                 $row = DB::getRow($query);\r
1039                 \r
1040                 if ( $row )\r
1041                 {\r
1042                         $itemidnext = $row['inumber'];\r
1043                         $itemtitlenext = $row['ititle'];\r
1044                 }\r
1045         }\r
1046         elseif ( $archive )\r
1047         {\r
1048                 // show archive\r
1049                 $type = 'archive';\r
1050                 \r
1051                 // sql queries for the timestamp of the first and the last published item\r
1052                 $query = sprintf('SELECT UNIX_TIMESTAMP(itime) as result FROM %s WHERE idraft=0 ORDER BY itime ASC', sql_table('item'));\r
1053                 $first_timestamp = DB::getValue($query);\r
1054                 $query = sprintf('SELECT UNIX_TIMESTAMP(itime) as result FROM %s WHERE idraft=0 ORDER BY itime DESC', sql_table('item'));\r
1055                 $last_timestamp = DB::getValue($query);\r
1056                 \r
1057                 sscanf($archive, '%d-%d-%d', $y, $m, $d);\r
1058                 \r
1059                 if ( $d != 0 )\r
1060                 {\r
1061                         $archivetype = _ARCHIVETYPE_DAY;\r
1062                         $t = mktime(0, 0, 0, $m, $d, $y);\r
1063                         // one day has 24 * 60 * 60 = 86400 seconds\r
1064                         $archiveprev = i18n::formatted_datetime('%Y-%m-%d', $t - 86400 );\r
1065                         // check for published items\r
1066                         if ( $t > $first_timestamp )\r
1067                         {\r
1068                                 $archiveprevexists = true;\r
1069                         }\r
1070                         else\r
1071                         {\r
1072                                 $archiveprevexists = false;\r
1073                         }\r
1074                         \r
1075                         // one day later\r
1076                         $t += 86400;\r
1077                         $archivenext = i18n::formatted_datetime('%Y-%m-%d', $t);\r
1078                         if ( $t < $last_timestamp )\r
1079                         {\r
1080                                 $archivenextexists = true;\r
1081                         }\r
1082                         else\r
1083                         {\r
1084                                 $archivenextexists = false;\r
1085                         }\r
1086                 }\r
1087                 elseif ( $m == 0 )\r
1088                 {\r
1089                         $archivetype = _ARCHIVETYPE_YEAR;\r
1090                         $t = mktime(0, 0, 0, 12, 31, $y - 1);\r
1091                         // one day before is in the previous year\r
1092                         $archiveprev = i18n::formatted_datetime('%Y', $t);\r
1093                         if ( $t > $first_timestamp )\r
1094                         {\r
1095                                 $archiveprevexists = true;\r
1096                         }\r
1097                         else\r
1098                         {\r
1099                                 $archiveprevexists = false;\r
1100                         }\r
1101 \r
1102                         // timestamp for the next year\r
1103                         $t = mktime(0, 0, 0, 1, 1, $y + 1);\r
1104                         $archivenext = i18n::formatted_datetime('%Y', $t);\r
1105                         if ( $t < $last_timestamp )\r
1106                         {\r
1107                                 $archivenextexists = true;\r
1108                         }\r
1109                         else\r
1110                         {\r
1111                                 $archivenextexists = false;\r
1112                         }\r
1113                 }\r
1114                 else\r
1115                 {\r
1116                         $archivetype = _ARCHIVETYPE_MONTH;\r
1117                         $t = mktime(0, 0, 0, $m, 1, $y);\r
1118                         // one day before is in the previous month\r
1119                         $archiveprev = i18n::formatted_datetime('%Y-%m', $t - 86400);\r
1120                         if ( $t > $first_timestamp )\r
1121                         {\r
1122                                 $archiveprevexists = true;\r
1123                         }\r
1124                         else\r
1125                         {\r
1126                                 $archiveprevexists = false;\r
1127                         }\r
1128                         \r
1129                         // timestamp for the next month\r
1130                         $t = mktime(0, 0, 0, $m+1, 1, $y);\r
1131                         $archivenext = i18n::formatted_datetime('%Y-%m', $t);\r
1132                         if ( $t < $last_timestamp )\r
1133                         {\r
1134                                 $archivenextexists = true;\r
1135                         }\r
1136                         else\r
1137                         {\r
1138                                 $archivenextexists = false;\r
1139                         }\r
1140                 }\r
1141         }\r
1142         elseif ( $archivelist )\r
1143         {\r
1144                 $type = 'archivelist';\r
1145                 \r
1146                 if ( is_numeric($archivelist) )\r
1147                 {\r
1148                         $blogid = intVal($archivelist);\r
1149                 }\r
1150                 else\r
1151                 {\r
1152                         $blogid = getBlogIDFromName($archivelist);\r
1153                 }\r
1154         \r
1155                 if ( !$blogid )\r
1156                 {\r
1157                         doError(_ERROR_NOSUCHBLOG);\r
1158                 }\r
1159         }\r
1160         elseif ( $query )\r
1161         {\r
1162                 global $startpos;\r
1163                 $type = 'search';\r
1164                 $query = stripslashes($query);\r
1165                 \r
1166                 if ( is_numeric($blogid) )\r
1167                 {\r
1168                         $blogid = intVal($blogid);\r
1169                 }\r
1170                 else\r
1171                 {\r
1172                         $blogid = getBlogIDFromName($blogid);\r
1173                 }\r
1174                 \r
1175                 if ( !$blogid )\r
1176                 {\r
1177                         doError(_ERROR_NOSUCHBLOG);\r
1178                 }\r
1179         }\r
1180         elseif ( $memberid )\r
1181         {\r
1182                 $type = 'member';\r
1183                 \r
1184                 if ( !Member::existsID($memberid) )\r
1185                 {\r
1186                         doError(_ERROR_NOSUCHMEMBER);\r
1187                 }\r
1188                 $memberinfo = $manager->getMember($memberid);\r
1189         }\r
1190         elseif ( $imagepopup )\r
1191         {\r
1192                 // media object (images etc.)\r
1193                 $type = 'imagepopup';\r
1194                 \r
1195                 // TODO: check if media-object exists\r
1196                 // TODO: set some vars?\r
1197         }\r
1198         else\r
1199         {\r
1200                 // show regular index page\r
1201                 global $startpos;\r
1202                 $type = 'index';\r
1203         }\r
1204         \r
1205         // any type of skin with catid\r
1206         if ( $catid && !$blogid )\r
1207         {\r
1208                 $blogid = getBlogIDFromCatID($catid);\r
1209         }\r
1210         \r
1211         // decide which blog should be displayed\r
1212         if ( !$blogid )\r
1213         {\r
1214                 $blogid = $CONF['DefaultBlog'];\r
1215         }\r
1216         \r
1217         $b =& $manager->getBlog($blogid);\r
1218         $blog = $b; // references can't be placed in global variables?\r
1219         \r
1220         if ( !$blog->isValid )\r
1221         {\r
1222                 doError(_ERROR_NOSUCHBLOG);\r
1223         }\r
1224         \r
1225         // set catid if necessary\r
1226         if ( $catid )\r
1227         {\r
1228                 // check if the category is valid\r
1229                 if ( !$blog->isValidCategory($catid) )\r
1230                 {\r
1231                         doError(_ERROR_NOSUCHCATEGORY);\r
1232                 }\r
1233                 else\r
1234                 {\r
1235                         $blog->setSelectedCategory($catid);\r
1236                 }\r
1237         }\r
1238         \r
1239         if ( !$skinid )\r
1240         {\r
1241                 $skinid = $blog->getDefaultSkin();\r
1242         }\r
1243         \r
1244         if ( !empty($special) && isValidShortName($special) )\r
1245         {\r
1246                 $type = strtolower($special);\r
1247         }\r
1248         \r
1249         $skin =& $manager->get($skinid);\r
1250         \r
1251         if ( !$skin->isValid() )\r
1252         {\r
1253                 doError(_ERROR_NOSUCHSKIN);\r
1254         }\r
1255         \r
1256         // set global skinpart variable so can determine quickly what is being parsed from any plugin or phpinclude\r
1257         $skinpart = $type;\r
1258         \r
1259         // parse the skin\r
1260         $skin->parse($type);\r
1261         \r
1262         // check to see we should throw JustPosted event\r
1263         $blog->checkJustPosted();\r
1264         return;\r
1265 }\r
1266 \r
1267 /**\r
1268  * doError()\r
1269  * Show error skin with given message. An optional skin-object to use can be given\r
1270  * \r
1271  * @param       string  $msg\r
1272  * @param       string  $skin\r
1273  * @return      void\r
1274  */\r
1275 function doError($msg, $skin = '')\r
1276 {\r
1277         global $errormessage, $CONF, $skinid, $blogid, $manager;\r
1278         \r
1279         if ( $skin == '' )\r
1280         {\r
1281                 if ( Skin::existsID($skinid) )\r
1282                 {\r
1283                         $id = $skinid;\r
1284                 }\r
1285                 elseif ( $manager->existsBlogID($blogid) )\r
1286                 {\r
1287                         $blog =& $manager->getBlog($blogid);\r
1288                         $id = $blog->getDefaultSkin();\r
1289                 }\r
1290                 elseif ($CONF['DefaultBlog'] )\r
1291                 {\r
1292                         $blog =& $manager->getBlog($CONF['DefaultBlog']);\r
1293                         $id = $blog->getDefaultSkin();\r
1294                 }\r
1295                 else\r
1296                 {\r
1297                         // this statement should actually never be executed\r
1298                         $id = $CONF['BaseSkin'];\r
1299                 }\r
1300                 $skin =& $manager->getSkin($id);\r
1301         }\r
1302         \r
1303         $errormessage = $msg;\r
1304         $skin->parse('error');\r
1305         return;
1306 }\r
1307 \r
1308 /**\r
1309  * Errors before the database connection has been made\r
1310  * \r
1311  * @param       string  $msg    message to notify\r
1312  * @param       string  $title  page title\r
1313  * @return      void\r
1314  */\r
1315 function startUpError($msg, $title)\r
1316 {\r
1317         header('Content-Type: text/xml; charset=' . i18n::get_current_charset());\r
1318         echo "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n";\r
1319         echo "<head>\n";\r
1320         echo "<title>{$title}</title></head>\n";\r
1321         echo "<body>\n";\r
1322         echo "<h1>{$title}</h1>\n";\r
1323         echo $msg;\r
1324         echo "</body>\n";\r
1325         echo "</html>\n";\r
1326         exit;\r
1327 }\r
1328 \r
1329 function isValidShortName($name)\r
1330 {\r
1331         return preg_match('#^[a-z0-9]+$#i', $name);\r
1332 }\r
1333 function isValidDisplayName($name)\r
1334 {\r
1335         return preg_match('#^[a-z0-9]+[a-z0-9 ]*[a-z0-9]+$#i', $name);\r
1336 }\r
1337 function isValidCategoryName($name)\r
1338 {\r
1339         return 1;\r
1340 }\r
1341 function isValidTemplateName($name)\r
1342 {\r
1343         return preg_match('#^[a-z0-9/_\-]+$#i', $name);\r
1344 }\r
1345 function isValidSkinName($name)\r
1346 {\r
1347         return preg_match('#^[a-z0-9/_\-]+$#i', $name);\r
1348 }\r
1349 \r
1350 // add and remove linebreaks\r
1351 function addBreaks($var)\r
1352 {\r
1353         return nl2br($var);\r
1354 }\r
1355 function removeBreaks($var)\r
1356 {\r
1357         return preg_replace("/<br \/>([\r\n])/", "$1", $var);\r
1358 }\r
1359 \r
1360 /**\r
1361  * parseFile()\r
1362  * \r
1363  * @param       string  $filename\r
1364  * @param       string  $includeMode\r
1365  * @param       string  $includePrefix\r
1366  * @return      void\r
1367  */\r
1368 function parseFile($filename, $includeMode = 'normal', $includePrefix = '')\r
1369 {\r
1370         global $manager, $skinid;\r
1371         \r
1372         if ( !$skinid || !existsID($skinid) )\r
1373         {\r
1374                 $skin =& $manager->getSkin($CONF['BaseSkin']);\r
1375         }\r
1376         else\r
1377         {\r
1378                 $skin =& $manager->getSkin($skinid);\r
1379         }\r
1380         \r
1381         $oldIncludeMode = Parser::getProperty('IncludeMode');\r
1382         $oldIncludePrefix = Parser::getProperty('IncludePrefix');\r
1383         \r
1384         $skin->parse('fileparse', $filename);\r
1385         \r
1386         Parser::setProperty('IncludeMode', $oldIncludeMode);\r
1387         Parser::setProperty('IncludePrefix', $oldIncludePrefix);\r
1388         \r
1389         return;\r
1390 }\r
1391 \r
1392 /**\r
1393  * debug()\r
1394  * Outputs a debug message\r
1395  * \r
1396  * @param       string  $msg\r
1397  * @return      void\r
1398  */\r
1399 function debug($msg)\r
1400 {\r
1401         echo '<p><b>' . $msg . "</b></p>\n";\r
1402         return;\r
1403 }\r
1404 \r
1405 // shows a link to help file\r
1406 function help($id)\r
1407 {\r
1408         echo helpHtml($id);\r
1409         return;\r
1410 }\r
1411 function helpHtml($id)\r
1412 {\r
1413         global $CONF;\r
1414         return helplink($id) . '<img src="' . $CONF['AdminURL'] . 'documentation/icon-help.gif" width="15" height="15" alt="' . _HELP_TT . '" title="' . _HELP_TT . '" /></a>';\r
1415 }\r
1416 function helplink($id)\r
1417 {\r
1418         global $CONF;\r
1419         return '<a href="' . $CONF['AdminURL'] . 'documentation/help.html#'. $id . '" onclick="if (event &amp;&amp; event.preventDefault) event.preventDefault(); return help(this.href);">';\r
1420 }\r
1421 \r
1422 /**\r
1423  * includephp()\r
1424  * Includes a PHP file. This method can be called while parsing templates and skins\r
1425  * \r
1426  * @param       string  $filename       name of file to parse\r
1427  * @return      void\r
1428  */\r
1429 function includephp($filename)\r
1430 {\r
1431         // make predefined variables global, so most simple scripts can be used here\r
1432         \r
1433         // apache (names taken from PHP doc)\r
1434         global $GATEWAY_INTERFACE, $SERVER_NAME, $SERVER_SOFTWARE, $SERVER_PROTOCOL;\r
1435         global $REQUEST_METHOD, $QUERY_STRING, $DOCUMENT_ROOT, $HTTP_ACCEPT;\r
1436         global $HTTP_ACCEPT_CHARSET, $HTTP_ACCEPT_ENCODING, $HTTP_ACCEPT_LANGUAGE;\r
1437         global $HTTP_CONNECTION, $HTTP_HOST, $HTTP_REFERER, $HTTP_USER_AGENT;\r
1438         global $REMOTE_ADDR, $REMOTE_PORT, $SCRIPT_FILENAME, $SERVER_ADMIN;\r
1439         global $SERVER_PORT, $SERVER_SIGNATURE, $PATH_TRANSLATED, $SCRIPT_NAME;\r
1440         global $REQUEST_URI;\r
1441         \r
1442         // php (taken from PHP doc)\r
1443         global $argv, $argc, $PHP_SELF, $HTTP_COOKIE_VARS, $HTTP_GET_VARS, $HTTP_POST_VARS;\r
1444         global $HTTP_POST_FILES, $HTTP_ENV_VARS, $HTTP_SERVER_VARS, $HTTP_SESSION_VARS;\r
1445         \r
1446         // other\r
1447         global $PATH_INFO, $HTTPS, $HTTP_RAW_POST_DATA, $HTTP_X_FORWARDED_FOR;\r
1448         \r
1449         if ( @file_exists($filename) )\r
1450         {\r
1451                 include($filename);\r
1452         }\r
1453         return;\r
1454 }\r
1455 \r
1456 /**\r
1457  * Checks if a certain plugin exists\r
1458  * @param       string  $plug   name of plugin\r
1459  * @return      boolean exists or not\r
1460  */\r
1461 function checkPlugin($name)\r
1462 {\r
1463         global $DIR_PLUGINS;\r
1464         return file_exists($DIR_PLUGINS . preg_replace('#[\\\\|/]#', '', $name) . '.php');\r
1465 }\r
1466 \r
1467 /**\r
1468  * alterQueryStr()\r
1469  * \r
1470  * @param       string  $querystr       querystring to alter (e.g. foo=1&bar=2&x=y)\r
1471  * @param       string  $param  name of parameter to change (e.g. 'foo')\r
1472  * @param       string  $value  New value for that parameter (e.g. 3)\r
1473  * @return      string  altered query string (for the examples above: foo=3&bar=2&x=y)\r
1474  */\r
1475 function alterQueryStr($querystr, $param, $value)\r
1476 {\r
1477         $vars = preg_split('#&#', $querystr);\r
1478         $set = FALSE;\r
1479         \r
1480         for ( $i = 0; $i < count($vars); $i++ )\r
1481         {\r
1482                 $v = preg_split('#=#', $vars[$i]);\r
1483                 \r
1484                 if ( $v[0] == $param )\r
1485                 {\r
1486                         $v[1] = $value;\r
1487                         $vars[$i] = implode('=', $v);\r
1488                         $set = true;\r
1489                         break;\r
1490                 }\r
1491         }\r
1492         if ( !$set )\r
1493         {\r
1494                 $vars[] = "{$param}={$value}";\r
1495         }\r
1496         return ltrim(implode('&', $vars), '&');\r
1497 }\r
1498 \r
1499 /**\r
1500  * passVar()\r
1501  * passes one variable as hidden input field (multiple fields for arrays)\r
1502  * @see passRequestVars in varsx.x.x.php\r
1503  * \r
1504  * @param       string  $key\r
1505  * @param       string  $value\r
1506  * @return      void\r
1507  */\r
1508 function passVar($key, $value)\r
1509 {\r
1510         // array ?\r
1511         if ( is_array($value) )\r
1512         {\r
1513                 for ( $i = 0; $i < sizeof($value); $i++ )\r
1514                 {\r
1515                         passVar($key . '[' . $i . ']', $value[$i]);\r
1516                 }\r
1517                 return;\r
1518         }\r
1519         \r
1520         // other values: do stripslashes if needed\r
1521         echo '<input type="hidden" name="' . Entity::hsc($key) . '" value="' . Entity::hsc(undoMagic($value)) . '" />' . "\n";\r
1522         return;\r
1523 }\r
1524 \r
1525 /**\r
1526  * checkVars()\r
1527  * \r
1528  * @param       string  $variables\r
1529  * @return      void\r
1530  */\r
1531 function checkVars($variables)\r
1532 {\r
1533         foreach ( $variables as $variable )\r
1534         {\r
1535                 if ( array_key_exists($variable, $_GET)\r
1536                   || array_key_exists($variable, $_POST)\r
1537                   || array_key_exists($variable, $_COOKIE)\r
1538                   || array_key_exists($variable, $_ENV)\r
1539                   || (session_id() !== '' && array_key_exists($variable, $_SESSION))\r
1540                   || array_key_exists($variable, $_FILES) )\r
1541                 {\r
1542                         die('Sorry. An error occurred.');\r
1543                 }\r
1544         }\r
1545         return;\r
1546 }\r
1547 \r
1548 /**\r
1549  * sanitizeParams()\r
1550  * Sanitize parameters such as $_GET and $_SERVER['REQUEST_URI'] etc.\r
1551  * to avoid XSS.\r
1552  * \r
1553  * @param       void\r
1554  * @return      void\r
1555  */\r
1556 function sanitizeParams()\r
1557 {\r
1558         $array = array();\r
1559         $str = '';\r
1560         $frontParam = '';\r
1561         \r
1562         // REQUEST_URI of $_SERVER\r
1563         $str =& $_SERVER["REQUEST_URI"];\r
1564         serverStringToArray($str, $array, $frontParam);\r
1565         sanitizeArray($array);\r
1566         arrayToServerString($array, $frontParam, $str);\r
1567         \r
1568         // QUERY_STRING of $_SERVER\r
1569         $str =& $_SERVER["QUERY_STRING"];\r
1570         serverStringToArray($str, $array, $frontParam);\r
1571         sanitizeArray($array);\r
1572         arrayToServerString($array, $frontParam, $str);\r
1573         \r
1574         // $_GET\r
1575         convArrayForSanitizing($_GET, $array);\r
1576         sanitizeArray($array);\r
1577         revertArrayForSanitizing($array, $_GET);\r
1578         \r
1579         // $_REQUEST (only GET param)\r
1580         convArrayForSanitizing($_REQUEST, $array);\r
1581         sanitizeArray($array);\r
1582         revertArrayForSanitizing($array, $_REQUEST);\r
1583         \r
1584         return;\r
1585 }\r
1586 \r
1587 function _addInputTags(&$keys,$prefix='')\r
1588 {\r
1589         foreach ( $keys as $key=>$value )\r
1590         {\r
1591                 if ( $prefix )\r
1592                 {\r
1593                         $key=$prefix.'['.$key.']';\r
1594                 }\r
1595                 if ( is_array($value) )\r
1596                 {\r
1597                         _addInputTags($value,$key);\r
1598                 }\r
1599                 else\r
1600                 {\r
1601                         if ( get_magic_quotes_gpc() )\r
1602                                 {$value=stripslashes($value);\r
1603                         }\r
1604                         if ( $key == 'ticket' )\r
1605                         {\r
1606                                 continue;\r
1607                         }\r
1608                         echo '<input type="hidden" name="'.Entity::hsc($key).\r
1609                              '" value="'.Entity::hsc($value).'" />'."\n";\r
1610                 }\r
1611         }\r
1612         return;\r
1613 }\r
1614 \r
1615 /**\r
1616  * serverStringToArray()\r
1617  * Convert the server string such as $_SERVER['REQUEST_URI']\r
1618  * to arry like arry['blogid']=1 and array['page']=2 etc.\r
1619  * \r
1620  * @param       string   $uri                           string\r
1621  * @param       string  &$query_elements        elements of query according to application/x-www-form-urlencoded\r
1622  * @param       string  &$hier_part                     hierarchical part includes path\r
1623  * \r
1624  * NOTE:\r
1625  * RFC 3986: Uniform Resource Identifiers (URI): Generic Syntax\r
1626  * 3.  Syntax Components\r
1627  * http://www.ietf.org/rfc/rfc3986.txt\r
1628  * \r
1629  * Hypertext Markup Language - 2.0\r
1630  * 8.2.1. The form-urlencoded Media Type\r
1631  * http://tools.ietf.org/html/rfc1866#section-8.2.1\r
1632  * \r
1633  * $_SERVER > Language Reference > Predefined Variables > PHP Manual\r
1634  * http://www.php.net/manual/en/reserved.variables.server.php\r
1635  */\r
1636 function serverStringToArray($uri, &$query_elements, &$hier_part)\r
1637 {\r
1638         // init param\r
1639         $query_elements = array();\r
1640         $hier_part = "";\r
1641         \r
1642         // split hierarchical part, e.g. /index.php, query and fragment, e.g. blogid=1&page=2#section1\r
1643         if ( i18n::strpos($uri, "?") > 0 )\r
1644         {\r
1645                 list($hier_part, $query_and_fragment) = preg_split("#\?#", $uri, 2);\r
1646         }\r
1647         else\r
1648         {\r
1649                 $query_and_fragment = $uri;\r
1650                 $hier_part = '';\r
1651         }\r
1652         \r
1653         // If there is no query like blogid=1&page=2, return\r
1654         if ( i18n::strpos($uri, "=") == FALSE && !i18n::strlen($hier_part) )\r
1655         {\r
1656                 $hier_part = $uri;\r
1657                 return;\r
1658         }\r
1659         \r
1660         $query_elements = preg_split("#&#", $query_and_fragment);\r
1661         return;\r
1662 }\r
1663 \r
1664 /**\r
1665  * arrayToServerString()\r
1666  * Convert array like array['blogid'] to server string\r
1667  * such as $_SERVER['REQUEST_URI']\r
1668  * \r
1669  * @param       array    $query_elements        elements of query according to application/x-www-form-urlencoded\r
1670  * @param       string   $hier_part                     hier-part defined in RFC3986\r
1671  * @param       string  &$uri                           return value\r
1672  * @return      void\r
1673  * \r
1674  * NOTE:\r
1675  * RFC 3986: Uniform Resource Identifiers (URI): Generic Syntax\r
1676  * 3.  Syntax Components\r
1677  * http://www.ietf.org/rfc/rfc3986.txt\r
1678  * \r
1679  * Hypertext Markup Language - 2.0\r
1680  * 8.2.1. The form-urlencoded Media Type\r
1681  * http://tools.ietf.org/html/rfc1866#section-8.2.1\r
1682  * \r
1683  * $_SERVER > Language Reference > Predefined Variables > PHP Manual\r
1684  * http://www.php.net/manual/en/reserved.variables.server.php\r
1685  */\r
1686 function arrayToServerString($query_elements, $hier_part, &$uri)\r
1687 {\r
1688         if ( i18n::strpos($uri, "?") !== FALSE )\r
1689         {\r
1690                 $uri = $hier_part . "?";\r
1691         }\r
1692         else\r
1693         {\r
1694                 $uri = $hier_part;\r
1695         }\r
1696         if ( count($query_elements) > 0 )\r
1697         {\r
1698                 $uri .= implode("&", $query_elements);\r
1699         }\r
1700         return;\r
1701 }\r
1702 \r
1703 /**\r
1704  * sanitizeArray()\r
1705  * Sanitize array parameters.\r
1706  * This function checks both key and value.\r
1707  * - check key if it inclues " (double quote),  remove from array\r
1708  * - check value if it includes \ (escape sequece), remove remaining string\r
1709  * \r
1710  * @param       array   &$array elements of query according to application/x-www-form-urlencoded\r
1711  * @return      void\r
1712  */\r
1713 function sanitizeArray(&$array)\r
1714 {\r
1715         $excludeListForSanitization = array('query');\r
1716         \r
1717         foreach ( $array as $k => $v )\r
1718         {\r
1719                 // split to key and value\r
1720                 list($key, $val) = preg_split("#=#", $v, 2);\r
1721                 if ( !isset($val) )\r
1722                 {\r
1723                         continue;\r
1724                 }\r
1725                 \r
1726                 // when magic quotes is on, need to use stripslashes,\r
1727                 // and then addslashes\r
1728                 if ( get_magic_quotes_gpc() )\r
1729                 {\r
1730                         $val = stripslashes($val);\r
1731                 }\r
1732                 \r
1733                 // note that we must use addslashes here because this function is called before the db connection is made\r
1734                 // and sql_real_escape_string needs a db connection\r
1735                 $val = addslashes($val);\r
1736                 \r
1737                 // if $key is included in exclude list, skip this param\r
1738                 if ( !in_array($key, $excludeListForSanitization) )\r
1739                 {\r
1740                         // check value\r
1741                         if ( i18n::strpos($val, '\\') > 0 )\r
1742                         {\r
1743                                 list($val, $tmp) = preg_split('#\\\\#', $val);\r
1744                         }\r
1745                         \r
1746                         // remove control code etc.\r
1747                         $val = strtr($val, "\0\r\n<>'\"", "       ");\r
1748                         \r
1749                         // check key\r
1750                         if ( preg_match('#\"#', $key) > 0 )\r
1751                         {\r
1752                                 unset($array[$k]);\r
1753                                 continue;\r
1754                         }\r
1755                         \r
1756                         // set sanitized info\r
1757                         $array[$k] = sprintf("%s=%s", $key, $val);\r
1758                 }\r
1759         }\r
1760         return;\r
1761 }\r
1762 \r
1763 /**\r
1764  * convArrayForSanitizing()\r
1765  * Convert array for sanitizeArray function\r
1766  * \r
1767  * @param       string  $src    array to be sanitized\r
1768  * @param       array   &$array array to be temporarily stored\r
1769  * @return      void\r
1770  */\r
1771 function convArrayForSanitizing($src, &$array)\r
1772 {\r
1773         $array = array();\r
1774         foreach ( $src as $key => $val )\r
1775         {\r
1776                 if ( !key_exists($key, $_GET) )\r
1777                 {\r
1778                         continue;\r
1779                 }\r
1780                 $array[] = sprintf("%s=%s", $key, $val);\r
1781                 continue;\r
1782         }\r
1783         return;\r
1784 }\r
1785 \r
1786 /**\r
1787  * revertArrayForSanitizing()\r
1788  * Revert array after sanitizeArray function\r
1789  * \r
1790  * @param       array   $array  element of query according to application/x-www-form-urlencoded\r
1791  * @param       array   &$dst   combination of key and value\r
1792  * @return      void\r
1793  */\r
1794 function revertArrayForSanitizing($array, &$dst)\r
1795 {\r
1796         foreach ( $array as $v )\r
1797         {\r
1798                 list($key, $val) = preg_split("#=#", $v, 2);\r
1799                 $dst[$key] = $val;\r
1800                 continue;\r
1801         }\r
1802         return;\r
1803 }\r
1804 \r
1805 /**\r
1806  * decodePathInfo()
1807  * 
1808  * @param       string  $virtualpath
1809  * @return      void
1810  */
1811 function decodePathInfo($virtualpath)
1812 {
1813         global $CONF, $manager, $archive, $blog, $catid, $memberid, $special;
1814         
1815         /* initialize keywords if this hasn't been done before */
1816         if ( !isset($CONF['ItemKey']) || empty($CONF['ItemKey']) )
1817         {
1818                 $CONF['ItemKey'] = 'item';
1819         }
1820         
1821         if ( !isset($CONF['ArchiveKey']) || empty($CONF['ArchiveKey']) )
1822         {
1823                 $CONF['ArchiveKey'] = 'archive';
1824         }
1825         
1826         if ( !isset($CONF['ArchivesKey']) || empty($CONF['ArchivesKey']) )
1827         {
1828                 $CONF['ArchivesKey'] = 'archives';
1829         }
1830         
1831         if ( !isset($CONF['MemberKey']) || empty($CONF['MemberKey']) )
1832         {
1833                 $CONF['MemberKey'] = 'member';
1834         }
1835         
1836         if ( !isset($CONF['BlogKey']) || empty($CONF['BlogKey']) )
1837         {
1838                 $CONF['BlogKey'] = 'blog';
1839         }
1840         
1841         if ( !isset($CONF['CategoryKey']) || empty($CONF['CategoryKey']) )
1842         {
1843                 $CONF['CategoryKey'] = 'category';
1844         }
1845         
1846         if ( !isset($CONF['SpecialskinKey']) || empty($CONF['SpecialskinKey']) )
1847         {
1848                 $CONF['SpecialskinKey'] = 'special';
1849         }
1850         
1851         $parsed = FALSE;
1852         $data = array(
1853                 'type'          =>  basename(serverVar('SCRIPT_NAME') ),
1854                 'info'          =>  $virtualpath,
1855                 'complete'      => &$parsed
1856         );
1857         $manager->notify('ParseURL', $data);
1858         
1859         /* already parsed by the other subsystem */
1860         if ( $parsed )
1861         {
1862                 return;
1863         }
1864         /* default implementation */
1865         $data = preg_split("#/#", $virtualpath);
1866         for ( $i = 0; $i < sizeof($data); $i++ )
1867         {
1868                 switch ( $data[$i] )
1869                 {
1870                         /* item/1 (blogid) */
1871                         case $CONF['ItemKey']:
1872                                 $i++;
1873                                 
1874                                 if ( $i < sizeof($data) )
1875                                 {
1876                                         $itemid = (integer) $data[$i];
1877                                 }
1878                                 break;
1879                         
1880                         /* archives/1 (blogid) */
1881                         case $CONF['ArchivesKey']:
1882                                         $i++;
1883                                         if ( $i < sizeof($data) )
1884                                         {
1885                                                 $archivelist = (integer) $data[$i];
1886                                         }
1887                                         break;
1888                                 
1889                         /* two possibilities: archive/yyyy-mm or archive/1/yyyy-mm (with blogid) */
1890                         case $CONF['ArchiveKey']:
1891                                 if ( (($i + 1) < sizeof($data) ) && (i18n::strpos($data[$i + 1], '-') === FALSE ) )
1892                                 {
1893                                         $blogid = (integer) $data[++$i];
1894                                 }
1895                                 $i++;
1896                                 if ( $i < sizeof($data) )
1897                                 {
1898                                         $archive = $data[$i];
1899                                 }
1900                                 break;
1901                                 
1902                         /* blogid/1 */
1903                         case 'blogid':
1904                         /* blog/1 */
1905                         case $CONF['BlogKey']:
1906                                 $i++;
1907                                 if ( $i < sizeof($data) )
1908                                 {
1909                                         $blogid = intval($data[$i]);
1910                                 }
1911                                 break;
1912                         
1913                         /* category/1 (catid) */
1914                         case $CONF['CategoryKey']:
1915                         case 'catid':
1916                                 $i++;
1917                                 if ( $i < sizeof($data) )
1918                                 {
1919                                         $catid = intval($data[$i]);
1920                                 }
1921                                 break;
1922                         
1923                         case $CONF['MemberKey']:
1924                                 $i++;
1925                                 if ( $i < sizeof($data) )
1926                                 {
1927                                         $memberid = intval($data[$i]);
1928                                 }
1929                                 break;
1930                         
1931                         case $CONF['SpecialskinKey']:
1932                                 $i++;
1933                                 if ( $i < sizeof($data) )
1934                                 {
1935                                         $special = $data[$i];
1936                                 }
1937                                 break;
1938                         
1939                         default:
1940                                 /* do nothing */
1941                                 break;
1942                 }
1943         }
1944         
1945         return;
1946 }
1947
1948
1949 /**
1950  * redirect()\r
1951  * Stops processing the request and redirects to the given URL.\r
1952  * - no actual contents should have been sent to the output yet\r
1953  * - the URL will be stripped of illegal or dangerous characters\r
1954  * \r
1955  * @param       string  $uri\r
1956  * @return      void\r
1957  */\r
1958 function redirect($url)\r
1959 {\r
1960         $url = preg_replace('#[^a-z0-9-~+_.?\#=&;,/:@%*]#i', '', $url);\r
1961         header('Location: ' . $url);\r
1962         exit;\r
1963 }\r
1964 \r
1965 /**\r
1966  * getBookmarklet()\r
1967  * Returns the Javascript code for a bookmarklet that works on most modern browsers\r
1968  * \r
1969  * @param       integer $blogid ID for weblog\r
1970  * @return      script to call Bookmarklet\r
1971  */\r
1972 function getBookmarklet($blogid, $width=600,  $height=500)\r
1973 {\r
1974         global $CONF;\r
1975         \r
1976         $script = "Q='';"\r
1977                 . "x=document;"\r
1978                 . "y=window;"\r
1979                 . "if ( x.selection )"\r
1980                 . "{"\r
1981                 . " Q=x.selection.createRange().text;"\r
1982                 . "}"\r
1983                 . "else if ( y.getSelection )"\r
1984                 . "{"\r
1985                 . " Q=y.getSelection();"\r
1986                 . "}"\r
1987                 . "else if ( x.getSelection )"\r
1988                 . "{"\r
1989                 . " Q=x.getSelection();"\r
1990                 . "}"\r
1991                 . "wingm = window.open('{$CONF['AdminURL']}bookmarklet.php?blogid={$blogid}"\r
1992                 . " &logtext=' + encodeURIComponent(Q) +"\r
1993                 . " '&loglink=' + encodeURIComponent(x.location.href) +"\r
1994                 . " '&loglinktitle=' + encodeURIComponent(x.title),"\r
1995                 . " 'nucleusbm',"\r
1996                 . " 'scrollbars=yes,width={$width},height={$height},left=10,top=10,status=yes,resizable=yes');"\r
1997                 . "wingm.focus();";\r
1998         \r
1999         return $script;\r
2000 }\r
2001 \r
2002 /**\r
2003  * cleanFileName()\r
2004  * cleans filename of uploaded file for writing to file system\r
2005  *\r
2006  * @param       string  $str\r
2007  * @return      string  $cleaned filename ready for use\r
2008  */\r
2009 function cleanFileName($str)\r
2010 {\r
2011         $str = strtolower($str);\r
2012         $ext_point = i18n::strrpos($str,".");\r
2013         if ( $ext_point === FALSE )\r
2014         {\r
2015                 return FALSE;\r
2016         }\r
2017         $ext = i18n::substr($str,$ext_point,i18n::strlen($str));\r
2018         $str = i18n::substr($str,0,$ext_point);\r
2019         \r
2020         return preg_replace("#[^a-z0-9-]#", "_", $str) . $ext;\r
2021 }\r
2022 \r
2023 /**\r
2024  * use Notification class instead of this\r
2025  * Deprecated since 4.0:\r
2026  */\r
2027 function getMailFooter()\r
2028 {\r
2029         NOTIFICATION::get_mail_footer();\r
2030 }\r
2031 function isValidMailAddress($address)\r
2032 {\r
2033         return NOTIFICATION::address_validation($address);\r
2034 }\r
2035 /**\r
2036  * use Entity class instead of this\r
2037  * Deprecated since 4.0:\r
2038  */\r
2039 function highlight($text, $expression, $highlight)\r
2040 {\r
2041         return Entity::highlight($text, $expression, $highlight);\r
2042 }\r
2043 function shorten($string, $maxlength, $suffix)\r
2044 {\r
2045         return Entity::shorten($string, $maxlength, $suffix);\r
2046 }\r
2047 function stringStripTags ($string)\r
2048 {\r
2049         return Entity::strip_tags($string);\r
2050 }\r
2051 function toAscii($string)\r
2052 {\r
2053         return Entity::anchor_footnoting($string);\r
2054 }\r
2055 function stringToAttribute ($string)\r
2056 {\r
2057         return Entity::hsc($string);\r
2058 }\r
2059 function stringToXML ($string)\r
2060 {\r
2061         return Entity::hen($string);\r
2062 }\r
2063 function encode_desc($data)\r
2064 {\r
2065         return Entity::hen($data);\r
2066 }\r
2067 /**\r
2068  * Centralisation of the functions that deals with locales\r
2069  * This functions is based on the old way to deal with languages\r
2070  * Deprecated since 4.0:\r
2071  */\r
2072 function getLanguageName()\r
2073 {\r
2074         if( ($language = i18n::convert_locale_to_old_language_file_name(i18n::get_current_locale())) === FALSE )\r
2075         {\r
2076                 $language ='english';\r
2077         }\r
2078         return $language;\r
2079 }\r
2080 function selectLanguage($language)\r
2081 {\r
2082         global $DIR_LANG;\r
2083         include($DIR_LANG . preg_replace('#[\\\\|/]#', '', $language) . '.php');\r
2084         return;\r
2085 }\r
2086 /**\r
2087  * use i18n class instead of these\r
2088  * Deprecated since 4.0\r
2089  */\r
2090 function checkLanguage($lang)\r
2091 {\r
2092         return ( preg_match('#^(.+)_(.+)_(.+)$#', $lang)\r
2093           || i18n::convert_old_language_file_name_to_locale($lang) );\r
2094 }\r
2095 function formatDate($format, $timestamp, $default_format, &$blog)\r
2096 {\r
2097         $offset = date('Z', $timestamp);\r
2098         if ( $blog )\r
2099         {\r
2100                 $offset += $blog->getTimeOffset() * 3600;\r
2101         }\r
2102         return i18n::formatted_datetime($format, $timestamp, $offset, $default_format);\r
2103 }\r
2104 \r
2105 /**\r
2106  * use DB class instead of these\r
2107  * Deprecated since 4.0\r
2108  */\r
2109 function quickQuery($query)\r
2110 {\r
2111         $row = DB::getRow($query);\r
2112         return $row['result'];\r
2113 }\r
2114 function mysqldate($timestamp)\r
2115 {\r
2116         return DB::formatDateTime($timestamp);\r
2117  }\r
2118 /**\r
2119  * Centralisation of the functions that generate links\r
2120  * Deprecated since 4.0:\r
2121  * Please use Link::FunctionName(...) instead\r
2122  */\r
2123 function createItemLink($itemid, $extra = '')\r
2124 {\r
2125         return Link::create_item_link($itemid, $extra);\r
2126 }\r
2127 function createMemberLink($memberid, $extra = '')\r
2128 {\r
2129         return Link::create_member_link($memberid, $extra);\r
2130 }\r
2131 function createCategoryLink($catid, $extra = '')\r
2132 {\r
2133         return Link::create_category_link($catid, $extra);\r
2134 }\r
2135 function createArchiveListLink($blogid = '', $extra = '')\r
2136 {\r
2137         return Link::create_archivelist_link($blogid, $extra);\r
2138 }\r
2139 function createArchiveLink($blogid, $archive, $extra = '')\r
2140 {\r
2141         return Link::create_archive_link($blogid, $archive, $extra);\r
2142 }\r
2143 function createBlogidLink($blogid, $params = '')\r
2144 {\r
2145         return Link::create_blogid_link($blogid, $params = '');\r
2146 }\r
2147 function createLink($type, $params)\r
2148 {\r
2149         return Link::create_link($type, $params);\r
2150 }\r
2151 function createBlogLink($url, $params)\r
2152 {\r
2153         return Link::create_blog_link($url, $params);\r
2154 }\r
2155 /**\r
2156  * use ActionLog class instead of this\r
2157  * Deprecated since 4.0\r
2158  */\r
2159 function addToLog($level, $msg)\r
2160 {\r
2161         ActionLog::add($level, $msg);\r
2162 }\r
2163 /**\r
2164  * use PHP's implement\r
2165  * Deprecated since 4.0\r
2166  */\r
2167 function ifset(&$var)\r
2168 {\r
2169         if ( isset($var) )\r
2170         {\r
2171                 return $var;\r
2172         }\r
2173         \r
2174         return NULL;\r
2175 }\r
2176 /**\r
2177  * use Manager::getPluginNameFromPid() instead of this\r
2178  * Deprecated since 4.0\r
2179  */\r
2180 function getPluginNameFromPid($pid)\r
2181 {\r
2182         global $manager;\r
2183         return $manager->getPluginNameFromPid($pid);\r
2184 }\r
2185 /**\r
2186  * use Manager::numberOfEventSubscribers() instead of this\r
2187  * Deprecated since 4.0\r
2188  */\r
2189 function numberOfEventSubscribers($event)\r
2190 {\r
2191         global $manager;\r
2192         return $manager->getNumberOfSubscribers($event);\r
2193 }\r
2194 \r
2195 /**\r
2196  * PluginAdmin has already the alternative implement\r
2197  * Deprecated since 4.0\r
2198  */\r
2199 function ticketForPlugin()\r
2200 {\r
2201         global $CONF, $DIR_LIBS, $DIR_LOCALES, $DIR_PLUGINS, $manager, $member, $ticketforplugin;\r
2202         \r
2203         /* initialize */\r
2204         $ticketforplugin = array();\r
2205         $ticketforplugin['ticket'] = FALSE;\r
2206         \r
2207         /* Check if using plugin's php file. */\r
2208         $p_translated = serverVar('SCRIPT_FILENAME');\r
2209         \r
2210         if (!file_exists($p_translated) )\r
2211         {\r
2212                 header("HTTP/1.0 404 Not Found");\r
2213                 exit('');\r
2214         }\r
2215         \r
2216         // check whether this is plugin or not\r
2217         $p_translated = str_replace('\\', '/', $p_translated);\r
2218         $d_plugins = str_replace('\\', '/', $DIR_PLUGINS);\r
2219         if ( i18n::strpos($p_translated, $d_plugins) !== 0 )\r
2220         {\r
2221                 return;\r
2222         }\r
2223         \r
2224         // Solve the plugin php file or admin directory\r
2225         $phppath = i18n::substr($p_translated, i18n::strlen($d_plugins) );\r
2226         // Remove the first "/" if exists.\r
2227         $phppath = preg_replace('#^/#', '', $phppath);\r
2228         // Remove the first "NP_" and the last ".php" if exists.\r
2229         $path = preg_replace('#^NP_(.*)\.php$#', '$1', $phppath);\r
2230         // Remove the "/" and beyond.\r
2231         $path = preg_replace('#^([^/]*)/(.*)$#', '$1', $path);\r
2232         \r
2233         // Solve the plugin name.\r
2234         $plugins = array();\r
2235         $query = sprintf('SELECT pfile FROM %s;', sql_table('plugin'));\r
2236         $res = DB::getResult($query);\r
2237         \r
2238         foreach ( $res as $row )\r
2239         {\r
2240                 $name = i18n::substr($row['pfile'], 3);\r
2241                 $plugins[strtolower($name)] = $name;\r
2242         }\r
2243         \r
2244         $res->closeCursor();\r
2245         \r
2246         if ( !array_key_exists($path, $plugins) )\r
2247         {\r
2248                 header("HTTP/1.0 404 Not Found");\r
2249                 exit('');\r
2250         }\r
2251         else\r
2252         {\r
2253                 $plugin_name = $plugins[$path];\r
2254         }\r
2255         \r
2256         /* Return if not index.php */\r
2257         if ( ($phppath != strtolower($plugin_name) . '/')\r
2258           && ($phppath != strtolower($plugin_name) . '/index.php') )\r
2259         {\r
2260                 return;\r
2261         }\r
2262         \r
2263         /* Exit if not logged in. */\r
2264         if ( !$member->isLoggedIn() )\r
2265         {\r
2266                 exit('You aren\'t logged in.');\r
2267         }\r
2268         \r
2269         /* Check if this feature is needed (ie, if "$manager->checkTicket()" is not included in the script). */\r
2270         if ( $file = @file($p_translated) )\r
2271         {\r
2272                 $prevline = '';\r
2273                 \r
2274                 foreach($file as $line)\r
2275                 {\r
2276                         if (preg_match('#[\$]manager([\s]*)[\-]>([\s]*)checkTicket([\s]*)[\(]#i', $prevline . $line) )\r
2277                         {\r
2278                                 return;\r
2279                         }\r
2280                         \r
2281                         $prevline = $line;\r
2282                 }\r
2283         }\r
2284         \r
2285         /* Show a form if not valid ticket */\r
2286         if ( (i18n::strpos(serverVar('REQUEST_URI'), '?') !== FALSE\r
2287           || serverVar('QUERY_STRING')\r
2288           || strtoupper(serverVar('REQUEST_METHOD') ) == 'POST')\r
2289           && !$manager->checkTicket() )\r
2290         {\r
2291                 $oPluginAdmin = new PluginAdmin($plugin_name);\r
2292                 $oPluginAdmin->start();\r
2293                 \r
2294                 echo '<p>' . _ERROR_BADTICKET . "</p>\n";\r
2295                 \r
2296                 // Resolve URI and QUERY_STRING\r
2297                 if ($uri = serverVar('REQUEST_URI') )\r
2298                 {\r
2299                         list($uri, $qstring) = preg_split('#\?#', $uri);\r
2300                 }\r
2301                 else\r
2302                 {\r
2303                         if ( !($uri = serverVar('PHP_SELF') ) )\r
2304                         {\r
2305                                 $uri = serverVar('SCRIPT_NAME');\r
2306                         }\r
2307                         $qstring = serverVar('QUERY_STRING');\r
2308                 }\r
2309                 if ($qstring)\r
2310                 {\r
2311                         $qstring = '?' . $qstring;\r
2312                 }\r
2313                 \r
2314                 echo '<p>' . _SETTINGS_UPDATE . ' : ' . _QMENU_PLUGINS . ' <span style="color:red;">' . Entity::hsc($plugin_name) . "</span> ?</p>\n";\r
2315                 \r
2316                 switch(strtoupper(serverVar('REQUEST_METHOD') ) )\r
2317                 {\r
2318                         case 'POST':\r
2319                                 echo '<form method="POST" action="'.Entity::hsc($uri.$qstring).'">';\r
2320                                 $manager->addTicketHidden();\r
2321                                 _addInputTags($_POST);\r
2322                                 break;\r
2323                         \r
2324                         case 'GET':\r
2325                                 echo '<form method="GET" action="'.Entity::hsc($uri).'">';\r
2326                                 $manager->addTicketHidden();\r
2327                                 _addInputTags($_GET);\r
2328                         \r
2329                         default:\r
2330                                 break;\r
2331                 }\r
2332                 \r
2333                 echo '<input type="submit" value="' . _YES . '" />&nbsp;&nbsp;&nbsp;&nbsp;';\r
2334                 echo '<input type="button" value="' . _NO . '" onclick="history.back(); return false;" />';\r
2335                 echo "</form>\n";\r
2336                 \r
2337                 $oPluginAdmin->end();\r
2338                 exit;\r
2339         }\r
2340         \r
2341         /* Create new ticket */\r
2342         $ticket=$manager->addTicketToUrl('');\r
2343         $ticketforplugin['ticket'] = preg_split($ticket, i18n::strpos($ticket, 'ticket=') + 7);\r
2344         return;\r
2345 }\r