OSDN Git Service

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