OSDN Git Service

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