OSDN Git Service

Shift_JIS support for mobile phone.
[nucleus-jp/nucleus-jp-ancient.git] / nucleus / libs / globalfunctions.php
index 3966005..bba7806 100755 (executable)
 /**
  * @license http://nucleuscms.org/license.txt GNU General Public License
  * @copyright Copyright (C) 2002-2007 The Nucleus Group
- * @version $Id: globalfunctions.php,v 1.16 2007-02-28 21:12:33 kmorimatsu Exp $
- * $NucleusJP: globalfunctions.php,v 1.15 2007/02/17 04:39:59 shizuki Exp $
+ * @version $Id: globalfunctions.php,v 1.24 2008-02-08 09:31:22 kimitake Exp $
+ * $NucleusJP: globalfunctions.php,v 1.23.2.7 2008/02/05 08:30:08 kimitake Exp $
  */
 
 // needed if we include globalfunctions from install.php
 global $nucleus, $CONF, $DIR_LIBS, $DIR_LANG, $manager, $member;
 
-//$nucleus['version'] = 'v3.3SVN';
-//$nucleus['codename'] = 'Lithium';
-$nucleus['version'] = 'v3.3';
+$nucleus['version'] = 'v3.4';
 $nucleus['codename'] = '';
 
 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'));
@@ -36,7 +34,7 @@ if ($CONF['debug']) {
 
 // Avoid notices
 if (!isset($CONF['Self'])) {
-       $CONF['Self'] = $_SERVER['PHP_SELF'];
+       $CONF['Self'] = htmlspecialchars($_SERVER['PHP_SELF'],ENT_QUOTES);
 }
 
 /*
@@ -171,6 +169,25 @@ if (($CONF['DisableJsTools'] == 0) && strstr(serverVar('HTTP_USER_AGENT'), 'Mozi
 // login if cookies set
 $member = new MEMBER();
 
+// secure cookie key settings (either 'none', 0, 8, 16, 24, or 32)
+if (!isset($CONF['secureCookieKey'])) $CONF['secureCookieKey']=24;
+switch($CONF['secureCookieKey']){
+case 8:
+       $CONF['secureCookieKeyIP']=preg_replace('/\.[0-9]+\.[0-9]+\.[0-9]+$/','',serverVar('REMOTE_ADDR'));
+       break;
+case 16:
+       $CONF['secureCookieKeyIP']=preg_replace('/\.[0-9]+\.[0-9]+$/','',serverVar('REMOTE_ADDR'));
+       break;
+case 24:
+       $CONF['secureCookieKeyIP']=preg_replace('/\.[0-9]+$/','',serverVar('REMOTE_ADDR'));
+       break;
+case 32:
+       $CONF['secureCookieKeyIP']=serverVar('REMOTE_ADDR');
+       break;
+default:
+       $CONF['secureCookieKeyIP']='';
+}
+
 // login/logout when required or renew cookies
 if ($action == 'login') {
        // Form Authentication
@@ -178,11 +195,19 @@ if ($action == 'login') {
        $pw = postVar('password');
        $shared = intPostVar('shared'); // shared computer or not
 
+       $pw=substr($pw,0,40); // avoid md5 collision by using a long key
+
        if ($member->login($login, $pw) ) {
 
                $member->newCookieKey();
                $member->setCookies($shared);
 
+               if ($CONF['secureCookieKey']!=='none') {
+                       // secure cookie key
+                       $member->setCookieKey(md5($member->getCookieKey().$CONF['secureCookieKeyIP']));
+                       $member->write();
+               }
+
                // allows direct access to parts of the admin area after logging in
                if ($nextaction) {
                        $action = $nextaction;
@@ -229,17 +254,23 @@ Backed out for now: See http://forum.nucleuscms.org/viewtopic.php?t=3684 for det
        $manager->notify('Logout', array('username' => cookieVar($CONF['CookiePrefix'] . 'user') ) );
 } elseif (cookieVar($CONF['CookiePrefix'] . 'user') ) {
        // Cookie Authentication
-       $res = $member->cookielogin(cookieVar($CONF['CookiePrefix'] . 'user'), cookieVar($CONF['CookiePrefix'] . 'loginkey') );
+       $ck=cookieVar($CONF['CookiePrefix'] . 'loginkey');
+       // secure cookie key
+       $ck=substr($ck,0,32); // avoid md5 collision by using a long key
+       if ($CONF['secureCookieKey']!=='none') $ck=md5($ck.$CONF['secureCookieKeyIP']);
+       $res = $member->cookielogin(cookieVar($CONF['CookiePrefix'] . 'user'), $ck );
+       unset($ck);
 
        // renew cookies when not on a shared computer
        if ($res && (cookieVar($CONF['CookiePrefix'] . 'sharedpc') != 1) && (!headers_sent() ) ) {
+               $member->setCookieKey(cookieVar($CONF['CookiePrefix'] . 'loginkey'));
                $member->setCookies();
        }
 }
 
 // login completed
-ticketForPlugin();
 $manager->notify('PostAuthentication', array('loggedIn' => $member->isLoggedIn() ) );
+ticketForPlugin();
 
 // first, let's see if the site is disabled or not. always allow admin area access.
 if ($CONF['DisableSite'] && !$member->isAdmin() && !$CONF['UsingAdminArea']) {
@@ -276,6 +307,13 @@ if (!headers_sent() ) {
 $language = getLanguageName();
 include($DIR_LANG . ereg_replace( '[\\|/]', '', $language) . '.php');
 
+// check if valid charset\r
+if (!encoding_check(false,false,_CHARSET)) {\r
+       foreach(array($_REQUEST, $_SERVER) as $input) {\r
+               array_walk($input, 'encoding_check');\r
+       }\r
+}\r
+\r
 /*
        Backed out for now: See http://forum.nucleuscms.org/viewtopic.php?t=3684 for details
 
@@ -324,6 +362,10 @@ if ($CONF['URLMode'] == 'pathinfo') {
                $CONF['CategoryKey'] = 'category';
        }
 
+       if ($CONF['SpecialskinKey'] == '') {
+               $CONF['SpecialskinKey'] = 'special';
+       }
+
        $parsed = false;
        $manager->notify(
                'ParseURL',
@@ -393,7 +435,7 @@ if ($CONF['URLMode'] == 'pathinfo') {
                                        }
                                        break;
 
-                case 'special':
+                case $CONF['SpecialskinKey']:
                     $i++;
 
                                        if ($i < sizeof($data) ) {
@@ -428,7 +470,7 @@ function intCookieVar($name) {
   * returns the currently used version (100 = 1.00, 101 = 1.01, etc...)
   */
 function getNucleusVersion() {
-       return 330;
+       return 340;
 }
 
 /**
@@ -516,6 +558,13 @@ function sendContentType($contenttype, $pagetype = '', $charset = _CHARSET) {
                } else {
                        header('Content-Type: ' . $contenttype);
                }
+\r
+               // check if valid charset\r
+               if (!encoding_check(false,false,$charset)) {\r
+                       foreach(array($_REQUEST, $_SERVER) as $input) {\r
+                               array_walk($input, 'encoding_check');\r
+                       }\r
+               }\r
        }
 }
 
@@ -523,9 +572,11 @@ function sendContentType($contenttype, $pagetype = '', $charset = _CHARSET) {
  * Errors before the database connection has been made
  */
 function startUpError($msg, $title) {
+       if (!defined('_CHARSET')) define('_CHARSET','iso-8859-1');\r
+       header('Content-Type: text/html; charset=' . _CHARSET);\r
        ?>
        <html xmlns="http://www.w3.org/1999/xhtml">
-               <head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+               <head><meta http-equiv="Content-Type" content="text/html; charset=<?php echo _CHARSET?>" />\r
                <title><?php echo htmlspecialchars($title)?></title></head>
                <body>
                        <h1><?php echo htmlspecialchars($title)?></h1>
@@ -749,7 +800,7 @@ function selector() {
 //             if ($blogid && (intval($blogid) != $obj->iblog) ) {
 //                     doError(_ERROR_NOSUCHITEM);
 //             }
-               if ($blogid && (intval($blogid) != $obj->iblog)) {
+               if ($blogid && (intval($blogid) != $obj->iblog) ) {
                        if (!headers_sent()) {
                                $b =& $manager->getBlog($obj->iblog);
                                $CONF['ItemURL'] = $b->getURL();
@@ -804,21 +855,61 @@ function selector() {
                // show archive
                $type = 'archive';
 
-               // get next and prev month links
-               global $archivenext, $archiveprev, $archivetype;
+               // get next and prev month links ...
+               global $archivenext, $archiveprev, $archivetype, $archivenextexists, $archiveprevexists;
+               
+               // sql queries for the timestamp of the first and the last published item
+               $query = "SELECT UNIX_TIMESTAMP(itime) as result FROM ".sql_table('item')." WHERE idraft=0 AND iblog=".(int)($blogid ? $blogid : $CONF['DefaultBlog'])." ORDER BY itime ASC";
+               $first_timestamp=quickQuery ($query);
+               $query = "SELECT UNIX_TIMESTAMP(itime) as result FROM ".sql_table('item')." WHERE idraft=0 AND iblog=".(int)($blogid ? $blogid : $CONF['DefaultBlog'])." ORDER BY itime DESC";
+               $last_timestamp=quickQuery ($query);
 
                sscanf($archive, '%d-%d-%d', $y, $m, $d);
 
                if ($d != 0) {
                        $archivetype = _ARCHIVETYPE_DAY;
                        $t = mktime(0, 0, 0, $m, $d, $y);
-                       $archiveprev = strftime('%Y-%m-%d', $t - (24 * 60 * 60) );
-                       $archivenext = strftime('%Y-%m-%d', $t + (24 * 60 * 60) );
+                       // one day has 24 * 60 * 60 = 86400 seconds                     
+                       $archiveprev = strftime('%Y-%m-%d', $t - 86400 );
+                       // check for published items                    
+                       if ($t > $first_timestamp) {
+                               $archiveprevexists = true;
+                       }
+                       else {
+                               $archiveprevexists = false;
+                       }
+                       
+                       // one day later
+                       $t += 86400; 
+                       $archivenext = strftime('%Y-%m-%d', $t);
+                       if ($t < $last_timestamp) {
+                               $archivenextexists = true;
+                       }
+                       else {
+                               $archivenextexists = false;
+                       }
+                       
                } else {
                        $archivetype = _ARCHIVETYPE_MONTH;
                        $t = mktime(0, 0, 0, $m, 1, $y);
-                       $archiveprev = strftime('%Y-%m', $t - (1 * 24 * 60 * 60) );
-                       $archivenext = strftime('%Y-%m', $t + (32 * 24 * 60 * 60) );
+                       // one day before is in the previous month
+                       $archiveprev = strftime('%Y-%m', $t - 86400);
+                       if ($t > $first_timestamp) {
+                               $archiveprevexists = true;
+                       }
+                       else {
+                               $archiveprevexists = false;
+                       }
+                       
+                       // timestamp for the next month                 
+                       $t = mktime(0, 0, 0, $m+1, 1, $y);
+                       $archivenext = strftime('%Y-%m', $t);
+                       if ($t < $last_timestamp) {
+                               $archivenextexists = true;
+                       }
+                       else {
+                               $archivenextexists = false;
+                       }
                }
 
        } elseif ($archivelist) {
@@ -913,6 +1004,9 @@ function selector() {
 
        // parse the skin
        $skin->parse($type);
+
+       // check to see we should throw JustPosted event
+       $blog->checkJustPosted();
 }
 
 /**
@@ -988,7 +1082,8 @@ function removeBreaks($var) {
 // at the end (end length is <= $maxlength)
 function shorten($text, $maxlength, $toadd) {
        // 1. remove entities...
-       $trans = get_html_translation_table(HTML_ENTITIES);
+//     $trans = get_html_translation_table(HTML_ENTITIES);
+       $trans = get_html_translation_table(HTML_SPECIALCHARS); // for Japanese
        $trans = array_flip($trans);
        $text = strtr($text, $trans);
 
@@ -1287,7 +1382,18 @@ function createLink($type, $params) {
 }
 
 function createBlogLink($url, $params) {
-       return addLinkParams($url . '?', $params);
+    global $CONF;
+    if ($CONF['URLMode'] == 'normal') {
+        if (strpos($url, '?') === FALSE && is_array($params)) {
+            $fParam = reset($params);
+            $fKey   = key($params);
+            array_shift($params);
+            $url .= '?' . $fKey . '=' . $fParam;
+        }
+    } elseif ($CONF['URLMode'] == 'pathinfo' && substr($url, -1) == '/') {
+        $url = substr($url, 0, -1);
+    }
+       return addLinkParams($url, $params);
 }
 
 function addLinkParams($link, $params) {
@@ -1405,6 +1511,75 @@ function formatDate($format, $timestamp, $defaultFormat, &$blog) {
        }
 }
 
+function encoding_check($val, $key, $encoding=false, $exclude=false) {\r
+       /*\r
+         When 3rd argument is set, return if checked already.\r
+         When 4th argument is set, set the excluded key(s).\r
+       */\r
+       static $search=false, $checked=array(), $excludes=array();\r
+       if ($exclude!==false) {\r
+               if (is_array($exclude)) {\r
+                       foreach($exclude as $v) $excludes[$v]=true;\r
+               } else $excludes[$excludes]=true;\r
+               return;\r
+       }\r
+       if ($encoding!==false) {\r
+               switch($encoding=strtolower($encoding)){\r
+                       case 'utf-8':\r
+                               $search='/^([\x00-\x7F]+'.\r
+                                       '|[\xC2-\xDF][\x80-\xBF]'.\r
+                                       '|[\xE0-\xEF][\x80-\xBF][\x80-\xBF]'.\r
+                                       '|[\xF0-\xF7][\x80-\xBF][\x80-\xBF][\x80-\xBF]'.\r
+                                       '|[\xF8-\xFB][\x80-\xBF][\x80-\xBF][\x80-\xBF][\x80-\xBF]'.\r
+                                       '|[\xFC-\xFD][\x80-\xBF][\x80-\xBF][\x80-\xBF][\x80-\xBF][\x80-\xBF])*/';\r
+                                       break;\r
+                       case 'euc-jp':\r
+                               $search='/^([\x00-\x7F]+'.\r
+                                       '|[\x8E][\xA0-\xDF]'.\r
+                                       '|[\x8F]?[\xA1-\xFE][\xA1-\xFE])*/';\r
+                               break;\r
+                       case 'gb2312':\r
+                               $search='/^([\x00-\x7F]+'.\r
+                                       '|[\xA1-\xF7][\xA1-\xFE])*/';\r
+                               break;\r
+                       case 'shift_jis':\r
+                               // Note that shift_jis is only supported for output.\r
+                               // Using shift_jis in DB is prohibited.\r
+                               $search='/^([\x00-\x7F\xA1-\xDF]+'.\r
+                                       '|[\x81-\x9F\xE0-\xFC][\x40-\xFC])*/';\r
+                               break;\r
+                       default:\r
+                               $search=false;\r
+                               if (preg_match('/^iso\-8859\-[0-9]{1,2}$/',$encoding)) break;\r
+                               if (preg_match('/^windows\-125[0-8]$/',$encoding)) break;\r
+                               startUpError('<p>Unknown or non-supported encoding.</p>', 'Encoding Error');\r
+                               exit;\r
+               }\r
+               if (isset($checked[$encoding])) return true; // Already checked.\r
+               $checked[$encoding]=true;\r
+       }\r
+       if ($key===false) return false; // Not yet checked.\r
+       if ($search===false) return true; // non-multibyte encoding\r
+       if (isset($excludes[$key])) return true; // This key isn't checked.\r
+       if (is_array($val)) {\r
+               array_walk($val, 'encoding_check');\r
+       } else {\r
+               preg_match($search,$val,$m);\r
+               $val2 = (string)$m[0];\r
+               if (!($val2 === (string)$val)) {\r
+                       startUpError('<p>Invalid input.</p>', 'Input Error');\r
+                       exit;\r
+               }\r
+       }\r
+       preg_match($search,$key,$m);\r
+       $key2 = (string)$m[0];\r
+       if (!($key2 === (string)$key)) {\r
+               startUpError('<p>Invalid input.</p>', 'Input Error');\r
+               exit;\r
+       }\r
+       return true;\r
+}\r
+\r
 function checkVars($aVars) {
        global $HTTP_GET_VARS, $HTTP_POST_VARS, $HTTP_COOKIE_VARS, $HTTP_ENV_VARS, $HTTP_POST_FILES, $HTTP_SESSION_VARS;
 
@@ -1518,7 +1693,7 @@ function ticketForPlugin(){
        /* Solve the plugin php file or admin directory */
        $phppath=substr($p_translated,strlen($d_plugins));
        $phppath=preg_replace('!^/!','',$phppath);// Remove the first "/" if exists.
-       $path=preg_replace('/^NP_([.]*)\.php$/','$1',$phppath); // Remove the first "NP_" and the last ".php" if exists.
+       $path=preg_replace('/^NP_(.*)\.php$/','$1',$phppath); // Remove the first "NP_" and the last ".php" if exists.
        $path=preg_replace('!^([^/]*)/(.*)$!','$1',$path); // Remove the "/" and beyond.
        
        /* Solve the plugin name. */
@@ -1531,7 +1706,7 @@ function ticketForPlugin(){
        }
        mysql_free_result($res);
        if ($plugins[$path]) $plugin_name=$plugins[$path];
-       else if (array_key_exists($path,$plugins)) $plugin_name=$path;
+       else if (in_array($path,$plugins)) $plugin_name=$path;
        else {
                header("HTTP/1.0 404 Not Found");
                exit('');
@@ -1702,7 +1877,7 @@ function sanitizeArray(&$array)
                if (!in_array($key, $excludeListForSanitization)) {
                                
                        // check value
-                       list($val, $tmp) = explode('\\', $val);
+                       @list($val, $tmp) = explode('\\', $val);
                        
                        // remove control code etc.
                        $val = strtr($val, "\0\r\n<>'\"", "       ");
@@ -1870,7 +2045,7 @@ function getBookmarklet($blogid) {
        $document = 'document';
        $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('";
        $bookmarkletline .= $CONF['AdminURL'] . "bookmarklet.php?blogid=$blogid";
-       $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();";
+       $bookmarkletline .="&logtext='+escape(Q)+'&loglink='+escape(x.location.href)+'&loglinktitle='+escape(x.title),'nucleusbm','scrollbars=yes,width=600,height=550,left=10,top=10,status=yes,resizable=yes');wingm.focus();";
 
        return $bookmarkletline;
 }
@@ -1890,4 +2065,17 @@ function ifset(&$var) {
        return null;
 }
 
+/**
+ * Returns number of subscriber to an event
+ *
+ * @param event
+ * @return number of subscriber(s)
+ */
+function numberOfEventSubscriber($event) {
+       $query = 'SELECT COUNT(*) as count FROM ' . sql_table('plugin_event') . ' WHERE event=\'' . $event . '\'';
+       $res = sql_query($query);
+       $obj = mysql_fetch_object($res);
+       return $obj->count;
+}
+
 ?>