OSDN Git Service

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