OSDN Git Service

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