OSDN Git Service

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