OSDN Git Service

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