OSDN Git Service

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