OSDN Git Service

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