OSDN Git Service

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