OSDN Git Service

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