OSDN Git Service

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