OSDN Git Service

CHANGE: NOTIFICATIONクラスの整備。i18nのメール送信メソッドを移植
[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 highlights a specific query in a given HTML text (not within HTML tags) and returns it
935          * @param string $text text to be highlighted
936          * @param string $expression regular expression to be matched (can be an array of expressions as well)
937          * @param string $highlight highlight to be used (use \\0 to indicate the matched expression)
938          * @return string
939          */
940         function highlight($text, $expression, $highlight)
941         {
942
943                 if ( !$highlight || !$expression )
944                 {
945                         return $text;
946                 }
947
948                 if ( is_array($expression) && (count($expression) == 0) )
949                 {
950                         return $text;
951                 }
952
953                 // add a tag in front (is needed for preg_match_all to work correctly)
954                 $text = '<!--h-->' . $text;
955
956                 // split the HTML up so we have HTML tags
957                 // $matches[0][i] = HTML + text
958                 // $matches[1][i] = HTML
959                 // $matches[2][i] = text
960                 preg_match_all('/(<[^>]+>)([^<>]*)/', $text, $matches);
961
962                 // throw it all together again while applying the highlight to the text pieces
963                 $result = '';
964
965                 $count_matches = count($matches[2]);
966
967                 for ( $i = 0; $i < $count_matches; $i++ )
968                 {
969
970                         if ( $i != 0 )
971                         {
972                                 $result .= $matches[1][$i];
973                         }
974
975                         if ( is_array($expression) )
976                         {
977
978                                 foreach ( $expression as $regex )
979                                 {
980
981                                         if ( $regex )
982                                         {
983                                                 //$matches[2][$i] = @eregi_replace($regex, $highlight, $matches[2][$i]);
984                                                 $matches[2][$i] = @preg_replace('#' . $regex . '#i', $highlight, $matches[2][$i]);
985                                         }
986
987                                 }
988
989                                 $result .= $matches[2][$i];
990
991                         }
992                         else
993                         {
994                                 //$result .= @eregi_replace($expression, $highlight, $matches[2][$i]);
995                                 $result .= @preg_replace('#' . $expression . '#i', $highlight, $matches[2][$i]);
996                         }
997
998                 }
999
1000                 return $result;
1001
1002         }
1003
1004
1005         /**
1006          * This function parses a query into an array of expressions that can be passed on to the highlight method
1007          * @param string $query
1008          */
1009         function parseHighlight($query)
1010         {
1011                 // TODO: add more intelligent splitting logic
1012                 
1013                 // get rid of quotes
1014                 $query = preg_replace('/\'|"/', '', $query);
1015                 
1016                 if ( !$query )
1017                 {
1018                         return array();
1019                 }
1020                 
1021                 $aHighlight = i18n::explode(' ', $query);
1022                 
1023                 for ( $i = 0; $i < count($aHighlight); $i++ )
1024                 {
1025                         $aHighlight[$i] = trim($aHighlight[$i]);
1026                         
1027                         if ( i18n::strlen($aHighlight[$i]) < 3 )
1028                         {
1029                                 unset($aHighlight[$i]);
1030                         }
1031                 }
1032                 
1033                 if ( count($aHighlight) == 1 )
1034                 {
1035                         return $aHighlight[0];
1036                 }
1037                 else
1038                 {
1039                         return $aHighlight;
1040                 }
1041         }
1042
1043         /**
1044          * This function gets the blog ID from the blog name
1045          * @param string $name
1046          * @return
1047          */
1048         function getBlogIDFromName($name)
1049         {
1050                 return quickQuery('SELECT `bnumber` AS `result` FROM `' . sql_table('blog') . '` WHERE `bshortname` = "' . sql_real_escape_string($name) . '"');
1051         }
1052
1053
1054         /**
1055          * This function gets the blog name from the blog ID
1056          * @param int $id
1057          * @return object
1058          */
1059         function getBlogNameFromID($id)
1060         {
1061                 return quickQuery('SELECT `bname` AS `result` FROM `' . sql_table('blog') . '` WHERE `bnumber` = ' . intval($id));
1062         }
1063
1064
1065         /**
1066          * This function gets the blog ID from the item ID
1067          * @param int $item_id
1068          * @return object
1069          */
1070         function getBlogIDFromItemID($item_id)
1071         {
1072                 return quickQuery('SELECT `iblog` AS `result` FROM `' . sql_table('item') . '` WHERE `inumber` = ' . intval($item_id));
1073         }
1074
1075
1076         /**
1077          * This function gets the blog ID from the comment ID
1078          * @param int $comment_id
1079          * @return object
1080          */
1081         function getBlogIDFromCommentID($comment_id)
1082         {
1083                 return quickQuery('SELECT `cblog` AS `result` FROM `' . sql_table('comment') . '` WHERE `cnumber` = ' . intval($comment_id));
1084         }
1085
1086
1087         /**
1088          * This function gets the blog ID from the category ID
1089          * @param int $category_id
1090          * @return object
1091          */
1092         function getBlogIDFromCatID($category_id)
1093         {
1094                 return quickQuery('SELECT `cblog` AS `result` FROM `' . sql_table('category') . '` WHERE `catid` = ' . intval($category_id));
1095         }
1096
1097
1098         /**
1099          * This function gets the category ID from the category name
1100          * @param int $name
1101          * @return object
1102          */
1103         function getCatIDFromName($name)
1104         {
1105                 return quickQuery('SELECT `catid` AS `result` FROM `' . sql_table('category') . '` WHERE `cname` = "' . sql_real_escape_string($name) . '"');
1106         }
1107
1108
1109         /**
1110          * This function performs a quick SQL query
1111          * @param string $query
1112          * @return object
1113          */
1114         function quickQuery($query)
1115         {
1116                 $res = sql_query($query);
1117                 $obj = sql_fetch_object($res);
1118                 return $obj->result;
1119         }
1120
1121 function getPluginNameFromPid($pid) {
1122     $res = sql_query('SELECT pfile FROM ' . sql_table('plugin') . ' WHERE pid=' . intval($pid) );
1123     $obj = sql_fetch_object($res);
1124     return $obj->pfile;
1125 //    return isset($obj->pfile) ? $obj->pfile : false;
1126 }
1127
1128 function selector() {
1129         global $itemid, $blogid, $memberid, $query, $amount, $archivelist, $maxresults;
1130         global $archive, $skinid, $blog, $memberinfo, $CONF, $member;
1131         global $imagepopup, $catid, $special;
1132         global $manager;
1133         
1134         $actionNames = array('addcomment', 'sendmessage', 'createaccount', 'forgotpassword', 'votepositive', 'votenegative', 'plugin');
1135         $action = requestVar('action');
1136         
1137         if ( in_array($action, $actionNames) )
1138         {
1139                 global $DIR_LIBS, $errormessage;
1140                 include_once($DIR_LIBS . 'ACTION.php');
1141                 $a = new ACTION();
1142                 $errorInfo = $a->doAction($action);
1143                 
1144                 if ( $errorInfo )
1145                 {
1146                         $errormessage = $errorInfo['message'];
1147                 }
1148         }
1149         
1150         // show error when headers already sent out
1151         if ( headers_sent() && $CONF['alertOnHeadersSent'] )
1152         {
1153                 // try to get line number/filename (extra headers_sent params only exists in PHP 4.3+)
1154                 if ( function_exists('version_compare') && version_compare('4.3.0', phpversion(), '<=') )
1155                 {
1156                         headers_sent($hsFile, $hsLine);
1157                         $extraInfo = ' in <code>' . $hsFile . '</code> line <code>' . $hsLine . '</code>';
1158                 }
1159                 else
1160                 {
1161                         $extraInfo = '';
1162                 }
1163                 
1164                 startUpError(
1165                         '<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>',
1166                         'Page headers already sent'
1167                 );
1168                 exit;
1169         }
1170         
1171         // make is so ?archivelist without blogname or blogid shows the archivelist
1172         // for the default weblog
1173         if ( serverVar('QUERY_STRING') == 'archivelist' )
1174         {
1175                 $archivelist = $CONF['DefaultBlog'];
1176         }
1177         
1178         // now decide which type of skin we need
1179         if ( $itemid )
1180         {
1181                 // itemid given -> only show that item
1182                 $type = 'item';
1183                 
1184                 if ( !$manager->existsItem($itemid,intval($CONF['allowFuture']),intval($CONF['allowDrafts'])) )
1185                 {
1186                         doError(_ERROR_NOSUCHITEM);
1187                 }
1188                 
1189                 global $itemidprev, $itemidnext, $catid, $itemtitlenext, $itemtitleprev;
1190                 
1191                 // 1. get timestamp, blogid and catid for item
1192                 $query = 'SELECT itime, iblog, icat FROM ' . sql_table('item') . ' WHERE inumber=' . intval($itemid);
1193                 $res = sql_query($query);
1194                 $obj = sql_fetch_object($res);
1195                 
1196                 // if a different blog id has been set through the request or selectBlog(),
1197                 // deny access
1198                 
1199                 if ( $blogid && (intval($blogid) != $obj->iblog) )
1200                 {
1201                         doError(_ERROR_NOSUCHITEM);
1202                 }
1203                 
1204                 // if a category has been selected which doesn't match the item, ignore the
1205                 // category. #85
1206                 if ( ($catid != 0) && ($catid != $obj->icat) )
1207                 {
1208                         $catid = 0;
1209                 }
1210                 
1211                 $blogid = $obj->iblog;
1212                 $timestamp = strtotime($obj->itime);
1213                 
1214                 $b =& $manager->getBlog($blogid);
1215                 
1216                 if ( $b->isValidCategory($catid) )
1217                 {
1218                         $catextra = ' and icat=' . $catid;
1219                 }
1220                 else
1221                 {
1222                         $catextra = '';
1223                 }
1224                 
1225                 // get previous itemid and title
1226                 $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';
1227                 $res = sql_query($query);
1228                 
1229                 $obj = sql_fetch_object($res);
1230                 
1231                 if ( $obj )
1232                 {
1233                         $itemidprev = $obj->inumber;
1234                         $itemtitleprev = $obj->ititle;
1235                 }
1236                 
1237                 // get next itemid and title
1238                 $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';
1239                 $res = sql_query($query);
1240                 
1241                 $obj = sql_fetch_object($res);
1242                 
1243                 if ( $obj )
1244                 {
1245                         $itemidnext = $obj->inumber;
1246                         $itemtitlenext = $obj->ititle;
1247                 }
1248         }
1249         elseif ($archive)
1250         {
1251                 // show archive
1252                 $type = 'archive';
1253                 
1254                 // get next and prev month links ...
1255                 global $archivenext, $archiveprev, $archivetype, $archivenextexists, $archiveprevexists;
1256                 
1257                 // sql queries for the timestamp of the first and the last published item
1258                 $query = "SELECT UNIX_TIMESTAMP(itime) as result FROM ".sql_table('item')." WHERE idraft=0 ORDER BY itime ASC";
1259                 $first_timestamp=quickQuery ($query);
1260                 $query = "SELECT UNIX_TIMESTAMP(itime) as result FROM ".sql_table('item')." WHERE idraft=0 ORDER BY itime DESC";
1261                 $last_timestamp=quickQuery ($query);
1262                 
1263                 sscanf($archive, '%d-%d-%d', $y, $m, $d);
1264                 
1265                 if ( $d != 0 )
1266                 {
1267                         $archivetype = _ARCHIVETYPE_DAY;
1268                         $t = mktime(0, 0, 0, $m, $d, $y);
1269                         // one day has 24 * 60 * 60 = 86400 seconds
1270                         $archiveprev = i18n::strftime('%Y-%m-%d', $t - 86400 );
1271                         // check for published items
1272                         if ( $t > $first_timestamp )
1273                         {
1274                                 $archiveprevexists = true;
1275                         }
1276                         else
1277                         {
1278                                 $archiveprevexists = false;
1279                         }
1280                         
1281                         // one day later
1282                         $t += 86400;
1283                         $archivenext = i18n::strftime('%Y-%m-%d', $t);
1284                         if ( $t < $last_timestamp )
1285                         {
1286                                 $archivenextexists = true;
1287                         }
1288                         else
1289                         {
1290                                 $archivenextexists = false;
1291                         }
1292                 }
1293                 elseif ( $m == 0 )
1294                 {
1295                         $archivetype = _ARCHIVETYPE_YEAR;
1296                         $t = mktime(0, 0, 0, 12, 31, $y - 1);
1297                         // one day before is in the previous year
1298                         $archiveprev = i18n::strftime('%Y', $t);
1299                         if ( $t > $first_timestamp )
1300                         {
1301                                 $archiveprevexists = true;
1302                         }
1303                         else
1304                         {
1305                                 $archiveprevexists = false;
1306                         }
1307
1308                         // timestamp for the next year
1309                         $t = mktime(0, 0, 0, 1, 1, $y + 1);
1310                         $archivenext = i18n::strftime('%Y', $t);
1311                         if ( $t < $last_timestamp )
1312                         {
1313                                 $archivenextexists = true;
1314                         }
1315                         else
1316                         {
1317                                 $archivenextexists = false;
1318                         }
1319                 }
1320                 else
1321                 {
1322                         $archivetype = _ARCHIVETYPE_MONTH;
1323                         $t = mktime(0, 0, 0, $m, 1, $y);
1324                         // one day before is in the previous month
1325                         $archiveprev = i18n::strftime('%Y-%m', $t - 86400);
1326                         if ( $t > $first_timestamp )
1327                         {
1328                                 $archiveprevexists = true;
1329                         }
1330                         else
1331                         {
1332                                 $archiveprevexists = false;
1333                         }
1334                         
1335                         // timestamp for the next month
1336                         $t = mktime(0, 0, 0, $m+1, 1, $y);
1337                         $archivenext = i18n::strftime('%Y-%m', $t);
1338                         if ( $t < $last_timestamp )
1339                         {
1340                                 $archivenextexists = true;
1341                         }
1342                         else
1343                         {
1344                                 $archivenextexists = false;
1345                         }
1346                 }
1347         }
1348         elseif ($archivelist)
1349         {
1350                 $type = 'archivelist';
1351                 
1352                 if ( is_numeric($archivelist) )
1353                 {
1354                         $blogid = intVal($archivelist);
1355                 }
1356                 else
1357                 {
1358                         $blogid = getBlogIDFromName($archivelist);
1359                 }
1360         
1361                 if ( !$blogid )
1362                 {
1363                         doError(_ERROR_NOSUCHBLOG);
1364                 }
1365         }
1366         elseif ( $query )
1367         {
1368                 global $startpos;
1369                 $type = 'search';
1370                 $query = stripslashes($query);
1371                 
1372                 if ( is_numeric($blogid) )
1373                 {
1374                         $blogid = intVal($blogid);
1375                 }
1376                 else
1377                 {
1378                         $blogid = getBlogIDFromName($blogid);
1379                 }
1380                 
1381                 if ( !$blogid )
1382                 {
1383                         doError(_ERROR_NOSUCHBLOG);
1384                 }
1385         }
1386         elseif ( $memberid )
1387         {
1388                 $type = 'member';
1389                 
1390                 if ( !MEMBER::existsID($memberid) )
1391                 {
1392                         doError(_ERROR_NOSUCHMEMBER);
1393                 }
1394                 $memberinfo = $manager->getMember($memberid);
1395         }
1396         elseif ( $imagepopup )
1397         {
1398                 // media object (images etc.)
1399                 $type = 'imagepopup';
1400                 
1401                 // TODO: check if media-object exists
1402                 // TODO: set some vars?
1403         }
1404         else
1405         {
1406                 // show regular index page
1407                 global $startpos;
1408                 $type = 'index';
1409         }
1410         
1411         // any type of skin with catid
1412         if ( $catid && !$blogid )
1413         {
1414                 $blogid = getBlogIDFromCatID($catid);
1415         }
1416         
1417         // decide which blog should be displayed
1418         if ( !$blogid )
1419         {
1420                 $blogid = $CONF['DefaultBlog'];
1421         }
1422         
1423         $b =& $manager->getBlog($blogid);
1424         $blog = $b; // references can't be placed in global variables?
1425         
1426         if ( !$blog->isValid )
1427         {
1428                 doError(_ERROR_NOSUCHBLOG);
1429         }
1430         
1431         // set catid if necessary
1432         if ( $catid )
1433         {
1434                 // check if the category is valid
1435                 if ( !$blog->isValidCategory($catid) )
1436                 {
1437                         doError(_ERROR_NOSUCHCATEGORY);
1438                 }
1439                 else
1440                 {
1441                         $blog->setSelectedCategory($catid);
1442                 }
1443         }
1444         
1445         // decide which skin should be used
1446         if ( $skinid != '' && ($skinid == 0) )
1447         {
1448                 selectSkin($skinid);
1449         }
1450         
1451         if ( !$skinid )
1452         {
1453                 $skinid = $blog->getDefaultSkin();
1454         }
1455         
1456         //$special = requestVar('special'); //get at top of file as global
1457         if ( !empty($special) && isValidShortName($special) )
1458         {
1459                 $type = strtolower($special);
1460         }
1461         
1462         $skin = new SKIN($skinid);
1463         
1464         if ( !$skin->isValid )
1465         {
1466                 doError(_ERROR_NOSUCHSKIN);
1467         }
1468         
1469         // set global skinpart variable so can determine quickly what is being parsed from any plugin or phpinclude
1470         global $skinpart;
1471         $skinpart = $type;
1472         
1473         // parse the skin
1474         $skin->parse($type);
1475         
1476         // check to see we should throw JustPosted event
1477         $blog->checkJustPosted();
1478         return;
1479 }
1480
1481 /**
1482   * Show error skin with given message. An optional skin-object to use can be given
1483   */
1484 function doError($msg, $skin = '') {
1485     global $errormessage, $CONF, $skinid, $blogid, $manager;
1486
1487     if ($skin == '') {
1488
1489         if (SKIN::existsID($skinid) ) {
1490             $skin = new SKIN($skinid);
1491         } elseif ($manager->existsBlogID($blogid) ) {
1492             $blog =& $manager->getBlog($blogid);
1493             $skin = new SKIN($blog->getDefaultSkin() );
1494         } elseif ($CONF['DefaultBlog']) {
1495             $blog =& $manager->getBlog($CONF['DefaultBlog']);
1496             $skin = new SKIN($blog->getDefaultSkin() );
1497         } else {
1498             // this statement should actually never be executed
1499             $skin = new SKIN($CONF['BaseSkin']);
1500         }
1501
1502     }
1503
1504     $skinid = $skin->id;
1505     $errormessage = $msg;
1506     $skin->parse('error');
1507     exit;
1508 }
1509
1510 function getConfig() {
1511     global $CONF;
1512
1513     $query = 'SELECT * FROM ' . sql_table('config');
1514     $res = sql_query($query);
1515
1516     while ($obj = sql_fetch_object($res) ) {
1517         $CONF[$obj->name] = $obj->value;
1518     }
1519 }
1520
1521 // some checks for names of blogs, categories, templates, members, ...
1522 function isValidShortName($name) {
1523
1524         # replaced eregi() below with preg_match(). ereg* functions are deprecated in PHP 5.3.0
1525         # original eregi: eregi('^[a-z0-9]+$', $name)
1526
1527         return preg_match('#^[a-z0-9]+$#i', $name);
1528
1529 }
1530
1531 function isValidDisplayName($name) {
1532
1533         # replaced eregi() below with preg_match(). ereg* functions are deprecated in PHP 5.3.0
1534         # original eregi: eregi('^[a-z0-9]+[a-z0-9 ]*[a-z0-9]+$', $name)
1535
1536         return preg_match('#^[a-z0-9]+[a-z0-9 ]*[a-z0-9]+$#i', $name);
1537
1538 }
1539
1540 function isValidCategoryName($name) {
1541     return 1;
1542 }
1543
1544 function isValidTemplateName($name) {
1545
1546         # replaced eregi() below with preg_match(). ereg* functions are deprecated in PHP 5.3.0
1547         # original eregi: eregi('^[a-z0-9/]+$', $name)
1548         // added - and _ to valid characters as of 4.00
1549
1550         return preg_match('#^[a-z0-9/_\-]+$#i', $name);
1551
1552 }
1553
1554 function isValidSkinName($name) {
1555
1556         # replaced eregi() below with preg_match(). ereg* functions are deprecated in PHP 5.3.0
1557         # original eregi: eregi('^[a-z0-9/]+$', $name);
1558         // added - and _ to valid characters as of 4.00
1559
1560         return preg_match('#^[a-z0-9/_\-]+$#i', $name);
1561
1562 }
1563
1564 // add and remove linebreaks
1565 function addBreaks($var) {
1566     return nl2br($var);
1567 }
1568
1569 function removeBreaks($var) {
1570     return preg_replace("/<br \/>([\r\n])/", "$1", $var);
1571 }
1572
1573 /**
1574  * shortens a text string to maxlength.
1575  * $suffix is what needs to be added at the end (end length is <= $maxlength)
1576  *
1577  * The purpose is to limit the width of string for rendered screen in web browser.
1578  * So it depends on style sheet, browser's rendering scheme, client's system font.
1579  *
1580  * NOTE: In general, non-Latin font such as Japanese, Chinese, Cyrillic have two times as width as Latin fonts,
1581  *  but this is not always correct, for example, rendered by proportional font.
1582  *
1583  * @param string $escaped_string target string
1584  * @param integer $maxlength maximum length of return string which includes suffix
1585  * @param string $suffix added in the end of shortened-string
1586  * @return string
1587 */
1588 function shorten($string, $maxlength, $suffix)
1589 {
1590         static $flag;
1591         
1592         $decoded_entities_pcre = array();
1593         $encoded_entities = array();
1594         
1595         /* 1. store html entities */
1596         preg_match('#&[^&]+?;#', $string, $encoded_entities);
1597         if ( !$encoded_entities )
1598         {
1599                 $flag = FALSE;
1600         }
1601         else
1602         {
1603                 $flag = TRUE;
1604         }
1605         if ( $flag )
1606         {
1607                 foreach ( $encoded_entities as $encoded_entity )
1608                 {
1609                         $decoded_entities_pcre[] = '#' . html_entity_decode($encoded_entity, ENT_QUOTES, i18n::get_current_charset()) . '#';
1610                 }
1611         }
1612         
1613         /* 2. decode string */
1614         $string = html_entity_decode($string, ENT_QUOTES, i18n::get_current_charset());
1615         
1616         /* 3. shorten string and add suffix if string length is longer */
1617         if ( i18n::strlen($string) > $maxlength - i18n::strlen($suffix) )
1618         {
1619                 $string = i18n::substr($string, 0, $maxlength - i18n::strlen($suffix) );
1620                 $string .= $suffix;
1621         }
1622         
1623         /* 4. recover entities */
1624         if ( $flag )
1625         {
1626                 $string = preg_replace($decoded_entities_pcre, $encoded_entities, $string);
1627         }
1628         
1629         return $string;
1630 }
1631
1632 /**
1633   * Converts a unix timestamp to a mysql DATETIME format, and places
1634   * quotes around it.
1635   */
1636 function mysqldate($timestamp) {
1637     return '"' . date('Y-m-d H:i:s', $timestamp) . '"';
1638 }
1639
1640 /**
1641   * functions for use in index.php
1642   */
1643 function selectBlog($shortname) {
1644     global $blogid, $archivelist;
1645     $blogid = getBlogIDFromName($shortname);
1646
1647     // also force archivelist variable, if it is set
1648     if ($archivelist) {
1649         $archivelist = $blogid;
1650     }
1651 }
1652
1653 function selectSkin($skinname) {
1654     global $skinid;
1655     $skinid = SKIN::getIdFromName($skinname);
1656 }
1657
1658 /**
1659  * Can take either a category ID or a category name (be aware that
1660  * multiple categories can have the same name)
1661  */
1662 function selectCategory($cat) {
1663     global $catid;
1664     if (is_numeric($cat) ) {
1665         $catid = intval($cat);
1666     } else {
1667         $catid = getCatIDFromName($cat);
1668     }
1669 }
1670
1671 function selectItem($id) {
1672     global $itemid;
1673     $itemid = intval($id);
1674 }
1675
1676 // force the use of a language file (warning: can cause warnings)
1677 function selectLanguage($language) {
1678
1679         global $DIR_LANG;
1680
1681         # replaced ereg_replace() below with preg_replace(). ereg* functions are deprecated in PHP 5.3.0
1682         # original ereg_replace: preg_replace( '@\\|/@', '', $language) . '.php')
1683         # important note that '\' must be matched with '\\\\' in preg* expressions
1684
1685         include($DIR_LANG . preg_replace('#[\\\\|/]#', '', $language) . '.php');
1686
1687 }
1688
1689 function parseFile($filename, $includeMode = 'normal', $includePrefix = '') {
1690     $handler = new ACTIONS('fileparser');
1691     $parser = new PARSER(SKIN::getAllowedActionsForType('fileparser'), $handler);
1692     $handler->parser =& $parser;
1693
1694     // set IncludeMode properties of parser
1695     PARSER::setProperty('IncludeMode', $includeMode);
1696     PARSER::setProperty('IncludePrefix', $includePrefix);
1697
1698     if (!file_exists($filename) ) {
1699         doError('A file is missing');
1700     }
1701
1702     $fsize = filesize($filename);
1703
1704     if ($fsize <= 0) {
1705         return;
1706     }
1707
1708     // read file
1709     $fd = fopen ($filename, 'r');
1710     $contents = fread ($fd, $fsize);
1711     fclose ($fd);
1712
1713     // parse file contents
1714     $parser->parse($contents);
1715 }
1716
1717 /**
1718   * Outputs a debug message
1719   */
1720 function debug($msg) {
1721     echo '<p><b>' . $msg . "</b></p>\n";
1722 }
1723
1724 // shortcut
1725 function addToLog($level, $msg) {
1726     ACTIONLOG::add($level, $msg);
1727 }
1728
1729 // shows a link to help file
1730 function help($id) {
1731     echo helpHtml($id);
1732 }
1733
1734 function helpHtml($id) {
1735     global $CONF;
1736     return helplink($id) . '<img src="' . $CONF['AdminURL'] . 'documentation/icon-help.gif" width="15" height="15" alt="' . _HELP_TT . '" title="' . _HELP_TT . '" /></a>';
1737 }
1738
1739 function helplink($id) {
1740     global $CONF;
1741     return '<a href="' . $CONF['AdminURL'] . 'documentation/help.html#'. $id . '" onclick="if (event &amp;&amp; event.preventDefault) event.preventDefault(); return help(this.href);">';
1742 }
1743
1744 /**
1745  * Deprecated since 4.0:
1746  * Please use functions in MAIL class instead
1747  */
1748 function getMailFooter()
1749 {
1750         NOTIFICATION::get_mail_footer();
1751 }
1752 function isValidMailAddress($address)
1753 {
1754         return NOTIFICATION::address_validation($address);
1755 }
1756
1757 /*
1758  * Returns the name of the language to use
1759  * preference priority: member - site
1760  * defaults to english-utf8 when no good language found
1761  *
1762  * NOTE: Deprecated, plugins to use this function should be re-worked as soon as possible!
1763  * TODO: this will be obsoleted soon.
1764  */
1765 function getLanguageName()
1766 {
1767         if( ($language = i18n::convert_locale_to_old_language_file_name(i18n::get_current_locale())) === FALSE )
1768         {
1769                 $language ='english';
1770         }
1771         return $language;
1772 }
1773
1774 /**
1775   * Includes a PHP file. This method can be called while parsing templates and skins
1776   */
1777 function includephp($filename) {
1778     // make predefined variables global, so most simple scripts can be used here
1779
1780     // apache (names taken from PHP doc)
1781     global $GATEWAY_INTERFACE, $SERVER_NAME, $SERVER_SOFTWARE, $SERVER_PROTOCOL;
1782     global $REQUEST_METHOD, $QUERY_STRING, $DOCUMENT_ROOT, $HTTP_ACCEPT;
1783     global $HTTP_ACCEPT_CHARSET, $HTTP_ACCEPT_ENCODING, $HTTP_ACCEPT_LANGUAGE;
1784     global $HTTP_CONNECTION, $HTTP_HOST, $HTTP_REFERER, $HTTP_USER_AGENT;
1785     global $REMOTE_ADDR, $REMOTE_PORT, $SCRIPT_FILENAME, $SERVER_ADMIN;
1786     global $SERVER_PORT, $SERVER_SIGNATURE, $PATH_TRANSLATED, $SCRIPT_NAME;
1787     global $REQUEST_URI;
1788
1789     // php (taken from PHP doc)
1790     global $argv, $argc, $PHP_SELF, $HTTP_COOKIE_VARS, $HTTP_GET_VARS, $HTTP_POST_VARS;
1791     global $HTTP_POST_FILES, $HTTP_ENV_VARS, $HTTP_SERVER_VARS, $HTTP_SESSION_VARS;
1792
1793     // other
1794     global $PATH_INFO, $HTTPS, $HTTP_RAW_POST_DATA, $HTTP_X_FORWARDED_FOR;
1795
1796     if (@file_exists($filename) ) {
1797         include($filename);
1798     }
1799 }
1800
1801 /**
1802  * Checks if a certain language exists
1803  * @param string $lang
1804  * @return bool
1805  * 
1806  * NOTE: Deprecated, plugins to use this function should be re-worked as soon as possible!
1807  * TODO: this will be obsoleted soon.
1808  **/
1809 function checkLanguage($lang)
1810 {
1811         return ( preg_match('#^(.+)_(.+)_(.+)$#', $lang)
1812           || i18n::convert_old_language_file_name_to_locale($lang) );
1813 }
1814
1815 /**
1816  * Checks if a certain plugin exists
1817  * @param string $plug
1818  * @return bool
1819  **/
1820 function checkPlugin($plug) {
1821
1822         global $DIR_PLUGINS;
1823
1824         # replaced ereg_replace() below with preg_replace(). ereg* functions are deprecated in PHP 5.3.0
1825         # original ereg_replace: ereg_replace( '[\\|/]', '', $plug) . '.php')
1826         # important note that '\' must be matched with '\\\\' in preg* expressions
1827
1828         return file_exists($DIR_PLUGINS . preg_replace('#[\\\\|/]#', '', $plug) . '.php');
1829
1830 }
1831
1832 /**
1833   * Centralisation of the functions that generate links
1834   * Deprecated since 3.70:
1835   * Please use Link::FunctionName(...) instead
1836   */
1837 function createItemLink($itemid, $extra = '') {
1838         return Link::createItemLink($itemid, $extra);
1839 }
1840
1841 function createMemberLink($memberid, $extra = '') {
1842         return Link::createMemberLink($memberid, $extra);
1843 }
1844
1845 function createCategoryLink($catid, $extra = '') {
1846         return Link::createCategoryLink($catid, $extra);
1847 }
1848
1849 function createArchiveListLink($blogid = '', $extra = '') {
1850         return Link::createArchiveListLink($blogid, $extra);
1851 }
1852
1853 function createArchiveLink($blogid, $archive, $extra = '') {
1854         return Link::createArchiveLink($blogid, $archive, $extra);
1855 }
1856
1857 function createBlogidLink($blogid, $params = '') {
1858         return Link::createBlogidLink($blogid, $params = '');
1859 }
1860
1861 function createLink($type, $params) {
1862         return Link::createLink($type, $params);
1863 }
1864
1865 function createBlogLink($url, $params) {
1866    return Link::createBlogLink($url, $params);
1867 }
1868
1869
1870 /**
1871  * @param $querystr
1872  *              querystring to alter (e.g. foo=1&bar=2&x=y)
1873  * @param $param
1874  *              name of parameter to change (e.g. 'foo')
1875  * @param $value
1876  *              New value for that parameter (e.g. 3)
1877  * @result
1878  *              altered query string (for the examples above: foo=3&bar=2&x=y)
1879  */
1880 function alterQueryStr($querystr, $param, $value) {
1881     $vars = i18n::explode('&', $querystr);
1882     $set  = false;
1883
1884     for ($i = 0; $i < count($vars); $i++) {
1885         $v = i18n::explode('=', $vars[$i]);
1886
1887         if ($v[0] == $param) {
1888             $v[1] = $value;
1889             $vars[$i] = implode('=', $v);
1890             $set = true;
1891             break;
1892         }
1893     }
1894
1895     if (!$set) {
1896         $vars[] = $param . '=' . $value;
1897     }
1898
1899     return ltrim(implode('&', $vars), '&');
1900 }
1901
1902 // passes one variable as hidden input field (multiple fields for arrays)
1903 // @see passRequestVars in varsx.x.x.php
1904 function passVar($key, $value) {
1905     // array ?
1906     if (is_array($value) ) {
1907         for ($i = 0; $i < sizeof($value); $i++) {
1908             passVar($key . '[' . $i . ']', $value[$i]);
1909         }
1910
1911         return;
1912     }
1913
1914     // other values: do stripslashes if needed
1915     ?><input type="hidden" name="<?php echo i18n::hsc($key)?>" value="<?php echo i18n::hsc(undoMagic($value) )?>" /><?php
1916 }
1917
1918 /*
1919     Date format functions (to be used from [%date(..)%] skinvars
1920 */
1921 function formatDate($format, $timestamp, $defaultFormat, &$blog) {
1922     // apply blog offset (#42)
1923     $boffset = $blog ? $blog->getTimeOffset() * 3600 : 0;
1924     $offset = date('Z', $timestamp) + $boffset;
1925
1926     switch ($format) {
1927         case 'rfc822':
1928             if ($offset >= 0) {
1929                 $tz = '+';
1930             } else {
1931                 $tz = '-';
1932                 $offset = -$offset;
1933             }
1934
1935             $tz .= sprintf("%02d%02d", floor($offset / 3600), round(($offset % 3600) / 60) );
1936             return date('D, j M Y H:i:s ', $timestamp) . $tz;
1937
1938         case 'rfc822GMT':
1939             $timestamp -= $offset;
1940             return date('D, j M Y H:i:s ', $timestamp) . 'GMT';
1941
1942         case 'utc':
1943             $timestamp -= $offset;
1944             return date('Y-m-d\TH:i:s\Z', $timestamp);
1945
1946         case 'iso8601':
1947             if ($offset >= 0) {
1948                 $tz = '+';
1949             } else {
1950                 $tz = '-';
1951                 $offset = -$offset;
1952             }
1953             $tz .= sprintf("%02d:%02d", floor($offset / 3600), round(($offset % 3600) / 60) );
1954             return date('Y-m-d\TH:i:s', $timestamp) . $tz;
1955
1956         default :
1957             return i18n::strftime($format ? $format : $defaultFormat, $timestamp);
1958     }
1959 }
1960
1961 function checkVars($aVars) {
1962     global $HTTP_GET_VARS, $HTTP_POST_VARS, $HTTP_COOKIE_VARS, $HTTP_ENV_VARS, $HTTP_POST_FILES, $HTTP_SESSION_VARS;
1963
1964     foreach ($aVars as $varName) {
1965
1966         if (phpversion() >= '4.1.0') {
1967
1968             if (   isset($_GET[$varName])
1969                 || isset($_POST[$varName])
1970                 || isset($_COOKIE[$varName])
1971                 || isset($_ENV[$varName])
1972                 || isset($_SESSION[$varName])
1973                 || isset($_FILES[$varName])
1974             ) {
1975                 die('Sorry. An error occurred.');
1976             }
1977
1978         } else {
1979
1980             if (   isset($HTTP_GET_VARS[$varName])
1981                 || isset($HTTP_POST_VARS[$varName])
1982                 || isset($HTTP_COOKIE_VARS[$varName])
1983                 || isset($HTTP_ENV_VARS[$varName])
1984                 || isset($HTTP_SESSION_VARS[$varName])
1985                 || isset($HTTP_POST_FILES[$varName])
1986             ) {
1987                 die('Sorry. An error occurred.');
1988             }
1989
1990         }
1991     }
1992 }
1993
1994
1995 /**
1996  * Sanitize parameters such as $_GET and $_SERVER['REQUEST_URI'] etc.
1997  * to avoid XSS
1998  */
1999 function sanitizeParams()
2000 {
2001     global $HTTP_SERVER_VARS;
2002
2003     $array = array();
2004     $str = '';
2005     $frontParam = '';
2006
2007     // REQUEST_URI of $HTTP_SERVER_VARS
2008     $str =& $HTTP_SERVER_VARS["REQUEST_URI"];
2009     serverStringToArray($str, $array, $frontParam);
2010     sanitizeArray($array);
2011     arrayToServerString($array, $frontParam, $str);
2012
2013     // QUERY_STRING of $HTTP_SERVER_VARS
2014     $str =& $HTTP_SERVER_VARS["QUERY_STRING"];
2015     serverStringToArray($str, $array, $frontParam);
2016     sanitizeArray($array);
2017     arrayToServerString($array, $frontParam, $str);
2018
2019     if (phpversion() >= '4.1.0') {
2020         // REQUEST_URI of $_SERVER
2021         $str =& $_SERVER["REQUEST_URI"];
2022         serverStringToArray($str, $array, $frontParam);
2023         sanitizeArray($array);
2024         arrayToServerString($array, $frontParam, $str);
2025
2026         // QUERY_STRING of $_SERVER
2027         $str =& $_SERVER["QUERY_STRING"];
2028         serverStringToArray($str, $array, $frontParam);
2029         sanitizeArray($array);
2030         arrayToServerString($array, $frontParam, $str);
2031     }
2032
2033     // $_GET
2034     convArrayForSanitizing($_GET, $array);
2035     sanitizeArray($array);
2036     revertArrayForSanitizing($array, $_GET);
2037
2038     // $_REQUEST (only GET param)
2039     convArrayForSanitizing($_REQUEST, $array);
2040     sanitizeArray($array);
2041     revertArrayForSanitizing($array, $_REQUEST);
2042 }
2043
2044 /**
2045  * Check ticket when not checked in plugin's admin page
2046  * to avoid CSRF.
2047  * Also avoid the access to plugin/index.php by guest user.
2048  */
2049 function ticketForPlugin()
2050 {
2051         global $CONF, $DIR_PLUGINS, $member, $ticketforplugin;
2052         
2053         /* initialize */
2054         $ticketforplugin = array();
2055         $ticketforplugin['ticket'] = FALSE;
2056         
2057         /* $_SERVER['PATH_TRANSLATED']
2058          * http://www.php.net/manual/en/reserved.variables.server.php
2059          * Note: As of PHP 4.3.2, PATH_TRANSLATED is no longer set implicitly
2060          * under the Apache 2 SAPI in contrast to the situation in Apache 1,
2061          * where it's set to the same value as the SCRIPT_FILENAME server variable
2062          * when it's not populated by Apache.
2063          * This change was made to comply with the CGI specification
2064          * that PATH_TRANSLATED should only exist if PATH_INFO is defined.
2065          * Apache 2 users may use AcceptPathInfo = On inside httpd.conf to define PATH_INFO. 
2066          */
2067         
2068         /* Check if using plugin's php file. */
2069         $p_translated = serverVar('SCRIPT_FILENAME');
2070         
2071         if (!file_exists($p_translated) )
2072         {
2073                 header("HTTP/1.0 404 Not Found");
2074                 exit('');
2075         }
2076         
2077         $p_translated = str_replace('\\', '/', $p_translated);
2078         $d_plugins = str_replace('\\', '/', $DIR_PLUGINS);
2079         
2080         // This isn't plugin php file.
2081         if ( i18n::strpos($p_translated, $d_plugins) !== 0 )
2082         {
2083                 return;
2084         }
2085
2086         // Solve the plugin php file or admin directory
2087         $phppath = i18n::substr($p_translated, i18n::strlen($d_plugins) );
2088         // Remove the first "/" if exists.
2089         $phppath = preg_replace('#^/#', '', $phppath);
2090         // Remove the first "NP_" and the last ".php" if exists.
2091         $path = preg_replace('#^NP_(.*)\.php$#', '$1', $phppath);
2092         // Remove the "/" and beyond.
2093         $path = preg_replace('#^([^/]*)/(.*)$#', '$1', $path);
2094         
2095         // Solve the plugin name.
2096         $plugins = array();
2097         $query = 'SELECT `pfile` FROM '.sql_table('plugin');
2098         $res = sql_query($query);
2099         
2100         while($row = sql_fetch_row($res) )
2101         {
2102                 $name = i18n::substr($row[0], 3);
2103                 $plugins[strtolower($name)] = $name;
2104         }
2105         
2106         sql_free_result($res);
2107         
2108         if (array_key_exists($path, $plugins))
2109         {
2110                 $plugin_name = $plugins[$path];
2111         }
2112         else if (in_array($path, $plugins))
2113         {
2114                 $plugin_name = $path;
2115         }
2116         else
2117         {
2118                 header("HTTP/1.0 404 Not Found");
2119                 exit('');
2120         }
2121         
2122         /* Return if not index.php */
2123         if ( ($phppath != strtolower($plugin_name) . '/') && ($phppath != strtolower($plugin_name) . '/index.php') )
2124         {
2125                 return;
2126         }
2127         
2128         /* Exit if not logged in. */
2129         if ( !$member->isLoggedIn() )
2130         {
2131                 exit('You aren\'t logged in.');
2132         }
2133         
2134         global $manager, $DIR_LIBS, $DIR_LANG, $HTTP_GET_VARS, $HTTP_POST_VARS;
2135         
2136         /* Check if this feature is needed (ie, if "$manager->checkTicket()" is not included in the script). */
2137         if (!($p_translated = serverVar('PATH_TRANSLATED') ) )
2138         {
2139                 $p_translated = serverVar('SCRIPT_FILENAME');
2140         }
2141         
2142         if ($file = @file($p_translated) )
2143         {
2144                 $prevline = '';
2145                 
2146                 foreach($file as $line)
2147                 {
2148                         if (preg_match('/[\$]manager([\s]*)[\-]>([\s]*)checkTicket([\s]*)[\(]/i', $prevline . $line) )
2149                         {
2150                                 return;
2151                         }
2152                         
2153                         $prevline = $line;
2154                 }
2155         }
2156         
2157         /* Show a form if not valid ticket */
2158         if ( ( strstr(serverVar('REQUEST_URI'), '?') || serverVar('QUERY_STRING')
2159          || strtoupper(serverVar('REQUEST_METHOD') ) == 'POST')
2160          && (!$manager->checkTicket() ) )
2161         {
2162                 $oPluginAdmin = new PluginAdmin($plugin_name);
2163                 $oPluginAdmin->start();
2164                 echo '<p>' . _ERROR_BADTICKET . "</p>\n";
2165                 
2166                 /* Show the form to confirm action */
2167                 // PHP 4.0.x support
2168                 $get = (isset($_GET) ) ? $_GET : $HTTP_GET_VARS;
2169                 $post = (isset($_POST) ) ? $_POST : $HTTP_POST_VARS;
2170                 
2171                 // Resolve URI and QUERY_STRING
2172                 if ($uri = serverVar('REQUEST_URI') )
2173                 {
2174                         list($uri, $qstring) = i18n::explode('?', $uri);
2175                 }
2176                 else
2177                 {
2178                         if ( !($uri = serverVar('PHP_SELF') ) )
2179                         {
2180                                 $uri = serverVar('SCRIPT_NAME');
2181                         }
2182                         $qstring = serverVar('QUERY_STRING');
2183                 }
2184                 if ($qstring)
2185                 {
2186                         $qstring = '?' . $qstring;
2187                 }
2188                 
2189                 echo '<p>' . _SETTINGS_UPDATE . ' : ' . _QMENU_PLUGINS . ' <span style="color:red;">' . i18n::hsc($plugin_name) . "</span> ?</p>\n";
2190                 
2191                 switch(strtoupper(serverVar('REQUEST_METHOD') ) )
2192                 {
2193                         case 'POST':
2194                                 echo '<form method="POST" action="'.i18n::hsc($uri.$qstring).'">';
2195                                 $manager->addTicketHidden();
2196                                 _addInputTags($post);
2197                                 break;
2198                         
2199                         case 'GET':
2200                                 echo '<form method="GET" action="'.i18n::hsc($uri).'">';
2201                                 $manager->addTicketHidden();
2202                                 _addInputTags($get);
2203                         
2204                         default:
2205                                 break;
2206                 }
2207                 
2208                 echo '<input type="submit" value="' . _YES . '" />&nbsp;&nbsp;&nbsp;&nbsp;';
2209                 echo '<input type="button" value="' . _NO . '" onclick="history.back(); return false;" />';
2210                 echo "</form>\n";
2211                 
2212                 $oPluginAdmin->end();
2213                 exit;
2214         }
2215         
2216         /* Create new ticket */
2217         $ticket=$manager->addTicketToUrl('');
2218         $ticketforplugin['ticket']=i18n::substr($ticket,i18n::strpos($ticket,'ticket=')+7);
2219 }
2220
2221 function _addInputTags(&$keys,$prefix=''){
2222     foreach($keys as $key=>$value){
2223         if ($prefix) $key=$prefix.'['.$key.']';
2224         if (is_array($value)) _addInputTags($value,$key);
2225         else {
2226             if (get_magic_quotes_gpc()) $value=stripslashes($value);
2227             if ($key=='ticket') continue;
2228             echo '<input type="hidden" name="'.i18n::hsc($key).
2229                 '" value="'.i18n::hsc($value).'" />'."\n";
2230         }
2231     }
2232 }
2233
2234 /**
2235  * Convert the server string such as $_SERVER['REQUEST_URI']
2236  * to arry like arry['blogid']=1 and array['page']=2 etc.
2237  */
2238 function serverStringToArray($str, &$array, &$frontParam)
2239 {
2240     // init param
2241     $array = array();
2242     $frontParam = "";
2243
2244     // split front param, e.g. /index.php, and others, e.g. blogid=1&page=2
2245     if (strstr($str, "?")){
2246         list($frontParam, $args) = preg_split("/\?/", $str, 2);
2247     }
2248     else {
2249         $args = $str;
2250         $frontParam = "";
2251     }
2252
2253     // If there is no args like blogid=1&page=2, return
2254     if (!strstr($str, "=") && !i18n::strlen($frontParam)) {
2255         $frontParam = $str;
2256         return;
2257     }
2258
2259     $array = i18n::explode("&", $args);
2260 }
2261
2262 /**
2263  * Convert array like array['blogid'] to server string
2264  * such as $_SERVER['REQUEST_URI']
2265  */
2266 function arrayToServerString($array, $frontParam, &$str)
2267 {
2268     if (strstr($str, "?")) {
2269         $str = $frontParam . "?";
2270     } else {
2271         $str = $frontParam;
2272     }
2273     if (count($array)) {
2274         $str .= implode("&", $array);
2275     }
2276 }
2277
2278 /**
2279  * Sanitize array parameters.
2280  * This function checks both key and value.
2281  * - check key if it inclues " (double quote),  remove from array
2282  * - check value if it includes \ (escape sequece), remove remaining string
2283  */
2284 function sanitizeArray(&$array)
2285 {
2286     $excludeListForSanitization = array('query');
2287 //      $excludeListForSanitization = array();
2288
2289     foreach ($array as $k => $v) {
2290
2291         // split to key and value
2292         list($key, $val) = preg_split("/=/", $v, 2);
2293         if (!isset($val)) {
2294             continue;
2295         }
2296
2297         // when magic quotes is on, need to use stripslashes,
2298         // and then addslashes
2299         if (get_magic_quotes_gpc()) {
2300             $val = stripslashes($val);
2301         }
2302                 // note that we must use addslashes here because this function is called before the db connection is made
2303                 // and sql_real_escape_string needs a db connection
2304         $val = addslashes($val);
2305
2306         // if $key is included in exclude list, skip this param
2307         if (!in_array($key, $excludeListForSanitization)) {
2308
2309             // check value
2310             if (i18n::strpos($val, '\\')) {
2311                 list($val, $tmp) = i18n::explode('\\', $val);
2312             }
2313
2314             // remove control code etc.
2315             $val = strtr($val, "\0\r\n<>'\"", "       ");
2316
2317             // check key
2318             if (preg_match('/\"/i', $key)) {
2319                 unset($array[$k]);
2320                 continue;
2321             }
2322
2323             // set sanitized info
2324             $array[$k] = sprintf("%s=%s", $key, $val);
2325         }
2326     }
2327 }
2328
2329 /**
2330  * Convert array for sanitizeArray function
2331  */
2332 function convArrayForSanitizing($src, &$array)
2333 {
2334     $array = array();
2335     foreach ($src as $key => $val) {
2336         if (key_exists($key, $_GET)) {
2337             array_push($array, sprintf("%s=%s", $key, $val));
2338         }
2339     }
2340 }
2341
2342 /**
2343  * Revert array after sanitizeArray function
2344  */
2345 function revertArrayForSanitizing($array, &$dst)
2346 {
2347     foreach ($array as $v) {
2348         list($key, $val) = preg_split("/=/", $v, 2);
2349         $dst[$key] = $val;
2350     }
2351 }
2352
2353 /**
2354  * Stops processing the request and redirects to the given URL.
2355  * - no actual contents should have been sent to the output yet
2356  * - the URL will be stripped of illegal or dangerous characters
2357  */
2358 function redirect($url) {
2359     $url = preg_replace('|[^a-z0-9-~+_.?#=&;,/:@%*]|i', '', $url);
2360     header('Location: ' . $url);
2361     exit;
2362 }
2363
2364 /**
2365  * Strip HTML tags from a string
2366  * This function is a bit more intelligent than a regular call to strip_tags(),
2367  * because it also deletes the contents of certain tags and cleans up any
2368  * unneeded whitespace.
2369  */
2370 function stringStripTags ($string) {
2371     $string = preg_replace("/<del[^>]*>.+<\/del[^>]*>/isU", '', $string);
2372     $string = preg_replace("/<script[^>]*>.+<\/script[^>]*>/isU", '', $string);
2373     $string = preg_replace("/<style[^>]*>.+<\/style[^>]*>/isU", '', $string);
2374     $string = str_replace('>', '> ', $string);
2375     $string = str_replace('<', ' <', $string);
2376     $string = strip_tags($string);
2377     $string = preg_replace("/\s+/", " ", $string);
2378     $string = trim($string);
2379     return $string;
2380 }
2381
2382 /**
2383  * NOTE: Deprecated since 4.0, use i18n::hen()
2384  * 
2385  * Make a string containing HTML safe for use in a HTML attribute
2386  * Tags are stripped and entities are normalized
2387  */
2388 function stringToAttribute ($string)
2389 {
2390         return i18n::hsc($string);
2391 }
2392
2393 /**
2394  * NOTE: Deprecated since 4.0, use i18n::hsc()
2395  * 
2396  * Make a string containing HTML safe for use in a XML document
2397  * Tags are stripped, entities are normalized and named entities are
2398  * converted to numeric entities.
2399  */
2400 function stringToXML ($string)
2401 {
2402         return i18n::hen($string);
2403 }
2404
2405 // START: functions from the end of file BLOG.php
2406 // used for mail notification (html -> text)
2407 function toAscii($html) {
2408     // strip off most tags
2409     $html = strip_tags($html,'<a>');
2410     $to_replace = "/<a[^>]*href=[\"\']([^\"^']*)[\"\'][^>]*>([^<]*)<\/a>/i";
2411     _links_init();
2412     $ascii = preg_replace_callback ($to_replace, '_links_add', $html);
2413     $ascii .= "\n\n" . _links_list();
2414     return strip_tags($ascii);
2415 }
2416
2417 function _links_init() {
2418    global $tmp_links;
2419    $tmp_links = array();
2420 }
2421
2422 function _links_add($match) {
2423    global $tmp_links;
2424    array_push($tmp_links, $match[1]);
2425    return $match[2] . ' [' . sizeof($tmp_links) .']';
2426 }
2427
2428 function _links_list() {
2429    global $tmp_links;
2430    $output = '';
2431    $i = 1;
2432    foreach ($tmp_links as $current) {
2433       $output .= "[$i] $current\n";
2434       $i++;
2435    }
2436    return $output;
2437 }
2438 // END: functions from the end of file BLOG.php
2439
2440 // START: functions from the end of file ADMIN.php
2441 /**
2442  * 
2443  * replace html entities for plugin description, but available for the other strings
2444  * NOTE: we can use i18n::hen() or i18n::hsc() alternatively and this is deprecated.
2445  * @param string $data  target string
2446  * @return       string
2447  */
2448 function encode_desc($data)
2449 {
2450         return i18n::hen($data);
2451 }
2452
2453 /*
2454  * Returns the Javascript code for a bookmarklet that works on most modern browsers
2455  * @param blogid
2456  */
2457 function getBookmarklet($blogid) {
2458     global $CONF;
2459
2460     // normal
2461     $document = 'document';
2462     $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('";
2463     $bookmarkletline .= $CONF['AdminURL'] . "bookmarklet.php?blogid=$blogid";
2464     $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();";
2465
2466     return $bookmarkletline;
2467 }
2468 // END: functions from the end of file ADMIN.php
2469
2470 /**
2471  * Returns a variable or null if not set
2472  *
2473  * @param mixed Variable
2474  * @return mixed Variable
2475  */
2476 function ifset(&$var) {
2477     if (isset($var)) {
2478         return $var;
2479     }
2480
2481     return null;
2482 }
2483
2484 /**
2485  * Returns number of subscriber to an event
2486  *
2487  * @param event
2488  * @return number of subscriber(s)
2489  */
2490 function numberOfEventSubscriber($event) {
2491     $query = 'SELECT COUNT(*) as count FROM ' . sql_table('plugin_event') . ' WHERE event=\'' . $event . '\'';
2492     $res = sql_query($query);
2493     $obj = sql_fetch_object($res);
2494     return $obj->count;
2495 }
2496
2497 /**
2498  * sets $special global variable for use in index.php before selector()
2499  *
2500  * @param String id
2501  * @return nothing
2502  */
2503 function selectSpecialSkinType($id) {
2504     global $special;
2505     $special = strtolower($id);
2506 }
2507
2508 /**
2509  * cleans filename of uploaded file for writing to file system
2510  *
2511  * @param String str
2512  * @return String cleaned filename ready for use
2513  */
2514 function cleanFileName($str) {
2515         $str = strtolower($str);
2516         $ext_point = i18n::strrpos($str,".");
2517         if ($ext_point===false) return false;
2518         $ext = i18n::substr($str,$ext_point,i18n::strlen($str));
2519         $str = i18n::substr($str,0,$ext_point);
2520
2521         return preg_replace("/[^a-z0-9-]/","_",$str).$ext;
2522 }
2523
2524 ?>