OSDN Git Service

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