OSDN Git Service

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