OSDN Git Service

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