OSDN Git Service

This commit was generated by cvs2svn to compensate for changes in r4,
[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-2004 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   * $Id: globalfunctions.php,v 1.1.1.1 2005-02-28 07:14:50 kimitake Exp $
14   */
15
16 // needed if we include globalfunctions from install.php
17 global $nucleus, $CONF, $DIR_LIBS, $DIR_LANG, $manager, $member; 
18
19
20 checkVars(array('nucleus', 'CONF', 'DIR_LIBS', 'MYSQL_HOST', 'MYSQL_USER', 'MYSQL_PASSWORD', 'MYSQL_DATABASE', 'DIR_LANG', 'DIR_PLUGINS'));
21
22 $CONF['debug'] = 0;
23
24 $nucleus['version'] = 'v3.1+ CVS';
25 if (getNucleusPatchLevel() > 0)
26 {
27         $nucleus['version'] .= '/' . getNucleusPatchLevel();
28 }
29
30 /*
31         Indicates when Nucleus should display startup errors. Set to 1 if you want
32         the error enabled (default), false otherwise
33
34         alertOnHeadersSent
35                 Displays an error when visiting a public Nucleus page and headers have
36                 been sent out to early. This usually indicates an error in either a
37                 configuration file or a language file, and could cause Nucleus to
38                 malfunction
39         alertOnSecurityRisk
40                 Displays an error only when visiting the admin area, and when one or
41                 more of the installation files (install.php, install.sql, upgrades/
42                 directory) are still on the server.
43 */
44 $CONF['alertOnHeadersSent'] = 1;
45 $CONF['alertOnSecurityRisk'] = 1;
46
47 /**
48   * returns the currently used version (100 = 1.00, 101 = 1.01, etc...)
49   */
50 function getNucleusVersion() {
51         return 310;
52 }
53
54 /**
55  * power users can install patches in between nucleus releases. These patches
56  * usually add new functionality in the plugin API and allow those to
57  * be tested without having to install CVS.
58  */
59 function getNucleusPatchLevel() {
60         return 1;
61 }
62
63
64 if ($CONF['debug']) {
65         error_reporting(E_ALL & ~E_NOTICE);     // report almost all errors!
66                                                                                 // (no uninitialized vars and such)
67 } else {
68         error_reporting(E_ERROR | E_WARNING | E_PARSE);
69 }
70
71 // we will use postVar, getVar, ... methods instead of HTTP_GET_VARS or _GET
72 if ($CONF['installscript']!=1){ // vars were already included in install.php
73   if (phpversion() >= '4.1.0')
74           include_once($DIR_LIBS . 'vars4.1.0.php');
75   else
76           include_once($DIR_LIBS . 'vars4.0.6.php');
77 }
78
79 function intPostVar($name) { return intval(postVar($name));}
80 function intGetVar($name) { return intval(getVar($name));}
81 function intRequestVar($name) { return intval(requestVar($name)); }
82 function intCookieVar($name) { return intval(cookieVar($name)); }
83
84 // get all variables that can come from the request and put them in the global scope
85 $blogid                 = requestVar('blogid');
86 $itemid                 = intRequestVar('itemid');
87 $catid                  = intRequestVar('catid');
88 $skinid                 = requestVar('skinid');
89 $memberid               = requestVar('memberid');
90 $archivelist    = requestVar('archivelist');
91 $imagepopup             = requestVar('imagepopup');
92 $archive                = requestVar('archive');
93 $query                  = requestVar('query');
94 $highlight              = requestVar('highlight');
95 $amount                 = requestVar('amount');
96 $action                 = requestVar('action');
97 $nextaction             = requestVar('nextaction');
98 $maxresults     = requestVar('maxresults');
99 $startpos       = intRequestVar('startpos');
100 $errormessage   = '';
101
102 if (!headers_sent())
103         header('Generator: Nucleus ' . $nucleus['version']);
104
105 // include core classes that are needed for login & plugin handling
106 include($DIR_LIBS . 'MEMBER.php');
107 include($DIR_LIBS . 'ACTIONLOG.php');
108 include($DIR_LIBS . 'MANAGER.php');
109 include($DIR_LIBS . 'PLUGIN.php');
110
111 $manager =& MANAGER::instance();
112
113 // make sure there's no unnecessary escaping:
114 set_magic_quotes_runtime(0);
115
116 // only needed when updating logs
117 if ($CONF['UsingAdminArea']) {
118         include($DIR_LIBS . 'xmlrpc.inc.php');  // XML-RPC client classes
119         include_once($DIR_LIBS . 'ADMIN.php');
120 }
121
122
123 // connect to sql
124 sql_connect();
125
126 // makes sure database connection gets closed on script termination
127 register_shutdown_function('sql_disconnect');
128
129 // read config
130 getConfig();
131
132 // automatically use simpler toolbar for mozilla
133 if (($CONF['DisableJsTools'] == 0) && strstr(serverVar('HTTP_USER_AGENT'),'Mozilla/5.0') && strstr(serverVar('HTTP_USER_AGENT'),'Gecko'))
134         $CONF['DisableJsTools'] = 2;
135
136 // login if cookies set
137
138 $member =& new MEMBER();
139
140 // login/logout when required or renew cookies
141 if ($action == 'login') {
142         // Form Authentication
143         $login  = postVar('login');
144         $pw     = postVar('password');
145         $shared = intPostVar('shared'); // shared computer or not
146
147         if ($member->login($login,$pw)) {
148
149                 $member->newCookieKey();
150                 $member->setCookies($shared);
151
152                 // allows direct access to parts of the admin area after logging in
153                 if ($nextaction)
154                         $action = $nextaction;
155
156                 $manager->notify('LoginSuccess',array('member' => &$member));
157                 ACTIONLOG::add(INFO, "Login successful for $login (sharedpc=$shared)");
158         } else {
159                 $manager->notify('LoginFailed',array('username' => $login));
160                 ACTIONLOG::add(INFO, 'Login failed for ' . $login);
161         }
162 /*
163
164 Backed out for now: See http://forum.nucleuscms.org/viewtopic.php?t=3684 for details
165
166 } elseif (serverVar('PHP_AUTH_USER') && serverVar('PHP_AUTH_PW')) {
167         // HTTP Authentication
168        $login  = serverVar('PHP_AUTH_USER');
169        $pw     = serverVar('PHP_AUTH_PW');
170
171        if ($member->login($login,$pw)) {
172                $manager->notify('LoginSuccess',array('member' => &$member));
173                ACTIONLOG::add(INFO, "HTTP authentication successful for $login");
174        } else {
175                $manager->notify('LoginFailed',array('username' => $login));
176                ACTIONLOG::add(INFO, 'HTTP authentication failed for ' . $login);
177
178                //Since bad credentials, generate an apropriate error page
179                header("WWW-Authenticate: Basic realm=\"Nucleus {$nucleus['version']}\"");
180                header('HTTP/1.0 401 Unauthorized');
181                echo 'Invalid username or password';
182                exit;
183        }
184 */
185
186 } elseif (($action == 'logout') && (!headers_sent()) && cookieVar($CONF['CookiePrefix'] . 'user')){
187         // remove cookies on logout
188         setcookie($CONF['CookiePrefix'] .'user','',(time()-2592000),$CONF['CookiePath'],$CONF['CookieDomain'],$CONF['CookieSecure']);
189         setcookie($CONF['CookiePrefix'] .'loginkey','',(time()-2592000),$CONF['CookiePath'],$CONF['CookieDomain'],$CONF['CookieSecure']);
190         $manager->notify('Logout',array('username' => cookieVar($CONF['CookiePrefix'] .'user')));
191 } elseif (cookieVar($CONF['CookiePrefix'] .'user')) {
192         // Cookie Authentication
193         $res = $member->cookielogin(cookieVar($CONF['CookiePrefix'] .'user'), cookieVar($CONF['CookiePrefix'] .'loginkey'));
194
195         // renew cookies when not on a shared computer
196         if ($res && (cookieVar($CONF['CookiePrefix'] .'sharedpc') != 1) && (!headers_sent()))
197                 $member->setCookies();
198 }
199
200 // login completed
201 $manager->notify('PostAuthentication',array('loggedIn' => $member->isLoggedIn()));
202
203 // load other classes
204 include($DIR_LIBS . 'PARSER.php');
205 include($DIR_LIBS . 'SKIN.php');
206 include($DIR_LIBS . 'TEMPLATE.php');
207 include($DIR_LIBS . 'BLOG.php');
208 include($DIR_LIBS . 'COMMENTS.php');
209 include($DIR_LIBS . 'COMMENT.php');
210 //include($DIR_LIBS . 'ITEM.php');
211 include($DIR_LIBS . 'NOTIFICATION.php');
212 include($DIR_LIBS . 'BAN.php');
213 include($DIR_LIBS . 'PAGEFACTORY.php');
214 include($DIR_LIBS . 'SEARCH.php');
215
216
217 // set lastVisit cookie (if allowed)
218 if (!headers_sent()) {
219         if ($CONF['LastVisit'])
220                 setcookie($CONF['CookiePrefix'] .'lastVisit',time(),time()+2592000,$CONF['CookiePath'],$CONF['CookieDomain'],$CONF['CookieSecure']);
221         else
222                 setcookie($CONF['CookiePrefix'] .'lastVisit','',(time()-2592000),$CONF['CookiePath'],$CONF['CookieDomain'],$CONF['CookieSecure']);
223 }
224
225 // read language file, only after user has been initialized
226 $language = getLanguageName();
227 include($DIR_LANG . ereg_replace( '[\\|/]', '', $language) . '.php');
228
229 /*
230         Backed out for now: See http://forum.nucleuscms.org/viewtopic.php?t=3684 for details
231         
232 // To remove after v2.5 is released and language files have been updated. 
233 // Including this makes sure that language files for v2.5beta can still be used for v2.5final
234 // without having weird _SETTINGS_EXTAUTH string showing up in the admin area.
235 if (!defined('_MEMBERS_BYPASS'))
236 {
237         define('_SETTINGS_EXTAUTH',                     'Enable External Authentication');
238         define('_WARNING_EXTAUTH',                      'Warning: Enable only if needed.');
239         define('_MEMBERS_BYPASS',                       'Use External Authentication');
240 }
241
242 */
243
244 // make sure the archivetype skinvar keeps working when _ARCHIVETYPE_XXX not defined
245 if (!defined('_ARCHIVETYPE_MONTH'))
246 {
247         define('_ARCHIVETYPE_DAY','day');
248         define('_ARCHIVETYPE_MONTH','month');
249 }
250
251
252 // decode path_info
253 if ($CONF['URLMode'] == 'pathinfo') {
254         $data = explode("/",serverVar('PATH_INFO'));
255         for ($i=0;$i<sizeof($data);$i++) {
256                 switch ($data[$i]) {
257                         case 'item':                    // item/1 (blogid)
258                                 $i++;
259                                 if ($i<sizeof($data)) $itemid = intval($data[$i]);
260                                 break;
261                         case 'archives':                // archives/1 (blogid)
262                                 $i++;
263                                 if ($i<sizeof($data)) $archivelist = intval($data[$i]);
264                                 break;
265                         case 'archive':                 // two possibilities: archive/yyyy-mm or archive/1/yyyy-mm (with blogid)
266                                 if ((($i+1)<sizeof($data)) && (!strstr($data[$i+1],'-')) ){
267                                         $blogid = intval($data[++$i]);
268                                 }
269                                 $i++;
270                                 if ($i<sizeof($data)) $archive = $data[$i];
271                                 break;
272                         case 'blogid':                  // blogid/1
273                         case 'blog':                    // blog/1
274                                 $i++;
275                                 if ($i<sizeof($data)) $blogid = intval($data[$i]);
276                                 break;
277                         case 'category':                // category/1 (catid)
278                         case 'catid':
279                                 $i++;
280                                 if ($i<sizeof($data)) $catid = intval($data[$i]);
281                                 break;
282                         case 'member':
283                                 $i++;
284                                 if ($i<sizeof($data)) $memberid = intval($data[$i]);
285                                 break;
286                         default:
287                                 // skip...
288                 }
289         }
290 }
291
292 /**
293   * Connects to mysql server
294   */
295 function sql_connect() {
296         global $MYSQL_HOST, $MYSQL_USER, $MYSQL_PASSWORD, $MYSQL_DATABASE;
297
298         $connection = @mysql_connect($MYSQL_HOST, $MYSQL_USER, $MYSQL_PASSWORD) or startUpError('<p>Could not connect to MySQL database.</p>','Connect Error');
299         mysql_select_db($MYSQL_DATABASE) or startUpError('<p>Could not select database: '. mysql_error().'</p>', 'Connect Error');
300
301         return $connection;
302 }
303
304 /**
305  * returns a prefixed nucleus table name
306  */
307 function sql_table($name)
308 {
309         global $MYSQL_PREFIX;
310
311         if ($MYSQL_PREFIX)
312                 return $MYSQL_PREFIX . 'nucleus_' . $name;
313         else
314                 return 'nucleus_' . $name;
315 }
316
317 function sendContentType($contenttype, $pagetype = '', $charset = _CHARSET) {
318         global $manager, $CONF;
319         
320         if (!headers_sent()) {
321                 // if content type is application/xhtml+xml, only send it to browsers
322                 // that can handle it (IE6 cannot). Otherwise, send text/html
323                 
324                 // v2.5: For admin area pages, keep sending text/html (unless it's a debug version)
325                 //       application/xhtml+xml still causes too much problems with the javascript implementations
326                 if (
327                                 ($contenttype == 'application/xhtml+xml')
328                         &&      (($CONF['UsingAdminArea'] && !$CONF['debug']) || !stristr(serverVar('HTTP_ACCEPT'),'application/xhtml+xml'))
329                         )
330                 {
331                         $contenttype = 'text/html';
332                 }
333                         
334                 $manager->notify(
335                         'PreSendContentType',
336                         array(
337                                 'contentType' => &$contenttype,
338                                 'charset' => &$charset,
339                                 'pageType' => $pagetype
340                         )
341                 );
342
343                 // strip strange characters
344                 $contenttype = preg_replace('|[^a-z0-9-+./]|i', '', $contenttype);
345                 $charset = preg_replace('|[^a-z0-9-_]|i', '', $charset);
346                 
347                 header('Content-Type: ' . $contenttype . '; charset=' . $charset);                      
348         }
349         
350         
351
352         
353 }
354
355 /**
356  * Errors before the database connection has been made
357  */
358 function startUpError($msg, $title) {
359         ?>
360         <html xmlns="http://www.w3.org/1999/xhtml">
361                 <head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title><?php echo htmlspecialchars($title)?></title></head>
362                 <body>
363                         <h1><?php echo htmlspecialchars($title)?></h1>
364                         <?php echo $msg?>
365                 </body>
366         </html>
367         <?php   exit;
368 }
369
370 /**
371   * disconnects from SQL server
372   */
373 function sql_disconnect() {
374         @mysql_close();
375 }
376
377 /**
378   * executes an SQL query
379   */
380 function sql_query($query) {
381         $res = mysql_query($query) or print("mySQL error with query $query: " . mysql_error() . '<p />');
382         return $res;
383 }
384
385
386 /**
387  * Highlights a specific query in a given HTML text (not within HTML tags) and returns it
388  *
389  * @param $text
390  *              text to be highlighted
391  * @param $expression
392  *              regular expression to be matched (can be an array of expressions as well)
393  * @param $highlight
394  *              highlight to be used (use \\0 to indicate the matched expression)
395  *
396  */
397 function highlight($text, $expression, $highlight) {
398         if (!$highlight || !$expression) return $text;
399         if (is_array($expression) && (count($expression) == 0))
400                 return $text;
401
402         // add a tag in front (is needed for preg_match_all to work correct)
403         $text = '<!--h-->'.$text;
404
405         // split the HTML up so we have HTML tags
406         // $matches[0][i] = HTML + text
407         // $matches[1][i] = HTML
408         // $matches[2][i] = text
409         preg_match_all('/(<[^>]+>)([^<>]*)/', $text, $matches);
410
411         // throw it all together again while applying the highlight to the text pieces
412         $result = '';
413         for ($i = 0; $i < sizeof($matches[2]); $i++) {
414                 if ($i != 0) $result .= $matches[1][$i];
415
416                 if (is_array($expression)) {
417                         foreach ($expression as $regex)
418                                 if ($regex)
419                                         $matches[2][$i] = @eregi_replace($regex,$highlight,$matches[2][$i]);
420                         $result .= $matches[2][$i];
421                 } else {
422                         $result .= @eregi_replace($expression,$highlight,$matches[2][$i]);
423                 }
424         }
425
426         return $result;
427 }
428
429 /**
430  * Parses a query into an array of expressions that can be passed on to the highlight method
431  */
432 function parseHighlight($query) {
433         // TODO: add more intelligent splitting logic
434
435         // get rid of quotes
436         $query = preg_replace('/\'|"/','',$query);
437
438         if (!query) return array();
439
440         $aHighlight = explode(' ', $query);
441
442         for ($i = 0; $i<count($aHighlight); $i++) {
443                 $aHighlight[$i] = trim($aHighlight[$i]);
444                 if (strlen($aHighlight[$i]) < 3)
445                         unset($aHighlight[$i]);
446         }
447
448         if (count($aHighlight) == 1)
449                 return $aHighlight[0];
450         else
451                 return $aHighlight;
452 }
453
454 /**
455   * Checks if email address is valid
456   */
457 function isValidMailAddress($address) {
458         if (preg_match('/^[a-zA-Z0-9\._-]+@[a-zA-Z0-9\._-]+\.[A-Za-z]{2,5}$/', $address))
459                 return 1;
460         else
461                 return 0;
462 }
463
464
465 // some helper functions
466 function getBlogIDFromName($name) {
467         return quickQuery('SELECT bnumber as result FROM '.sql_table('blog').' WHERE bshortname="'.addslashes($name).'"');
468 }
469 function getBlogNameFromID($id) {
470         return quickQuery('SELECT bname as result FROM '.sql_table('blog').' WHERE bnumber='.intval($id));
471 }
472 function getBlogIDFromItemID($itemid) {
473         return quickQuery('SELECT iblog as result FROM '.sql_table('item').' WHERE inumber='.intval($itemid));
474 }
475 function getBlogIDFromCommentID($commentid) {
476         return quickQuery('SELECT cblog as result FROM '.sql_table('comment').' WHERE cnumber='.intval($commentid));
477 }
478 function getBlogIDFromCatID($catid) {
479         return quickQuery('SELECT cblog as result FROM '.sql_table('category').' WHERE catid='.intval($catid));
480 }
481 function getCatIDFromName($name) {
482         return quickQuery('SELECT catid as result FROM '.sql_table('category').' WHERE cname="'.addslashes($name).'"');
483 }
484 function quickQuery($q) {
485         $res = sql_query($q);
486         $obj = mysql_fetch_object($res);
487         return $obj->result;
488 }
489
490 function getPluginNameFromPid($pid) {
491         $obj = mysql_fetch_object(sql_query('SELECT pfile FROM '.sql_table('plugin').' WHERE pid='.intval($pid)));
492         return $obj->pfile;
493 }
494
495 function selector() {
496         global $itemid, $blogid, $memberid, $query, $amount, $archivelist, $maxresults;
497         global $archive, $skinid, $blog, $memberinfo, $CONF, $member;
498         global $imagepopup, $catid;
499         global $manager;
500
501         // first, let's see if the site is disabled or not
502         if ($CONF['DisableSite'] && !$member->isAdmin()) {
503                 redirect($CONF['DisableSiteURL']);
504                 exit;
505         }
506         
507         $actionNames = array('addcomment', 'sendmessage', 'createaccount', 'forgotpassword', 'votepositive', 'votenegative', 'plugin');
508         $action = requestVar('action');
509         if (in_array($action, $actionNames))
510         {
511                 global $DIR_LIBS, $errormessage;
512                 include_once($DIR_LIBS . 'ACTION.php');
513                 $a =& new ACTION();
514                 $errorInfo = $a->doAction($action);
515                 if ($errorInfo)
516                         $errormessage = $errorInfo['message'];
517         }       
518
519         // show error when headers already sent out
520         if (headers_sent() && $CONF['alertOnHeadersSent']) {
521
522                 // try to get line number/filename (extra headers_sent params only exists in PHP 4.3+)
523                 if (function_exists('version_compare') && version_compare('4.3.0', phpversion(), '<=')) {
524                         headers_sent($hsFile, $hsLine);
525                         $extraInfo = ' in <code>'.$hsFile.'</code> line <code>'.$hsLine.'</code>';
526                 } else {
527                         $extraInfo = '';
528                 }
529
530
531                 startUpError(
532                         '<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>',
533                         'Page headers already sent'
534                 );
535                 exit;
536         }
537
538         // make is so ?archivelist without blogname or blogid shows the archivelist
539         // for the default weblog
540         if (serverVar('QUERY_STRING') == 'archivelist')
541                 $archivelist = $CONF['DefaultBlog'];
542
543         // now decide which type of skin we need
544         if ($itemid) {
545                 // itemid given -> only show that item
546                 $type = 'item';
547                 if (!$manager->existsItem($itemid,0,0))
548                         doError(_ERROR_NOSUCHITEM);
549
550
551                 global $itemidprev, $itemidnext, $catid, $itemtitlenext, $itemtitleprev;
552
553                 // 1. get timestamp and blogid for item
554                 $query = 'SELECT itime, iblog FROM '.sql_table('item').' WHERE inumber=' . intval($itemid);
555                 $res = sql_query($query);
556                 $obj = mysql_fetch_object($res);
557
558                 // if a different blog id has been set through the request or selectBlog(),
559                 // deny access
560                 if ($blogid && (intval($blogid) != $obj->iblog))
561                         doError(_ERROR_NOSUCHITEM);
562
563                 $blogid = $obj->iblog;
564                 $timestamp = strtotime($obj->itime);
565
566                 $b =& $manager->getBlog($blogid);
567                 if ($b->isValidCategory($catid))
568                         $catextra = ' and icat=' . $catid;
569
570                 // get previous itemid and title
571                 $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';
572                 $res = sql_query($query);
573
574                 $obj = mysql_fetch_object($res);
575                 if ($obj) {
576                         $itemidprev = $obj->inumber;
577                         $itemtitleprev = $obj->ititle;
578         }
579
580                 // get next itemid and title
581                 $query = 'SELECT inumber, ititle FROM '.sql_table('item').' WHERE itime>' . mysqldate($timestamp) . ' and itime <= ' . mysqldate(time()) . ' and idraft=0 and iblog=' . $blogid . $catextra . ' ORDER BY itime ASC LIMIT 1';
582                 $res = sql_query($query);
583
584                 $obj = mysql_fetch_object($res);
585                 if ($obj) {
586                         $itemidnext = $obj->inumber;
587                         $itemtitlenext = $obj->ititle;
588                 }
589
590         } elseif ($archive) {
591                 // show archive
592                 $type = 'archive';
593
594                 // get next and prev month links
595                 global $archivenext, $archiveprev, $archivetype;
596
597                 sscanf($archive,'%d-%d-%d',$y,$m,$d);
598                 if ($d != 0) {
599                         $archivetype = _ARCHIVETYPE_DAY;
600                         $t = mktime(0,0,0,$m,$d,$y);
601                         $archiveprev = strftime('%Y-%m-%d',$t - (24*60*60));
602                         $archivenext = strftime('%Y-%m-%d',$t + (24*60*60));
603
604                 } else {
605                         $archivetype = _ARCHIVETYPE_MONTH;
606                         $t = mktime(0,0,0,$m,1,$y);
607                         $archiveprev = strftime('%Y-%m',$t - (1*24*60*60));
608                         $archivenext = strftime('%Y-%m',$t + (32*24*60*60));
609                 }
610
611
612         } elseif ($archivelist) {
613                 $type = 'archivelist';
614                 if (intval($archivelist) != 0)
615                         $blogid = $archivelist;
616                 else
617                         $blogid = getBlogIDFromName($archivelist);
618                 if (!$blogid) doError(_ERROR_NOSUCHBLOG);
619         } elseif ($query) {
620             global $startpos;
621                 $type = 'search';
622                 $query = stripslashes($query);
623                 if(preg_match("/^(\xA1{2}|\xe3\x80{2}|\x20)+$/",$query)){
624                                         $type = 'index';
625                 }
626                 $query = mb_convert_encoding($query, _CHARSET, 'UTF-8, EUC-JP, JIS, SJIS, ASCII');
627                 if (intval($blogid)==0)
628                         $blogid = getBlogIDFromName($blogid);
629                 if (!$blogid) doError(_ERROR_NOSUCHBLOG);
630         } elseif ($memberid) {
631                 $type = 'member';
632                 if (!MEMBER::existsID($memberid))
633                         doError(_ERROR_NOSUCHMEMBER);
634                 $memberinfo = MEMBER::createFromID($memberid);
635
636         } elseif ($imagepopup) {
637                 // media object (images etc.)
638                 $type = 'imagepopup';
639
640                 // TODO: check if media-object exists
641                 // TODO: set some vars?
642         } else {
643                 // show regular index page
644             global $startpos;
645                 $type = 'index';
646         }
647
648         // decide which blog should be displayed
649         if (!$blogid)
650                 $blogid = $CONF['DefaultBlog'];
651
652         $b =& $manager->getBlog($blogid);
653         $blog = $b;     // references can't be placed in global variables?
654         if (!$blog->isValid)
655                 doError(_ERROR_NOSUCHBLOG);
656
657         // set catid if necessary
658         if ($catid)
659                 $blog->setSelectedCategory($catid);
660
661         // decide which skin should be used
662         if ($skinid != '' && ($skinid == 0))
663                 selectSkin($skinid);
664         if (!$skinid)
665                 $skinid = $blog->getDefaultSkin();
666
667         
668         $skin =& new SKIN($skinid);
669         if (!$skin->isValid)
670                 doError(_ERROR_NOSUCHSKIN);
671
672         // parse the skin
673         $skin->parse($type);
674 }
675
676 /**
677   * Show error skin with given message. An optional skin-object to use can be given
678   */
679 function doError($msg, $skin = '') {
680         global $errormessage, $CONF, $skinid, $blogid, $manager;
681
682         if ($skin == '') {
683                 if (SKIN::existsID($skinid)) {
684                         $skin =& new SKIN($skinid);
685                 } elseif ($manager->existsBlogID($blogid)) {
686                         $blog =& $manager->getBlog($blogid);
687                         $skin =& new SKIN($blog->getDefaultSkin());
688                 } elseif ($CONF['DefaultBlog']) {
689                         $blog =& $manager->getBlog($CONF['DefaultBlog']);
690                         $skin =& new SKIN($blog->getDefaultSkin());
691                 } else {
692                         // this statement should actually never be executed
693                         $skin =& new SKIN($CONF['BaseSkin']);
694                 }
695         }
696
697         $errormessage = $msg;
698         $skin->parse('error');
699         exit;
700 }
701
702 function getConfig() {
703         global $CONF;
704
705         $query = 'SELECT * FROM '.sql_table('config');
706         $res = sql_query($query);
707         while ($obj = mysql_fetch_object($res)) {
708                 $CONF[$obj->name] = $obj->value;
709         }
710 }
711
712 // some checks for names of blogs, categories, templates, members, ...
713 function isValidShortName($name) {              return eregi('^[a-z0-9]+$', $name); }
714 function isValidDisplayName($name) {    return eregi('^[a-z0-9]+[a-z0-9 ]*[a-z0-9]+$', $name); }
715 function isValidCategoryName($name) {   return 1; } 
716 function isValidTemplateName($name) {   return eregi('^[a-z0-9/]+$', $name); }
717 function isValidSkinName($name) {               return eregi('^[a-z0-9/]+$', $name); }
718
719 // add and remove linebreaks
720 function addBreaks($var) {                              return nl2br($var); }
721 function removeBreaks($var) {                   return preg_replace("/<br \/>([\r\n])/","$1",$var); }
722
723 // shortens a text string to maxlength ($toadd) is what needs to be added
724 // at the end (end length is <= $maxlength)
725 function shorten($text, $maxlength, $toadd) {
726         // 1. remove entities...
727         $trans = get_html_translation_table(HTML_ENTITIES);
728         $trans = array_flip($trans);
729         $text = strtr($text, $trans);
730         // 2. the actual shortening
731         if (strlen($text) > $maxlength)
732                 $text = mb_strimwidth($text, 0, $maxlength, $toadd, "UTF-8");
733         return $text;
734 }
735
736 /**
737   * Converts a unix timestamp to a mysql DATETIME format, and places
738   * quotes around it.
739   */
740 function mysqldate($timestamp) {
741         return '"' . date('Y-m-d H:i:s',$timestamp) . '"';
742 }
743
744 /**
745   * functions for use in index.php
746   */
747 function selectBlog($shortname) {
748         global $blogid, $archivelist;
749         $blogid = getBlogIDFromName($shortname);
750
751         // also force archivelist variable, if it is set
752         if ($archivelist)
753                 $archivelist = $blogid;
754 }
755
756 function selectSkin($skinname) {
757         global $skinid;
758         $skinid = SKIN::getIdFromName($skinname);
759 }
760
761 /**
762  * Can take either a category ID or a category name (be aware that
763  * multiple categories can have the same name)
764  */
765 function selectCategory($cat) {
766         global $catid;
767         if (is_numeric($cat))
768                 $catid = intval($cat);
769         else
770                 $catid = getCatIDFromName($cat);
771 }
772
773 function selectItem($id){
774         global $itemid;
775         $itemid = intval($id);
776 }
777
778 // force the use of a language file (warning: can cause warnings)
779 function selectLanguage($language) {
780         global $DIR_LANG;
781         include($DIR_LANG . ereg_replace( '[\\|/]', '', $language) . '.php');
782 }
783
784 function parseFile($filename) {
785         $handler =& new ACTIONS('fileparser');
786         $parser =& new PARSER(SKIN::getAllowedActionsForType('fileparser'), $handler);
787         $handler->parser =& $parser;
788
789         if (!file_exists($filename)) doError('A file is missing');
790
791         $fsize = filesize($filename);
792         if ($fsize <= 0)
793                 return;
794
795         // read file
796         $fd = fopen ($filename, 'r');
797         $contents = fread ($fd, $fsize);
798         fclose ($fd);
799
800         // parse file contents
801         $parser->parse($contents);
802 }
803
804 /**
805   * Outputs a debug message
806   */
807 function debug($msg) {
808         echo '<p><b>' . $msg . "</b></p>\n";
809 }
810
811 // shortcut
812 function addToLog($level, $msg) { ACTIONLOG::add($level, $msg); }
813
814 // shows a link to help file
815 function help($id) {
816         echo helpHtml($id);
817 }
818
819 function helpHtml($id) {
820         return helplink($id) . '<img src="documentation/icon-help.gif" width="15" height="15" alt="'._HELP_TT.'" /></a>';
821 }
822
823 function helplink($id) {
824         return '<a href="documentation/help.html#'. $id . '" onclick="if (event &amp;&amp; event.preventDefault) event.preventDefault(); return help(this.href);">';
825 }
826
827 function getMailFooter() {
828         $message = "\n\n-----------------------------";
829         $message .=  "\n   Powered by Nucleus CMS";
830         $message .=  "\n(http://www.nucleuscms.org/)";
831         return $message;
832 }
833
834 /**
835   * Returns the name of the language to use
836   * preference priority: member - site
837   * defaults to english when no good language found
838   *
839   * checks if file exists, etc...
840   */
841 function getLanguageName() {
842         global $CONF, $member;
843
844         if ($member) {
845                 // try to use members language
846                 $memlang = $member->getLanguage();
847
848                 if (($memlang != '') && (checkLanguage($memlang)))
849                         return $memlang;
850         }
851
852         // use default language
853         if (checkLanguage($CONF['Language']))
854                 return $CONF['Language'];
855         else
856                 return 'english';
857 }
858
859 /**
860   * Includes a PHP file. This method can be called while parsing templates and skins
861   */
862 function includephp($filename) {
863         // make predefined variables global, so most simple scripts can be used here
864
865         // apache (names taken from PHP doc)
866         global $GATEWAY_INTERFACE, $SERVER_NAME, $SERVER_SOFTWARE, $SERVER_PROTOCOL;
867         global $REQUEST_METHOD, $QUERY_STRING, $DOCUMENT_ROOT, $HTTP_ACCEPT;
868         global $HTTP_ACCEPT_CHARSET, $HTTP_ACCEPT_ENCODING, $HTTP_ACCEPT_LANGUAGE;
869         global $HTTP_CONNECTION, $HTTP_HOST, $HTTP_REFERER, $HTTP_USER_AGENT;
870         global $REMOTE_ADDR, $REMOTE_PORT, $SCRIPT_FILENAME, $SERVER_ADMIN;
871         global $SERVER_PORT, $SERVER_SIGNATURE, $PATH_TRANSLATED, $SCRIPT_NAME;
872         global $REQUEST_URI;
873
874         // php (taken from PHP doc)
875         global $argv, $argc, $PHP_SELF, $HTTP_COOKIE_VARS, $HTTP_GET_VARS, $HTTP_POST_VARS;
876         global $HTTP_POST_FILES, $HTTP_ENV_VARS, $HTTP_SERVER_VARS, $HTTP_SESSION_VARS;
877
878         // other
879         global $PATH_INFO, $HTTPS, $HTTP_RAW_POST_DATA, $HTTP_X_FORWARDED_FOR;
880
881         if (@file_exists($filename)) include($filename);
882 }
883
884 /**
885   * Checks if a certain language/plugin exists
886   */
887 function checkLanguage($lang) {
888         global $DIR_LANG ;
889         return file_exists($DIR_LANG . ereg_replace( '[\\|/]', '', $lang) . '.php');
890 }
891 function checkPlugin($plug) {
892         global $DIR_PLUGINS;
893         return file_exists($DIR_PLUGINS . ereg_replace( '[\\|/]', '', $plug) . '.php');
894 }
895
896
897 $CONF['ItemURL'] = $CONF['Self'];
898 $CONF['ArchiveURL'] = $CONF['Self'];
899 $CONF['ArchiveListURL'] = $CONF['Self'];
900 $CONF['MemberURL'] = $CONF['Self'];
901 $CONF['SearchURL'] = $CONF['Self'];
902 $CONF['BlogURL'] = $CONF['Self'];
903 $CONF['CategoryURL'] = $CONF['Self'];
904
905 // switch URLMode back to normal when $CONF['Self'] ends in .php
906 // this avoids urls like index.php/item/13/index.php/item/15
907 if (    ($CONF['URLMode'] == 'pathinfo')
908         &&      (substr($CONF['Self'], strlen($CONF['Self']) - 4) == '.php')
909         ) {
910         $CONF['URLMode'] = 'normal';
911 }
912
913 /**
914   * Centralisation of the functions that generate links
915   */
916 function createItemLink($itemid, $extra = '') {
917         global $CONF;
918         if ($CONF['URLMode'] == 'pathinfo') {
919           if (substr($CONF['ItemURL'],strlen($CONF['ItemURL'])-1,1)=='/')
920                   $link = $CONF['ItemURL'] . 'item/' . $itemid;
921                 else
922                   $link = $CONF['ItemURL'] . '/item/' . $itemid;
923         }
924         else
925                 $link = $CONF['ItemURL'] . '?itemid=' . $itemid;
926         return addLinkParams($link, $extra);
927 }
928 function createMemberLink($memberid, $extra = '') {
929         global $CONF;
930         if ($CONF['URLMode'] == 'pathinfo')
931                 $link = $CONF['MemberURL'] . '/member/' . $memberid;
932         else
933                 $link = $CONF['MemberURL'] . '?memberid=' . $memberid;
934         return addLinkParams($link, $extra);
935 }
936 function createCategoryLink($catid, $extra = '') {
937         global $CONF;
938         if ($CONF['URLMode'] == 'pathinfo')
939                 $link = $CONF['CategoryURL'] . '/category/' . $catid;
940         else
941                 $link = $CONF['CategoryURL'] . '?catid=' . $catid;
942         return addLinkParams($link, $extra);
943 }
944 function createArchiveListLink($blogid = '', $extra = '') {
945         global $CONF;
946         if (!$blogid)
947                 $blogid = $CONF['DefaultBlog'];
948         if ($CONF['URLMode'] == 'pathinfo')
949                 $link = $CONF['ArchiveListURL'] . '/archives/' . $blogid;
950         else
951                 $link = $CONF['ArchiveListURL'] . '?archivelist=' . $blogid;
952         return addLinkParams($link, $extra);
953 }
954 function createArchiveLink($blogid, $archive, $extra = '') {
955         global $CONF;
956         if ($CONF['URLMode'] == 'pathinfo')
957                 $link = $CONF['ArchiveURL'] . '/archive/'.$blogid.'/' . $archive;
958         else
959                 $link = $CONF['ArchiveURL'] . '?blogid='.$blogid.'&amp;archive=' . $archive;
960         return addLinkParams($link, $extra);
961 }
962 function createBlogLink($url, $params) {
963         return addLinkParams($url . '?', $params);
964 }
965 function createBlogidLink($blogid, $params = '') {
966         global $CONF;
967         if ($CONF['URLMode'] == 'pathinfo')
968                 $link = $CONF['BlogURL'] . '/blog/' . $blogid;
969         else
970                 $link = $CONF['BlogURL'] . '?blogid=' . $blogid;
971         return addLinkParams($link, $params);
972 }
973
974
975 function addLinkParams($link, $params) {
976         global $CONF;
977         if (is_array($params)) {
978                 if ($CONF['URLMode'] == 'pathinfo')     {
979                         foreach ($params as $param => $value) {
980                                 $link .= '/' . $param . '/' . urlencode($value);
981                         }
982                 } else {
983                         foreach ($params as $param => $value) {
984                                 $link .= '&amp;' . $param . '=' . urlencode($value);
985                         }
986                 }
987         }
988         return $link;
989 }
990
991 /**
992  * @param $querystr
993  *              querystring to alter (e.g. foo=1&bar=2&x=y)
994  * @param $param
995  *              name of parameter to change (e.g. 'foo')
996  * @param $value
997  *              New value for that parameter (e.g. 3)
998  * @result 
999  *              altered query string (for the examples above: foo=3&bar=2&x=y)
1000  */
1001 function alterQueryStr($querystr, $param, $value) {
1002     $vars = explode("&", $querystr);
1003     $set  = false;
1004     for ($i=0;$i<count($vars);$i++) {
1005         $v = explode('=',$vars[$i]);
1006         if ($v[0] == $param) {
1007             $v[1]     = $value;
1008             $vars[$i] = implode('=', $v);
1009             $set      = true;
1010             break;
1011         }
1012     }
1013     if (!$set) {$vars[] = $param . '=' . $value;}
1014     return ltrim(implode('&', $vars), '&');
1015 }
1016
1017 // passes one variable as hidden input field (multiple fields for arrays)
1018 // @see passRequestVars in varsx.x.x.php
1019 function passVar($key, $value) {
1020         // array ?
1021         if (is_array($value)) {
1022                 for ($i=0;$i<sizeof($value);$i++)
1023                         passVar($key.'['.$i.']',$value[$i]);
1024                         return;
1025         }
1026
1027         // other values: do stripslashes if needed
1028         ?><input type="hidden" name="<?php echo htmlspecialchars($key)?>" value="<?php echo htmlspecialchars(undoMagic($value))?>" /><?php
1029 }
1030
1031 /*
1032         Date format functions (to be used from [%date(..)%] skinvars
1033 */
1034 function formatDate($format, $timestamp, $defaultFormat) {
1035         if ($format == 'rfc822') {
1036                 return date('r', $timestamp);
1037         } else if ($format == 'rfc822GMT') {
1038                 return gmdate('r', $timestamp);
1039         } else if ($format == 'utc') {
1040                 return gmdate('Y-m-d\TH:i:s\Z', $timestamp);
1041         } else if ($format == 'iso8601') {
1042         $tz = date('O', $timestamp);
1043         $tz = substr($tz, 0, 3) . ':' . substr($tz, 3, 2);
1044                 return gmdate('Y-m-d\TH:i:s', $timestamp) . $tz;
1045         } else {
1046                 return strftime($format ? $format : $defaultFormat,$timestamp);
1047         }
1048
1049 }
1050
1051 function checkVars($aVars)
1052 {
1053         global $HTTP_GET_VARS, $HTTP_POST_VARS, $HTTP_COOKIE_VARS, $HTTP_ENV_VARS, $HTTP_POST_FILES, $HTTP_SESSION_VARS;
1054         foreach ($aVars as $varName)
1055         {
1056                 if (phpversion() >= '4.1.0')
1057                 {
1058                         if (   isset($_GET[$varName]) 
1059                                 || isset($_POST[$varName]) 
1060                                 || isset($_COOKIE[$varName])
1061                                 || isset($_ENV[$varName])
1062                                 || isset($_SESSION[$varName])
1063                                 || isset($_FILES[$varName])
1064                         ){
1065                                 die('Sorry. An error occurred.');
1066                         }
1067                 } else {
1068                         if (   isset($HTTP_GET_VARS[$varName]) 
1069                                 || isset($HTTP_POST_VARS[$varName]) 
1070                                 || isset($HTTP_COOKIE_VARS[$varName])
1071                                 || isset($HTTP_ENV_VARS[$varName])
1072                                 || isset($HTTP_SESSION_VARS[$varName])
1073                                 || isset($HTTP_POST_FILES[$varName])
1074                         ){
1075                                 die('Sorry. An error occurred.');
1076                         }               
1077                 }
1078         }
1079 }
1080
1081 /** 
1082  * Stops processing the request and redirects to the given URL.
1083  * - no actual contents should have been sent to the output yet
1084  * - the URL will be stripped of illegal or dangerous characters
1085  */
1086 function redirect($url)
1087 {
1088         $url = preg_replace('|[^a-z0-9-~+_.?#=&;,/:@%]|i', '', $url);
1089         header('Location: ' . $url);
1090         exit;
1091 }
1092
1093 ?>