OSDN Git Service

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