OSDN Git Service

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