OSDN Git Service

421763ccf1a8bb5caa16946b25d0063e57c2f73e
[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 /*/ <add for garble measure>\r
522         $resource = sql_query("show variables LIKE 'character_set_database'");\r
523         $fetchDat = mysql_fetch_assoc($resource);\r
524         $charset  = $fetchDat['Value'];\r
525         $mySqlVer = implode('.', array_map('intval', explode('.', mysql_get_server_info($MYSQL_CONN))));\r
526         if ($mySqlVer >= '5.0.7' && phpversion() >= '5.2.3') {\r
527                 mysql_set_charset($charset);\r
528         } else {\r
529                 sql_query("SET NAMES " . $charset);\r
530         }\r
531 // </add for garble measure>*/\r
532 \r
533         return $MYSQL_CONN;\r
534 }\r
535 \r
536 /**\r
537  * returns a prefixed nucleus table name\r
538  */\r
539 function sql_table($name) {\r
540         global $MYSQL_PREFIX;\r
541 \r
542         if ($MYSQL_PREFIX) {\r
543                 return $MYSQL_PREFIX . 'nucleus_' . $name;\r
544         } else {\r
545                 return 'nucleus_' . $name;\r
546         }\r
547 }\r
548 \r
549 function sendContentType($contenttype, $pagetype = '', $charset = _CHARSET) {\r
550         global $manager, $CONF;\r
551 \r
552         if (!headers_sent() ) {\r
553                 // if content type is application/xhtml+xml, only send it to browsers\r
554                 // that can handle it (IE6 cannot). Otherwise, send text/html\r
555 \r
556                 // v2.5: For admin area pages, keep sending text/html (unless it's a debug version)\r
557                 //       application/xhtml+xml still causes too much problems with the javascript implementations\r
558 \r
559                 // v3.3: ($CONF['UsingAdminArea'] && !$CONF['debug']) gets removed,\r
560                 //       application/xhtml+xml seems to be working, so we're going to use it if we can.\r
561                 //\r
562                 // Note: reverted the following function in JP version\r
563                 //\r
564         /*\r
565                 // v3.3 code\r
566                 if (\r
567                                 ($contenttype == 'application/xhtml+xml')\r
568                         &&      (!stristr(serverVar('HTTP_ACCEPT'), 'application/xhtml+xml') )\r
569                         ) {\r
570                         $contenttype = 'text/html';\r
571                 }\r
572         */\r
573                 // v3.2x code\r
574                 if (\r
575                                 ($contenttype == 'application/xhtml+xml')\r
576                         &&      (($CONF['UsingAdminArea'] && !$CONF['debug']) || !stristr(serverVar('HTTP_ACCEPT'),'application/xhtml+xml'))\r
577                         )\r
578                 {\r
579                         $contenttype = 'text/html';\r
580                 }\r
581 \r
582                 $manager->notify(\r
583                         'PreSendContentType',\r
584                         array(\r
585                                 'contentType' => &$contenttype,\r
586                                 'charset' => &$charset,\r
587                                 'pageType' => $pagetype\r
588                         )\r
589                 );\r
590 \r
591                 // strip strange characters\r
592                 $contenttype = preg_replace('|[^a-z0-9-+./]|i', '', $contenttype);\r
593                 $charset = preg_replace('|[^a-z0-9-_]|i', '', $charset);\r
594 \r
595                 if ($charset != '') {\r
596                         header('Content-Type: ' . $contenttype . '; charset=' . $charset);\r
597                 } else {\r
598                         header('Content-Type: ' . $contenttype);\r
599                 }\r
600 \r
601                 // check if valid charset\r
602                 if (!encoding_check(false,false,$charset)) {\r
603                         foreach(array($_GET, $_POST) as $input) {\r
604                                 array_walk($input, 'encoding_check');\r
605                         }\r
606                 }\r
607         }\r
608 }\r
609 \r
610 /**\r
611  * Errors before the database connection has been made\r
612  */\r
613 function startUpError($msg, $title) {\r
614         if (!defined('_CHARSET')) define('_CHARSET', 'iso-8859-1');\r
615         header('Content-Type: text/html; charset=' . _CHARSET);\r
616         ?>\r
617         <html <?php echo _HTML_XML_NAME_SPACE_AND_LANG_CODE; ?>>\r
618                 <head><meta http-equiv="Content-Type" content="text/html; charset=<?php echo _CHARSET?>" />\r
619                 <title><?php echo htmlspecialchars($title)?></title></head>\r
620                 <body>\r
621                         <h1><?php echo htmlspecialchars($title)?></h1>\r
622                         <?php echo $msg?>\r
623                 </body>\r
624         </html>\r
625         <?php   exit;\r
626 }\r
627 \r
628 /**\r
629   * disconnects from SQL server\r
630   */\r
631 function sql_disconnect() {\r
632         @mysql_close();\r
633 }\r
634 \r
635 /**\r
636   * executes an SQL query\r
637   */\r
638 function sql_query($query) {\r
639         global $SQLCount;\r
640         $SQLCount++;\r
641         $res = mysql_query($query) or print("mySQL error with query $query: " . mysql_error() . '<p />');\r
642         return $res;\r
643 }\r
644 \r
645 \r
646 /**\r
647  * Highlights a specific query in a given HTML text (not within HTML tags) and returns it\r
648  *\r
649  * @param $text\r
650  *              text to be highlighted\r
651  * @param $expression\r
652  *              regular expression to be matched (can be an array of expressions as well)\r
653  * @param $highlight\r
654  *              highlight to be used (use \\0 to indicate the matched expression)\r
655  *\r
656  */\r
657 function highlight($text, $expression, $highlight) {\r
658         if (!$highlight || !$expression) {\r
659                 return $text;\r
660         }\r
661 \r
662         if (is_array($expression) && (count($expression) == 0) ) {\r
663                 return $text;\r
664         }\r
665 \r
666         // add a tag in front (is needed for preg_match_all to work correct)\r
667         $text = '<!--h-->' . $text;\r
668 \r
669         // split the HTML up so we have HTML tags\r
670         // $matches[0][i] = HTML + text\r
671         // $matches[1][i] = HTML\r
672         // $matches[2][i] = text\r
673         preg_match_all('/(<[^>]+>)([^<>]*)/', $text, $matches);\r
674 \r
675         // throw it all together again while applying the highlight to the text pieces\r
676         $result = '';\r
677         for ($i = 0; $i < sizeof($matches[2]); $i++) {\r
678                 if ($i != 0) {\r
679                         $result .= $matches[1][$i];\r
680                 }\r
681 \r
682                 if (is_array($expression) ) {\r
683                         foreach ($expression as $regex) {\r
684                                 if ($regex) {\r
685                                         $matches[2][$i] = @eregi_replace($regex, $highlight, $matches[2][$i]);\r
686                                 }\r
687                         }\r
688 \r
689                         $result .= $matches[2][$i];\r
690                 } else {\r
691                         $result .= @eregi_replace($expression, $highlight, $matches[2][$i]);\r
692                 }\r
693         }\r
694 \r
695         return $result;\r
696 }\r
697 \r
698 /**\r
699  * Parses a query into an array of expressions that can be passed on to the highlight method\r
700  */\r
701 function parseHighlight($query) {\r
702         // TODO: add more intelligent splitting logic\r
703 \r
704         // get rid of quotes\r
705         $query = preg_replace('/\'|"/', '', $query);\r
706 \r
707         if (!query) {\r
708                 return array();\r
709         }\r
710 \r
711         $aHighlight = explode(' ', $query);\r
712 \r
713         for ($i = 0; $i < count($aHighlight); $i++) {\r
714                 $aHighlight[$i] = trim($aHighlight[$i]);\r
715 \r
716                 if (strlen($aHighlight[$i]) < 3) {\r
717                         unset($aHighlight[$i]);\r
718                 }\r
719         }\r
720 \r
721         if (count($aHighlight) == 1) {\r
722                 return $aHighlight[0];\r
723         } else {\r
724                 return $aHighlight;\r
725         }\r
726 }\r
727 \r
728 /**\r
729   * Checks if email address is valid\r
730   */\r
731 function isValidMailAddress($address) {\r
732         if (preg_match('/^[a-zA-Z+0-9\._-]+@[a-zA-Z0-9\._-]+\.[A-Za-z]{2,5}$/', $address)) {\r
733                 return 1;\r
734         } else {\r
735                 return 0;\r
736         }\r
737 }\r
738 \r
739 \r
740 // some helper functions\r
741 function getBlogIDFromName($name) {\r
742         return quickQuery('SELECT bnumber as result FROM ' . sql_table('blog') . ' WHERE bshortname="' . addslashes($name) . '"');\r
743 }\r
744 \r
745 function getBlogNameFromID($id) {\r
746         return quickQuery('SELECT bname as result FROM ' . sql_table('blog') . ' WHERE bnumber=' . intval($id) );\r
747 }\r
748 \r
749 function getBlogIDFromItemID($itemid) {\r
750         return quickQuery('SELECT iblog as result FROM ' . sql_table('item') . ' WHERE inumber=' . intval($itemid) );\r
751 }\r
752 \r
753 function getBlogIDFromCommentID($commentid) {\r
754         return quickQuery('SELECT cblog as result FROM ' . sql_table('comment') . ' WHERE cnumber=' . intval($commentid) );\r
755 }\r
756 \r
757 function getBlogIDFromCatID($catid) {\r
758         return quickQuery('SELECT cblog as result FROM ' . sql_table('category') . ' WHERE catid=' . intval($catid) );\r
759 }\r
760 \r
761 function getCatIDFromName($name) {\r
762         return quickQuery('SELECT catid as result FROM ' . sql_table('category') . ' WHERE cname="' . addslashes($name) . '"');\r
763 }\r
764 \r
765 function quickQuery($q) {\r
766         $res = sql_query($q);\r
767         $obj = mysql_fetch_object($res);\r
768         return $obj->result;\r
769 }\r
770 \r
771 function getPluginNameFromPid($pid) {\r
772         $res = sql_query('SELECT pfile FROM ' . sql_table('plugin') . ' WHERE pid=' . intval($pid) );\r
773         $obj = mysql_fetch_object($res);\r
774         return $obj->pfile;\r
775 }\r
776 \r
777 function selector() {\r
778         global $itemid, $blogid, $memberid, $query, $amount, $archivelist, $maxresults;\r
779         global $archive, $skinid, $blog, $memberinfo, $CONF, $member;\r
780         global $imagepopup, $catid;\r
781         global $manager;\r
782 \r
783         $actionNames = array('addcomment', 'sendmessage', 'createaccount', 'forgotpassword', 'votepositive', 'votenegative', 'plugin');\r
784         $action = requestVar('action');\r
785 \r
786         if (in_array($action, $actionNames) ) {\r
787                 global $DIR_LIBS, $errormessage;\r
788                 include_once($DIR_LIBS . 'ACTION.php');\r
789                 $a = new ACTION();\r
790                 $errorInfo = $a->doAction($action);\r
791 \r
792                 if ($errorInfo) {\r
793                         $errormessage = $errorInfo['message'];\r
794                 }\r
795         }\r
796 \r
797         // show error when headers already sent out\r
798         if (headers_sent() && $CONF['alertOnHeadersSent']) {\r
799 \r
800                 // try to get line number/filename (extra headers_sent params only exists in PHP 4.3+)\r
801                 if (function_exists('version_compare') && version_compare('4.3.0', phpversion(), '<=') ) {\r
802                         headers_sent($hsFile, $hsLine);\r
803                         $extraInfo = ' in <code>' . $hsFile . '</code> line <code>' . $hsLine . '</code>';\r
804                 } else {\r
805                         $extraInfo = '';\r
806                 }\r
807 \r
808                 startUpError(\r
809                         '<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
810                         'Page headers already sent'\r
811                 );\r
812                 exit;\r
813         }\r
814 \r
815         // make is so ?archivelist without blogname or blogid shows the archivelist\r
816         // for the default weblog\r
817         if (serverVar('QUERY_STRING') == 'archivelist') {\r
818                 $archivelist = $CONF['DefaultBlog'];\r
819         }\r
820 \r
821         // now decide which type of skin we need\r
822         if ($itemid) {\r
823                 // itemid given -> only show that item\r
824                 $type = 'item';\r
825 \r
826                 if (!$manager->existsItem($itemid,0,0) ) {\r
827                         doError(_ERROR_NOSUCHITEM);\r
828                 }\r
829 \r
830                 global $itemidprev, $itemidnext, $catid, $itemtitlenext, $itemtitleprev;\r
831 \r
832                 // 1. get timestamp, blogid and catid for item\r
833                 $query = 'SELECT itime, iblog, icat FROM ' . sql_table('item') . ' WHERE inumber=' . intval($itemid);\r
834                 $res = sql_query($query);\r
835                 $obj = mysql_fetch_object($res);\r
836 \r
837                 // if a different blog id has been set through the request or selectBlog(),\r
838                 // deny access\r
839 //              if ($blogid && (intval($blogid) != $obj->iblog) ) {\r
840 //                      doError(_ERROR_NOSUCHITEM);\r
841 //              }\r
842                 if ($blogid && (intval($blogid) != $obj->iblog) ) {\r
843                         if (!headers_sent()) {\r
844                                 $b =& $manager->getBlog($obj->iblog);\r
845                                 $CONF['ItemURL'] = $b->getURL();\r
846                                 if ($CONF['URLMode'] == 'pathinfo' and substr($CONF['ItemURL'],-1) == '/')\r
847                                         $CONF['ItemURL'] = substr($CONF['ItemURL'], 0, -1);\r
848                                 $correctURL = createItemLink($itemid, '');\r
849                                 redirect($correctURL);\r
850                                 exit;\r
851                         } else {\r
852                                 doError(_ERROR_NOSUCHITEM);\r
853                         }\r
854                 }\r
855 \r
856                 // if a category has been selected which doesn't match the item, ignore the\r
857                 // category. #85\r
858                 if (($catid != 0) && ($catid != $obj->icat) ) {\r
859                         $catid = 0;\r
860                 }\r
861 \r
862                 $blogid = $obj->iblog;\r
863                 $timestamp = strtotime($obj->itime);\r
864 \r
865                 $b =& $manager->getBlog($blogid);\r
866 \r
867                 if ($b->isValidCategory($catid) ) {\r
868                         $catextra = ' and icat=' . $catid;\r
869                 } else {\r
870                         $catextra = '';\r
871                 }\r
872 \r
873                 // get previous itemid and title\r
874                 $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
875                 $res = sql_query($query);\r
876 \r
877                 $obj = mysql_fetch_object($res);\r
878 \r
879                 if ($obj) {\r
880                         $itemidprev = $obj->inumber;\r
881                         $itemtitleprev = $obj->ititle;\r
882                 }\r
883 \r
884                 // get next itemid and title\r
885                 $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
886                 $res = sql_query($query);\r
887 \r
888                 $obj = mysql_fetch_object($res);\r
889 \r
890                 if ($obj) {\r
891                         $itemidnext = $obj->inumber;\r
892                         $itemtitlenext = $obj->ititle;\r
893                 }\r
894 \r
895         } elseif ($archive) {\r
896                 // show archive\r
897                 $type = 'archive';\r
898 \r
899                 // get next and prev month links ...\r
900                 global $archivenext, $archiveprev, $archivetype, $archivenextexists, $archiveprevexists;\r
901 \r
902                 // sql queries for the timestamp of the first and the last published item\r
903                 $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
904                 $first_timestamp=quickQuery ($query);\r
905                 $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
906                 $last_timestamp=quickQuery ($query);\r
907 \r
908                 sscanf($archive, '%d-%d-%d', $y, $m, $d);\r
909 \r
910                 if ($d != 0) {\r
911                         $archivetype = _ARCHIVETYPE_DAY;\r
912                         $t = mktime(0, 0, 0, $m, $d, $y);\r
913                         // one day has 24 * 60 * 60 = 86400 seconds\r
914                         $archiveprev = strftime('%Y-%m-%d', $t - 86400 );\r
915                         // check for published items\r
916                         if ($t > $first_timestamp) {\r
917                                 $archiveprevexists = true;\r
918                         }\r
919                         else {\r
920                                 $archiveprevexists = false;\r
921                         }\r
922 \r
923                         // one day later\r
924                         $t += 86400;\r
925                         $archivenext = strftime('%Y-%m-%d', $t);\r
926                         if ($t < $last_timestamp) {\r
927                                 $archivenextexists = true;\r
928                         }\r
929                         else {\r
930                                 $archivenextexists = false;\r
931                         }\r
932 \r
933                 } else {\r
934                         $archivetype = _ARCHIVETYPE_MONTH;\r
935                         $t = mktime(0, 0, 0, $m, 1, $y);\r
936                         // one day before is in the previous month\r
937                         $archiveprev = strftime('%Y-%m', $t - 86400);\r
938                         if ($t > $first_timestamp) {\r
939                                 $archiveprevexists = true;\r
940                         }\r
941                         else {\r
942                                 $archiveprevexists = false;\r
943                         }\r
944 \r
945                         // timestamp for the next month\r
946                         $t = mktime(0, 0, 0, $m+1, 1, $y);\r
947                         $archivenext = strftime('%Y-%m', $t);\r
948                         if ($t < $last_timestamp) {\r
949                                 $archivenextexists = true;\r
950                         }\r
951                         else {\r
952                                 $archivenextexists = false;\r
953                         }\r
954                 }\r
955 \r
956         } elseif ($archivelist) {\r
957                 $type = 'archivelist';\r
958 \r
959                 if (is_numeric($archivelist)) {\r
960                         $blogid = intVal($archivelist);\r
961                 } else {\r
962                         $blogid = getBlogIDFromName($archivelist);\r
963                 }\r
964 \r
965                 if (!$blogid) {\r
966                         doError(_ERROR_NOSUCHBLOG);\r
967                 }\r
968 \r
969         } elseif ($query) {\r
970                 global $startpos;\r
971                 $type = 'search';\r
972                 $query = stripslashes($query);\r
973                 if(preg_match("/^(\xA1{2}|\xe3\x80{2}|\x20)+$/", $query)){\r
974                                         $type = 'index';\r
975                 }\r
976                 $order = (_CHARSET == 'EUC-JP') ? 'EUC-JP, UTF-8,' : 'UTF-8, EUC-JP,';\r
977                 $query = mb_convert_encoding($query, _CHARSET, $order . ' JIS, SJIS, ASCII');\r
978                 if (is_numeric($blogid)) {\r
979                         $blogid = intVal($blogid);\r
980                 } else {\r
981                         $blogid = getBlogIDFromName($blogid);\r
982                 }\r
983 \r
984                 if (!$blogid) {\r
985                         doError(_ERROR_NOSUCHBLOG);\r
986                 }\r
987 \r
988         } elseif ($memberid) {\r
989                 $type = 'member';\r
990 \r
991                 if (!MEMBER::existsID($memberid) ) {\r
992                         doError(_ERROR_NOSUCHMEMBER);\r
993                 }\r
994 \r
995                 $memberinfo = $manager->getMember($memberid);\r
996 \r
997         } elseif ($imagepopup) {\r
998                 // media object (images etc.)\r
999                 $type = 'imagepopup';\r
1000 \r
1001                 // TODO: check if media-object exists\r
1002                 // TODO: set some vars?\r
1003         } else {\r
1004                 // show regular index page\r
1005                 global $startpos;\r
1006                 $type = 'index';\r
1007         }\r
1008 \r
1009         // decide which blog should be displayed\r
1010         if (!$blogid) {\r
1011                 $blogid = $CONF['DefaultBlog'];\r
1012         }\r
1013 \r
1014         $b =& $manager->getBlog($blogid);\r
1015         $blog = $b;     // references can't be placed in global variables?\r
1016 \r
1017         if (!$blog->isValid) {\r
1018                 doError(_ERROR_NOSUCHBLOG);\r
1019         }\r
1020 \r
1021         // set catid if necessary\r
1022         if ($catid) {\r
1023                 $blog->setSelectedCategory($catid);\r
1024         }\r
1025 \r
1026         // decide which skin should be used\r
1027         if ($skinid != '' && ($skinid == 0) ) {\r
1028                 selectSkin($skinid);\r
1029         }\r
1030 \r
1031         if (!$skinid) {\r
1032                 $skinid = $blog->getDefaultSkin();\r
1033         }\r
1034 \r
1035         $special = requestVar('special');\r
1036         if (!empty($special) && isValidShortName($special)) {\r
1037                 $type = strtolower($special);\r
1038         }\r
1039 \r
1040         $skin = new SKIN($skinid);\r
1041 \r
1042         if (!$skin->isValid) {\r
1043                 doError(_ERROR_NOSUCHSKIN);\r
1044         }\r
1045 \r
1046         // parse the skin\r
1047         $skin->parse($type);\r
1048 \r
1049         // check to see we should throw JustPosted event\r
1050         $blog->checkJustPosted();\r
1051 }\r
1052 \r
1053 /**\r
1054   * Show error skin with given message. An optional skin-object to use can be given\r
1055   */\r
1056 function doError($msg, $skin = '') {\r
1057         global $errormessage, $CONF, $skinid, $blogid, $manager;\r
1058 \r
1059         if ($skin == '') {\r
1060 \r
1061                 if (SKIN::existsID($skinid) ) {\r
1062                         $skin = new SKIN($skinid);\r
1063                 } elseif ($manager->existsBlogID($blogid) ) {\r
1064                         $blog =& $manager->getBlog($blogid);\r
1065                         $skin = new SKIN($blog->getDefaultSkin() );\r
1066                 } elseif ($CONF['DefaultBlog']) {\r
1067                         $blog =& $manager->getBlog($CONF['DefaultBlog']);\r
1068                         $skin = new SKIN($blog->getDefaultSkin() );\r
1069                 } else {\r
1070                         // this statement should actually never be executed\r
1071                         $skin = new SKIN($CONF['BaseSkin']);\r
1072                 }\r
1073 \r
1074         }\r
1075 \r
1076         $errormessage = $msg;\r
1077         $skin->parse('error');\r
1078         exit;\r
1079 }\r
1080 \r
1081 function getConfig() {\r
1082         global $CONF;\r
1083 \r
1084         $query = 'SELECT * FROM ' . sql_table('config');\r
1085         $res = sql_query($query);\r
1086 \r
1087         while ($obj = mysql_fetch_object($res) ) {\r
1088                 $CONF[$obj->name] = $obj->value;\r
1089         }\r
1090 }\r
1091 \r
1092 // some checks for names of blogs, categories, templates, members, ...\r
1093 function isValidShortName($name) {\r
1094         return eregi('^[a-z0-9]+$', $name);\r
1095 }\r
1096 \r
1097 function isValidDisplayName($name) {\r
1098         return eregi('^[a-z0-9]+[a-z0-9 ]*[a-z0-9]+$', $name);\r
1099 }\r
1100 \r
1101 function isValidCategoryName($name) {\r
1102         return 1;\r
1103 }\r
1104 \r
1105 function isValidTemplateName($name) {\r
1106         return eregi('^[a-z0-9/]+$', $name);\r
1107 }\r
1108 \r
1109 function isValidSkinName($name) {\r
1110         return eregi('^[a-z0-9/]+$', $name);\r
1111 }\r
1112 \r
1113 // add and remove linebreaks\r
1114 function addBreaks($var) {\r
1115         return nl2br($var);\r
1116 }\r
1117 \r
1118 function removeBreaks($var) {\r
1119         return preg_replace("/<br \/>([\r\n])/", "$1", $var);\r
1120 }\r
1121 \r
1122 // shortens a text string to maxlength ($toadd) is what needs to be added\r
1123 // at the end (end length is <= $maxlength)\r
1124 function shorten($text, $maxlength, $toadd) {\r
1125         // 1. remove entities...\r
1126 //      $trans = get_html_translation_table(HTML_ENTITIES);\r
1127         $trans = get_html_translation_table(HTML_SPECIALCHARS); // for Japanese\r
1128         $trans = array_flip($trans);\r
1129         $text  = strtr($text, $trans);\r
1130 \r
1131         // 2. the actual shortening\r
1132         if (strlen($text) > $maxlength) {\r
1133 //              $text = substr($text, 0, $maxlength - strlen($toadd) ) . $toadd;\r
1134                 $text = mb_strimwidth($text, 0, $maxlength, $toadd, _CHARSET); // for Japanese\r
1135         }\r
1136         return $text;\r
1137 }\r
1138 \r
1139 /**\r
1140   * Converts a unix timestamp to a mysql DATETIME format, and places\r
1141   * quotes around it.\r
1142   */\r
1143 function mysqldate($timestamp) {\r
1144         return '"' . date('Y-m-d H:i:s', $timestamp) . '"';\r
1145 }\r
1146 \r
1147 /**\r
1148   * functions for use in index.php\r
1149   */\r
1150 function selectBlog($shortname) {\r
1151         global $blogid, $archivelist;\r
1152         $blogid = getBlogIDFromName($shortname);\r
1153 \r
1154         // also force archivelist variable, if it is set\r
1155         if ($archivelist) {\r
1156                 $archivelist = $blogid;\r
1157         }\r
1158 }\r
1159 \r
1160 function selectSkin($skinname) {\r
1161         global $skinid;\r
1162         $skinid = SKIN::getIdFromName($skinname);\r
1163 }\r
1164 \r
1165 /**\r
1166  * Can take either a category ID or a category name (be aware that\r
1167  * multiple categories can have the same name)\r
1168  */\r
1169 function selectCategory($cat) {\r
1170         global $catid;\r
1171         if (is_numeric($cat) ) {\r
1172                 $catid = intval($cat);\r
1173         } else {\r
1174                 $catid = getCatIDFromName($cat);\r
1175         }\r
1176 }\r
1177 \r
1178 function selectItem($id) {\r
1179         global $itemid;\r
1180         $itemid = intval($id);\r
1181 }\r
1182 \r
1183 // force the use of a language file (warning: can cause warnings)\r
1184 function selectLanguage($language) {\r
1185         global $DIR_LANG;\r
1186         include($DIR_LANG . ereg_replace( '[\\|/]', '', $language) . '.php');\r
1187 }\r
1188 \r
1189 function parseFile($filename, $includeMode = 'normal', $includePrefix = '') {\r
1190         $handler = new ACTIONS('fileparser');\r
1191         $parser = new PARSER(SKIN::getAllowedActionsForType('fileparser'), $handler);\r
1192         $handler->parser =& $parser;\r
1193 \r
1194         // set IncludeMode properties of parser\r
1195         PARSER::setProperty('IncludeMode', $includeMode);\r
1196         PARSER::setProperty('IncludePrefix', $includePrefix);\r
1197 \r
1198         if (!file_exists($filename) ) {\r
1199                 doError('A file is missing');\r
1200         }\r
1201 \r
1202         $fsize = filesize($filename);\r
1203 \r
1204         if ($fsize <= 0) {\r
1205                 return;\r
1206         }\r
1207 \r
1208         // read file\r
1209         $fd = fopen ($filename, 'r');\r
1210         $contents = fread ($fd, $fsize);\r
1211         fclose ($fd);\r
1212 \r
1213         // parse file contents\r
1214         $parser->parse($contents);\r
1215 }\r
1216 \r
1217 /**\r
1218   * Outputs a debug message\r
1219   */\r
1220 function debug($msg) {\r
1221         echo '<p><b>' . $msg . "</b></p>\n";\r
1222 }\r
1223 \r
1224 // shortcut\r
1225 function addToLog($level, $msg) {\r
1226         ACTIONLOG::add($level, $msg);\r
1227 }\r
1228 \r
1229 // shows a link to help file\r
1230 function help($id) {\r
1231         echo helpHtml($id);\r
1232 }\r
1233 \r
1234 function helpHtml($id) {\r
1235         global $CONF;\r
1236         return helplink($id) . '<img src="' . $CONF['AdminURL'] . 'documentation/icon-help.gif" width="15" height="15" alt="' . _HELP_TT . '" title="' . _HELP_TT . '" /></a>';\r
1237 }\r
1238 \r
1239 function helplink($id) {\r
1240         global $CONF;\r
1241         return '<a href="' . $CONF['AdminURL'] . 'documentation/help.html#'. $id . '" onclick="if (event &amp;&amp; event.preventDefault) event.preventDefault(); return help(this.href);">';\r
1242 }\r
1243 \r
1244 function getMailFooter() {\r
1245         $message = "\n\n-----------------------------";\r
1246         $message .=  "\n   Powered by Nucleus CMS";\r
1247         $message .=  "\n(http://www.nucleuscms.org/)";\r
1248         return $message;\r
1249 }\r
1250 \r
1251 /**\r
1252   * Returns the name of the language to use\r
1253   * preference priority: member - site\r
1254   * defaults to english when no good language found\r
1255   *\r
1256   * checks if file exists, etc...\r
1257   */\r
1258 function getLanguageName() {\r
1259         global $CONF, $member;\r
1260 \r
1261         if ($member && $member->isLoggedIn() ) {\r
1262                 // try to use members language\r
1263                 $memlang = $member->getLanguage();\r
1264 \r
1265                 if (($memlang != '') && (checkLanguage($memlang) ) ) {\r
1266                         return $memlang;\r
1267                 }\r
1268         }\r
1269 \r
1270         // use default language\r
1271         if (checkLanguage($CONF['Language']) ) {\r
1272                 return $CONF['Language'];\r
1273         } else {\r
1274                 return 'english';\r
1275         }\r
1276 }\r
1277 \r
1278 /**\r
1279   * Includes a PHP file. This method can be called while parsing templates and skins\r
1280   */\r
1281 function includephp($filename) {\r
1282         // make predefined variables global, so most simple scripts can be used here\r
1283 \r
1284         // apache (names taken from PHP doc)\r
1285         global $GATEWAY_INTERFACE, $SERVER_NAME, $SERVER_SOFTWARE, $SERVER_PROTOCOL;\r
1286         global $REQUEST_METHOD, $QUERY_STRING, $DOCUMENT_ROOT, $HTTP_ACCEPT;\r
1287         global $HTTP_ACCEPT_CHARSET, $HTTP_ACCEPT_ENCODING, $HTTP_ACCEPT_LANGUAGE;\r
1288         global $HTTP_CONNECTION, $HTTP_HOST, $HTTP_REFERER, $HTTP_USER_AGENT;\r
1289         global $REMOTE_ADDR, $REMOTE_PORT, $SCRIPT_FILENAME, $SERVER_ADMIN;\r
1290         global $SERVER_PORT, $SERVER_SIGNATURE, $PATH_TRANSLATED, $SCRIPT_NAME;\r
1291         global $REQUEST_URI;\r
1292 \r
1293         // php (taken from PHP doc)\r
1294         global $argv, $argc, $PHP_SELF, $HTTP_COOKIE_VARS, $HTTP_GET_VARS, $HTTP_POST_VARS;\r
1295         global $HTTP_POST_FILES, $HTTP_ENV_VARS, $HTTP_SERVER_VARS, $HTTP_SESSION_VARS;\r
1296 \r
1297         // other\r
1298         global $PATH_INFO, $HTTPS, $HTTP_RAW_POST_DATA, $HTTP_X_FORWARDED_FOR;\r
1299 \r
1300         if (@file_exists($filename) ) {\r
1301                 include($filename);\r
1302         }\r
1303 }\r
1304 \r
1305 /**\r
1306   * Checks if a certain language/plugin exists\r
1307   */\r
1308 function checkLanguage($lang) {\r
1309         global $DIR_LANG ;\r
1310         return file_exists($DIR_LANG . ereg_replace( '[\\|/]', '', $lang) . '.php');\r
1311 }\r
1312 \r
1313 function checkPlugin($plug) {\r
1314         global $DIR_PLUGINS;\r
1315         return file_exists($DIR_PLUGINS . ereg_replace( '[\\|/]', '', $plug) . '.php');\r
1316 }\r
1317 \r
1318 /**\r
1319   * Centralisation of the functions that generate links\r
1320   */\r
1321 function createItemLink($itemid, $extra = '') {\r
1322         return createLink('item', array('itemid' => $itemid, 'extra' => $extra) );\r
1323 }\r
1324 \r
1325 function createMemberLink($memberid, $extra = '') {\r
1326         return createLink('member', array('memberid' => $memberid, 'extra' => $extra) );\r
1327 }\r
1328 \r
1329 function createCategoryLink($catid, $extra = '') {\r
1330         return createLink('category', array('catid' => $catid, 'extra' => $extra) );\r
1331 }\r
1332 \r
1333 function createArchiveListLink($blogid = '', $extra = '') {\r
1334         return createLink('archivelist', array('blogid' => $blogid, 'extra' => $extra) );\r
1335 }\r
1336 \r
1337 function createArchiveLink($blogid, $archive, $extra = '') {\r
1338         return createLink('archive', array('blogid' => $blogid, 'archive' => $archive, 'extra' => $extra) );\r
1339 }\r
1340 \r
1341 function createBlogidLink($blogid, $params = '') {\r
1342         return createLink('blog', array('blogid' => $blogid, 'extra' => $params) );\r
1343 }\r
1344 \r
1345 function createLink($type, $params) {\r
1346         global $manager, $CONF;\r
1347 \r
1348         $generatedURL = '';\r
1349         $usePathInfo = ($CONF['URLMode'] == 'pathinfo');\r
1350 \r
1351         // ask plugins first\r
1352         $created = false;\r
1353 \r
1354         if ($usePathInfo) {\r
1355                 $manager->notify(\r
1356                         'GenerateURL',\r
1357                         array(\r
1358                                 'type' => $type,\r
1359                                 'params' => $params,\r
1360                                 'completed' => &$created,\r
1361                                 'url' => &$url\r
1362                         )\r
1363                 );\r
1364         }\r
1365 \r
1366         // if a plugin created the URL, return it\r
1367         if ($created) {\r
1368                 return $url;\r
1369         }\r
1370 \r
1371         // default implementation\r
1372         switch ($type) {\r
1373                 case 'item':\r
1374                         if ($usePathInfo) {\r
1375                                 $url = $CONF['ItemURL'] . '/' . $CONF['ItemKey'] . '/' . $params['itemid'];\r
1376                         } else {\r
1377                                 $url = $CONF['ItemURL'] . '?itemid=' . $params['itemid'];\r
1378                         }\r
1379                         break;\r
1380 \r
1381                 case 'member':\r
1382                         if ($usePathInfo) {\r
1383                                 $url = $CONF['MemberURL'] . '/' . $CONF['MemberKey'] . '/' . $params['memberid'];\r
1384                         } else {\r
1385                                 $url = $CONF['MemberURL'] . '?memberid=' . $params['memberid'];\r
1386                         }\r
1387                         break;\r
1388 \r
1389                 case 'category':\r
1390                         if ($usePathInfo) {\r
1391                                 $url = $CONF['CategoryURL'] . '/' . $CONF['CategoryKey'] . '/' . $params['catid'];\r
1392                         } else {\r
1393                                 $url = $CONF['CategoryURL'] . '?catid=' . $params['catid'];\r
1394                         }\r
1395                         break;\r
1396 \r
1397                 case 'archivelist':\r
1398                         if (!$params['blogid']) {\r
1399                                 $params['blogid'] = $CONF['DefaultBlog'];\r
1400                         }\r
1401 \r
1402                         if ($usePathInfo) {\r
1403                                 $url = $CONF['ArchiveListURL'] . '/' . $CONF['ArchivesKey'] . '/' . $params['blogid'];\r
1404                         } else {\r
1405                                 $url = $CONF['ArchiveListURL'] . '?archivelist=' . $params['blogid'];\r
1406                         }\r
1407                         break;\r
1408 \r
1409                 case 'archive':\r
1410                         if ($usePathInfo) {\r
1411                                 $url = $CONF['ArchiveURL'] . '/' . $CONF['ArchiveKey'] . '/'.$params['blogid'].'/' . $params['archive'];\r
1412                         } else {\r
1413                                 $url = $CONF['ArchiveURL'] . '?blogid='.$params['blogid'].'&amp;archive=' . $params['archive'];\r
1414                         }\r
1415                         break;\r
1416 \r
1417                 case 'blog':\r
1418                         if ($usePathInfo) {\r
1419                                 $url = $CONF['BlogURL'] . '/' . $CONF['BlogKey'] . '/' . $params['blogid'];\r
1420                         } else {\r
1421                                 $url = $CONF['BlogURL'] . '?blogid=' . $params['blogid'];\r
1422                         }\r
1423                         break;\r
1424         }\r
1425 \r
1426         return addLinkParams($url, (isset($params['extra'])? $params['extra'] : null));\r
1427 }\r
1428 \r
1429 function createBlogLink($url, $params) {\r
1430     global $CONF;\r
1431     if ($CONF['URLMode'] == 'normal') {\r
1432         if (strpos($url, '?') === FALSE && is_array($params)) {\r
1433             $fParam = reset($params);\r
1434             $fKey   = key($params);\r
1435             array_shift($params);\r
1436             $url .= '?' . $fKey . '=' . $fParam;\r
1437         }\r
1438     } elseif ($CONF['URLMode'] == 'pathinfo' && substr($url, -1) == '/') {\r
1439         $url = substr($url, 0, -1);\r
1440     }\r
1441         return addLinkParams($url, $params);\r
1442 }\r
1443 \r
1444 function addLinkParams($link, $params) {\r
1445         global $CONF;\r
1446 \r
1447         if (is_array($params) ) {\r
1448 \r
1449                 if ($CONF['URLMode'] == 'pathinfo')     {\r
1450 \r
1451                         foreach ($params as $param => $value) {\r
1452                                 $link .= '/' . $param . '/' . urlencode($value);\r
1453                         }\r
1454 \r
1455                 } else {\r
1456 \r
1457                         foreach ($params as $param => $value) {\r
1458                                 $link .= '&amp;' . $param . '=' . urlencode($value);\r
1459                         }\r
1460 \r
1461                 }\r
1462         }\r
1463 \r
1464         return $link;\r
1465 }\r
1466 \r
1467 /**\r
1468  * @param $querystr\r
1469  *              querystring to alter (e.g. foo=1&bar=2&x=y)\r
1470  * @param $param\r
1471  *              name of parameter to change (e.g. 'foo')\r
1472  * @param $value\r
1473  *              New value for that parameter (e.g. 3)\r
1474  * @result\r
1475  *              altered query string (for the examples above: foo=3&bar=2&x=y)\r
1476  */\r
1477 function alterQueryStr($querystr, $param, $value) {\r
1478         $vars = explode('&', $querystr);\r
1479         $set  = false;\r
1480 \r
1481         for ($i = 0; $i < count($vars); $i++) {\r
1482                 $v = explode('=', $vars[$i]);\r
1483 \r
1484                 if ($v[0] == $param) {\r
1485                         $v[1] = $value;\r
1486                         $vars[$i] = implode('=', $v);\r
1487                         $set = true;\r
1488                         break;\r
1489                 }\r
1490         }\r
1491 \r
1492         if (!$set) {\r
1493                 $vars[] = $param . '=' . $value;\r
1494         }\r
1495 \r
1496         return ltrim(implode('&', $vars), '&');\r
1497 }\r
1498 \r
1499 // passes one variable as hidden input field (multiple fields for arrays)\r
1500 // @see passRequestVars in varsx.x.x.php\r
1501 function passVar($key, $value) {\r
1502         // array ?\r
1503         if (is_array($value) ) {\r
1504                 for ($i = 0; $i < sizeof($value); $i++) {\r
1505                         passVar($key . '[' . $i . ']', $value[$i]);\r
1506                 }\r
1507 \r
1508                 return;\r
1509         }\r
1510 \r
1511         // other values: do stripslashes if needed\r
1512         ?><input type="hidden" name="<?php echo htmlspecialchars($key)?>" value="<?php echo htmlspecialchars(undoMagic($value) )?>" /><?php\r
1513 }\r
1514 \r
1515 /*\r
1516         Date format functions (to be used from [%date(..)%] skinvars\r
1517 */\r
1518 function formatDate($format, $timestamp, $defaultFormat, &$blog) {\r
1519         // apply blog offset (#42)\r
1520         $boffset = $blog ? $blog->getTimeOffset() * 3600 : 0;\r
1521         $offset = date('Z', $timestamp) + $boffset;\r
1522 \r
1523         switch ($format) {\r
1524                 case 'rfc822':\r
1525                         if ($offset >= 0) {\r
1526                                 $tz = '+';\r
1527                         } else {\r
1528                                 $tz = '-';\r
1529                                 $offset = -$offset;\r
1530                         }\r
1531 \r
1532                         $tz .= sprintf("%02d%02d", floor($offset / 3600), round(($offset % 3600) / 60) );\r
1533                         return date('D, j M Y H:i:s ', $timestamp) . $tz;\r
1534 \r
1535                 case 'rfc822GMT':\r
1536                         $timestamp -= $offset;\r
1537                         return date('D, j M Y H:i:s ', $timestamp) . 'GMT';\r
1538 \r
1539                 case 'utc':\r
1540                         $timestamp -= $offset;\r
1541                         return date('Y-m-d\TH:i:s\Z', $timestamp);\r
1542 \r
1543                 case 'iso8601':\r
1544                         if ($offset >= 0) {\r
1545                                 $tz = '+';\r
1546                         } else {\r
1547                                 $tz = '-';\r
1548                                 $offset = -$offset;\r
1549                         }\r
1550 \r
1551                         $tz .= sprintf("%02d:%02d", floor($offset / 3600), round(($offset % 3600) / 60) );\r
1552                         return date('Y-m-d\TH:i:s', $timestamp) . $tz;\r
1553 \r
1554                 default :\r
1555                         return strftime($format ? $format : $defaultFormat, $timestamp);\r
1556         }\r
1557 }\r
1558 \r
1559 function encoding_check($val, $key, $encoding=false, $exclude=false) {\r
1560         /*\r
1561           Set $CONF['DisableEncodingCheck']=1 only for special occasion, e.g. install script.\r
1562           Don't set this permanently in nucleus_config table.\r
1563         */\r
1564         global $CONF;\r
1565 //      if (!empty($CONF['DisableEncodingCheck'])) return true;\r
1566         /*\r
1567           When 3rd argument is set, return if checked already.\r
1568           When 4th argument is set, set the excluded key(s).\r
1569         */\r
1570         static $search=false, $checked=array(), $excludes=array();\r
1571         if ($exclude!==false) {\r
1572                 if (is_array($exclude)) {\r
1573                         foreach($exclude as $v) $excludes[$v]=true;\r
1574                 } else $excludes[$exclude]=true;\r
1575                 return;\r
1576         }\r
1577         if ($encoding!==false) {\r
1578                 switch($encoding=strtolower($encoding)){\r
1579                         case 'utf-8':\r
1580                                 $search='/([\x00-\x7F]+'.\r
1581                                         '|[\xC2-\xDF][\x80-\xBF]'.\r
1582                                         '|[\xE0-\xEF][\x80-\xBF][\x80-\xBF]'.\r
1583                                         '|[\xF0-\xF7][\x80-\xBF][\x80-\xBF][\x80-\xBF]'.\r
1584                                         '|[\xF8-\xFB][\x80-\xBF][\x80-\xBF][\x80-\xBF][\x80-\xBF]'.\r
1585                                         '|[\xFC-\xFD][\x80-\xBF][\x80-\xBF][\x80-\xBF][\x80-\xBF][\x80-\xBF])/';\r
1586                                         break;\r
1587                         case 'euc-jp':\r
1588                                 $search='/([\x00-\x7F]+'.\r
1589                                         '|[\x8E][\xA0-\xDF]'.\r
1590                                         '|[\x8F]?[\xA1-\xFE][\xA1-\xFE])/';\r
1591                                 break;\r
1592                         case 'gb2312':\r
1593                                 $search='/([\x00-\x7F]+'.\r
1594                                         '|[\xA1-\xF7][\xA1-\xFE])/';\r
1595                                 break;\r
1596                         case 'shift_jis':\r
1597                                 // Note that shift_jis is only supported for output.\r
1598                                 // Using shift_jis in DB is prohibited.\r
1599                                 $search='/([\x00-\x7F\xA1-\xDF]+'.\r
1600                                         '|[\x81-\x9F\xE0-\xFC][\x40-\xFC])/';\r
1601                                 break;\r
1602                         default:\r
1603                                 $search=false;\r
1604                                 if (preg_match('/^iso\-8859\-[0-9]{1,2}$/',$encoding)) break;\r
1605                                 if (preg_match('/^windows\-125[0-8]$/',$encoding)) break;\r
1606                                 startUpError('<p>Unknown or non-supported encoding.</p>', 'Encoding Error');\r
1607                                 exit;\r
1608                 }\r
1609                 if (isset($checked[$encoding])) return true; // Already checked.\r
1610                 $checked[$encoding]=true;\r
1611         }\r
1612         if ($key===false) return false; // Not yet checked.\r
1613         if ($search===false) return true; // non-multibyte encoding\r
1614         if (isset($excludes[$key])) return true; // This key isn't checked.\r
1615         if (is_array($val)) {\r
1616                 array_walk($val, 'encoding_check');\r
1617         } else {\r
1618                 $result=preg_replace($search,'',$val);\r
1619                 if (strlen($result)!=0) {\r
1620                         startUpError('<p>Invalid input.</p>', 'Input Error');\r
1621                         exit;\r
1622                 }\r
1623         }\r
1624         $result=preg_replace($search,'',$key);\r
1625         if (strlen($result)!=0) {\r
1626                 startUpError('<p>Invalid input.</p>', 'Input Error');\r
1627                 exit;\r
1628         }\r
1629         return true;\r
1630 }\r
1631 \r
1632 function checkVars($aVars) {\r
1633         global $HTTP_GET_VARS, $HTTP_POST_VARS, $HTTP_COOKIE_VARS, $HTTP_ENV_VARS, $HTTP_POST_FILES, $HTTP_SESSION_VARS;\r
1634 \r
1635         foreach ($aVars as $varName) {\r
1636 \r
1637                 if (phpversion() >= '4.1.0') {\r
1638 \r
1639                         if (   isset($_GET[$varName])\r
1640                                 || isset($_POST[$varName])\r
1641                                 || isset($_COOKIE[$varName])\r
1642                                 || isset($_ENV[$varName])\r
1643                                 || isset($_SESSION[$varName])\r
1644                                 || isset($_FILES[$varName])\r
1645                         ) {\r
1646                                 die('Sorry. An error occurred.');\r
1647                         }\r
1648 \r
1649                 } else {\r
1650 \r
1651                         if (   isset($HTTP_GET_VARS[$varName])\r
1652                                 || isset($HTTP_POST_VARS[$varName])\r
1653                                 || isset($HTTP_COOKIE_VARS[$varName])\r
1654                                 || isset($HTTP_ENV_VARS[$varName])\r
1655                                 || isset($HTTP_SESSION_VARS[$varName])\r
1656                                 || isset($HTTP_POST_FILES[$varName])\r
1657                         ) {\r
1658                                 die('Sorry. An error occurred.');\r
1659                         }\r
1660 \r
1661                 }\r
1662         }\r
1663 }\r
1664 \r
1665 \r
1666 /**\r
1667  * Sanitize parameters such as $_GET and $_SERVER['REQUEST_URI'] etc.\r
1668  * to avoid XSS\r
1669  */\r
1670 function sanitizeParams()\r
1671 {\r
1672         global $HTTP_SERVER_VARS;\r
1673 \r
1674         $array = array();\r
1675         $str = '';\r
1676         $frontParam = '';\r
1677 \r
1678         // REQUEST_URI of $HTTP_SERVER_VARS\r
1679         $str =& $HTTP_SERVER_VARS["REQUEST_URI"];\r
1680         serverStringToArray($str, $array, $frontParam);\r
1681         sanitizeArray($array);\r
1682         arrayToServerString($array, $frontParam, $str);\r
1683 \r
1684         // QUERY_STRING of $HTTP_SERVER_VARS\r
1685         $str =& $HTTP_SERVER_VARS["QUERY_STRING"];\r
1686         serverStringToArray($str, $array, $frontParam);\r
1687         sanitizeArray($array);\r
1688         arrayToServerString($array, $frontParam, $str);\r
1689 \r
1690         if (phpversion() >= '4.1.0') {\r
1691                 // REQUEST_URI of $_SERVER\r
1692                 $str =& $_SERVER["REQUEST_URI"];\r
1693                 serverStringToArray($str, $array, $frontParam);\r
1694                 sanitizeArray($array);\r
1695                 arrayToServerString($array, $frontParam, $str);\r
1696 \r
1697                 // QUERY_STRING of $_SERVER\r
1698                 $str =& $_SERVER["QUERY_STRING"];\r
1699                 serverStringToArray($str, $array, $frontParam);\r
1700                 sanitizeArray($array);\r
1701                 arrayToServerString($array, $frontParam, $str);\r
1702         }\r
1703 \r
1704         // $_GET\r
1705         convArrayForSanitizing($_GET, $array);\r
1706         sanitizeArray($array);\r
1707         revertArrayForSanitizing($array, $_GET);\r
1708 \r
1709         // $_REQUEST (only GET param)\r
1710         convArrayForSanitizing($_REQUEST, $array);\r
1711         sanitizeArray($array);\r
1712         revertArrayForSanitizing($array, $_REQUEST);\r
1713 }\r
1714 \r
1715 /**\r
1716  * Check ticket when not checked in plugin's admin page\r
1717  * to avoid CSRF.\r
1718  * Also avoid the access to plugin/index.php by guest user.\r
1719  */\r
1720 function ticketForPlugin(){\r
1721         global $CONF,$DIR_PLUGINS,$member,$ticketforplugin;\r
1722 \r
1723         /* initialize */\r
1724         $ticketforplugin=array();\r
1725         $ticketforplugin['ticket']=false;\r
1726 \r
1727         /* Check if using plugin's php file. */\r
1728         if ($p_translated=serverVar('PATH_TRANSLATED')) {\r
1729                 if (!file_exists($p_translated)) $p_translated='';\r
1730         }\r
1731         if (!$p_translated) {\r
1732                 $p_translated=serverVar('SCRIPT_FILENAME');\r
1733                 if (!file_exists($p_translated)) {\r
1734                         header("HTTP/1.0 404 Not Found");\r
1735                         exit('');\r
1736                 }\r
1737         }\r
1738         $p_translated=str_replace('\\','/',$p_translated);\r
1739         $d_plugins=str_replace('\\','/',$DIR_PLUGINS);\r
1740         if (strpos($p_translated,$d_plugins)!==0) return;// This isn't plugin php file.\r
1741 \r
1742         /* Solve the plugin php file or admin directory */\r
1743         $phppath=substr($p_translated,strlen($d_plugins));\r
1744         $phppath=preg_replace('!^/!','',$phppath);// Remove the first "/" if exists.\r
1745         $path=preg_replace('/^NP_(.*)\.php$/','$1',$phppath); // Remove the first "NP_" and the last ".php" if exists.\r
1746         $path=preg_replace('!^([^/]*)/(.*)$!','$1',$path); // Remove the "/" and beyond.\r
1747 \r
1748         /* Solve the plugin name. */\r
1749         $plugins=array();\r
1750         $query='SELECT pfile FROM '.sql_table('plugin');\r
1751         $res=sql_query($query);\r
1752         while($row=mysql_fetch_row($res)) {\r
1753                 $name=substr($row[0],3);\r
1754                 $plugins[strtolower($name)]=$name;\r
1755         }\r
1756         mysql_free_result($res);\r
1757         if ($plugins[$path]) $plugin_name=$plugins[$path];\r
1758         else if (in_array($path,$plugins)) $plugin_name=$path;\r
1759         else {\r
1760                 header("HTTP/1.0 404 Not Found");\r
1761                 exit('');\r
1762         }\r
1763 \r
1764         /* Return if not index.php */\r
1765         if ( $phppath!=strtolower($plugin_name).'/'\r
1766                 && $phppath!=strtolower($plugin_name).'/index.php' ) return;\r
1767 \r
1768         /* Exit if not logged in. */\r
1769         if ( !$member->isLoggedIn() ) exit("You aren't logged in.");\r
1770 \r
1771         global $manager,$DIR_LIBS,$DIR_LANG,$HTTP_GET_VARS,$HTTP_POST_VARS;\r
1772 \r
1773         /* Check if this feature is needed (ie, if "$manager->checkTicket()" is not included in the script). */\r
1774         if (!($p_translated=serverVar('PATH_TRANSLATED'))) $p_translated=serverVar('SCRIPT_FILENAME');\r
1775         if ($file=@file($p_translated)) {\r
1776                 $prevline='';\r
1777                 foreach($file as $line) {\r
1778                         if (preg_match('/[\$]manager([\s]*)[\-]>([\s]*)checkTicket([\s]*)[\(]/i',$prevline.$line)) return;\r
1779                         $prevline=$line;\r
1780                 }\r
1781         }\r
1782 \r
1783         /* Show a form if not valid ticket */\r
1784         if ( ( strstr(serverVar('REQUEST_URI'),'?') || serverVar('QUERY_STRING')\r
1785                         || strtoupper(serverVar('REQUEST_METHOD'))=='POST' )\r
1786                                 && (!$manager->checkTicket()) ){\r
1787 \r
1788                 if (!class_exists('PluginAdmin')) {\r
1789                         $language = getLanguageName();\r
1790                         include($DIR_LANG . ereg_replace( '[\\|/]', '', $language) . '.php');\r
1791                         include($DIR_LIBS . 'PLUGINADMIN.php');\r
1792                 }\r
1793                 if (!(function_exists('mb_strimwidth') || extension_loaded('mbstring'))) {\r
1794                         if (file_exists($DIR_LIBS.'mb_emulator/mb-emulator.php')) {\r
1795                                 global $mbemu_internals;\r
1796                                 include_once($DIR_LIBS.'mb_emulator/mb-emulator.php');\r
1797                         }\r
1798                 }\r
1799                 $oPluginAdmin = new PluginAdmin($plugin_name);\r
1800                 $oPluginAdmin->start();\r
1801                 echo '<p>' . _ERROR_BADTICKET . "</p>\n";\r
1802 \r
1803                 /* Show the form to confirm action */\r
1804                 // PHP 4.0.x support\r
1805                 $get=  (isset($_GET))  ? $_GET  : $HTTP_GET_VARS;\r
1806                 $post= (isset($_POST)) ? $_POST : $HTTP_POST_VARS;\r
1807                 // Resolve URI and QUERY_STRING\r
1808                 if ($uri=serverVar('REQUEST_URI')) {\r
1809                         list($uri,$qstring)=explode('?',$uri);\r
1810                 } else {\r
1811                         if ( !($uri=serverVar('PHP_SELF')) ) $uri=serverVar('SCRIPT_NAME');\r
1812                         $qstring=serverVar('QUERY_STRING');\r
1813                 }\r
1814                 if ($qstring) $qstring='?'.$qstring;\r
1815                 echo '<p>'._SETTINGS_UPDATE.' : '._QMENU_PLUGINS.' <span style="color:red;">'.\r
1816                         htmlspecialchars($plugin_name)."</span> ?</p>\n";\r
1817                 switch(strtoupper(serverVar('REQUEST_METHOD'))){\r
1818                 case 'POST':\r
1819                         echo '<form method="POST" action="'.htmlspecialchars($uri.$qstring).'">';\r
1820                         $manager->addTicketHidden();\r
1821                         _addInputTags($post);\r
1822                         break;\r
1823                 case 'GET':\r
1824                         echo '<form method="GET" action="'.htmlspecialchars($uri).'">';\r
1825                         $manager->addTicketHidden();\r
1826                         _addInputTags($get);\r
1827                 default:\r
1828                         break;\r
1829                 }\r
1830                 echo '<input type="submit" value="'._YES.'" />&nbsp;&nbsp;&nbsp;&nbsp;';\r
1831                 echo '<input type="button" value="'._NO.'" onclick="history.back(); return false;" />';\r
1832                 echo "</form>\n";\r
1833 \r
1834                 $oPluginAdmin->end();\r
1835                 exit;\r
1836         }\r
1837 \r
1838         /* Create new ticket */\r
1839         $ticket=$manager->addTicketToUrl('');\r
1840         $ticketforplugin['ticket']=substr($ticket,strpos($ticket,'ticket=')+7);\r
1841 }\r
1842 function _addInputTags(&$keys,$prefix=''){\r
1843         foreach($keys as $key=>$value){\r
1844                 if ($prefix) $key=$prefix.'['.$key.']';\r
1845                 if (is_array($value)) _addInputTags($value,$key);\r
1846                 else {\r
1847                         if (get_magic_quotes_gpc()) $value=stripslashes($value);\r
1848                         if ($key=='ticket') continue;\r
1849                         echo '<input type="hidden" name="'.htmlspecialchars($key).\r
1850                                 '" value="'.htmlspecialchars($value).'" />'."\n";\r
1851                 }\r
1852         }\r
1853 }\r
1854 \r
1855 /**\r
1856  * Convert the server string such as $_SERVER['REQUEST_URI']\r
1857  * to arry like arry['blogid']=1 and array['page']=2 etc.\r
1858  */\r
1859 function serverStringToArray($str, &$array, &$frontParam)\r
1860 {\r
1861         // init param\r
1862         $array = array();\r
1863         $fronParam = "";\r
1864 \r
1865         // split front param, e.g. /index.php, and others, e.g. blogid=1&page=2\r
1866         if (strstr($str, "?")){\r
1867                 list($frontParam, $args) = preg_split("/\?/", $str, 2);\r
1868         }\r
1869         else {\r
1870                 $args = $str;\r
1871                 $frontParam = "";\r
1872         }\r
1873 \r
1874         // If there is no args like blogid=1&page=2, return\r
1875         if (!strstr($str, "=") && !strlen($frontParam)) {\r
1876                 $frontParam = $str;\r
1877                 return;\r
1878         }\r
1879 \r
1880         $array = explode("&", $args);\r
1881 }\r
1882 \r
1883 /**\r
1884  * Convert array like array['blogid'] to server string\r
1885  * such as $_SERVER['REQUEST_URI']\r
1886  */\r
1887 function arrayToServerString($array, $frontParam, &$str)\r
1888 {\r
1889         if (strstr($str, "?")) {\r
1890                 $str = $frontParam . "?";\r
1891         } else {\r
1892                 $str = $frontParam;\r
1893         }\r
1894         if (count($array)) {\r
1895                 $str .= implode("&", $array);\r
1896         }\r
1897 }\r
1898 \r
1899 /**\r
1900  * Sanitize array parameters.\r
1901  * This function checks both key and value.\r
1902  * - check key if it inclues " (double quote),  remove from array\r
1903  * - check value if it includes \ (escape sequece), remove remaining string\r
1904  */\r
1905 function sanitizeArray(&$array)\r
1906 {\r
1907         $excludeListForSanitization = array('query');\r
1908 //      $excludeListForSanitization = array();\r
1909 \r
1910         foreach ($array as $k => $v) {\r
1911 \r
1912                 // split to key and value\r
1913                 list($key, $val) = preg_split("/=/", $v, 2);\r
1914                 if (!isset($val)) {\r
1915                         continue;\r
1916                 }\r
1917 \r
1918                 // when magic quotes is on, need to use stripslashes,\r
1919                 // and then addslashes\r
1920                 if (get_magic_quotes_gpc()) {\r
1921                         $val = stripslashes($val);\r
1922                 }\r
1923                 $val = addslashes($val);\r
1924 \r
1925                 // if $key is included in exclude list, skip this param\r
1926                 if (!in_array($key, $excludeListForSanitization)) {\r
1927 \r
1928                         // check value\r
1929                         if (strpos($val, '\\')) {\r
1930                                 list($val, $tmp) = explode('\\', $val);\r
1931                         }\r
1932 \r
1933                         // remove control code etc.\r
1934                         $val = strtr($val, "\0\r\n<>'\"", "       ");\r
1935 \r
1936                         // check key\r
1937                         if (preg_match('/\"/i', $key)) {\r
1938                                 unset($array[$k]);\r
1939                                 continue;\r
1940                         }\r
1941 \r
1942                         // set sanitized info\r
1943                         $array[$k] = sprintf("%s=%s", $key, $val);\r
1944                 }\r
1945         }\r
1946 }\r
1947 \r
1948 /**\r
1949  * Convert array for sanitizeArray function\r
1950  */\r
1951 function convArrayForSanitizing($src, &$array)\r
1952 {\r
1953         $array = array();\r
1954         foreach ($src as $key => $val) {\r
1955                 if (key_exists($key, $_GET)) {\r
1956                         array_push($array, sprintf("%s=%s", $key, $val));\r
1957                 }\r
1958         }\r
1959 }\r
1960 \r
1961 /**\r
1962  * Revert array after sanitizeArray function\r
1963  */\r
1964 function revertArrayForSanitizing($array, &$dst)\r
1965 {\r
1966         foreach ($array as $v) {\r
1967                 list($key, $val) = preg_split("/=/", $v, 2);\r
1968                 $dst[$key] = $val;\r
1969         }\r
1970 }\r
1971 \r
1972 /**\r
1973  * Stops processing the request and redirects to the given URL.\r
1974  * - no actual contents should have been sent to the output yet\r
1975  * - the URL will be stripped of illegal or dangerous characters\r
1976  */\r
1977 function redirect($url) {\r
1978         $url = preg_replace('|[^a-z0-9-~+_.?#=&;,/:@%*]|i', '', $url);\r
1979         header('Location: ' . $url);\r
1980         exit;\r
1981 }\r
1982 \r
1983 /**\r
1984  * Strip HTML tags from a string\r
1985  * This function is a bit more intelligent than a regular call to strip_tags(),\r
1986  * because it also deletes the contents of certain tags and cleans up any\r
1987  * unneeded whitespace.\r
1988  */\r
1989 function stringStripTags ($string) {\r
1990         $string = preg_replace("/<del[^>]*>.+<\/del[^>]*>/isU", '', $string);\r
1991         $string = preg_replace("/<script[^>]*>.+<\/script[^>]*>/isU", '', $string);\r
1992         $string = preg_replace("/<style[^>]*>.+<\/style[^>]*>/isU", '', $string);\r
1993         $string = str_replace('>', '> ', $string);\r
1994         $string = str_replace('<', ' <', $string);\r
1995         $string = strip_tags($string);\r
1996         $string = preg_replace("/\s+/", " ", $string);\r
1997         $string = trim($string);\r
1998         return $string;\r
1999 }\r
2000 \r
2001 /**\r
2002  * Make a string containing HTML safe for use in a HTML attribute\r
2003  * Tags are stripped and entities are normalized\r
2004  */\r
2005 function stringToAttribute ($string) {\r
2006         $string = stringStripTags($string);\r
2007         $string = entity::named_to_numeric($string);\r
2008         $string = entity::normalize_numeric($string);\r
2009 \r
2010         if (_CHARSET == 'UTF-8') {\r
2011                 $string = entity::numeric_to_utf8($string);\r
2012         }\r
2013 \r
2014         $string = entity::specialchars($string, 'html');\r
2015         $string = entity::numeric_to_named($string);\r
2016         return $string;\r
2017 }\r
2018 \r
2019 /**\r
2020  * Make a string containing HTML safe for use in a XML document\r
2021  * Tags are stripped, entities are normalized and named entities are\r
2022  * converted to numeric entities.\r
2023  */\r
2024 function stringToXML ($string) {\r
2025         $string = stringStripTags($string);\r
2026         $string = entity::named_to_numeric($string);\r
2027         $string = entity::normalize_numeric($string);\r
2028 \r
2029         if (_CHARSET == 'UTF-8') {\r
2030                 $string = entity::numeric_to_utf8($string);\r
2031         }\r
2032 \r
2033         $string = entity::specialchars($string, 'xml');\r
2034         return $string;\r
2035 }\r
2036 \r
2037 // START: functions from the end of file BLOG.php\r
2038 // used for mail notification (html -> text)\r
2039 function toAscii($html) {\r
2040         // strip off most tags\r
2041         $html = strip_tags($html,'<a>');\r
2042         $to_replace = "/<a[^>]*href=[\"\']([^\"^']*)[\"\'][^>]*>([^<]*)<\/a>/i";\r
2043         _links_init();\r
2044         $ascii = preg_replace_callback ($to_replace, '_links_add', $html);\r
2045         $ascii .= "\n\n" . _links_list();\r
2046         return strip_tags($ascii);\r
2047 }\r
2048 \r
2049 function _links_init() {\r
2050    global $tmp_links;\r
2051    $tmp_links = array();\r
2052 }\r
2053 \r
2054 function _links_add($match) {\r
2055    global $tmp_links;\r
2056    array_push($tmp_links, $match[1]);\r
2057    return $match[2] . ' [' . sizeof($tmp_links) .']';\r
2058 }\r
2059 \r
2060 function _links_list() {\r
2061    global $tmp_links;\r
2062    $output = '';\r
2063    $i = 1;\r
2064    foreach ($tmp_links as $current) {\r
2065           $output .= "[$i] $current\n";\r
2066           $i++;\r
2067    }\r
2068    return $output;\r
2069 }\r
2070 // END: functions from the end of file BLOG.php\r
2071 \r
2072 // START: functions from the end of file ADMIN.php\r
2073 /**\r
2074  * @todo document this\r
2075  */\r
2076 function encode_desc(&$data)\r
2077 {\r
2078 //      _$to_entities = get_html_translation_table(HTML_ENTITIES);\r
2079         $to_entities = get_html_translation_table(HTML_SPECIALCHARS); // for Japanese\r
2080         $from_entities = array_flip($to_entities);\r
2081         $data = str_replace('<br />', '\n', $data); //hack\r
2082         $data = strtr($data,$from_entities);\r
2083         $data = strtr($data,$to_entities);\r
2084         $data = str_replace('\n', '<br />', $data); //hack\r
2085         return $data;\r
2086 }\r
2087 \r
2088 /**\r
2089  * Returns the Javascript code for a bookmarklet that works on most modern browsers\r
2090  *\r
2091  * @param blogid\r
2092  */\r
2093 function getBookmarklet($blogid) {\r
2094         global $CONF;\r
2095 \r
2096         // normal\r
2097         $document = 'document';\r
2098         $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
2099         $bookmarkletline .= $CONF['AdminURL'] . "bookmarklet.php?blogid=$blogid";\r
2100         $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
2101 \r
2102         return $bookmarkletline;\r
2103 }\r
2104 // END: functions from the end of file ADMIN.php\r
2105 \r
2106 /**\r
2107  * Returns a variable or null if not set\r
2108  *\r
2109  * @param mixed Variable\r
2110  * @return mixed Variable\r
2111  */\r
2112 function ifset(&$var) {\r
2113         if (isset($var)) {\r
2114                 return $var;\r
2115         }\r
2116 \r
2117         return null;\r
2118 }\r
2119 \r
2120 /**\r
2121  * Returns number of subscriber to an event\r
2122  *\r
2123  * @param event\r
2124  * @return number of subscriber(s)\r
2125  */\r
2126 function numberOfEventSubscriber($event) {\r
2127         $query = 'SELECT COUNT(*) as count FROM ' . sql_table('plugin_event') . ' WHERE event=\'' . $event . '\'';\r
2128         $res = sql_query($query);\r
2129         $obj = mysql_fetch_object($res);\r
2130         return $obj->count;\r
2131 }\r
2132 \r
2133 ?>