OSDN Git Service

encode_desc is modified to apply JP hack
[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.9 2006-08-31 21:00:21 kimitake Exp $
17  * $NucleusJP: globalfunctions.php,v 1.8 2006/07/18 08:42:04 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 (is_numeric($archivelist)) {
790                         $blogid = intVal($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 (is_numeric($blogid)) {
809                         $blogid = intVal($blogid);
810                 } else {
811                         $blogid = getBlogIDFromName($blogid);
812                 }
813
814                 if (!$blogid) {
815                         doError(_ERROR_NOSUCHBLOG);
816                 }
817
818         } elseif ($memberid) {
819                 $type = 'member';
820
821                 if (!MEMBER::existsID($memberid) ) {
822                         doError(_ERROR_NOSUCHMEMBER);
823                 }
824
825                 $memberinfo = $manager->getMember($memberid);
826
827         } elseif ($imagepopup) {
828                 // media object (images etc.)
829                 $type = 'imagepopup';
830
831                 // TODO: check if media-object exists
832                 // TODO: set some vars?
833         } else {
834                 // show regular index page
835                 global $startpos;
836                 $type = 'index';
837         }
838
839         // decide which blog should be displayed
840         if (!$blogid) {
841                 $blogid = $CONF['DefaultBlog'];
842         }
843
844         $b =& $manager->getBlog($blogid);
845         $blog = $b;     // references can't be placed in global variables?
846
847         if (!$blog->isValid) {
848                 doError(_ERROR_NOSUCHBLOG);
849         }
850
851         // set catid if necessary
852         if ($catid) {
853                 $blog->setSelectedCategory($catid);
854         }
855
856         // decide which skin should be used
857         if ($skinid != '' && ($skinid == 0) ) {
858                 selectSkin($skinid);
859         }
860
861         if (!$skinid) {
862                 $skinid = $blog->getDefaultSkin();
863         }
864
865         $special = requestVar('special');
866         if (!empty($special) && isValidShortName($special)) {
867                 $type = strtolower($special);
868         }
869
870         $skin = new SKIN($skinid);
871
872         if (!$skin->isValid) {
873                 doError(_ERROR_NOSUCHSKIN);
874         }
875
876         // parse the skin
877         $skin->parse($type);
878 }
879
880 /**
881   * Show error skin with given message. An optional skin-object to use can be given
882   */
883 function doError($msg, $skin = '') {
884         global $errormessage, $CONF, $skinid, $blogid, $manager;
885
886         if ($skin == '') {
887
888                 if (SKIN::existsID($skinid) ) {
889                         $skin = new SKIN($skinid);
890                 } elseif ($manager->existsBlogID($blogid) ) {
891                         $blog =& $manager->getBlog($blogid);
892                         $skin = new SKIN($blog->getDefaultSkin() );
893                 } elseif ($CONF['DefaultBlog']) {
894                         $blog =& $manager->getBlog($CONF['DefaultBlog']);
895                         $skin = new SKIN($blog->getDefaultSkin() );
896                 } else {
897                         // this statement should actually never be executed
898                         $skin = new SKIN($CONF['BaseSkin']);
899                 }
900
901         }
902
903         $errormessage = $msg;
904         $skin->parse('error');
905         exit;
906 }
907
908 function getConfig() {
909         global $CONF;
910
911         $query = 'SELECT * FROM ' . sql_table('config');
912         $res = sql_query($query);
913
914         while ($obj = mysql_fetch_object($res) ) {
915                 $CONF[$obj->name] = $obj->value;
916         }
917 }
918
919 // some checks for names of blogs, categories, templates, members, ...
920 function isValidShortName($name) {
921         return eregi('^[a-z0-9]+$', $name);
922 }
923
924 function isValidDisplayName($name) {
925         return eregi('^[a-z0-9]+[a-z0-9 ]*[a-z0-9]+$', $name);
926 }
927
928 function isValidCategoryName($name) {
929         return 1;
930 }
931
932 function isValidTemplateName($name) {
933         return eregi('^[a-z0-9/]+$', $name);
934 }
935
936 function isValidSkinName($name) {
937         return eregi('^[a-z0-9/]+$', $name);
938 }
939
940 // add and remove linebreaks
941 function addBreaks($var) {
942         return nl2br($var);
943 }
944
945 function removeBreaks($var) {
946         return preg_replace("/<br \/>([\r\n])/", "$1", $var);
947 }
948
949 // shortens a text string to maxlength ($toadd) is what needs to be added
950 // at the end (end length is <= $maxlength)
951 function shorten($text, $maxlength, $toadd) {
952         // 1. remove entities...
953         $trans = get_html_translation_table(HTML_ENTITIES);
954         $trans = array_flip($trans);
955         $text = strtr($text, $trans);
956
957         // 2. the actual shortening
958         if (strlen($text) > $maxlength)
959                 $text = mb_strimwidth($text, 0, $maxlength, $toadd, _CHARSET);
960         return $text;
961 }
962
963 /**
964   * Converts a unix timestamp to a mysql DATETIME format, and places
965   * quotes around it.
966   */
967 function mysqldate($timestamp) {
968         return '"' . date('Y-m-d H:i:s', $timestamp) . '"';
969 }
970
971 /**
972   * functions for use in index.php
973   */
974 function selectBlog($shortname) {
975         global $blogid, $archivelist;
976         $blogid = getBlogIDFromName($shortname);
977
978         // also force archivelist variable, if it is set
979         if ($archivelist) {
980                 $archivelist = $blogid;
981         }
982 }
983
984 function selectSkin($skinname) {
985         global $skinid;
986         $skinid = SKIN::getIdFromName($skinname);
987 }
988
989 /**
990  * Can take either a category ID or a category name (be aware that
991  * multiple categories can have the same name)
992  */
993 function selectCategory($cat) {
994         global $catid;
995         if (is_numeric($cat) ) {
996                 $catid = intval($cat);
997         } else {
998                 $catid = getCatIDFromName($cat);
999         }
1000 }
1001
1002 function selectItem($id) {
1003         global $itemid;
1004         $itemid = intval($id);
1005 }
1006
1007 // force the use of a language file (warning: can cause warnings)
1008 function selectLanguage($language) {
1009         global $DIR_LANG;
1010         include($DIR_LANG . ereg_replace( '[\\|/]', '', $language) . '.php');
1011 }
1012
1013 function parseFile($filename, $includeMode = 'normal', $includePrefix = '') {
1014         $handler = new ACTIONS('fileparser');
1015         $parser = new PARSER(SKIN::getAllowedActionsForType('fileparser'), $handler);
1016         $handler->parser =& $parser;
1017
1018         // set IncludeMode properties of parser
1019         PARSER::setProperty('IncludeMode', $includeMode);
1020         PARSER::setProperty('IncludePrefix', $includePrefix);
1021
1022         if (!file_exists($filename) ) {
1023                 doError('A file is missing');
1024         }
1025
1026         $fsize = filesize($filename);
1027
1028         if ($fsize <= 0) {
1029                 return;
1030         }
1031
1032         // read file
1033         $fd = fopen ($filename, 'r');
1034         $contents = fread ($fd, $fsize);
1035         fclose ($fd);
1036
1037         // parse file contents
1038         $parser->parse($contents);
1039 }
1040
1041 /**
1042   * Outputs a debug message
1043   */
1044 function debug($msg) {
1045         echo '<p><b>' . $msg . "</b></p>\n";
1046 }
1047
1048 // shortcut
1049 function addToLog($level, $msg) {
1050         ACTIONLOG::add($level, $msg);
1051 }
1052
1053 // shows a link to help file
1054 function help($id) {
1055         echo helpHtml($id);
1056 }
1057
1058 function helpHtml($id) {
1059         return helplink($id) . '<img src="documentation/icon-help.gif" width="15" height="15" alt="' . _HELP_TT . '" /></a>';
1060 }
1061
1062 function helplink($id) {
1063         return '<a href="documentation/help.html#'. $id . '" onclick="if (event &amp;&amp; event.preventDefault) event.preventDefault(); return help(this.href);">';
1064 }
1065
1066 function getMailFooter() {
1067         $message = "\n\n-----------------------------";
1068         $message .=  "\n   Powered by Nucleus CMS";
1069         $message .=  "\n(http://www.nucleuscms.org/)";
1070         return $message;
1071 }
1072
1073 /**
1074   * Returns the name of the language to use
1075   * preference priority: member - site
1076   * defaults to english when no good language found
1077   *
1078   * checks if file exists, etc...
1079   */
1080 function getLanguageName() {
1081         global $CONF, $member;
1082
1083         if ($member && $member->isLoggedIn() ) {
1084                 // try to use members language
1085                 $memlang = $member->getLanguage();
1086
1087                 if (($memlang != '') && (checkLanguage($memlang) ) ) {
1088                         return $memlang;
1089                 }
1090         }
1091
1092         // use default language
1093         if (checkLanguage($CONF['Language']) ) {
1094                 return $CONF['Language'];
1095         } else {
1096                 return 'english';
1097         }
1098 }
1099
1100 /**
1101   * Includes a PHP file. This method can be called while parsing templates and skins
1102   */
1103 function includephp($filename) {
1104         // make predefined variables global, so most simple scripts can be used here
1105
1106         // apache (names taken from PHP doc)
1107         global $GATEWAY_INTERFACE, $SERVER_NAME, $SERVER_SOFTWARE, $SERVER_PROTOCOL;
1108         global $REQUEST_METHOD, $QUERY_STRING, $DOCUMENT_ROOT, $HTTP_ACCEPT;
1109         global $HTTP_ACCEPT_CHARSET, $HTTP_ACCEPT_ENCODING, $HTTP_ACCEPT_LANGUAGE;
1110         global $HTTP_CONNECTION, $HTTP_HOST, $HTTP_REFERER, $HTTP_USER_AGENT;
1111         global $REMOTE_ADDR, $REMOTE_PORT, $SCRIPT_FILENAME, $SERVER_ADMIN;
1112         global $SERVER_PORT, $SERVER_SIGNATURE, $PATH_TRANSLATED, $SCRIPT_NAME;
1113         global $REQUEST_URI;
1114
1115         // php (taken from PHP doc)
1116         global $argv, $argc, $PHP_SELF, $HTTP_COOKIE_VARS, $HTTP_GET_VARS, $HTTP_POST_VARS;
1117         global $HTTP_POST_FILES, $HTTP_ENV_VARS, $HTTP_SERVER_VARS, $HTTP_SESSION_VARS;
1118
1119         // other
1120         global $PATH_INFO, $HTTPS, $HTTP_RAW_POST_DATA, $HTTP_X_FORWARDED_FOR;
1121
1122         if (@file_exists($filename) ) {
1123                 include($filename);
1124         }
1125 }
1126
1127 /**
1128   * Checks if a certain language/plugin exists
1129   */
1130 function checkLanguage($lang) {
1131         global $DIR_LANG ;
1132         return file_exists($DIR_LANG . ereg_replace( '[\\|/]', '', $lang) . '.php');
1133 }
1134
1135 function checkPlugin($plug) {
1136         global $DIR_PLUGINS;
1137         return file_exists($DIR_PLUGINS . ereg_replace( '[\\|/]', '', $plug) . '.php');
1138 }
1139
1140 /**
1141   * Centralisation of the functions that generate links
1142   */
1143 function createItemLink($itemid, $extra = '') {
1144         return createLink('item', array('itemid' => $itemid, 'extra' => $extra) );
1145 }
1146
1147 function createMemberLink($memberid, $extra = '') {
1148         return createLink('member', array('memberid' => $memberid, 'extra' => $extra) );
1149 }
1150
1151 function createCategoryLink($catid, $extra = '') {
1152         return createLink('category', array('catid' => $catid, 'extra' => $extra) );
1153 }
1154
1155 function createArchiveListLink($blogid = '', $extra = '') {
1156         return createLink('archivelist', array('blogid' => $blogid, 'extra' => $extra) );
1157 }
1158
1159 function createArchiveLink($blogid, $archive, $extra = '') {
1160         return createLink('archive', array('blogid' => $blogid, 'archive' => $archive, 'extra' => $extra) );
1161 }
1162
1163 function createBlogidLink($blogid, $params = '') {
1164         return createLink('blog', array('blogid' => $blogid, 'extra' => $params) );
1165 }
1166
1167 function createLink($type, $params) {
1168         global $manager, $CONF;
1169
1170         $generatedURL = '';
1171         $usePathInfo = ($CONF['URLMode'] == 'pathinfo');
1172
1173         // ask plugins first
1174         $created = false;
1175
1176         if ($usePathInfo) {
1177                 $manager->notify(
1178                         'GenerateURL',
1179                         array(
1180                                 'type' => $type,
1181                                 'params' => $params,
1182                                 'completed' => &$created,
1183                                 'url' => &$url
1184                         )
1185                 );
1186         }
1187
1188         // if a plugin created the URL, return it
1189         if ($created) {
1190                 return $url;
1191         }
1192
1193         // default implementation
1194         switch ($type) {
1195                 case 'item':
1196                         if ($usePathInfo) {
1197                                 $url = $CONF['ItemURL'] . '/' . $CONF['ItemKey'] . '/' . $params['itemid'];
1198                         } else {
1199                                 $url = $CONF['ItemURL'] . '?itemid=' . $params['itemid'];
1200                         }
1201                         break;
1202
1203                 case 'member':
1204                         if ($usePathInfo) {
1205                                 $url = $CONF['MemberURL'] . '/' . $CONF['MemberKey'] . '/' . $params['memberid'];
1206                         } else {
1207                                 $url = $CONF['MemberURL'] . '?memberid=' . $params['memberid'];
1208                         }
1209                         break;
1210
1211                 case 'category':
1212                         if ($usePathInfo) {
1213                                 $url = $CONF['CategoryURL'] . '/' . $CONF['CategoryKey'] . '/' . $params['catid'];
1214                         } else {
1215                                 $url = $CONF['CategoryURL'] . '?catid=' . $params['catid'];
1216                         }
1217                         break;
1218
1219                 case 'archivelist':
1220                         if (!$params['blogid']) {
1221                                 $params['blogid'] = $CONF['DefaultBlog'];
1222                         }
1223
1224                         if ($usePathInfo) {
1225                                 $url = $CONF['ArchiveListURL'] . '/' . $CONF['ArchivesKey'] . '/' . $params['blogid'];
1226                         } else {
1227                                 $url = $CONF['ArchiveListURL'] . '?archivelist=' . $params['blogid'];
1228                         }
1229                         break;
1230
1231                 case 'archive':
1232                         if ($usePathInfo) {
1233                                 $url = $CONF['ArchiveURL'] . '/' . $CONF['ArchiveKey'] . '/'.$params['blogid'].'/' . $params['archive'];
1234                         } else {
1235                                 $url = $CONF['ArchiveURL'] . '?blogid='.$params['blogid'].'&amp;archive=' . $params['archive'];
1236                         }
1237                         break;
1238
1239                 case 'blog':
1240                         if ($usePathInfo) {
1241                                 $url = $CONF['BlogURL'] . '/' . $CONF['BlogKey'] . '/' . $params['blogid'];
1242                         } else {
1243                                 $url = $CONF['BlogURL'] . '?blogid=' . $params['blogid'];
1244                         }
1245                         break;
1246         }
1247
1248         return addLinkParams($url, (isset($params['extra'])? $params['extra'] : null));
1249 }
1250
1251 function createBlogLink($url, $params) {
1252         return addLinkParams($url . '?', $params);
1253 }
1254
1255 function addLinkParams($link, $params) {
1256         global $CONF;
1257
1258         if (is_array($params) ) {
1259
1260                 if ($CONF['URLMode'] == 'pathinfo')     {
1261
1262                         foreach ($params as $param => $value) {
1263                                 $link .= '/' . $param . '/' . urlencode($value);
1264                         }
1265
1266                 } else {
1267
1268                         foreach ($params as $param => $value) {
1269                                 $link .= '&amp;' . $param . '=' . urlencode($value);
1270                         }
1271
1272                 }
1273         }
1274
1275         return $link;
1276 }
1277
1278 /**
1279  * @param $querystr
1280  *              querystring to alter (e.g. foo=1&bar=2&x=y)
1281  * @param $param
1282  *              name of parameter to change (e.g. 'foo')
1283  * @param $value
1284  *              New value for that parameter (e.g. 3)
1285  * @result
1286  *              altered query string (for the examples above: foo=3&bar=2&x=y)
1287  */
1288 function alterQueryStr($querystr, $param, $value) {
1289         $vars = explode('&', $querystr);
1290         $set  = false;
1291
1292         for ($i = 0; $i < count($vars); $i++) {
1293                 $v = explode('=', $vars[$i]);
1294
1295                 if ($v[0] == $param) {
1296                         $v[1] = $value;
1297                         $vars[$i] = implode('=', $v);
1298                         $set = true;
1299                         break;
1300                 }
1301         }
1302
1303         if (!$set) {
1304                 $vars[] = $param . '=' . $value;
1305         }
1306
1307         return ltrim(implode('&', $vars), '&');
1308 }
1309
1310 // passes one variable as hidden input field (multiple fields for arrays)
1311 // @see passRequestVars in varsx.x.x.php
1312 function passVar($key, $value) {
1313         // array ?
1314         if (is_array($value) ) {
1315                 for ($i = 0; $i < sizeof($value); $i++) {
1316                         passVar($key . '[' . $i . ']', $value[$i]);
1317                 }
1318
1319                 return;
1320         }
1321
1322         // other values: do stripslashes if needed
1323         ?><input type="hidden" name="<?php echo htmlspecialchars($key)?>" value="<?php echo htmlspecialchars(undoMagic($value) )?>" /><?php
1324 }
1325
1326 /*
1327         Date format functions (to be used from [%date(..)%] skinvars
1328 */
1329 function formatDate($format, $timestamp, $defaultFormat, &$blog) {
1330         // apply blog offset (#42)
1331         $boffset = $blog ? $blog->getTimeOffset() * 3600 : 0;
1332         $offset = date('Z', $timestamp) + $boffset;
1333
1334         switch ($format) {
1335                 case 'rfc822':
1336                         if ($offset >= 0) {
1337                                 $tz = '+';
1338                         } else {
1339                                 $tz = '-';
1340                                 $offset = -$offset;
1341                         }
1342
1343                         $tz .= sprintf("%02d%02d", floor($offset / 3600), round(($offset % 3600) / 60) );
1344                         return date('D, j M Y H:i:s ', $timestamp) . $tz;
1345
1346                 case 'rfc822GMT':
1347                         $timestamp -= $offset;
1348                         return date('D, j M Y H:i:s ', $timestamp) . 'GMT';
1349
1350                 case 'utc':
1351                         $timestamp -= $offset;
1352                         return date('Y-m-d\TH:i:s\Z', $timestamp);
1353
1354                 case 'iso8601':
1355                         if ($offset >= 0) {
1356                                 $tz = '+';
1357                         } else {
1358                                 $tz = '-';
1359                                 $offset = -$offset;
1360                         }
1361
1362                         $tz .= sprintf("%02d:%02d", floor($offset / 3600), round(($offset % 3600) / 60) );
1363                         return date('Y-m-d\TH:i:s', $timestamp) . $tz;
1364
1365                 default :
1366                         return strftime($format ? $format : $defaultFormat, $timestamp);
1367         }
1368 }
1369
1370 function checkVars($aVars) {
1371         global $HTTP_GET_VARS, $HTTP_POST_VARS, $HTTP_COOKIE_VARS, $HTTP_ENV_VARS, $HTTP_POST_FILES, $HTTP_SESSION_VARS;
1372
1373         foreach ($aVars as $varName) {
1374
1375                 if (phpversion() >= '4.1.0') {
1376
1377                         if (   isset($_GET[$varName])
1378                                 || isset($_POST[$varName])
1379                                 || isset($_COOKIE[$varName])
1380                                 || isset($_ENV[$varName])
1381                                 || isset($_SESSION[$varName])
1382                                 || isset($_FILES[$varName])
1383                         ) {
1384                                 die('Sorry. An error occurred.');
1385                         }
1386
1387                 } else {
1388
1389                         if (   isset($HTTP_GET_VARS[$varName])
1390                                 || isset($HTTP_POST_VARS[$varName])
1391                                 || isset($HTTP_COOKIE_VARS[$varName])
1392                                 || isset($HTTP_ENV_VARS[$varName])
1393                                 || isset($HTTP_SESSION_VARS[$varName])
1394                                 || isset($HTTP_POST_FILES[$varName])
1395                         ) {
1396                                 die('Sorry. An error occurred.');
1397                         }
1398
1399                 }
1400         }
1401 }
1402
1403 /**
1404  * Stops processing the request and redirects to the given URL.
1405  * - no actual contents should have been sent to the output yet
1406  * - the URL will be stripped of illegal or dangerous characters
1407  */
1408 function redirect($url) {
1409         $url = preg_replace('|[^a-z0-9-~+_.?#=&;,/:@%]|i', '', $url);
1410         header('Location: ' . $url);
1411         exit;
1412 }
1413
1414 /**
1415  * Strip HTML tags from a string
1416  * This function is a bit more intelligent than a regular call to strip_tags(),
1417  * because it also deletes the contents of certain tags and cleans up any
1418  * unneeded whitespace.
1419  */
1420 function stringStripTags ($string) {
1421         $string = preg_replace("/<del[^>]*>.+<\/del[^>]*>/isU", '', $string);
1422         $string = preg_replace("/<script[^>]*>.+<\/script[^>]*>/isU", '', $string);
1423         $string = preg_replace("/<style[^>]*>.+<\/style[^>]*>/isU", '', $string);
1424         $string = str_replace('>', '> ', $string);
1425         $string = str_replace('<', ' <', $string);
1426         $string = strip_tags($string);
1427         $string = preg_replace("/\s+/", " ", $string);
1428         $string = trim($string);
1429         return $string;
1430 }
1431
1432 /**
1433  * Make a string containing HTML safe for use in a HTML attribute
1434  * Tags are stripped and entities are normalized
1435  */
1436 function stringToAttribute ($string) {
1437         $string = stringStripTags($string);
1438         $string = entity::named_to_numeric($string);
1439         $string = entity::normalize_numeric($string);
1440
1441         if (_CHARSET == 'UTF-8') {
1442                 $string = entity::numeric_to_utf8($string);
1443         }
1444
1445         $string = entity::specialchars($string, 'html');
1446         $string = entity::numeric_to_named($string);
1447         return $string;
1448 }
1449
1450 /**
1451  * Make a string containing HTML safe for use in a XML document
1452  * Tags are stripped, entities are normalized and named entities are
1453  * converted to numeric entities.
1454  */
1455 function stringToXML ($string) {
1456         $string = stringStripTags($string);
1457         $string = entity::named_to_numeric($string);
1458         $string = entity::normalize_numeric($string);
1459
1460         if (_CHARSET == 'UTF-8') {
1461                 $string = entity::numeric_to_utf8($string);
1462         }
1463
1464         $string = entity::specialchars($string, 'xml');
1465         return $string;
1466 }
1467
1468 // START: functions from the end of file BLOG.php
1469 // used for mail notification (html -> text)
1470 function toAscii($html) {
1471         // strip off most tags
1472         $html = strip_tags($html,'<a>');
1473         $to_replace = "/<a[^>]*href=[\"\']([^\"^']*)[\"\'][^>]*>([^<]*)<\/a>/i";
1474         _links_init();
1475         $ascii = preg_replace_callback ($to_replace, '_links_add', $html);
1476         $ascii .= "\n\n" . _links_list();
1477         return strip_tags($ascii);
1478 }
1479
1480 function _links_init() {
1481    global $tmp_links;
1482    $tmp_links = array();
1483 }
1484
1485 function _links_add($match) {
1486    global $tmp_links;
1487    array_push($tmp_links, $match[1]);
1488    return $match[2] . ' [' . sizeof($tmp_links) .']';
1489 }
1490
1491 function _links_list() {
1492    global $tmp_links;
1493    $output = '';
1494    $i = 1;
1495    foreach ($tmp_links as $current) {
1496           $output .= "[$i] $current\n";
1497           $i++;
1498    }
1499    return $output;
1500 }
1501 // END: functions from the end of file BLOG.php
1502
1503 // START: functions from the end of file ADMIN.php
1504 /**
1505  * @todo document this
1506  */
1507 function encode_desc(&$data)
1508     {   //_$to_entities = get_html_translation_table(HTML_ENTITIES);
1509         $to_entities = get_html_translation_table(HTML_SPECIALCHARS);
1510         $from_entities = array_flip($to_entities);
1511         $data = str_replace('<br />','\n',$data); //hack
1512         $data = strtr($data,$from_entities);
1513         $data = strtr($data,$to_entities);
1514         $data = str_replace('\n','<br />',$data); //hack
1515         return $data;
1516     }
1517  
1518 /**
1519  * Returns the Javascript code for a bookmarklet that works on most modern browsers
1520  *
1521  * @param blogid
1522  */
1523 function getBookmarklet($blogid) {
1524         global $CONF;
1525
1526         // normal
1527         $document = 'document';
1528         $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('";
1529         $bookmarkletline .= $CONF['AdminURL'] . "bookmarklet.php?blogid=$blogid";
1530         $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();";
1531
1532         return $bookmarkletline;
1533 }
1534 // END: functions from the end of file ADMIN.php
1535
1536 /**
1537  * Returns a variable or null if not set
1538  *
1539  * @param mixed Variable
1540  * @return mixed Variable
1541  */
1542 function ifset(&$var) {
1543         if (isset($var)) {
1544                 return $var;
1545         }
1546
1547         return null;
1548 }
1549
1550 ?>