OSDN Git Service

Revert "FIX:ブックマークレットで、スキン変数<%itemtime%>が正しくパースされない不具合を修正"
[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                         return;\r
983                 }\r
984                 \r
985                 // 1. get timestamp, blogid and catid for item\r
986                 $query = 'SELECT itime, iblog, icat FROM %s WHERE inumber=%d';\r
987                 $query = sprintf($query, sql_table('item'), intval($itemid));\r
988                 $row = DB::getRow($query);\r
989                 \r
990                 // if a different blog id has been set through the request or selectBlog(),\r
991                 // deny access\r
992                 \r
993                 if ( $blogid && (intval($blogid) != $row['iblog']) )\r
994                 {\r
995                         doError(_ERROR_NOSUCHITEM);\r
996                         return;\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                         return;\r
1161                 }\r
1162         }\r
1163         elseif ( $query )\r
1164         {\r
1165                 global $startpos;\r
1166                 $type = 'search';\r
1167                 $query = stripslashes($query);\r
1168                 \r
1169                 if ( is_numeric($blogid) )\r
1170                 {\r
1171                         $blogid = intVal($blogid);\r
1172                 }\r
1173                 else\r
1174                 {\r
1175                         $blogid = getBlogIDFromName($blogid);\r
1176                 }\r
1177                 \r
1178                 if ( !$blogid )\r
1179                 {\r
1180                         doError(_ERROR_NOSUCHBLOG);\r
1181                         return;\r
1182                 }\r
1183         }\r
1184         elseif ( $memberid )\r
1185         {\r
1186                 $type = 'member';\r
1187                 \r
1188                 if ( !Member::existsID($memberid) )\r
1189                 {\r
1190                         doError(_ERROR_NOSUCHMEMBER);\r
1191                         return;\r
1192                 }\r
1193                 $memberinfo = $manager->getMember($memberid);\r
1194         }\r
1195         elseif ( $imagepopup )\r
1196         {\r
1197                 // media object (images etc.)\r
1198                 $type = 'imagepopup';\r
1199                 \r
1200                 // TODO: check if media-object exists\r
1201                 // TODO: set some vars?\r
1202         }\r
1203         else\r
1204         {\r
1205                 // show regular index page\r
1206                 global $startpos;\r
1207                 $type = 'index';\r
1208         }\r
1209         \r
1210         // any type of skin with catid\r
1211         if ( $catid && !$blogid )\r
1212         {\r
1213                 $blogid = getBlogIDFromCatID($catid);\r
1214         }\r
1215         \r
1216         // decide which blog should be displayed\r
1217         if ( !$blogid )\r
1218         {\r
1219                 $blogid = $CONF['DefaultBlog'];\r
1220         }\r
1221         \r
1222         $b =& $manager->getBlog($blogid);\r
1223         $blog = $b; // references can't be placed in global variables?\r
1224         \r
1225         if ( !$blog->isValid )\r
1226         {\r
1227                 doError(_ERROR_NOSUCHBLOG);\r
1228                 return;\r
1229         }\r
1230         \r
1231         // set catid if necessary\r
1232         if ( $catid )\r
1233         {\r
1234                 // check if the category is valid\r
1235                 if ( !$blog->isValidCategory($catid) )\r
1236                 {\r
1237                         doError(_ERROR_NOSUCHCATEGORY);\r
1238                         return;\r
1239                 }\r
1240                 else\r
1241                 {\r
1242                         $blog->setSelectedCategory($catid);\r
1243                 }\r
1244         }\r
1245         \r
1246         if ( !$skinid )\r
1247         {\r
1248                 $skinid = $blog->getDefaultSkin();\r
1249         }\r
1250         \r
1251         if ( !empty($special) && isValidShortName($special) )\r
1252         {\r
1253                 $type = strtolower($special);\r
1254         }\r
1255         \r
1256         $skin =& $manager->getSkin($skinid);\r
1257         \r
1258         if ( !$skin->isValid() )\r
1259         {\r
1260                 doError(_ERROR_NOSUCHSKIN);\r
1261                 return;\r
1262         }\r
1263         \r
1264         // set global skinpart variable so can determine quickly what is being parsed from any plugin or phpinclude\r
1265         $skinpart = $type;\r
1266         \r
1267         // parse the skin\r
1268         $skin->parse($type);\r
1269         \r
1270         // check to see we should throw JustPosted event\r
1271         $blog->checkJustPosted();\r
1272         return;\r
1273 }\r
1274 \r
1275 /**\r
1276  * doError()\r
1277  * Show error skin with given message. An optional skin-object to use can be given\r
1278  * \r
1279  * @param       string  $msg\r
1280  * @param       string  $skin\r
1281  * @return      void\r
1282  */\r
1283 function doError($msg, $skin = '')\r
1284 {\r
1285         global $errormessage, $CONF, $skinid, $blogid, $manager;\r
1286         \r
1287         if ( $skin == '' )\r
1288         {\r
1289                 if ( Skin::existsID($skinid) )\r
1290                 {\r
1291                         $id = $skinid;\r
1292                 }\r
1293                 elseif ( $manager->existsBlogID($blogid) )\r
1294                 {\r
1295                         $blog =& $manager->getBlog($blogid);\r
1296                         $id = $blog->getDefaultSkin();\r
1297                 }\r
1298                 elseif ($CONF['DefaultBlog'] )\r
1299                 {\r
1300                         $blog =& $manager->getBlog($CONF['DefaultBlog']);\r
1301                         $id = $blog->getDefaultSkin();\r
1302                 }\r
1303                 else\r
1304                 {\r
1305                         // this statement should actually never be executed\r
1306                         $id = $CONF['BaseSkin'];\r
1307                 }\r
1308                 $skin =& $manager->getSkin($id);\r
1309         }\r
1310         \r
1311         $errormessage = $msg;\r
1312         $skin->parse('error');\r
1313         return;
1314 }\r
1315 \r
1316 /**\r
1317  * Errors before the database connection has been made\r
1318  * \r
1319  * @param       string  $msg    message to notify\r
1320  * @param       string  $title  page title\r
1321  * @return      void\r
1322  */\r
1323 function startUpError($msg, $title)\r
1324 {\r
1325         header('Content-Type: text/xml; charset=' . i18n::get_current_charset());\r
1326         echo "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n";\r
1327         echo "<head>\n";\r
1328         echo "<title>{$title}</title></head>\n";\r
1329         echo "<body>\n";\r
1330         echo "<h1>{$title}</h1>\n";\r
1331         echo $msg;\r
1332         echo "</body>\n";\r
1333         echo "</html>\n";\r
1334         exit;\r
1335 }\r
1336 \r
1337 function isValidShortName($name)\r
1338 {\r
1339         return preg_match('#^[a-z0-9]+$#i', $name);\r
1340 }\r
1341 function isValidDisplayName($name)\r
1342 {\r
1343         return preg_match('#^[a-z0-9]+[a-z0-9 ]*[a-z0-9]+$#i', $name);\r
1344 }\r
1345 function isValidCategoryName($name)\r
1346 {\r
1347         return 1;\r
1348 }\r
1349 function isValidTemplateName($name)\r
1350 {\r
1351         return preg_match('#^[a-z0-9/_\-]+$#i', $name);\r
1352 }\r
1353 function isValidSkinName($name)\r
1354 {\r
1355         return preg_match('#^[a-z0-9/_\-]+$#i', $name);\r
1356 }\r
1357 \r
1358 // add and remove linebreaks\r
1359 function addBreaks($var)\r
1360 {\r
1361         return nl2br($var);\r
1362 }\r
1363 function removeBreaks($var)\r
1364 {\r
1365         return preg_replace("/<br \/>([\r\n])/", "$1", $var);\r
1366 }\r
1367 \r
1368 /**\r
1369  * parseFile()\r
1370  * \r
1371  * @param       string  $filename\r
1372  * @param       string  $includeMode\r
1373  * @param       string  $includePrefix\r
1374  * @return      void\r
1375  */\r
1376 function parseFile($filename, $includeMode = 'normal', $includePrefix = '')\r
1377 {\r
1378         global $manager, $skinid;\r
1379         \r
1380         if ( !$skinid || !existsID($skinid) )\r
1381         {\r
1382                 $skin =& $manager->getSkin($CONF['BaseSkin']);\r
1383         }\r
1384         else\r
1385         {\r
1386                 $skin =& $manager->getSkin($skinid);\r
1387         }\r
1388         \r
1389         $oldIncludeMode = Parser::getProperty('IncludeMode');\r
1390         $oldIncludePrefix = Parser::getProperty('IncludePrefix');\r
1391         \r
1392         $skin->parse('fileparse', $filename);\r
1393         \r
1394         Parser::setProperty('IncludeMode', $oldIncludeMode);\r
1395         Parser::setProperty('IncludePrefix', $oldIncludePrefix);\r
1396         \r
1397         return;\r
1398 }\r
1399 \r
1400 /**\r
1401  * debug()\r
1402  * Outputs a debug message\r
1403  * \r
1404  * @param       string  $msg\r
1405  * @return      void\r
1406  */\r
1407 function debug($msg)\r
1408 {\r
1409         echo '<p><b>' . $msg . "</b></p>\n";\r
1410         return;\r
1411 }\r
1412 \r
1413 // shows a link to help file\r
1414 function help($id)\r
1415 {\r
1416         echo helpHtml($id);\r
1417         return;\r
1418 }\r
1419 function helpHtml($id)\r
1420 {\r
1421         global $CONF;\r
1422         return helplink($id) . '<img src="' . $CONF['AdminURL'] . 'documentation/icon-help.gif" width="15" height="15" alt="' . _HELP_TT . '" title="' . _HELP_TT . '" /></a>';\r
1423 }\r
1424 function helplink($id)\r
1425 {\r
1426         global $CONF;\r
1427         return '<a href="' . $CONF['AdminURL'] . 'documentation/help.html#'. $id . '" onclick="if (event &amp;&amp; event.preventDefault) event.preventDefault(); return help(this.href);">';\r
1428 }\r
1429 \r
1430 /**\r
1431  * includephp()\r
1432  * Includes a PHP file. This method can be called while parsing templates and skins\r
1433  * \r
1434  * @param       string  $filename       name of file to parse\r
1435  * @return      void\r
1436  */\r
1437 function includephp($filename)\r
1438 {\r
1439         // make predefined variables global, so most simple scripts can be used here\r
1440         \r
1441         // apache (names taken from PHP doc)\r
1442         global $GATEWAY_INTERFACE, $SERVER_NAME, $SERVER_SOFTWARE, $SERVER_PROTOCOL;\r
1443         global $REQUEST_METHOD, $QUERY_STRING, $DOCUMENT_ROOT, $HTTP_ACCEPT;\r
1444         global $HTTP_ACCEPT_CHARSET, $HTTP_ACCEPT_ENCODING, $HTTP_ACCEPT_LANGUAGE;\r
1445         global $HTTP_CONNECTION, $HTTP_HOST, $HTTP_REFERER, $HTTP_USER_AGENT;\r
1446         global $REMOTE_ADDR, $REMOTE_PORT, $SCRIPT_FILENAME, $SERVER_ADMIN;\r
1447         global $SERVER_PORT, $SERVER_SIGNATURE, $PATH_TRANSLATED, $SCRIPT_NAME;\r
1448         global $REQUEST_URI;\r
1449         \r
1450         // php (taken from PHP doc)\r
1451         global $argv, $argc, $PHP_SELF, $HTTP_COOKIE_VARS, $HTTP_GET_VARS, $HTTP_POST_VARS;\r
1452         global $HTTP_POST_FILES, $HTTP_ENV_VARS, $HTTP_SERVER_VARS, $HTTP_SESSION_VARS;\r
1453         \r
1454         // other\r
1455         global $PATH_INFO, $HTTPS, $HTTP_RAW_POST_DATA, $HTTP_X_FORWARDED_FOR;\r
1456         \r
1457         if ( @file_exists($filename) )\r
1458         {\r
1459                 include($filename);\r
1460         }\r
1461         return;\r
1462 }\r
1463 \r
1464 /**\r
1465  * Checks if a certain plugin exists\r
1466  * @param       string  $plug   name of plugin\r
1467  * @return      boolean exists or not\r
1468  */\r
1469 function checkPlugin($name)\r
1470 {\r
1471         global $DIR_PLUGINS;\r
1472         return file_exists($DIR_PLUGINS . preg_replace('#[\\\\|/]#', '', $name) . '.php');\r
1473 }\r
1474 \r
1475 /**\r
1476  * alterQueryStr()\r
1477  * \r
1478  * @param       string  $querystr       querystring to alter (e.g. foo=1&bar=2&x=y)\r
1479  * @param       string  $param  name of parameter to change (e.g. 'foo')\r
1480  * @param       string  $value  New value for that parameter (e.g. 3)\r
1481  * @return      string  altered query string (for the examples above: foo=3&bar=2&x=y)\r
1482  */\r
1483 function alterQueryStr($querystr, $param, $value)\r
1484 {\r
1485         $vars = preg_split('#&#', $querystr);\r
1486         $set = FALSE;\r
1487         \r
1488         for ( $i = 0; $i < count($vars); $i++ )\r
1489         {\r
1490                 $v = preg_split('#=#', $vars[$i]);\r
1491                 \r
1492                 if ( $v[0] == $param )\r
1493                 {\r
1494                         $v[1] = $value;\r
1495                         $vars[$i] = implode('=', $v);\r
1496                         $set = true;\r
1497                         break;\r
1498                 }\r
1499         }\r
1500         if ( !$set )\r
1501         {\r
1502                 $vars[] = "{$param}={$value}";\r
1503         }\r
1504         return ltrim(implode('&', $vars), '&');\r
1505 }\r
1506 \r
1507 /**\r
1508  * passVar()\r
1509  * passes one variable as hidden input field (multiple fields for arrays)\r
1510  * @see passRequestVars in varsx.x.x.php\r
1511  * \r
1512  * @param       string  $key\r
1513  * @param       string  $value\r
1514  * @return      void\r
1515  */\r
1516 function passVar($key, $value)\r
1517 {\r
1518         // array ?\r
1519         if ( is_array($value) )\r
1520         {\r
1521                 for ( $i = 0; $i < sizeof($value); $i++ )\r
1522                 {\r
1523                         passVar($key . '[' . $i . ']', $value[$i]);\r
1524                 }\r
1525                 return;\r
1526         }\r
1527         \r
1528         // other values: do stripslashes if needed\r
1529         echo '<input type="hidden" name="' . Entity::hsc($key) . '" value="' . Entity::hsc(undoMagic($value)) . '" />' . "\n";\r
1530         return;\r
1531 }\r
1532 \r
1533 /**\r
1534  * checkVars()\r
1535  * \r
1536  * @param       string  $variables\r
1537  * @return      void\r
1538  */\r
1539 function checkVars($variables)\r
1540 {\r
1541         foreach ( $variables as $variable )\r
1542         {\r
1543                 if ( array_key_exists($variable, $_GET)\r
1544                   || array_key_exists($variable, $_POST)\r
1545                   || array_key_exists($variable, $_COOKIE)\r
1546                   || array_key_exists($variable, $_ENV)\r
1547                   || (session_id() !== '' && array_key_exists($variable, $_SESSION))\r
1548                   || array_key_exists($variable, $_FILES) )\r
1549                 {\r
1550                         die('Sorry. An error occurred.');\r
1551                 }\r
1552         }\r
1553         return;\r
1554 }\r
1555 \r
1556 /**\r
1557  * sanitizeParams()\r
1558  * Sanitize parameters such as $_GET and $_SERVER['REQUEST_URI'] etc.\r
1559  * to avoid XSS.\r
1560  * \r
1561  * @param       void\r
1562  * @return      void\r
1563  */\r
1564 function sanitizeParams()\r
1565 {\r
1566         $array = array();\r
1567         $str = '';\r
1568         $frontParam = '';\r
1569         \r
1570         // REQUEST_URI of $_SERVER\r
1571         $str =& $_SERVER["REQUEST_URI"];\r
1572         serverStringToArray($str, $array, $frontParam);\r
1573         sanitizeArray($array);\r
1574         arrayToServerString($array, $frontParam, $str);\r
1575         \r
1576         // QUERY_STRING of $_SERVER\r
1577         $str =& $_SERVER["QUERY_STRING"];\r
1578         serverStringToArray($str, $array, $frontParam);\r
1579         sanitizeArray($array);\r
1580         arrayToServerString($array, $frontParam, $str);\r
1581         \r
1582         // $_GET\r
1583         convArrayForSanitizing($_GET, $array);\r
1584         sanitizeArray($array);\r
1585         revertArrayForSanitizing($array, $_GET);\r
1586         \r
1587         // $_REQUEST (only GET param)\r
1588         convArrayForSanitizing($_REQUEST, $array);\r
1589         sanitizeArray($array);\r
1590         revertArrayForSanitizing($array, $_REQUEST);\r
1591         \r
1592         return;\r
1593 }\r
1594 \r
1595 function _addInputTags(&$keys,$prefix='')\r
1596 {\r
1597         foreach ( $keys as $key=>$value )\r
1598         {\r
1599                 if ( $prefix )\r
1600                 {\r
1601                         $key=$prefix.'['.$key.']';\r
1602                 }\r
1603                 if ( is_array($value) )\r
1604                 {\r
1605                         _addInputTags($value,$key);\r
1606                 }\r
1607                 else\r
1608                 {\r
1609                         if ( get_magic_quotes_gpc() )\r
1610                                 {$value=stripslashes($value);\r
1611                         }\r
1612                         if ( $key == 'ticket' )\r
1613                         {\r
1614                                 continue;\r
1615                         }\r
1616                         echo '<input type="hidden" name="'.Entity::hsc($key).\r
1617                              '" value="'.Entity::hsc($value).'" />'."\n";\r
1618                 }\r
1619         }\r
1620         return;\r
1621 }\r
1622 \r
1623 /**\r
1624  * serverStringToArray()\r
1625  * Convert the server string such as $_SERVER['REQUEST_URI']\r
1626  * to arry like arry['blogid']=1 and array['page']=2 etc.\r
1627  * \r
1628  * @param       string   $uri                           string\r
1629  * @param       string  &$query_elements        elements of query according to application/x-www-form-urlencoded\r
1630  * @param       string  &$hier_part                     hierarchical part includes path\r
1631  * \r
1632  * NOTE:\r
1633  * RFC 3986: Uniform Resource Identifiers (URI): Generic Syntax\r
1634  * 3.  Syntax Components\r
1635  * http://www.ietf.org/rfc/rfc3986.txt\r
1636  * \r
1637  * Hypertext Markup Language - 2.0\r
1638  * 8.2.1. The form-urlencoded Media Type\r
1639  * http://tools.ietf.org/html/rfc1866#section-8.2.1\r
1640  * \r
1641  * $_SERVER > Language Reference > Predefined Variables > PHP Manual\r
1642  * http://www.php.net/manual/en/reserved.variables.server.php\r
1643  */\r
1644 function serverStringToArray($uri, &$query_elements, &$hier_part)\r
1645 {\r
1646         // init param\r
1647         $query_elements = array();\r
1648         $hier_part = "";\r
1649         \r
1650         // split hierarchical part, e.g. /index.php, query and fragment, e.g. blogid=1&page=2#section1\r
1651         if ( i18n::strpos($uri, "?") > 0 )\r
1652         {\r
1653                 list($hier_part, $query_and_fragment) = preg_split("#\?#", $uri, 2);\r
1654         }\r
1655         else\r
1656         {\r
1657                 $query_and_fragment = $uri;\r
1658                 $hier_part = '';\r
1659         }\r
1660         \r
1661         // If there is no query like blogid=1&page=2, return\r
1662         if ( i18n::strpos($uri, "=") == FALSE && !i18n::strlen($hier_part) )\r
1663         {\r
1664                 $hier_part = $uri;\r
1665                 return;\r
1666         }\r
1667         \r
1668         $query_elements = preg_split("#&#", $query_and_fragment);\r
1669         return;\r
1670 }\r
1671 \r
1672 /**\r
1673  * arrayToServerString()\r
1674  * Convert array like array['blogid'] to server string\r
1675  * such as $_SERVER['REQUEST_URI']\r
1676  * \r
1677  * @param       array    $query_elements        elements of query according to application/x-www-form-urlencoded\r
1678  * @param       string   $hier_part                     hier-part defined in RFC3986\r
1679  * @param       string  &$uri                           return value\r
1680  * @return      void\r
1681  * \r
1682  * NOTE:\r
1683  * RFC 3986: Uniform Resource Identifiers (URI): Generic Syntax\r
1684  * 3.  Syntax Components\r
1685  * http://www.ietf.org/rfc/rfc3986.txt\r
1686  * \r
1687  * Hypertext Markup Language - 2.0\r
1688  * 8.2.1. The form-urlencoded Media Type\r
1689  * http://tools.ietf.org/html/rfc1866#section-8.2.1\r
1690  * \r
1691  * $_SERVER > Language Reference > Predefined Variables > PHP Manual\r
1692  * http://www.php.net/manual/en/reserved.variables.server.php\r
1693  */\r
1694 function arrayToServerString($query_elements, $hier_part, &$uri)\r
1695 {\r
1696         if ( i18n::strpos($uri, "?") !== FALSE )\r
1697         {\r
1698                 $uri = $hier_part . "?";\r
1699         }\r
1700         else\r
1701         {\r
1702                 $uri = $hier_part;\r
1703         }\r
1704         if ( count($query_elements) > 0 )\r
1705         {\r
1706                 $uri .= implode("&", $query_elements);\r
1707         }\r
1708         return;\r
1709 }\r
1710 \r
1711 /**\r
1712  * sanitizeArray()\r
1713  * Sanitize array parameters.\r
1714  * This function checks both key and value.\r
1715  * - check key if it inclues " (double quote),  remove from array\r
1716  * - check value if it includes \ (escape sequece), remove remaining string\r
1717  * \r
1718  * @param       array   &$array elements of query according to application/x-www-form-urlencoded\r
1719  * @return      void\r
1720  */\r
1721 function sanitizeArray(&$array)\r
1722 {\r
1723         $excludeListForSanitization = array('query');\r
1724         \r
1725         foreach ( $array as $k => $v )\r
1726         {\r
1727                 // split to key and value\r
1728                 list($key, $val) = preg_split("#=#", $v, 2);\r
1729                 if ( !isset($val) )\r
1730                 {\r
1731                         continue;\r
1732                 }\r
1733                 \r
1734                 // when magic quotes is on, need to use stripslashes,\r
1735                 // and then addslashes\r
1736                 if ( get_magic_quotes_gpc() )\r
1737                 {\r
1738                         $val = stripslashes($val);\r
1739                 }\r
1740                 \r
1741                 // note that we must use addslashes here because this function is called before the db connection is made\r
1742                 // and sql_real_escape_string needs a db connection\r
1743                 $val = addslashes($val);\r
1744                 \r
1745                 // if $key is included in exclude list, skip this param\r
1746                 if ( !in_array($key, $excludeListForSanitization) )\r
1747                 {\r
1748                         // check value\r
1749                         if ( i18n::strpos($val, '\\') > 0 )\r
1750                         {\r
1751                                 list($val, $tmp) = preg_split('#\\\\#', $val);\r
1752                         }\r
1753                         \r
1754                         // remove control code etc.\r
1755                         $val = strtr($val, "\0\r\n<>'\"", "       ");\r
1756                         \r
1757                         // check key\r
1758                         if ( preg_match('#\"#', $key) > 0 )\r
1759                         {\r
1760                                 unset($array[$k]);\r
1761                                 continue;\r
1762                         }\r
1763                         \r
1764                         // set sanitized info\r
1765                         $array[$k] = sprintf("%s=%s", $key, $val);\r
1766                 }\r
1767         }\r
1768         return;\r
1769 }\r
1770 \r
1771 /**\r
1772  * convArrayForSanitizing()\r
1773  * Convert array for sanitizeArray function\r
1774  * \r
1775  * @param       string  $src    array to be sanitized\r
1776  * @param       array   &$array array to be temporarily stored\r
1777  * @return      void\r
1778  */\r
1779 function convArrayForSanitizing($src, &$array)\r
1780 {\r
1781         $array = array();\r
1782         foreach ( $src as $key => $val )\r
1783         {\r
1784                 if ( !key_exists($key, $_GET) )\r
1785                 {\r
1786                         continue;\r
1787                 }\r
1788                 $array[] = sprintf("%s=%s", $key, $val);\r
1789                 continue;\r
1790         }\r
1791         return;\r
1792 }\r
1793 \r
1794 /**\r
1795  * revertArrayForSanitizing()\r
1796  * Revert array after sanitizeArray function\r
1797  * \r
1798  * @param       array   $array  element of query according to application/x-www-form-urlencoded\r
1799  * @param       array   &$dst   combination of key and value\r
1800  * @return      void\r
1801  */\r
1802 function revertArrayForSanitizing($array, &$dst)\r
1803 {\r
1804         foreach ( $array as $v )\r
1805         {\r
1806                 list($key, $val) = preg_split("#=#", $v, 2);\r
1807                 $dst[$key] = $val;\r
1808                 continue;\r
1809         }\r
1810         return;\r
1811 }\r
1812 \r
1813 /**\r
1814  * decodePathInfo()
1815  * 
1816  * @param       string  $virtualpath
1817  * @return      void
1818  */
1819 function decodePathInfo($virtualpath)
1820 {
1821         global $CONF, $manager, $archive, $blog, $catid, $memberid, $special;
1822         
1823         /* initialize keywords if this hasn't been done before */
1824         if ( !isset($CONF['ItemKey']) || empty($CONF['ItemKey']) )
1825         {
1826                 $CONF['ItemKey'] = 'item';
1827         }
1828         
1829         if ( !isset($CONF['ArchiveKey']) || empty($CONF['ArchiveKey']) )
1830         {
1831                 $CONF['ArchiveKey'] = 'archive';
1832         }
1833         
1834         if ( !isset($CONF['ArchivesKey']) || empty($CONF['ArchivesKey']) )
1835         {
1836                 $CONF['ArchivesKey'] = 'archives';
1837         }
1838         
1839         if ( !isset($CONF['MemberKey']) || empty($CONF['MemberKey']) )
1840         {
1841                 $CONF['MemberKey'] = 'member';
1842         }
1843         
1844         if ( !isset($CONF['BlogKey']) || empty($CONF['BlogKey']) )
1845         {
1846                 $CONF['BlogKey'] = 'blog';
1847         }
1848         
1849         if ( !isset($CONF['CategoryKey']) || empty($CONF['CategoryKey']) )
1850         {
1851                 $CONF['CategoryKey'] = 'category';
1852         }
1853         
1854         if ( !isset($CONF['SpecialskinKey']) || empty($CONF['SpecialskinKey']) )
1855         {
1856                 $CONF['SpecialskinKey'] = 'special';
1857         }
1858         
1859         $parsed = FALSE;
1860         $data = array(
1861                 'type'          =>  basename(serverVar('SCRIPT_NAME') ),
1862                 'info'          =>  $virtualpath,
1863                 'complete'      => &$parsed
1864         );
1865         $manager->notify('ParseURL', $data);
1866         
1867         /* already parsed by the other subsystem */
1868         if ( $parsed )
1869         {
1870                 return;
1871         }
1872         /* default implementation */
1873         $data = preg_split("#/#", $virtualpath);
1874         for ( $i = 0; $i < sizeof($data); $i++ )
1875         {
1876                 switch ( $data[$i] )
1877                 {
1878                         /* item/1 (blogid) */
1879                         case $CONF['ItemKey']:
1880                                 $i++;
1881                                 
1882                                 if ( $i < sizeof($data) )
1883                                 {
1884                                         $itemid = (integer) $data[$i];
1885                                 }
1886                                 break;
1887                         
1888                         /* archives/1 (blogid) */
1889                         case $CONF['ArchivesKey']:
1890                                         $i++;
1891                                         if ( $i < sizeof($data) )
1892                                         {
1893                                                 $archivelist = (integer) $data[$i];
1894                                         }
1895                                         break;
1896                                 
1897                         /* two possibilities: archive/yyyy-mm or archive/1/yyyy-mm (with blogid) */
1898                         case $CONF['ArchiveKey']:
1899                                 if ( (($i + 1) < sizeof($data) ) && (i18n::strpos($data[$i + 1], '-') === FALSE ) )
1900                                 {
1901                                         $blogid = (integer) $data[++$i];
1902                                 }
1903                                 $i++;
1904                                 if ( $i < sizeof($data) )
1905                                 {
1906                                         $archive = $data[$i];
1907                                 }
1908                                 break;
1909                                 
1910                         /* blogid/1 */
1911                         case 'blogid':
1912                         /* blog/1 */
1913                         case $CONF['BlogKey']:
1914                                 $i++;
1915                                 if ( $i < sizeof($data) )
1916                                 {
1917                                         $blogid = intval($data[$i]);
1918                                 }
1919                                 break;
1920                         
1921                         /* category/1 (catid) */
1922                         case $CONF['CategoryKey']:
1923                         case 'catid':
1924                                 $i++;
1925                                 if ( $i < sizeof($data) )
1926                                 {
1927                                         $catid = intval($data[$i]);
1928                                 }
1929                                 break;
1930                         
1931                         case $CONF['MemberKey']:
1932                                 $i++;
1933                                 if ( $i < sizeof($data) )
1934                                 {
1935                                         $memberid = intval($data[$i]);
1936                                 }
1937                                 break;
1938                         
1939                         case $CONF['SpecialskinKey']:
1940                                 $i++;
1941                                 if ( $i < sizeof($data) )
1942                                 {
1943                                         $special = $data[$i];
1944                                 }
1945                                 break;
1946                         
1947                         default:
1948                                 /* do nothing */
1949                                 break;
1950                 }
1951         }
1952         
1953         return;
1954 }
1955
1956
1957 /**
1958  * redirect()\r
1959  * Stops processing the request and redirects to the given URL.\r
1960  * - no actual contents should have been sent to the output yet\r
1961  * - the URL will be stripped of illegal or dangerous characters\r
1962  * \r
1963  * @param       string  $uri\r
1964  * @return      void\r
1965  */\r
1966 function redirect($url)\r
1967 {\r
1968         $url = preg_replace('#[^a-z0-9-~+_.?\#=&;,/:@%*]#i', '', $url);\r
1969         header('Location: ' . $url);\r
1970         exit;\r
1971 }\r
1972 \r
1973 /**\r
1974  * getBookmarklet()\r
1975  * Returns the Javascript code for a bookmarklet that works on most modern browsers\r
1976  * \r
1977  * @param       integer $blogid ID for weblog\r
1978  * @return      script to call Bookmarklet\r
1979  */\r
1980 function getBookmarklet($blogid, $width=600,  $height=500)\r
1981 {\r
1982         global $CONF;\r
1983         \r
1984         $script = "Q='';"\r
1985                 . "x=document;"\r
1986                 . "y=window;"\r
1987                 . "if ( x.selection )"\r
1988                 . "{"\r
1989                 . " Q=x.selection.createRange().text;"\r
1990                 . "}"\r
1991                 . "else if ( y.getSelection )"\r
1992                 . "{"\r
1993                 . " Q=y.getSelection();"\r
1994                 . "}"\r
1995                 . "else if ( x.getSelection )"\r
1996                 . "{"\r
1997                 . " Q=x.getSelection();"\r
1998                 . "}"\r
1999                 . "wingm = window.open('{$CONF['AdminURL']}bookmarklet.php?blogid={$blogid}"\r
2000                 . " &logtext=' + encodeURIComponent(Q) +"\r
2001                 . " '&loglink=' + encodeURIComponent(x.location.href) +"\r
2002                 . " '&loglinktitle=' + encodeURIComponent(x.title),"\r
2003                 . " 'nucleusbm',"\r
2004                 . " 'scrollbars=yes,width={$width},height={$height},left=10,top=10,status=yes,resizable=yes');"\r
2005                 . "wingm.focus();";\r
2006         \r
2007         return $script;\r
2008 }\r
2009 \r
2010 /**\r
2011  * cleanFileName()\r
2012  * cleans filename of uploaded file for writing to file system\r
2013  *\r
2014  * @param       string  $str\r
2015  * @return      string  $cleaned filename ready for use\r
2016  */\r
2017 function cleanFileName($str)\r
2018 {\r
2019         $str = strtolower($str);\r
2020         $ext_point = i18n::strrpos($str,".");\r
2021         if ( $ext_point === FALSE )\r
2022         {\r
2023                 return FALSE;\r
2024         }\r
2025         $ext = i18n::substr($str,$ext_point,i18n::strlen($str));\r
2026         $str = i18n::substr($str,0,$ext_point);\r
2027         \r
2028         return preg_replace("#[^a-z0-9-]#", "_", $str) . $ext;\r
2029 }\r
2030 \r
2031 /**\r
2032  * use Notification class instead of this\r
2033  * Deprecated since 4.0:\r
2034  */\r
2035 function getMailFooter()\r
2036 {\r
2037         NOTIFICATION::get_mail_footer();\r
2038 }\r
2039 function isValidMailAddress($address)\r
2040 {\r
2041         return NOTIFICATION::address_validation($address);\r
2042 }\r
2043 /**\r
2044  * use Entity class instead of this\r
2045  * Deprecated since 4.0:\r
2046  */\r
2047 function highlight($text, $expression, $highlight)\r
2048 {\r
2049         return Entity::highlight($text, $expression, $highlight);\r
2050 }\r
2051 function shorten($string, $maxlength, $suffix)\r
2052 {\r
2053         return Entity::shorten($string, $maxlength, $suffix);\r
2054 }\r
2055 function stringStripTags ($string)\r
2056 {\r
2057         return Entity::strip_tags($string);\r
2058 }\r
2059 function toAscii($string)\r
2060 {\r
2061         return Entity::anchor_footnoting($string);\r
2062 }\r
2063 function stringToAttribute ($string)\r
2064 {\r
2065         return Entity::hsc($string);\r
2066 }\r
2067 function stringToXML ($string)\r
2068 {\r
2069         return Entity::hen($string);\r
2070 }\r
2071 function encode_desc($data)\r
2072 {\r
2073         return Entity::hen($data);\r
2074 }\r
2075 /**\r
2076  * Centralisation of the functions that deals with locales\r
2077  * This functions is based on the old way to deal with languages\r
2078  * Deprecated since 4.0:\r
2079  */\r
2080 function getLanguageName()\r
2081 {\r
2082         if( ($language = i18n::convert_locale_to_old_language_file_name(i18n::get_current_locale())) === FALSE )\r
2083         {\r
2084                 $language ='english';\r
2085         }\r
2086         return $language;\r
2087 }\r
2088 function selectLanguage($language)\r
2089 {\r
2090         global $DIR_LANG;\r
2091         include($DIR_LANG . preg_replace('#[\\\\|/]#', '', $language) . '.php');\r
2092         return;\r
2093 }\r
2094 /**\r
2095  * use i18n class instead of these\r
2096  * Deprecated since 4.0\r
2097  */\r
2098 function checkLanguage($lang)\r
2099 {\r
2100         return ( preg_match('#^(.+)_(.+)_(.+)$#', $lang)\r
2101           || i18n::convert_old_language_file_name_to_locale($lang) );\r
2102 }\r
2103 function formatDate($format, $timestamp, $default_format, &$blog)\r
2104 {\r
2105         $offset = date('Z', $timestamp);\r
2106         if ( $blog )\r
2107         {\r
2108                 $offset += $blog->getTimeOffset() * 3600;\r
2109         }\r
2110         return i18n::formatted_datetime($format, $timestamp, $offset, $default_format);\r
2111 }\r
2112 \r
2113 /**\r
2114  * use DB class instead of these\r
2115  * Deprecated since 4.0\r
2116  */\r
2117 function quickQuery($query)\r
2118 {\r
2119         $row = DB::getRow($query);\r
2120         return $row['result'];\r
2121 }\r
2122 function mysqldate($timestamp)\r
2123 {\r
2124         return DB::formatDateTime($timestamp);\r
2125  }\r
2126 /**\r
2127  * Centralisation of the functions that generate links\r
2128  * Deprecated since 4.0:\r
2129  * Please use Link::FunctionName(...) instead\r
2130  */\r
2131 function createItemLink($itemid, $extra = '')\r
2132 {\r
2133         return Link::create_item_link($itemid, $extra);\r
2134 }\r
2135 function createMemberLink($memberid, $extra = '')\r
2136 {\r
2137         return Link::create_member_link($memberid, $extra);\r
2138 }\r
2139 function createCategoryLink($catid, $extra = '')\r
2140 {\r
2141         return Link::create_category_link($catid, $extra);\r
2142 }\r
2143 function createArchiveListLink($blogid = '', $extra = '')\r
2144 {\r
2145         return Link::create_archivelist_link($blogid, $extra);\r
2146 }\r
2147 function createArchiveLink($blogid, $archive, $extra = '')\r
2148 {\r
2149         return Link::create_archive_link($blogid, $archive, $extra);\r
2150 }\r
2151 function createBlogidLink($blogid, $params = '')\r
2152 {\r
2153         return Link::create_blogid_link($blogid, $params = '');\r
2154 }\r
2155 function createLink($type, $params)\r
2156 {\r
2157         return Link::create_link($type, $params);\r
2158 }\r
2159 function createBlogLink($url, $params)\r
2160 {\r
2161         return Link::create_blog_link($url, $params);\r
2162 }\r
2163 /**\r
2164  * use ActionLog class instead of this\r
2165  * Deprecated since 4.0\r
2166  */\r
2167 function addToLog($level, $msg)\r
2168 {\r
2169         ActionLog::add($level, $msg);\r
2170 }\r
2171 /**\r
2172  * use PHP's implement\r
2173  * Deprecated since 4.0\r
2174  */\r
2175 function ifset(&$var)\r
2176 {\r
2177         if ( isset($var) )\r
2178         {\r
2179                 return $var;\r
2180         }\r
2181         \r
2182         return NULL;\r
2183 }\r
2184 /**\r
2185  * use Manager::getPluginNameFromPid() instead of this\r
2186  * Deprecated since 4.0\r
2187  */\r
2188 function getPluginNameFromPid($pid)\r
2189 {\r
2190         global $manager;\r
2191         return $manager->getPluginNameFromPid($pid);\r
2192 }\r
2193 /**\r
2194  * use Manager::numberOfEventSubscribers() instead of this\r
2195  * Deprecated since 4.0\r
2196  */\r
2197 function numberOfEventSubscribers($event)\r
2198 {\r
2199         global $manager;\r
2200         return $manager->getNumberOfSubscribers($event);\r
2201 }\r
2202 \r
2203 /**\r
2204  * PluginAdmin has already the alternative implement\r
2205  * Deprecated since 4.0\r
2206  */\r
2207 function ticketForPlugin()\r
2208 {\r
2209         global $CONF, $DIR_LIBS, $DIR_LOCALES, $DIR_PLUGINS, $manager, $member, $ticketforplugin;\r
2210         \r
2211         /* initialize */\r
2212         $ticketforplugin = array();\r
2213         $ticketforplugin['ticket'] = FALSE;\r
2214         \r
2215         /* Check if using plugin's php file. */\r
2216         $p_translated = serverVar('SCRIPT_FILENAME');\r
2217         \r
2218         if (!file_exists($p_translated) )\r
2219         {\r
2220                 header("HTTP/1.0 404 Not Found");\r
2221                 exit('');\r
2222         }\r
2223         \r
2224         // check whether this is plugin or not\r
2225         $p_translated = str_replace('\\', '/', $p_translated);\r
2226         $d_plugins = str_replace('\\', '/', $DIR_PLUGINS);\r
2227         if ( i18n::strpos($p_translated, $d_plugins) !== 0 )\r
2228         {\r
2229                 return;\r
2230         }\r
2231         \r
2232         // Solve the plugin php file or admin directory\r
2233         $phppath = i18n::substr($p_translated, i18n::strlen($d_plugins) );\r
2234         // Remove the first "/" if exists.\r
2235         $phppath = preg_replace('#^/#', '', $phppath);\r
2236         // Remove the first "NP_" and the last ".php" if exists.\r
2237         $path = preg_replace('#^NP_(.*)\.php$#', '$1', $phppath);\r
2238         // Remove the "/" and beyond.\r
2239         $path = preg_replace('#^([^/]*)/(.*)$#', '$1', $path);\r
2240         \r
2241         // Solve the plugin name.\r
2242         $plugins = array();\r
2243         $query = sprintf('SELECT pfile FROM %s;', sql_table('plugin'));\r
2244         $res = DB::getResult($query);\r
2245         \r
2246         foreach ( $res as $row )\r
2247         {\r
2248                 $name = i18n::substr($row['pfile'], 3);\r
2249                 $plugins[strtolower($name)] = $name;\r
2250         }\r
2251         \r
2252         $res->closeCursor();\r
2253         \r
2254         if ( !array_key_exists($path, $plugins) )\r
2255         {\r
2256                 header("HTTP/1.0 404 Not Found");\r
2257                 exit('');\r
2258         }\r
2259         else\r
2260         {\r
2261                 $plugin_name = $plugins[$path];\r
2262         }\r
2263         \r
2264         /* Return if not index.php */\r
2265         if ( ($phppath != strtolower($plugin_name) . '/')\r
2266           && ($phppath != strtolower($plugin_name) . '/index.php') )\r
2267         {\r
2268                 return;\r
2269         }\r
2270         \r
2271         /* Exit if not logged in. */\r
2272         if ( !$member->isLoggedIn() )\r
2273         {\r
2274                 exit('You aren\'t logged in.');\r
2275         }\r
2276         \r
2277         /* Check if this feature is needed (ie, if "$manager->checkTicket()" is not included in the script). */\r
2278         if ( $file = @file($p_translated) )\r
2279         {\r
2280                 $prevline = '';\r
2281                 \r
2282                 foreach($file as $line)\r
2283                 {\r
2284                         if (preg_match('#[\$]manager([\s]*)[\-]>([\s]*)checkTicket([\s]*)[\(]#i', $prevline . $line) )\r
2285                         {\r
2286                                 return;\r
2287                         }\r
2288                         \r
2289                         $prevline = $line;\r
2290                 }\r
2291         }\r
2292         \r
2293         /* Show a form if not valid ticket */\r
2294         if ( (i18n::strpos(serverVar('REQUEST_URI'), '?') !== FALSE\r
2295           || serverVar('QUERY_STRING')\r
2296           || strtoupper(serverVar('REQUEST_METHOD') ) == 'POST')\r
2297           && !$manager->checkTicket() )\r
2298         {\r
2299                 $oPluginAdmin = new PluginAdmin($plugin_name);\r
2300                 $oPluginAdmin->start();\r
2301                 \r
2302                 echo '<p>' . _ERROR_BADTICKET . "</p>\n";\r
2303                 \r
2304                 // Resolve URI and QUERY_STRING\r
2305                 if ($uri = serverVar('REQUEST_URI') )\r
2306                 {\r
2307                         list($uri, $qstring) = preg_split('#\?#', $uri);\r
2308                 }\r
2309                 else\r
2310                 {\r
2311                         if ( !($uri = serverVar('PHP_SELF') ) )\r
2312                         {\r
2313                                 $uri = serverVar('SCRIPT_NAME');\r
2314                         }\r
2315                         $qstring = serverVar('QUERY_STRING');\r
2316                 }\r
2317                 if ($qstring)\r
2318                 {\r
2319                         $qstring = '?' . $qstring;\r
2320                 }\r
2321                 \r
2322                 echo '<p>' . _SETTINGS_UPDATE . ' : ' . _QMENU_PLUGINS . ' <span style="color:red;">' . Entity::hsc($plugin_name) . "</span> ?</p>\n";\r
2323                 \r
2324                 switch(strtoupper(serverVar('REQUEST_METHOD') ) )\r
2325                 {\r
2326                         case 'POST':\r
2327                                 echo '<form method="POST" action="'.Entity::hsc($uri.$qstring).'">';\r
2328                                 $manager->addTicketHidden();\r
2329                                 _addInputTags($_POST);\r
2330                                 break;\r
2331                         \r
2332                         case 'GET':\r
2333                                 echo '<form method="GET" action="'.Entity::hsc($uri).'">';\r
2334                                 $manager->addTicketHidden();\r
2335                                 _addInputTags($_GET);\r
2336                         \r
2337                         default:\r
2338                                 break;\r
2339                 }\r
2340                 \r
2341                 echo '<input type="submit" value="' . _YES . '" />&nbsp;&nbsp;&nbsp;&nbsp;';\r
2342                 echo '<input type="button" value="' . _NO . '" onclick="history.back(); return false;" />';\r
2343                 echo "</form>\n";\r
2344                 \r
2345                 $oPluginAdmin->end();\r
2346                 exit;\r
2347         }\r
2348         \r
2349         /* Create new ticket */\r
2350         $ticket=$manager->addTicketToUrl('');\r
2351         $ticketforplugin['ticket'] = preg_split($ticket, i18n::strpos($ticket, 'ticket=') + 7);\r
2352         return;\r
2353 }\r