OSDN Git Service

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