OSDN Git Service

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