OSDN Git Service

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