X-Git-Url: http://git.osdn.net/view?p=nucleus-jp%2Fnucleus-next.git;a=blobdiff_plain;f=nucleus%2Flibs%2Fglobalfunctions.php;h=e6448a809c963a3f00df2ea8c285c6cd118abb7f;hp=8a1b8327c91ff392960cbe546edf584ffcf02683;hb=c90b0980cfa3e79cd4bc7eed551a64a5e2b02a5c;hpb=7e3069ed54acaed49a1ea33a4773454e06167941 diff --git a/nucleus/libs/globalfunctions.php b/nucleus/libs/globalfunctions.php index 8a1b832..e6448a8 100644 --- a/nucleus/libs/globalfunctions.php +++ b/nucleus/libs/globalfunctions.php @@ -1,3 +1,1811 @@ +<<<<<<< HEAD + 0 ) +{ + $nucleus['version'] .= '/' . getNucleusPatchLevel(); +} + +/* Avoid notices */ +if ( !array_key_exists('installscript', $CONF) || empty($CONF['installscript']) ) +{ + $CONF['installscript'] = 0; +} +if ( !array_key_exists('UsingAdminArea', $CONF) ) +{ + $CONF['UsingAdminArea'] = 0; +} + +if ( !headers_sent() ) +{ + header('Generator: Nucleus CMS ' . $nucleus['version']); +} + + +/* TODO: This is for compatibility since 4.0, should be obsoleted at future release. */ +if ( !isset($DIR_LOCALES) ) +{ + $DIR_LOCALES = $DIR_NUCLEUS . 'locales/'; +} +global $DIR_LANG; +if ( !isset($DIR_LANG) ) +{ + $DIR_LANG = $DIR_LOCALES; +} + +/* load and initialize i18n class */ +if (!class_exists('i18n', FALSE)) +{ + include($DIR_LIBS . 'i18n.php'); +} +if ( !i18n::init('UTF-8', $DIR_LOCALES) ) +{ + exit('Fail to initialize i18n class.'); +} + +/* TODO: This is just for compatibility since 4.0, should be obsoleted at future release. */ +define('_CHARSET', i18n::get_current_charset()); + + +/* + * NOTE: Since 4.0 release, Entity class becomes to be important class + * with some wrapper functions for htmlspechalchars/htmlentity PHP's built-in function + */ +include($DIR_LIBS . 'ENTITY.php'); + +/* we will use postVar, getVar, ... methods instead of $_GET, $_POST ... */ +if ( $CONF['installscript'] != 1 ) +{ + /* vars were already included in install.php */ + include_once($DIR_LIBS . 'vars4.1.0.php'); + + /* added for 4.0 DB::* wrapper and compatibility sql_* */ + include_once($DIR_LIBS . 'sql/sql.php'); +} + +/* include core classes that are needed for login & plugin handling */ +include($DIR_LIBS . 'MEMBER.php'); +include($DIR_LIBS . 'ACTIONLOG.php'); +include($DIR_LIBS . 'MANAGER.php'); +include($DIR_LIBS . 'PLUGIN.php'); + +$manager =& MANAGER::instance(); + +/* only needed when updating logs */ +if ( $CONF['UsingAdminArea'] ) +{ + /* XML-RPC client classes */ + include($DIR_LIBS . 'xmlrpc.inc.php'); + include($DIR_LIBS . 'ADMIN.php'); +} + + +/* connect to database */ +if ( !isset($MYSQL_HANDLER) ) +{ + $MYSQL_HANDLER = array('mysql',''); +} +if ( $MYSQL_HANDLER[0] == '' ) +{ + $MYSQL_HANDLER[0] = 'mysql'; +} +DB::setConnectionInfo($MYSQL_HANDLER[1], $MYSQL_HOST, $MYSQL_USER, $MYSQL_PASSWORD, $MYSQL_DATABASE); + + +/* force locale or charset */ +$locale = ''; +$charset = i18n::get_current_charset(); + +$data = array( + 'locale' => &$locale, + 'charset' => &$charset +); +$manager->notify('ForceLocale', $data); + +if ( $data['locale'] !== '' ) +{ + i18n::set_forced_locale($data['locale']); +} +if ( $data['charset'] !== '' ) +{ + i18n::set_forced_charset($data['charset']); +} +unset($locale); +unset($charset); + + +/* convert forced charset to current charset */ +if ( i18n::get_forced_charset() != i18n::get_current_charset() ) +{ + $_POST = i18n::convert_array($_POST, i18n::get_forced_charset()); + $_GET = i18n::convert_array($_GET, i18n::get_forced_charset()); + $_REQUEST = i18n::convert_array($_REQUEST, i18n::get_forced_charset()); + $_COOKIE = i18n::convert_array($_COOKIE, i18n::get_forced_charset()); + $_FILES = i18n::convert_array($_FILES, i18n::get_forced_charset()); + + if ( session_id() !== '' ) + { + $_SESSION = i18n::convert_array($_SESSION, i18n::get_forced_charset()); + } +} + + +/* sanitize option */ +$bLoggingSanitizedResult = 0; +$bSanitizeAndContinue = 0; +$orgRequestURI = serverVar('REQUEST_URI'); +sanitizeParams(); + +/* logs sanitized result if need */ +if ( $orgRequestURI !== serverVar('REQUEST_URI') ) +{ + $msg = "Sanitized [" . serverVar('REMOTE_ADDR') . "] "; + $msg .= $orgRequestURI . " -> " . serverVar('REQUEST_URI'); + if ( $bLoggingSanitizedResult ) + { + addToLog(WARNING, $msg); + } + if ( !$bSanitizeAndContinue ) + { + die(""); + } +} + +/* get all variables that can come from the request and put them in the global scope */ +$blogid = requestVar('blogid'); +$itemid = intRequestVar('itemid'); +$catid = intRequestVar('catid'); +$skinid = requestVar('skinid'); +$memberid = requestVar('memberid'); +$archivelist = requestVar('archivelist'); +$imagepopup = requestVar('imagepopup'); +$archive = requestVar('archive'); +$query = requestVar('query'); +$highlight = requestVar('highlight'); +$amount = requestVar('amount'); +$action = requestVar('action'); +$nextaction = requestVar('nextaction'); +$maxresults = requestVar('maxresults'); +$startpos = intRequestVar('startpos'); +$errormessage = ''; +$error = ''; +$special = requestVar('special'); + + +/* read config */ +getConfig(); + + +/* Properly set $CONF['Self'] and others if it's not set... + * usually when we are access from admin menu + */ +if ( !array_key_exists('Self', $CONF) ) +{ + $CONF['Self'] = $CONF['IndexURL']; + /* strip trailing */ + if ( $CONF['Self'][i18n::strlen($CONF['Self']) -1] == "/" ) + { + $CONF['Self'] = i18n::substr($CONF['Self'], 0, i18n::strlen($CONF['Self']) -1); + } +} + +$CONF['ItemURL'] = $CONF['Self']; +$CONF['ArchiveURL'] = $CONF['Self']; +$CONF['ArchiveListURL'] = $CONF['Self']; +$CONF['MemberURL'] = $CONF['Self']; +$CONF['SearchURL'] = $CONF['Self']; +$CONF['BlogURL'] = $CONF['Self']; +$CONF['CategoryURL'] = $CONF['Self']; + +/* automatically use simpler toolbar for mozilla */ +if ( ($CONF['DisableJsTools'] == 0) + && i18n::strpos(serverVar('HTTP_USER_AGENT'), 'Mozilla/5.0') !== FALSE + && i18n::strpos(serverVar('HTTP_USER_AGENT'), 'Gecko') !== FALSE ) +{ + $CONF['DisableJsTools'] = 2; +} + +/* login processing */ +$member = new Member(); + +if ( $action == 'login' ) +{ + $login = postVar('login'); + $password = postVar('password'); + $shared = intPostVar('shared'); + $member->login($login, $password, $shared); +} +elseif ( ($action == 'logout') ) +{ + $member->logout(); +} +else +{ + $member->cookielogin(); +} + + +/* TODO: This is for backward compatibility, should be obsoleted near future. */ +if ( !preg_match('#^(.+)_(.+)_(.+)$#', $CONF['Locale']) + && ($CONF['Locale'] = i18n::convert_old_language_file_name_to_locale($CONF['Locale'])) === FALSE ) +{ + $CONF['Locale'] = 'en_Latn_US'; +} +if ( !array_key_exists('Language', $CONF) ) +{ + $CONF['Language'] = i18n::convert_locale_to_old_language_file_name($CONF['Locale']); +} +$locale = $CONF['Locale']; + + +/* NOTE: include translation file and set locale */ +if ( $member->isLoggedIn() ) +{ + if ( $member->getLocale() ) + { + $locale = $member->getLocale(); + } +} +else +{ + if ( i18n::get_forced_locale() !== '' ) + { + $locale = i18n::get_forced_locale(); + } +} +include_translation($locale); +i18n::set_current_locale($locale); + + +/* login completed */ +$manager->notify('PostAuthentication', array('loggedIn' => $member->isLoggedIn() ) ); + +/* next action */ +if ( $member->isLoggedIn() && $nextaction ) +{ + $action = $nextaction; +} + +/* first, let's see if the site is disabled or not. always allow admin area access. */ +if ( $CONF['DisableSite'] && !$member->isAdmin() && !$CONF['UsingAdminArea'] ) +{ + redirect($CONF['DisableSiteURL']); + exit; +} + +/* load other classes */ +include($DIR_LIBS . 'PARSER.php'); +include($DIR_LIBS . 'SKIN.php'); +include($DIR_LIBS . 'TEMPLATE.php'); +include($DIR_LIBS . 'BLOG.php'); +include($DIR_LIBS . 'BODYACTIONS.php'); +include($DIR_LIBS . 'COMMENTS.php'); +include($DIR_LIBS . 'COMMENT.php'); +include($DIR_LIBS . 'NOTIFICATION.php'); +include($DIR_LIBS . 'BAN.php'); +include($DIR_LIBS . 'PAGEFACTORY.php'); +include($DIR_LIBS . 'SEARCH.php'); +include($DIR_LIBS . 'LINK.php'); + +/* set lastVisit cookie (if allowed) */ +if ( !headers_sent() ) +{ + if ( $CONF['LastVisit'] ) + { + setcookie($CONF['CookiePrefix'] . 'lastVisit', time(), time() + 2592000, $CONF['CookiePath'], $CONF['CookieDomain'], $CONF['CookieSecure']); + } + else + { + setcookie($CONF['CookiePrefix'] . 'lastVisit', '', (time() - 2592000), $CONF['CookiePath'], $CONF['CookieDomain'], $CONF['CookieSecure']); + } +} + +if ( !defined('_ARCHIVETYPE_MONTH') ) +{ + define('_ARCHIVETYPE_DAY', 'day'); + define('_ARCHIVETYPE_MONTH', 'month'); + define('_ARCHIVETYPE_YEAR', 'year'); +} + +/* for path resolving */ +$virtualpath = getVar('virtualpath'); +if ( getVar('virtualpath') == '' ) + { + $virtualpath = serverVar('PATH_INFO'); + } + +/* + * switch URLMode back to normal when $CONF['Self'] ends in .php + * this avoids urls like index.php/item/13/index.php/item/15 + */ +if ( !array_key_exists('URLMode', $CONF) || ($CONF['URLMode'] != 'pathinfo') ) + { + $CONF['URLMode'] = 'normal'; + } +else + { + if ( i18n::substr($CONF['Self'], i18n::strlen($CONF['Self']) - 4) != '.php' ) + { + decodePathInfo($virtualpath); + } +} + +/* + * PostParseURL is a place to cleanup any of the path-related global variables before the selector function is run. + * It has 2 values in the data in case the original virtualpath is needed, but most the use will be in tweaking + * global variables to clean up (scrub out catid or add catid) or to set someother global variable based on + * the values of something like catid or itemid + * New in 3.60 + */ +$data = array( + 'type' => basename(serverVar('SCRIPT_NAME')), + 'info' => $virtualpath +); +$manager->notify('PostParseURL', $data); + +/* + * NOTE: Here is the end of initialization + */ + +/** + * include_libs() + * This function includes or requires the specified library file + * + * @param string $file + * @param boolean $once use the _once() version + * @param boolean $require use require() instead of include() + * @return void + */ +function include_libs($file, $once = TRUE, $require = TRUE) +{ + global $DIR_LIBS; + + // $DIR_LIBS isn't a directory + if ( !is_dir($DIR_LIBS) ) + { + exit; + } + + $lib_path = $DIR_LIBS . $file; + + if ( $once && $require ) + { + require_once($lib_path); + } + else if ( $once && !$require ) + { + include_once($lib_path); + } + else if ( $require ) + { + require($lib_path); + } + else + { + include($lib_path); + } + return; +} + +/** + * include_plugins() + * This function includes or requires the specified plugin file + * + * @param string $file + * @param boolean $once use the _once() version + * @param boolean $require use require() instead of include() + * @return + */ +function include_plugins($file, $once = TRUE, $require = TRUE) +{ + global $DIR_PLUGINS; + + // begin if: $DIR_LIBS isn't a directory + if ( !is_dir($DIR_PLUGINS) ) + { + exit; + } + + $plugin_path = $DIR_PLUGINS . $file; + + // begin if: + if ( $once && $require ) + { + require_once($plugin_path); + } + else if ( $once && !$require ) + { + include_once($plugin_path); + } + elseif ( $require ) + { + require($plugin_path); + } + else + { + include($plugin_path); + } + return; +} + +/** + * include_translation() + * This function decide which locale is used and include translation + * + * @param string &$locale locale name referring to 'language tags' defined in RFC 5646 + * @return void + */ +function include_translation(&$locale) +{ + global $DIR_LOCALES; + + $translation_file = $DIR_LOCALES . $locale . '.' . i18n::get_current_charset() . '.php'; + if ( !file_exists($translation_file) ) + { + $locale = 'en_Latn_US'; + $translation_file = $DIR_LOCALES . 'en_Latn_US.ISO-8859-1.php'; + } + include($translation_file); + return; +} + +/** + * intPostVar() + * This function returns the integer value of $_POST for the variable $name + * + * @param string $name field to get the integer value of + * @return integer + */ +function intPostVar($name) +{ + return (integer) postVar($name); +} + + +/** + * intGetVar() + * This function returns the integer value of $_GET for the variable $name + * + * @param string $name field to get the integer value of + * @return integer + */ +function intGetVar($name) +{ + return (integer) getVar($name); +} + + +/** + * intRequestVar() + * This function returns the integer value of $_REQUEST for the variable $name. Also checks $_GET and $_POST if not found in $_REQUEST + * + * @param string $name field to get the integer value of + * @return int + */ +function intRequestVar($name) +{ + return (integer) requestVar($name); +} + + +/** + * intCookieVar() + * This function returns the integer value of $_COOKIE for the variable $name + * + * @param string $name field to get the integer value of + * @return integer + */ +function intCookieVar($name) +{ + return (integer) cookieVar($name); +} + +/** + * getNucleusVersion() + * This function returns the current Nucleus version (100 = 1.00, 101 = 1.01, etc...) + * + * @param void + * @return integer + */ +function getNucleusVersion() +{ + return 400; +} + +/** + * getNucleusPatchLevel() + * TODO: Better description of this function. + * + * Power users can install patches in between nucleus releases. These patches + * usually add new functionality in the plugin API and allow those to + * be tested without having to install CVS. + * + *@param void + * @return integer + */ +function getNucleusPatchLevel() +{ + return 0; +} + +/** + * getLatestVersion() + * This function returns the latest Nucleus version available for download from nucleuscms.org or FALSE if unable to attain data + * Format will be major.minor/patachlevel e.g. 3.41 or 3.41/02 + * + * @param void + * @return mixed + */ +function getLatestVersion() +{ + // begin if: cURL is not available in this PHP installation + if ( !function_exists('curl_init') ) + { + return FALSE; + } + + $curl = curl_init(); + $timeout = 5; + + curl_setopt ($curl, CURLOPT_URL, 'http://nucleuscms.org/version_check.php'); + curl_setopt ($curl, CURLOPT_RETURNTRANSFER, 1); + curl_setopt ($curl, CURLOPT_CONNECTTIMEOUT, $timeout); + + $return = curl_exec($curl); + + curl_close($curl); + + return $return; +} + +/** + * sql_table() + * This function returns a Nucleus table name with the appropriate prefix + * @param string $name + * @return string + */ +function sql_table($name) +{ + global $MYSQL_PREFIX; + + // begin if: no MySQL prefix + if ( empty($MYSQL_PREFIX) ) + { + return 'nucleus_' . $name; + } + // else: use MySQL prefix + else + { + return $MYSQL_PREFIX . 'nucleus_' . $name; + } + return; +} + +/** + * sendContentType() + * This function sends the Content-Type header if headers have not already been sent + * It also determines if the browser can accept application/xhtml+xml and sends it only to those that can. + * + * if content type is application/xhtml+xml, only send it to browsers + * that can handle it (IE6 cannot). Otherwise, send text/html + * + * v2.5: + * For admin area pages, keep sending text/html (unless it's a debug version) + * application/xhtml+xml still causes too much problems with the javascript implementations + * + * v3.3: + * ($CONF['UsingAdminArea'] && !$CONF['debug']) gets removed, + * application/xhtml+xml seems to be working, so we're going to use it if we can. + * + * @param string $content_type MIME media type registered to IANA, http://www.iana.org/assignments/media-types/index.html + * @param string $page_type + * @param string $charset Deprecated. This has no meaning. + * @return void + * + */ +function sendContentType($content_type, $page_type = '', $charset = '') +{ + global $manager, $CONF; + + if ( headers_sent() ) + { + return; + } + + /* NOTE: MIME Media Type */ + if ( ($content_type == 'application/xhtml+xml') + && (!stristr(serverVar('HTTP_ACCEPT'), 'application/xhtml+xml') ) ) + { + $content_type = 'text/html'; + } + + /* NOTE: generate event */ + $data = array( + 'pageType' => $page_type, + 'contentType' => &$content_type + ); + $manager->notify('PreSendContentType', $data); + + /* NOTE: confirm MIME Media Type */ + $content_type = preg_replace('#[^a-zA-Z0-9-+./]#', '', $content_type); + + /* NOTE: confirm character set */ + $charset = i18n::get_current_charset(); + if ( i18n::get_forced_charset() !== '' ) + { + $charset = i18n::get_forced_charset(); + } + + /* NOTE: send HTTP 1.1 header */ + header("Content-Type: {$content_type}; charset={$charset}"); + + /* NOTE: set handler for translating character set */ + if ( $charset != i18n::get_current_charset() ) + { + ob_start(array('i18n', 'convert_handler')); + } + + return; +} + +/** + * parseHighlight() + * This function parses a query into an array of expressions that can be passed on to the highlight method + * @param string $query + * @return void + */ +function parseHighlight($query) +{ + // TODO: add more intelligent splitting logic + + // get rid of quotes + $query = preg_replace('/\'|"/', '', $query); + + if ( !$query ) + { + return array(); + } + + $aHighlight = preg_split('# #', $query); + + for ( $i = 0; $i < count($aHighlight); $i++ ) + { + $aHighlight[$i] = trim($aHighlight[$i]); + + if ( i18n::strlen($aHighlight[$i]) < 3 ) + { + unset($aHighlight[$i]); + } + } + + if ( count($aHighlight) == 1 ) + { + return $aHighlight[0]; + } + else + { + return $aHighlight; + } + return; +} + +/** + * getConfig() + * + * @param void + * @return void + */ +function getConfig() +{ + global $CONF; + + $query = sprintf('SELECT * FROM %s', sql_table('config')); + $res = DB::getResult($query); + + foreach ( $res as $row ) + { + $CONF[$row['name']] = $row['value']; + } + return; +} + +/** + * This function gets the blog ID from the blog name + * @param string $name + * @return + */ +function getBlogIDFromName($name) +{ + $query = sprintf('SELECT bnumber AS result FROM %s WHERE bshortname=%s', sql_table('blog'), DB::quoteValue($name)); + return DB::getValue($query); +} + +/** + * This function gets the blog name from the blog ID + * @param int $id + * @return object + */ +function getBlogNameFromID($id) +{ + $query = sprintf('SELECT bname AS result FROM %s WHERE bnumber=%d', sql_table('blog'), intval($id)); + return DB::getValue($query); +} + +/** + * This function gets the blog ID from the item ID + * @param int $item_id + * @return object + */ +function getBlogIDFromItemID($item_id) +{ + $query = sprintf('SELECT iblog AS result FROM %s WHERE inumber=%d', sql_table('item'), intval($item_id)); + return DB::getValue($query); +} + +/** + * This function gets the blog ID from the comment ID + * @param int $comment_id + * @return object + */ +function getBlogIDFromCommentID($comment_id) +{ + $query = sprintf('SELECT cblog AS result FROM %s WHERE cnumber=%d', sql_table('comment'), intval($comment_id)); + return DB::getValue($query); +} + +/** + * This function gets the blog ID from the category ID + * @param int $category_id + * @return object + */ +function getBlogIDFromCatID($category_id) +{ + $query = sprintf('SELECT cblog AS result FROM %s WHERE catid=%d', sql_table('category'), intval($category_id)); + return DB::getValue($query); +} + +/** + * This function gets the category ID from the category name + * @param int $name + * @return object + */ +function getCatIDFromName($name) +{ + $query = sprintf('SELECT catid AS result FROM %s WHERE cname=%s', sql_table('category'), DB::quoteValue($name)); + return DB::getValue($query); +} + + +/** + * functions to be used in index.php to select something + */ +function selectBlog($shortname) +{ + global $blogid, $archivelist; + $blogid = getBlogIDFromName($shortname); + + // also force archivelist variable, if it is set + if ( $archivelist ) + { + $archivelist = $blogid; + } + return; +} +function selectSkin($skinname) +{ + global $skinid; + $skinid = SKIN::getIdFromName($skinname); + return; +} +function selectCategory($cat) +{ + global $catid; + if ( is_numeric($cat) ) + { + $catid = (integer) $cat; + } + else + { + $catid = getCatIDFromName($cat); + } + return; +} +function selectItem($id) +{ + global $itemid; + $itemid = (integer) $id; + return; +} +function selectSpecialSkinType($id) +{ + global $special; + $special = strtolower($id); + return; +} +function selector() +{ + global $archive, $archivelist, $archivenext, $archivenextexists, $archiveprev, $archiveprevexists, $archivetype; + global $blog, $blogid; + global $catid; + global $itemid, $itemidnext, $itemidprev, $itemtitlenext, $itemtitleprev; + global $CONF, $DIR_LIBS, $amount, $errormessage, $imagepopup; + global $manager, $maxresults, $query; + global $member, $memberid, $memberinfo; + global $skinid, $skinpart, $special; + + $actionNames = array('addcomment', 'sendmessage', 'createaccount', 'forgotpassword', 'votepositive', 'votenegative', 'plugin'); + $action = requestVar('action'); + + if ( in_array($action, $actionNames) ) + { + include_once($DIR_LIBS . 'ACTION.php'); + $a = new Action(); + $errorInfo = $a->doAction($action); + + if ( $errorInfo ) + { + $errormessage = $errorInfo['message']; + } + } + + // show error when headers already sent out + if ( headers_sent() && $CONF['alertOnHeadersSent'] ) + { + // try to get line number/filename (extra headers_sent params only exists in PHP 4.3+) + if ( function_exists('version_compare') && version_compare('4.3.0', phpversion(), '<=') ) + { + headers_sent($hsFile, $hsLine); + $extraInfo = ' in ' . $hsFile . ' line ' . $hsLine . ''; + } + else + { + $extraInfo = ''; + } + + startUpError( + "

The page headers have already been sent out{$extraInfo}. This could cause Nucleus not to work in the expected way.

" + . "

Usually, this is caused by spaces or newlines at the end of the config.php file, " + . "at the end of the translation file or at the end of a plugin file.

" + . "

Please check this and try again.

" + . "

If you don't want to see this error message again, without solving the problem, " + . "set {$CONF['alertOnHeadersSent']} in globalfunctions.php to 0

" + . "Page headers already sent" + ); + exit; + } + + // make is so ?archivelist without blogname or blogid shows the archivelist + // for the default weblog + if ( serverVar('QUERY_STRING') == 'archivelist' ) + { + $archivelist = $CONF['DefaultBlog']; + } + + // now decide which type of skin we need + if ( $itemid ) + { + // itemid given -> only show that item + $type = 'item'; + + if ( !$manager->existsItem($itemid,intval($CONF['allowFuture']),intval($CONF['allowDrafts'])) ) + { + doError(_ERROR_NOSUCHITEM); + } + + // 1. get timestamp, blogid and catid for item + $query = 'SELECT itime, iblog, icat FROM %s WHERE inumber=%d'; + $query = sprintf($query, sql_table('item'), intval($itemid)); + $row = DB::getRow($query); + + // if a different blog id has been set through the request or selectBlog(), + // deny access + + if ( $blogid && (intval($blogid) != $row['iblog']) ) + { + doError(_ERROR_NOSUCHITEM); + } + + // if a category has been selected which doesn't match the item, ignore the + // category. #85 + if ( ($catid != 0) && ($catid != $row['icat']) ) + { + $catid = 0; + } + + $blogid = $row['iblog']; + $timestamp = strtotime($row['itime']); + + $b =& $manager->getBlog($blogid); + + if ( !$b->isValidCategory($catid) ) + { + $query = "SELECT inumber, ititle FROM %s WHERE itime<%s AND idraft=0 AND iblog=%d ORDER BY itime DESC LIMIT 1"; + $query = sprintf($query, sql_table('item'), DB::formatDateTime($timestamp), intval($blogid)); + } + else + { + $query = "SELECT inumber, ititle FROM %s WHERE itime<%s AND idraft=0 AND iblog=%d AND icat=%d ORDER BY itime DESC LIMIT 1"; + $query = sprintf($query, sql_table('item'), DB::formatDateTime($timestamp), intval($blogid), intval($catid)); + } + $row = DB::getRow($query); + + if ( $row ) + { + $itemidprev = $row['inumber']; + $itemtitleprev = $row['ititle']; + } + + // get next itemid and title + if ( !$b->isValidCategory($catid) ) + { + $query = "SELECT inumber, ititle FROM %s WHERE itime>%s AND itime<=%s AND idraft=0 AND iblog=%d ORDER BY itime ASC LIMIT 1"; + $query = sprintf($query, sql_table('item'), DB::formatDateTime($timestamp), DB::formatDateTime($b->getCorrectTime()), intval($blogid)); + } + else + { + $query = "SELECT inumber, ititle FROM %s WHERE itime>%s AND itime<=%s AND idraft=0 AND iblog=%d AND icat=%d ORDER BY itime ASC LIMIT 1"; + $query = sprintf($query, sql_table('item'), DB::formatDateTime($timestamp), DB::formatDateTime($b->getCorrectTime()), intval($blogid), intval($catid)); + } + $row = DB::getRow($query); + + if ( $row ) + { + $itemidnext = $row['inumber']; + $itemtitlenext = $row['ititle']; + } + } + elseif ( $archive ) + { + // show archive + $type = 'archive'; + + // sql queries for the timestamp of the first and the last published item + $query = sprintf('SELECT UNIX_TIMESTAMP(itime) as result FROM %s WHERE idraft=0 ORDER BY itime ASC', sql_table('item')); + $first_timestamp = DB::getValue($query); + $query = sprintf('SELECT UNIX_TIMESTAMP(itime) as result FROM %s WHERE idraft=0 ORDER BY itime DESC', sql_table('item')); + $last_timestamp = DB::getValue($query); + + sscanf($archive, '%d-%d-%d', $y, $m, $d); + + if ( $d != 0 ) + { + $archivetype = _ARCHIVETYPE_DAY; + $t = mktime(0, 0, 0, $m, $d, $y); + // one day has 24 * 60 * 60 = 86400 seconds + $archiveprev = i18n::formatted_datetime('%Y-%m-%d', $t - 86400 ); + // check for published items + if ( $t > $first_timestamp ) + { + $archiveprevexists = true; + } + else + { + $archiveprevexists = false; + } + + // one day later + $t += 86400; + $archivenext = i18n::formatted_datetime('%Y-%m-%d', $t); + if ( $t < $last_timestamp ) + { + $archivenextexists = true; + } + else + { + $archivenextexists = false; + } + } + elseif ( $m == 0 ) + { + $archivetype = _ARCHIVETYPE_YEAR; + $t = mktime(0, 0, 0, 12, 31, $y - 1); + // one day before is in the previous year + $archiveprev = i18n::formatted_datetime('%Y', $t); + if ( $t > $first_timestamp ) + { + $archiveprevexists = true; + } + else + { + $archiveprevexists = false; + } + + // timestamp for the next year + $t = mktime(0, 0, 0, 1, 1, $y + 1); + $archivenext = i18n::formatted_datetime('%Y', $t); + if ( $t < $last_timestamp ) + { + $archivenextexists = true; + } + else + { + $archivenextexists = false; + } + } + else + { + $archivetype = _ARCHIVETYPE_MONTH; + $t = mktime(0, 0, 0, $m, 1, $y); + // one day before is in the previous month + $archiveprev = i18n::formatted_datetime('%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 = i18n::formatted_datetime('%Y-%m', $t); + if ( $t < $last_timestamp ) + { + $archivenextexists = true; + } + else + { + $archivenextexists = false; + } + } + } + elseif ( $archivelist ) + { + $type = 'archivelist'; + + if ( is_numeric($archivelist) ) + { + $blogid = intVal($archivelist); + } + else + { + $blogid = getBlogIDFromName($archivelist); + } + + if ( !$blogid ) + { + doError(_ERROR_NOSUCHBLOG); + } + } + elseif ( $query ) + { + global $startpos; + $type = 'search'; + $query = stripslashes($query); + + if ( is_numeric($blogid) ) + { + $blogid = intVal($blogid); + } + else + { + $blogid = getBlogIDFromName($blogid); + } + + if ( !$blogid ) + { + doError(_ERROR_NOSUCHBLOG); + } + } + elseif ( $memberid ) + { + $type = 'member'; + + if ( !Member::existsID($memberid) ) + { + doError(_ERROR_NOSUCHMEMBER); + } + $memberinfo = $manager->getMember($memberid); + } + elseif ( $imagepopup ) + { + // media object (images etc.) + $type = 'imagepopup'; + + // TODO: check if media-object exists + // TODO: set some vars? + } + else + { + // show regular index page + global $startpos; + $type = 'index'; + } + + // any type of skin with catid + if ( $catid && !$blogid ) + { + $blogid = getBlogIDFromCatID($catid); + } + + // decide which blog should be displayed + if ( !$blogid ) + { + $blogid = $CONF['DefaultBlog']; + } + + $b =& $manager->getBlog($blogid); + $blog = $b; // references can't be placed in global variables? + + if ( !$blog->isValid ) + { + doError(_ERROR_NOSUCHBLOG); + } + + // set catid if necessary + if ( $catid ) + { + // check if the category is valid + if ( !$blog->isValidCategory($catid) ) + { + doError(_ERROR_NOSUCHCATEGORY); + } + else + { + $blog->setSelectedCategory($catid); + } + } + + if ( !$skinid ) + { + $skinid = $blog->getDefaultSkin(); + } + + if ( !empty($special) && isValidShortName($special) ) + { + $type = strtolower($special); + } + + $skin = new SKIN($skinid); + + if ( !$skin->isValid() ) + { + doError(_ERROR_NOSUCHSKIN); + } + + // set global skinpart variable so can determine quickly what is being parsed from any plugin or phpinclude + $skinpart = $type; + + // parse the skin + $skin->parse($type); + + // check to see we should throw JustPosted event + $blog->checkJustPosted(); + return; +} + +/** + * doError() + * Show error skin with given message. An optional skin-object to use can be given + * + * @param string $msg + * @param string $skin + * @return void + */ +function doError($msg, $skin = '') +{ + global $errormessage, $CONF, $skinid, $blogid, $manager; + + if ( $skin == '' ) + { + if ( Skin::existsID($skinid) ) + { + $id = $skinid; + } + elseif ( $manager->existsBlogID($blogid) ) + { + $blog =& $manager->getBlog($blogid); + $id = $blog->getDefaultSkin(); + } + elseif ($CONF['DefaultBlog'] ) + { + $blog =& $manager->getBlog($CONF['DefaultBlog']); + $id = $blog->getDefaultSkin(); + } + else + { + // this statement should actually never be executed + $id = $CONF['BaseSkin']; + } + $skin = new Skin($id); + } + + $errormessage = $msg; + $skin->parse('error'); + return; +} + +/** + * Errors before the database connection has been made + * + * @param string $msg message to notify + * @param string $title page title + * @return void + */ +function startUpError($msg, $title) +{ + header('Content-Type: text/xml; charset=' . i18n::get_current_charset()); + echo "\n"; + echo "\n"; + echo "{$title}\n"; + echo "\n"; + echo "

{$title}

\n"; + echo $msg; + echo "\n"; + echo "\n"; + exit; +} + +function isValidShortName($name) +{ + return preg_match('#^[a-z0-9]+$#i', $name); +} +function isValidDisplayName($name) +{ + return preg_match('#^[a-z0-9]+[a-z0-9 ]*[a-z0-9]+$#i', $name); +} +function isValidCategoryName($name) +{ + return 1; +} +function isValidTemplateName($name) +{ + return preg_match('#^[a-z0-9/_\-]+$#i', $name); +} +function isValidSkinName($name) +{ + return preg_match('#^[a-z0-9/_\-]+$#i', $name); +} + +// add and remove linebreaks +function addBreaks($var) +{ + return nl2br($var); +} +function removeBreaks($var) +{ + return preg_replace("/
([\r\n])/", "$1", $var); +} + +/** + * parseFile() + * + * @param string $filename + * @param string $includeMode + * @param string $includePrefix + * @return void + */ +function parseFile($filename, $includeMode = 'normal', $includePrefix = '') +{ + global $skinid; + + if ( !$skinid || !existsID($skinid) ) + { + $skin = new Skin($CONF['BaseSkin']); + } + else + { + $skin = new Skin($skinid); + } + + $oldIncludeMode = Parser::getProperty('IncludeMode'); + $oldIncludePrefix = Parser::getProperty('IncludePrefix'); + + $skin->parse('fileparse', $filename); + + Parser::setProperty('IncludeMode', $oldIncludeMode); + Parser::setProperty('IncludePrefix', $oldIncludePrefix); + + return; +} + +/** + * debug() + * Outputs a debug message + * + * @param string $msg + * @return void + */ +function debug($msg) +{ + echo '

' . $msg . "

\n"; + return; +} + +// shows a link to help file +function help($id) +{ + echo helpHtml($id); + return; +} +function helpHtml($id) +{ + global $CONF; + return helplink($id) . '' . _HELP_TT . ''; +} +function helplink($id) +{ + global $CONF; + return ''; +} + +/** + * includephp() + * Includes a PHP file. This method can be called while parsing templates and skins + * + * @param string $filename name of file to parse + * @return void + */ +function includephp($filename) +{ + // make predefined variables global, so most simple scripts can be used here + + // apache (names taken from PHP doc) + global $GATEWAY_INTERFACE, $SERVER_NAME, $SERVER_SOFTWARE, $SERVER_PROTOCOL; + global $REQUEST_METHOD, $QUERY_STRING, $DOCUMENT_ROOT, $HTTP_ACCEPT; + global $HTTP_ACCEPT_CHARSET, $HTTP_ACCEPT_ENCODING, $HTTP_ACCEPT_LANGUAGE; + global $HTTP_CONNECTION, $HTTP_HOST, $HTTP_REFERER, $HTTP_USER_AGENT; + global $REMOTE_ADDR, $REMOTE_PORT, $SCRIPT_FILENAME, $SERVER_ADMIN; + global $SERVER_PORT, $SERVER_SIGNATURE, $PATH_TRANSLATED, $SCRIPT_NAME; + global $REQUEST_URI; + + // php (taken from PHP doc) + global $argv, $argc, $PHP_SELF, $HTTP_COOKIE_VARS, $HTTP_GET_VARS, $HTTP_POST_VARS; + global $HTTP_POST_FILES, $HTTP_ENV_VARS, $HTTP_SERVER_VARS, $HTTP_SESSION_VARS; + + // other + global $PATH_INFO, $HTTPS, $HTTP_RAW_POST_DATA, $HTTP_X_FORWARDED_FOR; + + if ( @file_exists($filename) ) + { + include($filename); + } + return; +} + +/** + * Checks if a certain plugin exists + * @param string $plug name of plugin + * @return boolean exists or not + */ +function checkPlugin($name) +{ + global $DIR_PLUGINS; + return file_exists($DIR_PLUGINS . preg_replace('#[\\\\|/]#', '', $name) . '.php'); +} + +/** + * alterQueryStr() + * + * @param string $querystr querystring to alter (e.g. foo=1&bar=2&x=y) + * @param string $param name of parameter to change (e.g. 'foo') + * @param string $value New value for that parameter (e.g. 3) + * @return string altered query string (for the examples above: foo=3&bar=2&x=y) + */ +function alterQueryStr($querystr, $param, $value) +{ + $vars = preg_split('#&#', $querystr); + $set = FALSE; + + for ( $i = 0; $i < count($vars); $i++ ) + { + $v = preg_split('#=#', $vars[$i]); + + if ( $v[0] == $param ) + { + $v[1] = $value; + $vars[$i] = implode('=', $v); + $set = true; + break; + } + } + if ( !$set ) + { + $vars[] = "{$param}={$value}"; + } + return ltrim(implode('&', $vars), '&'); +} + +/** + * passVar() + * passes one variable as hidden input field (multiple fields for arrays) + * @see passRequestVars in varsx.x.x.php + * + * @param string $key + * @param string $value + * @return void + */ +function passVar($key, $value) +{ + // array ? + if ( is_array($value) ) + { + for ( $i = 0; $i < sizeof($value); $i++ ) + { + passVar($key . '[' . $i . ']', $value[$i]); + } + return; + } + + // other values: do stripslashes if needed + echo '' . "\n"; + return; +} + +/** + * checkVars() + * + * @param string $variables + * @return void + */ +function checkVars($variables) +{ + foreach ( $variables as $variable ) + { + if ( array_key_exists($variable, $_GET) + || array_key_exists($variable, $_POST) + || array_key_exists($variable, $_COOKIE) + || array_key_exists($variable, $_ENV) + || (session_id() !== '' && array_key_exists($variable, $_SESSION)) + || array_key_exists($variable, $_FILES) ) + { + die('Sorry. An error occurred.'); + } + } + return; +} + +/** + * sanitizeParams() + * Sanitize parameters such as $_GET and $_SERVER['REQUEST_URI'] etc. + * to avoid XSS. + * + * @param void + * @return void + */ +function sanitizeParams() +{ + $array = array(); + $str = ''; + $frontParam = ''; + + // REQUEST_URI of $_SERVER + $str =& $_SERVER["REQUEST_URI"]; + serverStringToArray($str, $array, $frontParam); + sanitizeArray($array); + arrayToServerString($array, $frontParam, $str); + + // QUERY_STRING of $_SERVER + $str =& $_SERVER["QUERY_STRING"]; + serverStringToArray($str, $array, $frontParam); + sanitizeArray($array); + arrayToServerString($array, $frontParam, $str); + + // $_GET + convArrayForSanitizing($_GET, $array); + sanitizeArray($array); + revertArrayForSanitizing($array, $_GET); + + // $_REQUEST (only GET param) + convArrayForSanitizing($_REQUEST, $array); + sanitizeArray($array); + revertArrayForSanitizing($array, $_REQUEST); + + return; +} + +function _addInputTags(&$keys,$prefix='') +{ + foreach ( $keys as $key=>$value ) + { + if ( $prefix ) + { + $key=$prefix.'['.$key.']'; + } + if ( is_array($value) ) + { + _addInputTags($value,$key); + } + else + { + if ( get_magic_quotes_gpc() ) + {$value=stripslashes($value); + } + if ( $key == 'ticket' ) + { + continue; + } + echo ''."\n"; + } + } + return; +} + +/** + * serverStringToArray() + * Convert the server string such as $_SERVER['REQUEST_URI'] + * to arry like arry['blogid']=1 and array['page']=2 etc. + * + * @param string $uri string + * @param string &$query_elements elements of query according to application/x-www-form-urlencoded + * @param string &$hier_part hierarchical part includes path + * + * NOTE: + * RFC 3986: Uniform Resource Identifiers (URI): Generic Syntax + * 3. Syntax Components + * http://www.ietf.org/rfc/rfc3986.txt + * + * Hypertext Markup Language - 2.0 + * 8.2.1. The form-urlencoded Media Type + * http://tools.ietf.org/html/rfc1866#section-8.2.1 + * + * $_SERVER > Language Reference > Predefined Variables > PHP Manual + * http://www.php.net/manual/en/reserved.variables.server.php + */ +function serverStringToArray($uri, &$query_elements, &$hier_part) +{ + // init param + $query_elements = array(); + $hier_part = ""; + + // split hierarchical part, e.g. /index.php, query and fragment, e.g. blogid=1&page=2#section1 + if ( i18n::strpos($uri, "?") > 0 ) + { + list($hier_part, $query_and_fragment) = preg_split("#\?#", $uri, 2); + } + else + { + $query_and_fragment = $uri; + $hier_part = ''; + } + + // If there is no query like blogid=1&page=2, return + if ( i18n::strpos($uri, "=") == FALSE && !i18n::strlen($hier_part) ) + { + $hier_part = $uri; + return; + } + + $query_elements = preg_split("#&#", $query_and_fragment); + return; +} + +/** + * arrayToServerString() + * Convert array like array['blogid'] to server string + * such as $_SERVER['REQUEST_URI'] + * + * @param array $query_elements elements of query according to application/x-www-form-urlencoded + * @param string $hier_part hier-part defined in RFC3986 + * @param string &$uri return value + * @return void + * + * NOTE: + * RFC 3986: Uniform Resource Identifiers (URI): Generic Syntax + * 3. Syntax Components + * http://www.ietf.org/rfc/rfc3986.txt + * + * Hypertext Markup Language - 2.0 + * 8.2.1. The form-urlencoded Media Type + * http://tools.ietf.org/html/rfc1866#section-8.2.1 + * + * $_SERVER > Language Reference > Predefined Variables > PHP Manual + * http://www.php.net/manual/en/reserved.variables.server.php + */ +function arrayToServerString($query_elements, $hier_part, &$uri) +{ + if ( i18n::strpos($uri, "?") !== FALSE ) + { + $uri = $hier_part . "?"; + } + else + { + $uri = $hier_part; + } + if ( count($query_elements) > 0 ) + { + $uri .= implode("&", $query_elements); + } + return; +} + +/** + * sanitizeArray() + * Sanitize array parameters. + * This function checks both key and value. + * - check key if it inclues " (double quote), remove from array + * - check value if it includes \ (escape sequece), remove remaining string + * + * @param array &$array elements of query according to application/x-www-form-urlencoded + * @return void + */ +function sanitizeArray(&$array) +{ + $excludeListForSanitization = array('query'); + + foreach ( $array as $k => $v ) + { + // split to key and value + list($key, $val) = preg_split("#=#", $v, 2); + if ( !isset($val) ) + { + continue; + } + + // when magic quotes is on, need to use stripslashes, + // and then addslashes + if ( get_magic_quotes_gpc() ) + { + $val = stripslashes($val); + } + + // note that we must use addslashes here because this function is called before the db connection is made + // and sql_real_escape_string needs a db connection + $val = addslashes($val); + + // if $key is included in exclude list, skip this param + if ( !in_array($key, $excludeListForSanitization) ) + { + // check value + if ( i18n::strpos($val, '\\') > 0 ) + { + list($val, $tmp) = preg_split('#\\\\#', $val); + } + + // remove control code etc. + $val = strtr($val, "\0\r\n<>'\"", " "); + + // check key + if ( preg_match('#\"#', $key) > 0 ) + { + unset($array[$k]); + continue; + } + + // set sanitized info + $array[$k] = sprintf("%s=%s", $key, $val); + } + } + return; +} + +/** + * convArrayForSanitizing() + * Convert array for sanitizeArray function + * + * @param string $src array to be sanitized + * @param array &$array array to be temporarily stored + * @return void + */ +function convArrayForSanitizing($src, &$array) +{ + $array = array(); + foreach ( $src as $key => $val ) + { + if ( !key_exists($key, $_GET) ) + { + continue; + } + $array[] = sprintf("%s=%s", $key, $val); + continue; + } + return; +} + +/** + * revertArrayForSanitizing() + * Revert array after sanitizeArray function + * + * @param array $array element of query according to application/x-www-form-urlencoded + * @param array &$dst combination of key and value + * @return void + */ +function revertArrayForSanitizing($array, &$dst) +{ + foreach ( $array as $v ) + { + list($key, $val) = preg_split("#=#", $v, 2); + $dst[$key] = $val; + continue; + } + return; +} + +/** +======= 0 ) } /* Avoid notices */ -if ( !isset($CONF['installscript']) ) +if ( !array_key_exists('installscript', $CONF) || empty($CONF['installscript']) ) { $CONF['installscript'] = 0; } +if ( !array_key_exists('UsingAdminArea', $CONF) ) +{ + $CONF['UsingAdminArea'] = 0; +} -/* we will use postVar, getVar, ... methods instead of $_GET, $_POST ...*/ -if ($CONF['installscript'] != 1) +if ( !headers_sent() ) { - /* vars were already included in install.php */ - include_once($DIR_LIBS . 'vars4.1.0.php'); + header('Generator: Nucleus CMS ' . $nucleus['version']); } -/* sanitize option */ -$bLoggingSanitizedResult=0; -$bSanitizeAndContinue=0; -$orgRequestURI = serverVar('REQUEST_URI'); -sanitizeParams(); +/* TODO: This is for compatibility since 4.0, should be obsoleted at future release. */ +if ( !isset($DIR_LOCALES) ) +{ + $DIR_LOCALES = $DIR_NUCLEUS . 'locales/'; +} +global $DIR_LANG; +if ( !isset($DIR_LANG) ) +{ + $DIR_LANG = $DIR_LOCALES; +} -/* get all variables that can come from the request and put them in the global scope */ -$blogid = requestVar('blogid'); -$itemid = intRequestVar('itemid'); -$catid = intRequestVar('catid'); -$skinid = requestVar('skinid'); -$memberid = requestVar('memberid'); -$archivelist = requestVar('archivelist'); -$imagepopup = requestVar('imagepopup'); -$archive = requestVar('archive'); -$query = requestVar('query'); -$highlight = requestVar('highlight'); -$amount = requestVar('amount'); -$action = requestVar('action'); -$nextaction = requestVar('nextaction'); -$maxresults = requestVar('maxresults'); -$startpos = intRequestVar('startpos'); -$errormessage = ''; -$error = ''; -$special = requestVar('special'); -$virtualpath = ((getVar('virtualpath') != null) ? getVar('virtualpath') : serverVar('PATH_INFO')); +/* load and initialize i18n class */ +if (!class_exists('i18n', FALSE)) +{ + include($DIR_LIBS . 'i18n.php'); +} +if ( !i18n::init('UTF-8', $DIR_LOCALES) ) +{ + exit('Fail to initialize i18n class.'); +} -if ( !headers_sent() ) +/* TODO: This is just for compatibility since 4.0, should be obsoleted at future release. */ +define('_CHARSET', i18n::get_current_charset()); + + +/* + * NOTE: Since 4.0 release, Entity class becomes to be important class + * with some wrapper functions for htmlspechalchars/htmlentity PHP's built-in function + */ +include($DIR_LIBS . 'ENTITY.php'); + +/* we will use postVar, getVar, ... methods instead of $_GET, $_POST ... */ +if ( $CONF['installscript'] != 1 ) { - header('Generator: Nucleus CMS ' . $nucleus['version']); + /* vars were already included in install.php */ + include_once($DIR_LIBS . 'vars4.1.0.php'); + + /* added for 4.0 DB::* wrapper and compatibility sql_* */ + include_once($DIR_LIBS . 'sql/sql.php'); } /* include core classes that are needed for login & plugin handling */ -include_once($DIR_LIBS . 'mysql.php'); -/* added for 3.5 sql_* wrapper */ -global $MYSQL_HANDLER; +include($DIR_LIBS . 'MEMBER.php'); +include($DIR_LIBS . 'ACTIONLOG.php'); +include($DIR_LIBS . 'MANAGER.php'); +include($DIR_LIBS . 'PLUGIN.php'); + +$manager =& MANAGER::instance(); + +/* only needed when updating logs */ +if ( $CONF['UsingAdminArea'] ) +{ + /* XML-RPC client classes */ + include($DIR_LIBS . 'xmlrpc.inc.php'); + include($DIR_LIBS . 'ADMIN.php'); +} + + +/* connect to database */ if ( !isset($MYSQL_HANDLER) ) { $MYSQL_HANDLER = array('mysql',''); @@ -166,50 +1985,61 @@ if ( $MYSQL_HANDLER[0] == '' ) { $MYSQL_HANDLER[0] = 'mysql'; } -include_once($DIR_LIBS . 'sql/'.$MYSQL_HANDLER[0].'.php'); -/* end new for 3.5 sql_* wrapper */ -include($DIR_LIBS . 'MEMBER.php'); -include($DIR_LIBS . 'ACTIONLOG.php'); -include($DIR_LIBS . 'MANAGER.php'); -include($DIR_LIBS . 'PLUGIN.php'); +DB::setConnectionInfo($MYSQL_HANDLER[1], $MYSQL_HOST, $MYSQL_USER, $MYSQL_PASSWORD, $MYSQL_DATABASE); -$manager =& MANAGER::instance(); -/* - * make sure there's no unnecessary escaping: - * set_magic_quotes_runtime(0); - */ -if ( version_compare(PHP_VERSION, '5.3.0', '<') ) +/* force locale or charset */ +$locale = ''; +$charset = i18n::get_current_charset(); + +$data = array( + 'locale' => &$locale, + 'charset' => &$charset +); +$manager->notify('ForceLocale', $data); + +if ( $data['locale'] !== '' ) { - ini_set('magic_quotes_runtime', '0'); + i18n::set_forced_locale($data['locale']); } - -/* Avoid notices */ -if ( !isset($CONF['UsingAdminArea']) ) +if ( $data['charset'] !== '' ) { - $CONF['UsingAdminArea'] = 0; + i18n::set_forced_charset($data['charset']); } +unset($locale); +unset($charset); -/* only needed when updating logs */ -if ( $CONF['UsingAdminArea'] ) + +/* convert forced charset to current charset */ +if ( i18n::get_forced_charset() != i18n::get_current_charset() ) { - /* XML-RPC client classes */ - include($DIR_LIBS . 'xmlrpc.inc.php'); - include_once($DIR_LIBS . 'ADMIN.php'); + $_POST = i18n::convert_array($_POST, i18n::get_forced_charset()); + $_GET = i18n::convert_array($_GET, i18n::get_forced_charset()); + $_REQUEST = i18n::convert_array($_REQUEST, i18n::get_forced_charset()); + $_COOKIE = i18n::convert_array($_COOKIE, i18n::get_forced_charset()); + $_FILES = i18n::convert_array($_FILES, i18n::get_forced_charset()); + + if ( session_id() !== '' ) + { + $_SESSION = i18n::convert_array($_SESSION, i18n::get_forced_charset()); + } } -/* connect to database */ -sql_connect(); -$SQLCount = 0; + +/* sanitize option */ +$bLoggingSanitizedResult = 0; +$bSanitizeAndContinue = 0; +$orgRequestURI = serverVar('REQUEST_URI'); +sanitizeParams(); /* logs sanitized result if need */ -if ( $orgRequestURI!==serverVar('REQUEST_URI') ) +if ( $orgRequestURI !== serverVar('REQUEST_URI') ) { $msg = "Sanitized [" . serverVar('REMOTE_ADDR') . "] "; $msg .= $orgRequestURI . " -> " . serverVar('REQUEST_URI'); if ( $bLoggingSanitizedResult ) { - addToLog(WARNING, $msg); + addToLog(WARNING, $msg); } if ( !$bSanitizeAndContinue ) { @@ -217,28 +2047,35 @@ if ( $orgRequestURI!==serverVar('REQUEST_URI') ) } } -/* makes sure database connection gets closed on script termination */ -register_shutdown_function('sql_disconnect'); +/* get all variables that can come from the request and put them in the global scope */ +$blogid = requestVar('blogid'); +$itemid = intRequestVar('itemid'); +$catid = intRequestVar('catid'); +$skinid = requestVar('skinid'); +$memberid = requestVar('memberid'); +$archivelist = requestVar('archivelist'); +$imagepopup = requestVar('imagepopup'); +$archive = requestVar('archive'); +$query = requestVar('query'); +$highlight = requestVar('highlight'); +$amount = requestVar('amount'); +$action = requestVar('action'); +$nextaction = requestVar('nextaction'); +$maxresults = requestVar('maxresults'); +$startpos = intRequestVar('startpos'); +$errormessage = ''; +$error = ''; +$special = requestVar('special'); + /* read config */ getConfig(); -/* - * Nucleus CMS 4.0 uses 'locale' instead of 'language' to decide which translation file used - * Here simply convert old name to new name without checking translation file existance - * FIXME: This is for compatibility, should be obsoleted near future. - */ -if ( !preg_match('#^(.+)_(.+)_(.+)$#', $CONF['Language']) - && ($CONF['Language'] = i18n::convert_old_language_file_name_to_locale($CONF['Language'])) === FALSE ) -{ - $CONF['Language'] = ''; -} -$locale = $CONF['Language']; /* Properly set $CONF['Self'] and others if it's not set... * usually when we are access from admin menu */ -if ( !isset($CONF['Self']) ) +if ( !array_key_exists('Self', $CONF) ) { $CONF['Self'] = $CONF['IndexURL']; /* strip trailing */ @@ -248,206 +2085,81 @@ if ( !isset($CONF['Self']) ) } } -$CONF['ItemURL'] = $CONF['Self']; -$CONF['ArchiveURL'] = $CONF['Self']; -$CONF['ArchiveListURL'] = $CONF['Self']; -$CONF['MemberURL'] = $CONF['Self']; -$CONF['SearchURL'] = $CONF['Self']; -$CONF['BlogURL'] = $CONF['Self']; -$CONF['CategoryURL'] = $CONF['Self']; - -/* - *switch URLMode back to normal when $CONF['Self'] ends in .php - * this avoids urls like index.php/item/13/index.php/item/15 - */ -if ( !isset($CONF['URLMode']) - || (($CONF['URLMode'] == 'pathinfo') - && (i18n::substr($CONF['Self'], i18n::strlen($CONF['Self']) - 4) == '.php')) ) -{ - $CONF['URLMode'] = 'normal'; -} +$CONF['ItemURL'] = $CONF['Self']; +$CONF['ArchiveURL'] = $CONF['Self']; +$CONF['ArchiveListURL'] = $CONF['Self']; +$CONF['MemberURL'] = $CONF['Self']; +$CONF['SearchURL'] = $CONF['Self']; +$CONF['BlogURL'] = $CONF['Self']; +$CONF['CategoryURL'] = $CONF['Self']; /* automatically use simpler toolbar for mozilla */ if ( ($CONF['DisableJsTools'] == 0) - && strstr(serverVar('HTTP_USER_AGENT'), 'Mozilla/5.0') - && strstr(serverVar('HTTP_USER_AGENT'), 'Gecko') ) + && i18n::strpos(serverVar('HTTP_USER_AGENT'), 'Mozilla/5.0') !== FALSE + && i18n::strpos(serverVar('HTTP_USER_AGENT'), 'Gecko') !== FALSE ) { $CONF['DisableJsTools'] = 2; } -/* login if cookies set*/ -$member = new MEMBER(); - -/* secure cookie key settings (either 'none', 0, 8, 16, 24, or 32) */ -if ( !isset($CONF['secureCookieKey']) ) +/* login processing */ +$member = new Member(); +if ( $action == 'login' ) { - $CONF['secureCookieKey'] = 24; + $login = postVar('login'); + $password = postVar('password'); + $shared = intPostVar('shared'); + $member->login($login, $password, $shared); } -switch( $CONF['secureCookieKey'] ) +elseif ( ($action == 'logout') ) { - 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'] = ''; + $member->logout(); } - -/* - * login/logout when required or renew cookies - * and decide locale on this session before plugin event generates - */ -if ( $action == 'login' ) +else { - /* Form Authentication */ - $login = postVar('login'); - $pw = postVar('password'); - /* shared computer or not */ - $shared = intPostVar('shared'); - /* avoid md5 collision by using a long key */ - $pw=i18n::substr($pw,0,40); - - 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; - } - - /* NOTE: include translation file and set locale */ - $locale = include_translation($locale, $member); - i18n::set_current_locale($locale); - - $manager->notify('LoginSuccess', array('member' => &$member, 'username' => $login) ); - $errormessage = ''; - ACTIONLOG::add(INFO, "Login successful for $login (sharedpc=$shared)"); - } - else - { - /* errormessage for [%errordiv%] */ - $trimlogin = trim($login); - if ( empty($trimlogin) ) - { - $errormessage = "Please enter a username."; - } - else - { - $errormessage = 'Login failed for ' . $login; - } - - /* NOTE: include translation file and set locale */ - $locale = include_translation($locale); - i18n::set_current_locale($locale); - - $manager->notify('LoginFailed', array('username' => $login) ); - ACTIONLOG::add(INFO, $errormessage); - } + $member->cookielogin(); } -/* - * TODO: this should be removed when releasing 4.0 -Backed out for now: See http://forum.nucleuscms.org/viewtopic.php?t=3684 for details -elseif ( serverVar('PHP_AUTH_USER') && serverVar('PHP_AUTH_PW') ) +/* TODO: This is for backward compatibility, should be obsoleted near future. */ +if ( !preg_match('#^(.+)_(.+)_(.+)$#', $CONF['Locale']) + && ($CONF['Locale'] = i18n::convert_old_language_file_name_to_locale($CONF['Locale'])) === FALSE ) { - // HTTP Authentication - $login = serverVar('PHP_AUTH_USER'); - $pw = serverVar('PHP_AUTH_PW'); - - if ( $member->login($login, $pw) ) - { - $manager->notify('LoginSuccess',array('member' => &$member)); - ACTIONLOG::add(INFO, "HTTP authentication successful for $login"); - } - else - { - $manager->notify('LoginFailed',array('username' => $login)); - ACTIONLOG::add(INFO, 'HTTP authentication failed for ' . $login); - - //Since bad credentials, generate an apropriate error page - header("WWW-Authenticate: Basic realm=\"Nucleus CMS {$nucleus['version']}\""); - header('HTTP/1.0 401 Unauthorized'); - echo 'Invalid username or password'; - exit; - } + $CONF['Locale'] = 'en_Latn_US'; } -*/ - -elseif ( ($action == 'logout') - && (!headers_sent()) - && cookieVar($CONF['CookiePrefix'] . 'user') ) +if ( !array_key_exists('Language', $CONF) ) { - /* remove cookies on logout */ - setcookie($CONF['CookiePrefix'] . 'user', '', (time() - 2592000), $CONF['CookiePath'], $CONF['CookieDomain'], $CONF['CookieSecure']); - setcookie($CONF['CookiePrefix'] . 'loginkey', '', (time() - 2592000), $CONF['CookiePath'], $CONF['CookieDomain'], $CONF['CookieSecure']); - - /* NOTE: include translation file and set locale */ - $locale = include_translation($locale); - i18n::set_current_locale($locale); - - $manager->notify('Logout', array('username' => cookieVar($CONF['CookiePrefix'] . 'user') ) ); + $CONF['Language'] = i18n::convert_locale_to_old_language_file_name($CONF['Locale']); } -elseif ( cookieVar($CONF['CookiePrefix'] . 'user') ) +$locale = $CONF['Locale']; + + +/* NOTE: include translation file and set locale */ +if ( $member->isLoggedIn() ) { - /* Cookie Authentication */ - $ck=cookieVar($CONF['CookiePrefix'] . 'loginkey'); - /* - * secure cookie key - * avoid md5 collision by using a long key - */ - $ck = i18n::substr($ck,0,32); - 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() ) ) + if ( $member->getLocale() ) { - $member->setCookieKey(cookieVar($CONF['CookiePrefix'] . 'loginkey')); - $member->setCookies(); + $locale = $member->getLocale(); } - - /* NOTE: include translation file and set locale */ - $locale = include_translation($locale, $member); - i18n::set_current_locale($locale); } else { - /* NOTE: include translation file and set locale */ - $locale = include_translation($locale); - i18n::set_current_locale($locale); + if ( i18n::get_forced_locale() !== '' ) + { + $locale = i18n::get_forced_locale(); + } } +include_translation($locale); +i18n::set_current_locale($locale); + /* login completed */ -$manager->notify('PostAuthentication', array('loggedIn' => $member->isLoggedIn() ) ); +$data = array('loggedIn' => $member->isLoggedIn()); +$manager->notify('PostAuthentication', $data); -/* - * Release ticket for plugin - */ -ticketForPlugin(); +/* next action */ +if ( $member->isLoggedIn() && $nextaction ) +{ + $action = $nextaction; +} /* first, let's see if the site is disabled or not. always allow admin area access. */ if ( $CONF['DisableSite'] && !$member->isAdmin() && !$CONF['UsingAdminArea'] ) @@ -464,13 +2176,10 @@ include($DIR_LIBS . 'BLOG.php'); include($DIR_LIBS . 'BODYACTIONS.php'); include($DIR_LIBS . 'COMMENTS.php'); include($DIR_LIBS . 'COMMENT.php'); -/* include($DIR_LIBS . 'ITEM.php'); */ include($DIR_LIBS . 'NOTIFICATION.php'); include($DIR_LIBS . 'BAN.php'); -include($DIR_LIBS . 'PAGEFACTORY.php'); include($DIR_LIBS . 'SEARCH.php'); -include($DIR_LIBS . 'entity.php'); -include($DIR_LIBS . 'Link.php'); +include($DIR_LIBS . 'LINK.php'); /* set lastVisit cookie (if allowed) */ if ( !headers_sent() ) @@ -485,660 +2194,572 @@ if ( !headers_sent() ) } } -/* -Backed out for now: See http://forum.nucleuscms.org/viewtopic.php?t=3684 for details - -// To remove after v2.5 is released and language files have been updated. -// Including this makes sure that language files for v2.5beta can still be used for v2.5final -// without having weird _SETTINGS_EXTAUTH string showing up in the admin area. -if (!defined('_MEMBERS_BYPASS')) +/* for path resolving */ +$virtualpath = getVar('virtualpath'); +if ( getVar('virtualpath') == '' ) { - define('_SETTINGS_EXTAUTH', 'Enable External Authentication'); - define('_WARNING_EXTAUTH', 'Warning: Enable only if needed.'); - define('_MEMBERS_BYPASS', 'Use External Authentication'); + $virtualpath = serverVar('PATH_INFO'); } -*/ -/* make sure the archivetype skinvar keeps working when _ARCHIVETYPE_XXX not defined */ -if ( !defined('_ARCHIVETYPE_MONTH') ) +/* + * switch URLMode back to normal when $CONF['Self'] ends in .php + * this avoids urls like index.php/item/13/index.php/item/15 + */ +if ( !array_key_exists('URLMode', $CONF) || ($CONF['URLMode'] != 'pathinfo') ) { - define('_ARCHIVETYPE_DAY', 'day'); - define('_ARCHIVETYPE_MONTH', 'month'); - define('_ARCHIVETYPE_YEAR', 'year'); + $CONF['URLMode'] = 'normal'; } - -/* decode path_info */ -if ( $CONF['URLMode'] == 'pathinfo' ) +else { - /* initialize keywords if this hasn't been done before */ - if ( !isset($CONF['ItemKey']) || $CONF['ItemKey'] == '' ) + if ( i18n::substr($CONF['Self'], i18n::strlen($CONF['Self']) - 4) != '.php' ) { - $CONF['ItemKey'] = 'item'; + decodePathInfo($virtualpath); } +} + +/* + * PostParseURL is a place to cleanup any of the path-related global variables before the selector function is run. + * It has 2 values in the data in case the original virtualpath is needed, but most the use will be in tweaking + * global variables to clean up (scrub out catid or add catid) or to set someother global variable based on + * the values of something like catid or itemid + * New in 3.60 + */ +$data = array( + 'type' => basename(serverVar('SCRIPT_NAME')), + 'info' => $virtualpath +); +$manager->notify('PostParseURL', $data); + +/* + * NOTE: Here is the end of initialization + */ + +/** + * include_libs() + * This function includes or requires the specified library file + * + * @param string $file + * @param boolean $once use the _once() version + * @param boolean $require use require() instead of include() + * @return void + */ +function include_libs($file, $once = TRUE, $require = TRUE) +{ + global $DIR_LIBS; - if ( !isset($CONF['ArchiveKey']) || $CONF['ArchiveKey'] == '' ) + // $DIR_LIBS isn't a directory + if ( !is_dir($DIR_LIBS) ) { - $CONF['ArchiveKey'] = 'archive'; + exit; } - if ( !isset($CONF['ArchivesKey']) || $CONF['ArchivesKey'] == '' ) + $lib_path = $DIR_LIBS . $file; + + if ( $once && $require ) { - $CONF['ArchivesKey'] = 'archives'; + require_once($lib_path); } - - if ( !isset($CONF['MemberKey']) || $CONF['MemberKey'] == '' ) + else if ( $once && !$require ) { - $CONF['MemberKey'] = 'member'; + include_once($lib_path); } - - if ( !isset($CONF['BlogKey']) || $CONF['BlogKey'] == '' ) + else if ( $require ) { - $CONF['BlogKey'] = 'blog'; + require($lib_path); + } + else + { + include($lib_path); } + return; +} + +/** + * include_plugins() + * This function includes or requires the specified plugin file + * + * @param string $file + * @param boolean $once use the _once() version + * @param boolean $require use require() instead of include() + * @return + */ +function include_plugins($file, $once = TRUE, $require = TRUE) +{ + global $DIR_PLUGINS; - if ( !isset($CONF['CategoryKey']) || $CONF['CategoryKey'] == '' ) + // begin if: $DIR_LIBS isn't a directory + if ( !is_dir($DIR_PLUGINS) ) { - $CONF['CategoryKey'] = 'category'; + exit; } - if ( !isset($CONF['SpecialskinKey']) || $CONF['SpecialskinKey'] == '' ) + $plugin_path = $DIR_PLUGINS . $file; + + // begin if: + if ( $once && $require ) { - $CONF['SpecialskinKey'] = 'special'; + require_once($plugin_path); + } + else if ( $once && !$require ) + { + include_once($plugin_path); + } + elseif ( $require ) + { + require($plugin_path); + } + else + { + include($plugin_path); } + return; +} + +/** + * include_translation() + * This function decide which locale is used and include translation + * + * @param string &$locale locale name referring to 'language tags' defined in RFC 5646 + * @return void + */ +function include_translation(&$locale) +{ + global $DIR_LOCALES; - $parsed = false; - $manager->notify( - 'ParseURL', - array( - /* e.g. item, blog, ... */ - 'type' => basename(serverVar('SCRIPT_NAME') ), - 'info' => $virtualpath, - 'complete' => &$parsed - ) - ); + $translation_file = $DIR_LOCALES . $locale . '.' . i18n::get_current_charset() . '.php'; + if ( !file_exists($translation_file) ) + { + $locale = 'en_Latn_US'; + $translation_file = $DIR_LOCALES . 'en_Latn_US.ISO-8859-1.php'; + } + include($translation_file); - if ( !$parsed ) + /* + * NOTE: + * PHP is written by C and utilize C library, whose APIs are defined in POSIX. + * + * setlocale() is one of APIs of C library. + * but the argument value for setlocale() depends on each implements + * + * The latest POSIX standard: + * The Open Group Base Specifications Issue 7 + * IEEE Std 1003.1™-2008 + * http://pubs.opengroup.org/onlinepubs/9699919799/mindex.html + * + * Microsoft's operating system uses their own implementation + * Language Strings + * http://msdn.microsoft.com/en-us/library/39cwe7zf%28v=vs.110%29.aspx + * Country/Region Strings + * http://msdn.microsoft.com/en-us/library/cdax410z%28v=vs.110%29.aspx + * + * Linux and Unix (in this meaning, Apple's OS X derives from UNIX) uses ISO standard. + * two characters language tag (ISO 639-1) + * two characters region and country lag (ISO 3166-1 alpha-1) + * + */ + if ( PHP_OS == "WIN32" || PHP_OS == "WINNT" ) { - /* default implementation */ - $data = i18n::explode("/", $virtualpath ); - for ( $i = 0; $i < sizeof($data); $i++ ) - { - switch ( $data[$i] ) - { - /* item/1 (blogid) */ - case $CONF['ItemKey']: - $i++; - - if ( $i < sizeof($data) ) - { - $itemid = intval($data[$i]); - } - break; - - /* archives/1 (blogid) */ - case $CONF['ArchivesKey']: - $i++; - if ( $i < sizeof($data) ) - { - $archivelist = intval($data[$i]); - } - break; - - /* two possibilities: archive/yyyy-mm or archive/1/yyyy-mm (with blogid) */ - case $CONF['ArchiveKey']: - if ( (($i + 1) < sizeof($data) ) && (!strstr($data[$i + 1], '-') ) ) - { - $blogid = intval($data[++$i]); - } - $i++; - if ( $i < sizeof($data) ) - { - $archive = $data[$i]; - } - break; - - /* blogid/1 */ - case 'blogid': - /* blog/1 */ - case $CONF['BlogKey']: - $i++; - if ( $i < sizeof($data) ) - { - $blogid = intval($data[$i]); - } - break; - - /* category/1 (catid) */ - case $CONF['CategoryKey']: - case 'catid': - $i++; - if ( $i < sizeof($data) ) - { - $catid = intval($data[$i]); - } - break; - - case $CONF['MemberKey']: - $i++; - if ( $i < sizeof($data) ) - { - $memberid = intval($data[$i]); - } - break; - - case $CONF['SpecialskinKey']: - $i++; - if ( $i < sizeof($data) ) - { - $special = $data[$i]; - $_REQUEST['special'] = $special; - } - break; - - default: - // skip... - } - } + /* LOCALE_IN_WINDOWS is defined in each translation files */ + setlocale(LC_ALL, _LOCALE_IN_WINDOWS); } + else + { + setlocale(LC_ALL, preg_replace('#(.+)_(.+)_(.+)#', '$1-$3', $locale)); + } + return; } -/* - * PostParseURL is a place to cleanup any of the path-related global variables before the selector function is run. - * It has 2 values in the data in case the original virtualpath is needed, but most the use will be in tweaking - * global variables to clean up (scrub out catid or add catid) or to set someother global variable based on - * the values of something like catid or itemid - * New in 3.60 - */ -$manager->notify( - 'PostParseURL', - array( - /* e.g. item, blog, ... */ - 'type' => basename(serverVar('SCRIPT_NAME') ), - 'info' => $virtualpath - ) -); -/* - * NOTE: Here is the end of initialization +/** + * intPostVar() + * This function returns the integer value of $_POST for the variable $name + * + * @param string $name field to get the integer value of + * @return integer */ +function intPostVar($name) +{ + return (integer) postVar($name); +} - /** - * This function includes or requires the specified library file - * @param string $file - * @param bool $once use the _once() version - * @param bool $require use require() instead of include() - */ - function include_libs($file, $once = TRUE, $require = TRUE) - { - global $DIR_LIBS; - - // begin if: $DIR_LIBS isn't a directory - if ( !is_dir($DIR_LIBS) ) - { - exit; - } // end if - $lib_path = $DIR_LIBS . $file; +/** + * intGetVar() + * This function returns the integer value of $_GET for the variable $name + * + * @param string $name field to get the integer value of + * @return integer + */ +function intGetVar($name) +{ + return (integer) getVar($name); +} - // begin if: - if ( $once && $require ) - { - require_once($lib_path); - } - else if ( $once && !$require ) - { - include_once($lib_path); - } - else if ( $require ) - { - require($lib_path); - } - else - { - include($lib_path); - } // end if - } +/** + * intRequestVar() + * This function returns the integer value of $_REQUEST for the variable $name. Also checks $_GET and $_POST if not found in $_REQUEST + * + * @param string $name field to get the integer value of + * @return int + */ +function intRequestVar($name) +{ + return (integer) requestVar($name); +} - /** - * This function includes or requires the specified plugin file - * @param string $file - * @param bool $once use the _once() version - * @param bool $require use require() instead of include() - */ - function include_plugins($file, $once = TRUE, $require = TRUE) - { - global $DIR_PLUGINS; +/** + * intCookieVar() + * This function returns the integer value of $_COOKIE for the variable $name + * + * @param string $name field to get the integer value of + * @return integer + */ +function intCookieVar($name) +{ + return (integer) cookieVar($name); +} - // begin if: $DIR_LIBS isn't a directory - if ( !is_dir($DIR_PLUGINS) ) - { - exit; - } // end if +/** + * getNucleusVersion() + * This function returns the current Nucleus version (100 = 1.00, 101 = 1.01, etc...) + * + * @param void + * @return integer + */ +function getNucleusVersion() +{ + return 400; +} - $plugin_path = $DIR_PLUGINS . $file; +/** + * getNucleusPatchLevel() + * TODO: Better description of this function. + * + * Power users can install patches in between nucleus releases. These patches + * usually add new functionality in the plugin API and allow those to + * be tested without having to install CVS. + * + *@param void + * @return integer + */ +function getNucleusPatchLevel() +{ + return 0; +} - // begin if: - if ( $once && $require ) - { - require_once($plugin_path); - } - else if ( $once && !$require ) - { - include_once($plugin_path); - } - elseif ( $require ) - { - require($plugin_path); - } - else - { - include($plugin_path); - } - } - - /** - * This function decide which locale is used and include translation - * @param string $locale locale name referring to 'language tags' defined in RFC 5646 - * @param mixed $member member object - */ - function include_translation($locale, $member = FALSE) +/** + * getLatestVersion() + * This function returns the latest Nucleus version available for download from nucleuscms.org or FALSE if unable to attain data + * Format will be major.minor/patachlevel e.g. 3.41 or 3.41/02 + * + * @param void + * @return mixed + */ +function getLatestVersion() +{ + // begin if: cURL is not available in this PHP installation + if ( !function_exists('curl_init') ) { - global $DIR_LANG; - - /* - * 1. user's locale is used if set - * 2. system default is used if it is not empty - * 3. else 'en_Latn_US.ISO-8859-1.php' is included - * because this translation file is expected to include only 7bit ASCII characters - * which common in whole character coding scheme - */ - if ( $member && $member->getLocale() ) - { - $locale = $member->getLocale(); - } - $translation_file = $DIR_LANG . $locale . '.' . i18n::get_current_charset() . '.php'; - if ( !file_exists($translation_file) ) - { - $locale = 'en_Latn_US'; - $translation_file = $DIR_LANG . 'en_Latn_US.ISO-8859-1.php'; - } - include($translation_file); - return $locale; + return FALSE; } - /** - * This function returns the integer value of $_POST for the variable $name - * @param string $name field to get the integer value of - * @return int - */ - function intPostVar($name) - { - return intval(postVar($name)); - } - + $curl = curl_init(); + $timeout = 5; + + curl_setopt ($curl, CURLOPT_URL, 'http://nucleuscms.org/version_check.php'); + curl_setopt ($curl, CURLOPT_RETURNTRANSFER, 1); + curl_setopt ($curl, CURLOPT_CONNECTTIMEOUT, $timeout); + + $return = curl_exec($curl); + + curl_close($curl); + + return $return; +} - /** - * This function returns the integer value of $_GET for the variable $name - * @param string $name field to get the integer value of - * @return int - */ - function intGetVar($name) +/** + * sql_table() + * This function returns a Nucleus table name with the appropriate prefix + * @param string $name + * @return string + */ +function sql_table($name) +{ + global $MYSQL_PREFIX; + + // begin if: no MySQL prefix + if ( empty($MYSQL_PREFIX) ) { - return intval(getVar($name)); + return 'nucleus_' . $name; } - - - /** - * This function returns the integer value of $_REQUEST for the variable $name. Also checks $_GET and $_POST if not found in $_REQUEST - * @param string $name field to get the integer value of - * @return int - */ - function intRequestVar($name) + // else: use MySQL prefix + else { - return intval(requestVar($name)); + return $MYSQL_PREFIX . 'nucleus_' . $name; } + return; +} - - /** - * This function returns the integer value of $_COOKIE for the variable $name - * @param string $name field to get the integer value of - * @return int - */ - function intCookieVar($name) +/** + * sendContentType() + * This function sends the Content-Type header if headers have not already been sent + * It also determines if the browser can accept application/xhtml+xml and sends it only to those that can. + * + * if content type is application/xhtml+xml, only send it to browsers + * that can handle it (IE6 cannot). Otherwise, send text/html + * + * v2.5: + * For admin area pages, keep sending text/html (unless it's a debug version) + * application/xhtml+xml still causes too much problems with the javascript implementations + * + * v3.3: + * ($CONF['UsingAdminArea'] && !$CONF['debug']) gets removed, + * application/xhtml+xml seems to be working, so we're going to use it if we can. + * + * @param string $content_type MIME media type registered to IANA, http://www.iana.org/assignments/media-types/index.html + * @param string $page_type + * @param string $charset Deprecated. This has no meaning. + * @return void + * + */ +function sendContentType($content_type, $page_type = '', $charset = '') +{ + global $manager, $CONF; + + if ( headers_sent() ) { - return intval(cookieVar($name)); + return; } - - - /** - * This function returns the current Nucleus version (100 = 1.00, 101 = 1.01, etc...) - * @return int - */ - function getNucleusVersion() + + /* NOTE: MIME Media Type */ + if ( ($content_type == 'application/xhtml+xml') + && (!stristr(serverVar('HTTP_ACCEPT'), 'application/xhtml+xml') ) ) { - return 400; + $content_type = 'text/html'; } - - - /** - * TODO: Better description of this function. - * - * Power users can install patches in between nucleus releases. These patches - * usually add new functionality in the plugin API and allow those to - * be tested without having to install CVS. - * - * @return int - */ - function getNucleusPatchLevel() + + /* NOTE: generate event */ + $data = array( + 'pageType' => $page_type, + 'contentType' => &$content_type + ); + $manager->notify('PreSendContentType', $data); + + /* NOTE: confirm MIME Media Type */ + $content_type = preg_replace('#[^a-zA-Z0-9-+./]#', '', $content_type); + + /* NOTE: confirm character set */ + $charset = i18n::get_current_charset(); + if ( i18n::get_forced_charset() !== '' ) { - return 0; + $charset = i18n::get_forced_charset(); } - - - /** - * This function returns the latest Nucleus version available for download from nucleuscms.org or FALSE if unable to attain data - * Format will be major.minor/patachlevel e.g. 3.41 or 3.41/02 - * @return string|bool - */ - function getLatestVersion() + + /* NOTE: send HTTP 1.1 header */ + header("Content-Type: {$content_type}; charset={$charset}"); + + /* NOTE: set handler for translating character set */ + if ( $charset != i18n::get_current_charset() ) { - // begin if: cURL is not available in this PHP installation - if ( !function_exists('curl_init') ) - { - return FALSE; - } // end if - - $curl = curl_init(); - $timeout = 5; - curl_setopt ($curl, CURLOPT_URL, 'http://nucleuscms.org/version_check.php'); - curl_setopt ($curl, CURLOPT_RETURNTRANSFER, 1); - curl_setopt ($curl, CURLOPT_CONNECTTIMEOUT, $timeout); - $return = curl_exec($curl); - curl_close($curl); - return $return; + ob_start(array('i18n', 'convert_handler')); } + + return; +} - - /** - * This function returns a Nucleus table name with the appropriate prefix - * @param string $name - * @return string - */ - function sql_table($name) +/** + * parseHighlight() + * This function parses a query into an array of expressions that can be passed on to the highlight method + * @param string $query + * @return void + */ +function parseHighlight($query) +{ + // TODO: add more intelligent splitting logic + + // get rid of quotes + $query = preg_replace('/\'|"/', '', $query); + + if ( !$query ) { - global $MYSQL_PREFIX; - - // begin if: no MySQL prefix - if ( empty($MYSQL_PREFIX) ) - { - return 'nucleus_' . $name; - } - // else: use MySQL prefix - else - { - return $MYSQL_PREFIX . 'nucleus_' . $name; - } // end if - + return array(); } - - - /** - * TODO: This function should be changed to send_content_type() per the Coding Guidelines. Ensure this change is compatible with rest of core. - * - * This function sends the Content-Type header if headers have not already been sent - * It also determines if the browser can accept application/xhtml+xml and sends it only to those that can. - * @param string $content_type - * @param string $page_type - * @param string $charset Deprecated. This has no meaning. - */ - function sendContentType($content_type, $page_type = '', $charset = _CHARSET) + + $aHighlight = preg_split('# #', $query); + + for ( $i = 0; $i < count($aHighlight); $i++ ) { - global $manager, $CONF; + $aHighlight[$i] = trim($aHighlight[$i]); - if ( !headers_sent() ) + if ( i18n::strlen($aHighlight[$i]) < 3 ) { - // if content type is application/xhtml+xml, only send it to browsers - // that can handle it (IE6 cannot). Otherwise, send text/html - - // v2.5: For admin area pages, keep sending text/html (unless it's a debug version) - // application/xhtml+xml still causes too much problems with the javascript implementations - - // v3.3: ($CONF['UsingAdminArea'] && !$CONF['debug']) gets removed, - // application/xhtml+xml seems to be working, so we're going to use it if we can. - - if ( ($content_type == 'application/xhtml+xml') - && (!stristr(serverVar('HTTP_ACCEPT'), 'application/xhtml+xml') ) ) - { - $content_type = 'text/html'; - } // end if - - $manager->notify( - 'PreSendContentType', - array( - 'contentType' => &$content_type, - 'charset' => i18n::get_current_charset(), - 'pageType' => $page_type - ) - ); - - // strip strange characters - $content_type = preg_replace('|[^a-z0-9-+./]|i', '', $content_type); - header('Content-Type: ' . $content_type . '; charset=' . i18n::get_current_charset()); - } // end if - + unset($aHighlight[$i]); + } } - - - /** - * This function highlights a specific query in a given HTML text (not within HTML tags) and returns it - * @param string $text text to be highlighted - * @param string $expression regular expression to be matched (can be an array of expressions as well) - * @param string $highlight highlight to be used (use \\0 to indicate the matched expression) - * @return string - */ - function highlight($text, $expression, $highlight) + + if ( count($aHighlight) == 1 ) { - - if ( !$highlight || !$expression ) - { - return $text; - } - - if ( is_array($expression) && (count($expression) == 0) ) - { - return $text; - } - - // add a tag in front (is needed for preg_match_all to work correctly) - $text = '' . $text; - - // split the HTML up so we have HTML tags - // $matches[0][i] = HTML + text - // $matches[1][i] = HTML - // $matches[2][i] = text - preg_match_all('/(<[^>]+>)([^<>]*)/', $text, $matches); - - // throw it all together again while applying the highlight to the text pieces - $result = ''; - - $count_matches = count($matches[2]); - - for ( $i = 0; $i < $count_matches; $i++ ) - { - - if ( $i != 0 ) - { - $result .= $matches[1][$i]; - } - - if ( is_array($expression) ) - { - - foreach ( $expression as $regex ) - { - - if ( $regex ) - { - //$matches[2][$i] = @eregi_replace($regex, $highlight, $matches[2][$i]); - $matches[2][$i] = @preg_replace('#' . $regex . '#i', $highlight, $matches[2][$i]); - } - - } - - $result .= $matches[2][$i]; - - } - else - { - //$result .= @eregi_replace($expression, $highlight, $matches[2][$i]); - $result .= @preg_replace('#' . $expression . '#i', $highlight, $matches[2][$i]); - } - - } - - return $result; - + return $aHighlight[0]; } - - - /** - * This function parses a query into an array of expressions that can be passed on to the highlight method - * @param string $query - */ - function parseHighlight($query) + else { - // TODO: add more intelligent splitting logic - - // get rid of quotes - $query = preg_replace('/\'|"/', '', $query); - - if ( !$query ) - { - return array(); - } - - $aHighlight = i18n::explode(' ', $query); - - for ( $i = 0; $i < count($aHighlight); $i++ ) - { - $aHighlight[$i] = trim($aHighlight[$i]); - - if ( i18n::strlen($aHighlight[$i]) < 3 ) - { - unset($aHighlight[$i]); - } - } - - if ( count($aHighlight) == 1 ) - { - return $aHighlight[0]; - } - else - { - return $aHighlight; - } + return $aHighlight; } + return; +} - /** - * This function gets the blog ID from the blog name - * @param string $name - * @return - */ - function getBlogIDFromName($name) +/** + * getConfig() + * + * @param void + * @return void + */ +function getConfig() +{ + global $CONF; + + $query = sprintf('SELECT * FROM %s', sql_table('config')); + $res = DB::getResult($query); + + foreach ( $res as $row ) { - return quickQuery('SELECT `bnumber` AS `result` FROM `' . sql_table('blog') . '` WHERE `bshortname` = "' . sql_real_escape_string($name) . '"'); + $CONF[$row['name']] = $row['value']; } + return; +} +/** + * This function gets the blog ID from the blog name + * @param string $name + * @return + */ +function getBlogIDFromName($name) +{ + $query = sprintf('SELECT bnumber AS result FROM %s WHERE bshortname=%s', sql_table('blog'), DB::quoteValue($name)); + return DB::getValue($query); +} - /** - * This function gets the blog name from the blog ID - * @param int $id - * @return object - */ - function getBlogNameFromID($id) - { - return quickQuery('SELECT `bname` AS `result` FROM `' . sql_table('blog') . '` WHERE `bnumber` = ' . intval($id)); - } +/** + * This function gets the blog name from the blog ID + * @param int $id + * @return object + */ +function getBlogNameFromID($id) +{ + $query = sprintf('SELECT bname AS result FROM %s WHERE bnumber=%d', sql_table('blog'), intval($id)); + return DB::getValue($query); +} +/** + * This function gets the blog ID from the item ID + * @param int $item_id + * @return object + */ +function getBlogIDFromItemID($item_id) +{ + $query = sprintf('SELECT iblog AS result FROM %s WHERE inumber=%d', sql_table('item'), intval($item_id)); + return DB::getValue($query); +} - /** - * This function gets the blog ID from the item ID - * @param int $item_id - * @return object - */ - function getBlogIDFromItemID($item_id) - { - return quickQuery('SELECT `iblog` AS `result` FROM `' . sql_table('item') . '` WHERE `inumber` = ' . intval($item_id)); - } +/** + * This function gets the blog ID from the comment ID + * @param int $comment_id + * @return object + */ +function getBlogIDFromCommentID($comment_id) +{ + $query = sprintf('SELECT cblog AS result FROM %s WHERE cnumber=%d', sql_table('comment'), intval($comment_id)); + return DB::getValue($query); +} +/** + * This function gets the blog ID from the category ID + * @param int $category_id + * @return object + */ +function getBlogIDFromCatID($category_id) +{ + $query = sprintf('SELECT cblog AS result FROM %s WHERE catid=%d', sql_table('category'), intval($category_id)); + return DB::getValue($query); +} - /** - * This function gets the blog ID from the comment ID - * @param int $comment_id - * @return object - */ - function getBlogIDFromCommentID($comment_id) - { - return quickQuery('SELECT `cblog` AS `result` FROM `' . sql_table('comment') . '` WHERE `cnumber` = ' . intval($comment_id)); - } +/** + * This function gets the category ID from the category name + * @param int $name + * @return object + */ +function getCatIDFromName($name) +{ + $query = sprintf('SELECT catid AS result FROM %s WHERE cname=%s', sql_table('category'), DB::quoteValue($name)); + return DB::getValue($query); +} - /** - * This function gets the blog ID from the category ID - * @param int $category_id - * @return object - */ - function getBlogIDFromCatID($category_id) +/** + * functions to be used in index.php to select something + */ +function selectBlog($shortname) +{ + global $blogid, $archivelist; + $blogid = getBlogIDFromName($shortname); + + // also force archivelist variable, if it is set + if ( $archivelist ) { - return quickQuery('SELECT `cblog` AS `result` FROM `' . sql_table('category') . '` WHERE `catid` = ' . intval($category_id)); + $archivelist = $blogid; } - - - /** - * This function gets the category ID from the category name - * @param int $name - * @return object - */ - function getCatIDFromName($name) + return; +} +function selectSkin($skinname) +{ + global $skinid; + $skinid = SKIN::getIdFromName($skinname); + return; +} +function selectCategory($cat) +{ + global $catid; + if ( is_numeric($cat) ) { - return quickQuery('SELECT `catid` AS `result` FROM `' . sql_table('category') . '` WHERE `cname` = "' . sql_real_escape_string($name) . '"'); + $catid = (integer) $cat; } - - - /** - * This function performs a quick SQL query - * @param string $query - * @return object - */ - function quickQuery($query) + else { - $res = sql_query($query); - $obj = sql_fetch_object($res); - return $obj->result; + $catid = getCatIDFromName($cat); } - -function getPluginNameFromPid($pid) { - $res = sql_query('SELECT pfile FROM ' . sql_table('plugin') . ' WHERE pid=' . intval($pid) ); - $obj = sql_fetch_object($res); - return $obj->pfile; -// return isset($obj->pfile) ? $obj->pfile : false; + return; } - -function selector() { - global $itemid, $blogid, $memberid, $query, $amount, $archivelist, $maxresults; - global $archive, $skinid, $blog, $memberinfo, $CONF, $member; - global $imagepopup, $catid, $special; - global $manager; +function selectItem($id) +{ + global $itemid; + $itemid = (integer) $id; + return; +} +function selectSpecialSkinType($id) +{ + global $special; + $special = strtolower($id); + return; +} +function selector() +{ + global $archive, $archivelist, $archivenext, $archivenextexists, $archiveprev, $archiveprevexists, $archivetype; + global $blog, $blogid; + global $catid; + global $itemid, $itemidnext, $itemidprev, $itemtitlenext, $itemtitleprev; + global $CONF, $DIR_LIBS, $amount, $errormessage, $imagepopup; + global $manager, $maxresults, $query; + global $member, $memberid, $memberinfo; + global $skinid, $skinpart, $special; $actionNames = array('addcomment', 'sendmessage', 'createaccount', 'forgotpassword', 'votepositive', 'votenegative', 'plugin'); $action = requestVar('action'); if ( in_array($action, $actionNames) ) { - global $DIR_LIBS, $errormessage; include_once($DIR_LIBS . 'ACTION.php'); - $a = new ACTION(); + $a = new Action(); $errorInfo = $a->doAction($action); if ( $errorInfo ) @@ -1162,8 +2783,13 @@ function selector() { } startUpError( - '

The page headers have already been sent out' . $extraInfo . '. This could cause Nucleus not to work in the expected way.

Usually, this is caused by spaces or newlines at the end of the config.php file, at the end of the language file or at the end of a plugin file. Please check this and try again.

If you don\'t want to see this error message again, without solving the problem, set $CONF[\'alertOnHeadersSent\'] in globalfunctions.php to 0

', - 'Page headers already sent' + "

The page headers have already been sent out{$extraInfo}. This could cause Nucleus not to work in the expected way.

" + . "

Usually, this is caused by spaces or newlines at the end of the config.php file, " + . "at the end of the translation file or at the end of a plugin file.

" + . "

Please check this and try again.

" + . "

If you don't want to see this error message again, without solving the problem, " + . "set {$CONF['alertOnHeadersSent']} in globalfunctions.php to 0

" + . "Page headers already sent" ); exit; } @@ -1184,90 +2810,91 @@ function selector() { if ( !$manager->existsItem($itemid,intval($CONF['allowFuture']),intval($CONF['allowDrafts'])) ) { doError(_ERROR_NOSUCHITEM); + return; } - global $itemidprev, $itemidnext, $catid, $itemtitlenext, $itemtitleprev; - // 1. get timestamp, blogid and catid for item - $query = 'SELECT itime, iblog, icat FROM ' . sql_table('item') . ' WHERE inumber=' . intval($itemid); - $res = sql_query($query); - $obj = sql_fetch_object($res); + $query = 'SELECT itime, iblog, icat FROM %s WHERE inumber=%d'; + $query = sprintf($query, sql_table('item'), intval($itemid)); + $row = DB::getRow($query); // if a different blog id has been set through the request or selectBlog(), // deny access - if ( $blogid && (intval($blogid) != $obj->iblog) ) + if ( $blogid && (intval($blogid) != $row['iblog']) ) { doError(_ERROR_NOSUCHITEM); + return; } // if a category has been selected which doesn't match the item, ignore the // category. #85 - if ( ($catid != 0) && ($catid != $obj->icat) ) + if ( ($catid != 0) && ($catid != $row['icat']) ) { $catid = 0; } - $blogid = $obj->iblog; - $timestamp = strtotime($obj->itime); + $blogid = $row['iblog']; + $timestamp = strtotime($row['itime']); $b =& $manager->getBlog($blogid); - if ( $b->isValidCategory($catid) ) + if ( !$b->isValidCategory($catid) ) { - $catextra = ' and icat=' . $catid; + $query = "SELECT inumber, ititle FROM %s WHERE itime<%s AND idraft=0 AND iblog=%d ORDER BY itime DESC LIMIT 1"; + $query = sprintf($query, sql_table('item'), DB::formatDateTime($timestamp), intval($blogid)); } else { - $catextra = ''; + $query = "SELECT inumber, ititle FROM %s WHERE itime<%s AND idraft=0 AND iblog=%d AND icat=%d ORDER BY itime DESC LIMIT 1"; + $query = sprintf($query, sql_table('item'), DB::formatDateTime($timestamp), intval($blogid), intval($catid)); } + $row = DB::getRow($query); - // get previous itemid and title - $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'; - $res = sql_query($query); - - $obj = sql_fetch_object($res); - - if ( $obj ) + if ( $row ) { - $itemidprev = $obj->inumber; - $itemtitleprev = $obj->ititle; + $itemidprev = $row['inumber']; + $itemtitleprev = $row['ititle']; } // get next itemid and title - $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'; - $res = sql_query($query); - - $obj = sql_fetch_object($res); + if ( !$b->isValidCategory($catid) ) + { + $query = "SELECT inumber, ititle FROM %s WHERE itime>%s AND itime<=%s AND idraft=0 AND iblog=%d ORDER BY itime ASC LIMIT 1"; + $query = sprintf($query, sql_table('item'), DB::formatDateTime($timestamp), DB::formatDateTime($b->getCorrectTime()), intval($blogid)); + } + else + { + $query = "SELECT inumber, ititle FROM %s WHERE itime>%s AND itime<=%s AND idraft=0 AND iblog=%d AND icat=%d ORDER BY itime ASC LIMIT 1"; + $query = sprintf($query, sql_table('item'), DB::formatDateTime($timestamp), DB::formatDateTime($b->getCorrectTime()), intval($blogid), intval($catid)); + } + $row = DB::getRow($query); - if ( $obj ) + if ( $row ) { - $itemidnext = $obj->inumber; - $itemtitlenext = $obj->ititle; + $itemidnext = $row['inumber']; + $itemtitlenext = $row['ititle']; } } - elseif ($archive) + elseif ( $archive ) { // show archive $type = 'archive'; - // 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 ORDER BY itime ASC"; - $first_timestamp=quickQuery ($query); - $query = "SELECT UNIX_TIMESTAMP(itime) as result FROM ".sql_table('item')." WHERE idraft=0 ORDER BY itime DESC"; - $last_timestamp=quickQuery ($query); + $query = sprintf('SELECT UNIX_TIMESTAMP(itime) as result FROM %s WHERE idraft=0 ORDER BY itime ASC', sql_table('item')); + $first_timestamp = DB::getValue($query); + $query = sprintf('SELECT UNIX_TIMESTAMP(itime) as result FROM %s WHERE idraft=0 ORDER BY itime DESC', sql_table('item')); + $last_timestamp = DB::getValue($query); sscanf($archive, '%d-%d-%d', $y, $m, $d); if ( $d != 0 ) { - $archivetype = _ARCHIVETYPE_DAY; + $archivetype = _LABEL_DAY_UNIT; $t = mktime(0, 0, 0, $m, $d, $y); // one day has 24 * 60 * 60 = 86400 seconds - $archiveprev = i18n::strftime('%Y-%m-%d', $t - 86400 ); + $archiveprev = i18n::formatted_datetime('%Y-%m-%d', $t - 86400 ); // check for published items if ( $t > $first_timestamp ) { @@ -1280,7 +2907,7 @@ function selector() { // one day later $t += 86400; - $archivenext = i18n::strftime('%Y-%m-%d', $t); + $archivenext = i18n::formatted_datetime('%Y-%m-%d', $t); if ( $t < $last_timestamp ) { $archivenextexists = true; @@ -1292,10 +2919,10 @@ function selector() { } elseif ( $m == 0 ) { - $archivetype = _ARCHIVETYPE_YEAR; + $archivetype = _LABEL_YEAR_UNIT; $t = mktime(0, 0, 0, 12, 31, $y - 1); // one day before is in the previous year - $archiveprev = i18n::strftime('%Y', $t); + $archiveprev = i18n::formatted_datetime('%Y', $t); if ( $t > $first_timestamp ) { $archiveprevexists = true; @@ -1307,7 +2934,7 @@ function selector() { // timestamp for the next year $t = mktime(0, 0, 0, 1, 1, $y + 1); - $archivenext = i18n::strftime('%Y', $t); + $archivenext = i18n::formatted_datetime('%Y', $t); if ( $t < $last_timestamp ) { $archivenextexists = true; @@ -1319,10 +2946,10 @@ function selector() { } else { - $archivetype = _ARCHIVETYPE_MONTH; + $archivetype = _LABEL_MONTH_UNIT; $t = mktime(0, 0, 0, $m, 1, $y); // one day before is in the previous month - $archiveprev = i18n::strftime('%Y-%m', $t - 86400); + $archiveprev = i18n::formatted_datetime('%Y-%m', $t - 86400); if ( $t > $first_timestamp ) { $archiveprevexists = true; @@ -1334,7 +2961,7 @@ function selector() { // timestamp for the next month $t = mktime(0, 0, 0, $m+1, 1, $y); - $archivenext = i18n::strftime('%Y-%m', $t); + $archivenext = i18n::formatted_datetime('%Y-%m', $t); if ( $t < $last_timestamp ) { $archivenextexists = true; @@ -1345,7 +2972,7 @@ function selector() { } } } - elseif ($archivelist) + elseif ( $archivelist ) { $type = 'archivelist'; @@ -1361,6 +2988,7 @@ function selector() { if ( !$blogid ) { doError(_ERROR_NOSUCHBLOG); + return; } } elseif ( $query ) @@ -1381,15 +3009,17 @@ function selector() { if ( !$blogid ) { doError(_ERROR_NOSUCHBLOG); + return; } } elseif ( $memberid ) { $type = 'member'; - if ( !MEMBER::existsID($memberid) ) + if ( !Member::existsID($memberid) ) { doError(_ERROR_NOSUCHMEMBER); + return; } $memberinfo = $manager->getMember($memberid); } @@ -1426,324 +3056,1211 @@ function selector() { if ( !$blog->isValid ) { doError(_ERROR_NOSUCHBLOG); + return; } // set catid if necessary if ( $catid ) { - // check if the category is valid - if ( !$blog->isValidCategory($catid) ) + // check if the category is valid + if ( !$blog->isValidCategory($catid) ) + { + doError(_ERROR_NOSUCHCATEGORY); + return; + } + else + { + $blog->setSelectedCategory($catid); + } + } + + if ( !$skinid ) + { + $skinid = $blog->getDefaultSkin(); + } + + if ( !empty($special) && isValidShortName($special) ) + { + $type = strtolower($special); + } + + $skin =& $manager->getSkin($skinid); + + if ( !$skin->isValid() ) + { + doError(_ERROR_NOSUCHSKIN); + return; + } + + // set global skinpart variable so can determine quickly what is being parsed from any plugin or phpinclude + $skinpart = $type; + + // parse the skin + $skin->parse($type); + + // check to see we should throw JustPosted event + $blog->checkJustPosted(); + return; +} + +/** + * doError() + * Show error skin with given message. An optional skin-object to use can be given + * + * @param string $msg + * @param string $skin + * @return void + */ +function doError($msg, $skin = '') +{ + global $errormessage, $CONF, $skinid, $blogid, $manager; + + if ( $skin == '' ) + { + if ( Skin::existsID($skinid) ) + { + $id = $skinid; + } + elseif ( $manager->existsBlogID($blogid) ) + { + $blog =& $manager->getBlog($blogid); + $id = $blog->getDefaultSkin(); + } + elseif ($CONF['DefaultBlog'] ) + { + $blog =& $manager->getBlog($CONF['DefaultBlog']); + $id = $blog->getDefaultSkin(); + } + else + { + // this statement should actually never be executed + $id = $CONF['BaseSkin']; + } + $skin =& $manager->getSkin($id); + } + + $errormessage = $msg; + $skin->parse('error'); + return; +} + +/** + * Errors before the database connection has been made + * + * @param string $msg message to notify + * @param string $title page title + * @return void + */ +function startUpError($msg, $title) +{ + header('Content-Type: text/xml; charset=' . i18n::get_current_charset()); + echo "\n"; + echo "\n"; + echo "{$title}\n"; + echo "\n"; + echo "

{$title}

\n"; + echo $msg; + echo "\n"; + echo "\n"; + exit; +} + +function isValidShortName($name) +{ + return preg_match('#^[a-z0-9]+$#i', $name); +} +function isValidDisplayName($name) +{ + return preg_match('#^[a-z0-9]+[a-z0-9 ]*[a-z0-9]+$#i', $name); +} +function isValidCategoryName($name) +{ + return 1; +} +function isValidTemplateName($name) +{ + return preg_match('#^[a-z0-9/_\-]+$#i', $name); +} +function isValidSkinName($name) +{ + return preg_match('#^[a-z0-9/_\-]+$#i', $name); +} + +// add and remove linebreaks +function addBreaks($var) +{ + return nl2br($var); +} +function removeBreaks($var) +{ + return preg_replace("/
([\r\n])/", "$1", $var); +} + +/** + * parseFile() + * + * @param string $filename + * @param string $includeMode + * @param string $includePrefix + * @return void + */ +function parseFile($filename, $includeMode = 'normal', $includePrefix = '') +{ + global $manager, $skinid; + + if ( !$skinid || !existsID($skinid) ) + { + $skin =& $manager->getSkin($CONF['BaseSkin']); + } + else + { + $skin =& $manager->getSkin($skinid); + } + + $oldIncludeMode = Parser::getProperty('IncludeMode'); + $oldIncludePrefix = Parser::getProperty('IncludePrefix'); + + $skin->parse('fileparse', $filename); + + Parser::setProperty('IncludeMode', $oldIncludeMode); + Parser::setProperty('IncludePrefix', $oldIncludePrefix); + + return; +} + +/** + * debug() + * Outputs a debug message + * + * @param string $msg + * @return void + */ +function debug($msg) +{ + echo '

' . $msg . "

\n"; + return; +} + +// shows a link to help file +function help($id) +{ + echo helpHtml($id); + return; +} +function helpHtml($id) +{ + global $CONF; + return helplink($id) . '' . _HELP_TT . '
'; +} +function helplink($id) +{ + global $CONF; + return ''; +} + +/** + * includephp() + * Includes a PHP file. This method can be called while parsing templates and skins + * + * @param string $filename name of file to parse + * @return void + */ +function includephp($filename) +{ + // make predefined variables global, so most simple scripts can be used here + + // apache (names taken from PHP doc) + global $GATEWAY_INTERFACE, $SERVER_NAME, $SERVER_SOFTWARE, $SERVER_PROTOCOL; + global $REQUEST_METHOD, $QUERY_STRING, $DOCUMENT_ROOT, $HTTP_ACCEPT; + global $HTTP_ACCEPT_CHARSET, $HTTP_ACCEPT_ENCODING, $HTTP_ACCEPT_LANGUAGE; + global $HTTP_CONNECTION, $HTTP_HOST, $HTTP_REFERER, $HTTP_USER_AGENT; + global $REMOTE_ADDR, $REMOTE_PORT, $SCRIPT_FILENAME, $SERVER_ADMIN; + global $SERVER_PORT, $SERVER_SIGNATURE, $PATH_TRANSLATED, $SCRIPT_NAME; + global $REQUEST_URI; + + // php (taken from PHP doc) + global $argv, $argc, $PHP_SELF, $HTTP_COOKIE_VARS, $HTTP_GET_VARS, $HTTP_POST_VARS; + global $HTTP_POST_FILES, $HTTP_ENV_VARS, $HTTP_SERVER_VARS, $HTTP_SESSION_VARS; + + // other + global $PATH_INFO, $HTTPS, $HTTP_RAW_POST_DATA, $HTTP_X_FORWARDED_FOR; + + if ( @file_exists($filename) ) + { + include($filename); + } + return; +} + +/** + * Checks if a certain plugin exists + * @param string $plug name of plugin + * @return boolean exists or not + */ +function checkPlugin($name) +{ + global $DIR_PLUGINS; + return file_exists($DIR_PLUGINS . preg_replace('#[\\\\|/]#', '', $name) . '.php'); +} + +/** + * alterQueryStr() + * + * @param string $querystr querystring to alter (e.g. foo=1&bar=2&x=y) + * @param string $param name of parameter to change (e.g. 'foo') + * @param string $value New value for that parameter (e.g. 3) + * @return string altered query string (for the examples above: foo=3&bar=2&x=y) + */ +function alterQueryStr($querystr, $param, $value) +{ + $vars = preg_split('#&#', $querystr); + $set = FALSE; + + for ( $i = 0; $i < count($vars); $i++ ) + { + $v = preg_split('#=#', $vars[$i]); + + if ( $v[0] == $param ) + { + $v[1] = $value; + $vars[$i] = implode('=', $v); + $set = true; + break; + } + } + if ( !$set ) + { + $vars[] = "{$param}={$value}"; + } + return ltrim(implode('&', $vars), '&'); +} + +/** + * passVar() + * passes one variable as hidden input field (multiple fields for arrays) + * @see passRequestVars in varsx.x.x.php + * + * @param string $key + * @param string $value + * @return void + */ +function passVar($key, $value) +{ + // array ? + if ( is_array($value) ) + { + for ( $i = 0; $i < sizeof($value); $i++ ) + { + passVar($key . '[' . $i . ']', $value[$i]); + } + return; + } + + // other values: do stripslashes if needed + echo '' . "\n"; + return; +} + +/** + * checkVars() + * + * @param string $variables + * @return void + */ +function checkVars($variables) +{ + foreach ( $variables as $variable ) + { + if ( array_key_exists($variable, $_GET) + || array_key_exists($variable, $_POST) + || array_key_exists($variable, $_COOKIE) + || array_key_exists($variable, $_ENV) + || (session_id() !== '' && array_key_exists($variable, $_SESSION)) + || array_key_exists($variable, $_FILES) ) + { + die('Sorry. An error occurred.'); + } + } + return; +} + +/** + * sanitizeParams() + * Sanitize parameters such as $_GET and $_SERVER['REQUEST_URI'] etc. + * to avoid XSS. + * + * @param void + * @return void + */ +function sanitizeParams() +{ + $array = array(); + $str = ''; + $frontParam = ''; + + // REQUEST_URI of $_SERVER + $str =& $_SERVER["REQUEST_URI"]; + serverStringToArray($str, $array, $frontParam); + sanitizeArray($array); + arrayToServerString($array, $frontParam, $str); + + // QUERY_STRING of $_SERVER + $str =& $_SERVER["QUERY_STRING"]; + serverStringToArray($str, $array, $frontParam); + sanitizeArray($array); + arrayToServerString($array, $frontParam, $str); + + // $_GET + convArrayForSanitizing($_GET, $array); + sanitizeArray($array); + revertArrayForSanitizing($array, $_GET); + + // $_REQUEST (only GET param) + convArrayForSanitizing($_REQUEST, $array); + sanitizeArray($array); + revertArrayForSanitizing($array, $_REQUEST); + + return; +} + +function _addInputTags(&$keys,$prefix='') +{ + foreach ( $keys as $key=>$value ) + { + if ( $prefix ) { - doError(_ERROR_NOSUCHCATEGORY); + $key=$prefix.'['.$key.']'; + } + if ( is_array($value) ) + { + _addInputTags($value,$key); } else { - $blog->setSelectedCategory($catid); + if ( get_magic_quotes_gpc() ) + {$value=stripslashes($value); + } + if ( $key == 'ticket' ) + { + continue; + } + echo ''."\n"; } } + return; +} + +/** + * serverStringToArray() + * Convert the server string such as $_SERVER['REQUEST_URI'] + * to arry like arry['blogid']=1 and array['page']=2 etc. + * + * @param string $uri string + * @param string &$query_elements elements of query according to application/x-www-form-urlencoded + * @param string &$hier_part hierarchical part includes path + * + * NOTE: + * RFC 3986: Uniform Resource Identifiers (URI): Generic Syntax + * 3. Syntax Components + * http://www.ietf.org/rfc/rfc3986.txt + * + * Hypertext Markup Language - 2.0 + * 8.2.1. The form-urlencoded Media Type + * http://tools.ietf.org/html/rfc1866#section-8.2.1 + * + * $_SERVER > Language Reference > Predefined Variables > PHP Manual + * http://www.php.net/manual/en/reserved.variables.server.php + */ +function serverStringToArray($uri, &$query_elements, &$hier_part) +{ + // init param + $query_elements = array(); + $hier_part = ""; - // decide which skin should be used - if ( $skinid != '' && ($skinid == 0) ) - { - selectSkin($skinid); - } - - if ( !$skinid ) + // split hierarchical part, e.g. /index.php, query and fragment, e.g. blogid=1&page=2#section1 + if ( i18n::strpos($uri, "?") > 0 ) { - $skinid = $blog->getDefaultSkin(); + list($hier_part, $query_and_fragment) = preg_split("#\?#", $uri, 2); } - - //$special = requestVar('special'); //get at top of file as global - if ( !empty($special) && isValidShortName($special) ) + else { - $type = strtolower($special); + $query_and_fragment = $uri; + $hier_part = ''; } - $skin = new SKIN($skinid); - - if ( !$skin->isValid ) + // If there is no query like blogid=1&page=2, return + if ( i18n::strpos($uri, "=") == FALSE && !i18n::strlen($hier_part) ) { - doError(_ERROR_NOSUCHSKIN); + $hier_part = $uri; + return; } - // set global skinpart variable so can determine quickly what is being parsed from any plugin or phpinclude - global $skinpart; - $skinpart = $type; - - // parse the skin - $skin->parse($type); - - // check to see we should throw JustPosted event - $blog->checkJustPosted(); + $query_elements = preg_split("#&#", $query_and_fragment); return; } /** - * Show error skin with given message. An optional skin-object to use can be given - */ -function doError($msg, $skin = '') { - global $errormessage, $CONF, $skinid, $blogid, $manager; - - if ($skin == '') { - - if (SKIN::existsID($skinid) ) { - $skin = new SKIN($skinid); - } elseif ($manager->existsBlogID($blogid) ) { - $blog =& $manager->getBlog($blogid); - $skin = new SKIN($blog->getDefaultSkin() ); - } elseif ($CONF['DefaultBlog']) { - $blog =& $manager->getBlog($CONF['DefaultBlog']); - $skin = new SKIN($blog->getDefaultSkin() ); - } else { - // this statement should actually never be executed - $skin = new SKIN($CONF['BaseSkin']); - } - - } - - $skinid = $skin->id; - $errormessage = $msg; - $skin->parse('error'); - exit; -} - -function getConfig() { - global $CONF; - - $query = 'SELECT * FROM ' . sql_table('config'); - $res = sql_query($query); - - while ($obj = sql_fetch_object($res) ) { - $CONF[$obj->name] = $obj->value; - } -} - -// some checks for names of blogs, categories, templates, members, ... -function isValidShortName($name) { - - # replaced eregi() below with preg_match(). ereg* functions are deprecated in PHP 5.3.0 - # original eregi: eregi('^[a-z0-9]+$', $name) - - return preg_match('#^[a-z0-9]+$#i', $name); - -} - -function isValidDisplayName($name) { - - # replaced eregi() below with preg_match(). ereg* functions are deprecated in PHP 5.3.0 - # original eregi: eregi('^[a-z0-9]+[a-z0-9 ]*[a-z0-9]+$', $name) - - return preg_match('#^[a-z0-9]+[a-z0-9 ]*[a-z0-9]+$#i', $name); - -} - -function isValidCategoryName($name) { - return 1; -} - -function isValidTemplateName($name) { - - # replaced eregi() below with preg_match(). ereg* functions are deprecated in PHP 5.3.0 - # original eregi: eregi('^[a-z0-9/]+$', $name) - // added - and _ to valid characters as of 4.00 - - return preg_match('#^[a-z0-9/_\-]+$#i', $name); - + * arrayToServerString() + * Convert array like array['blogid'] to server string + * such as $_SERVER['REQUEST_URI'] + * + * @param array $query_elements elements of query according to application/x-www-form-urlencoded + * @param string $hier_part hier-part defined in RFC3986 + * @param string &$uri return value + * @return void + * + * NOTE: + * RFC 3986: Uniform Resource Identifiers (URI): Generic Syntax + * 3. Syntax Components + * http://www.ietf.org/rfc/rfc3986.txt + * + * Hypertext Markup Language - 2.0 + * 8.2.1. The form-urlencoded Media Type + * http://tools.ietf.org/html/rfc1866#section-8.2.1 + * + * $_SERVER > Language Reference > Predefined Variables > PHP Manual + * http://www.php.net/manual/en/reserved.variables.server.php + */ +function arrayToServerString($query_elements, $hier_part, &$uri) +{ + if ( i18n::strpos($uri, "?") !== FALSE ) + { + $uri = $hier_part . "?"; + } + else + { + $uri = $hier_part; + } + if ( count($query_elements) > 0 ) + { + $uri .= implode("&", $query_elements); + } + return; } -function isValidSkinName($name) { - - # replaced eregi() below with preg_match(). ereg* functions are deprecated in PHP 5.3.0 - # original eregi: eregi('^[a-z0-9/]+$', $name); - // added - and _ to valid characters as of 4.00 - - return preg_match('#^[a-z0-9/_\-]+$#i', $name); - +/** + * sanitizeArray() + * Sanitize array parameters. + * This function checks both key and value. + * - check key if it inclues " (double quote), remove from array + * - check value if it includes \ (escape sequece), remove remaining string + * + * @param array &$array elements of query according to application/x-www-form-urlencoded + * @return void + */ +function sanitizeArray(&$array) +{ + $excludeListForSanitization = array('query'); + + foreach ( $array as $k => $v ) + { + // split to key and value + list($key, $val) = preg_split("#=#", $v, 2); + if ( !isset($val) ) + { + continue; + } + + // when magic quotes is on, need to use stripslashes, + // and then addslashes + if ( get_magic_quotes_gpc() ) + { + $val = stripslashes($val); + } + + // note that we must use addslashes here because this function is called before the db connection is made + // and sql_real_escape_string needs a db connection + $val = addslashes($val); + + // if $key is included in exclude list, skip this param + if ( !in_array($key, $excludeListForSanitization) ) + { + // check value + if ( i18n::strpos($val, '\\') > 0 ) + { + list($val, $tmp) = preg_split('#\\\\#', $val); + } + + // remove control code etc. + $val = strtr($val, "\0\r\n<>'\"", " "); + + // check key + if ( preg_match('#\"#', $key) > 0 ) + { + unset($array[$k]); + continue; + } + + // set sanitized info + $array[$k] = sprintf("%s=%s", $key, $val); + } + } + return; } -// add and remove linebreaks -function addBreaks($var) { - return nl2br($var); +/** + * convArrayForSanitizing() + * Convert array for sanitizeArray function + * + * @param string $src array to be sanitized + * @param array &$array array to be temporarily stored + * @return void + */ +function convArrayForSanitizing($src, &$array) +{ + $array = array(); + foreach ( $src as $key => $val ) + { + if ( !key_exists($key, $_GET) ) + { + continue; + } + $array[] = sprintf("%s=%s", $key, $val); + continue; + } + return; } -function removeBreaks($var) { - return preg_replace("/
([\r\n])/", "$1", $var); +/** + * revertArrayForSanitizing() + * Revert array after sanitizeArray function + * + * @param array $array element of query according to application/x-www-form-urlencoded + * @param array &$dst combination of key and value + * @return void + */ +function revertArrayForSanitizing($array, &$dst) +{ + foreach ( $array as $v ) + { + list($key, $val) = preg_split("#=#", $v, 2); + $dst[$key] = $val; + continue; + } + return; } /** - * shortens a text string to maxlength. - * $suffix is what needs to be added at the end (end length is <= $maxlength) - * - * The purpose is to limit the width of string for rendered screen in web browser. - * So it depends on style sheet, browser's rendering scheme, client's system font. - * - * NOTE: In general, non-Latin font such as Japanese, Chinese, Cyrillic have two times as width as Latin fonts, - * but this is not always correct, for example, rendered by proportional font. - * - * @param string $escaped_string target string - * @param integer $maxlength maximum length of return string which includes suffix - * @param string $suffix added in the end of shortened-string - * @return string -*/ -function shorten($string, $maxlength, $suffix) +>>>>>>> skinnable-master + * decodePathInfo() + * + * @param string $virtualpath + * @return void + */ +function decodePathInfo($virtualpath) { - static $flag; + global $CONF, $manager, $archive, $blog, $catid, $memberid, $special; - $decoded_entities_pcre = array(); - $encoded_entities = array(); + /* initialize keywords if this hasn't been done before */ + if ( !isset($CONF['ItemKey']) || empty($CONF['ItemKey']) ) + { + $CONF['ItemKey'] = 'item'; + } - /* 1. store html entities */ - preg_match('#&[^&]+?;#', $string, $encoded_entities); - if ( !$encoded_entities ) + if ( !isset($CONF['ArchiveKey']) || empty($CONF['ArchiveKey']) ) { - $flag = FALSE; + $CONF['ArchiveKey'] = 'archive'; } - else + + if ( !isset($CONF['ArchivesKey']) || empty($CONF['ArchivesKey']) ) { - $flag = TRUE; + $CONF['ArchivesKey'] = 'archives'; } - if ( $flag ) + + if ( !isset($CONF['MemberKey']) || empty($CONF['MemberKey']) ) { - foreach ( $encoded_entities as $encoded_entity ) - { - $decoded_entities_pcre[] = '#' . html_entity_decode($encoded_entity, ENT_QUOTES, i18n::get_current_charset()) . '#'; - } + $CONF['MemberKey'] = 'member'; + } + + if ( !isset($CONF['BlogKey']) || empty($CONF['BlogKey']) ) + { + $CONF['BlogKey'] = 'blog'; } - /* 2. decode string */ - $string = html_entity_decode($string, ENT_QUOTES, i18n::get_current_charset()); + if ( !isset($CONF['CategoryKey']) || empty($CONF['CategoryKey']) ) + { + $CONF['CategoryKey'] = 'category'; + } - /* 3. shorten string and add suffix if string length is longer */ - if ( i18n::strlen($string) > $maxlength - i18n::strlen($suffix) ) + if ( !isset($CONF['SpecialskinKey']) || empty($CONF['SpecialskinKey']) ) { - $string = i18n::substr($string, 0, $maxlength - i18n::strlen($suffix) ); - $string .= $suffix; + $CONF['SpecialskinKey'] = 'special'; } - /* 4. recover entities */ - if ( $flag ) + $parsed = FALSE; + $data = array( + 'type' => basename(serverVar('SCRIPT_NAME') ), + 'info' => $virtualpath, + 'complete' => &$parsed + ); + $manager->notify('ParseURL', $data); + + /* already parsed by the other subsystem */ + if ( $parsed ) + { + return; + } + /* default implementation */ + $data = preg_split("#/#", $virtualpath); + for ( $i = 0; $i < sizeof($data); $i++ ) { - $string = preg_replace($decoded_entities_pcre, $encoded_entities, $string); + switch ( $data[$i] ) + { + /* item/1 (blogid) */ + case $CONF['ItemKey']: + $i++; + + if ( $i < sizeof($data) ) + { + $itemid = (integer) $data[$i]; + } + break; + + /* archives/1 (blogid) */ + case $CONF['ArchivesKey']: + $i++; + if ( $i < sizeof($data) ) + { + $archivelist = (integer) $data[$i]; + } + break; + + /* two possibilities: archive/yyyy-mm or archive/1/yyyy-mm (with blogid) */ + case $CONF['ArchiveKey']: + if ( (($i + 1) < sizeof($data) ) && (i18n::strpos($data[$i + 1], '-') === FALSE ) ) + { + $blogid = (integer) $data[++$i]; + } + $i++; + if ( $i < sizeof($data) ) + { + $archive = $data[$i]; + } + break; + + /* blogid/1 */ + case 'blogid': + /* blog/1 */ + case $CONF['BlogKey']: + $i++; + if ( $i < sizeof($data) ) + { + $blogid = intval($data[$i]); + } + break; + + /* category/1 (catid) */ + case $CONF['CategoryKey']: + case 'catid': + $i++; + if ( $i < sizeof($data) ) + { + $catid = intval($data[$i]); + } + break; + + case $CONF['MemberKey']: + $i++; + if ( $i < sizeof($data) ) + { + $memberid = intval($data[$i]); + } + break; + + case $CONF['SpecialskinKey']: + $i++; + if ( $i < sizeof($data) ) + { + $special = $data[$i]; + } + break; + + default: + /* do nothing */ + break; + } } - return $string; + return; } -/** - * Converts a unix timestamp to a mysql DATETIME format, and places - * quotes around it. - */ -function mysqldate($timestamp) { - return '"' . date('Y-m-d H:i:s', $timestamp) . '"'; -} /** - * functions for use in index.php - */ -function selectBlog($shortname) { - global $blogid, $archivelist; - $blogid = getBlogIDFromName($shortname); - - // also force archivelist variable, if it is set - if ($archivelist) { - $archivelist = $blogid; - } -} - -function selectSkin($skinname) { - global $skinid; - $skinid = SKIN::getIdFromName($skinname); +<<<<<<< HEAD + * redirect() + * Stops processing the request and redirects to the given URL. + * - no actual contents should have been sent to the output yet + * - the URL will be stripped of illegal or dangerous characters + * + * @param string $uri + * @return void + */ +function redirect($url) +{ + $url = preg_replace('#[^a-z0-9-~+_.?\#=&;,/:@%*]#i', '', $url); + header('Location: ' . $url); + exit; +} + +/** + * getBookmarklet() + * Returns the Javascript code for a bookmarklet that works on most modern browsers + * + * @param integer $blogid ID for weblog + * @return script to call Bookmarklet + */ +function getBookmarklet($blogid, $width=600, $height=500) +{ + global $CONF; + + $script = "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('{$CONF['AdminURL']}bookmarklet.php?blogid={$blogid}" + . " &logtext=' + encodeURIComponent(Q) +" + . " '&loglink=' + encodeURIComponent(x.location.href) +" + . " '&loglinktitle=' + encodeURIComponent(x.title)," + . " 'nucleusbm'," + . " 'scrollbars=yes,width={$width},height={$height},left=10,top=10,status=yes,resizable=yes');" + . "wingm.focus();"; + + return $script; +} + +/** + * cleanFileName() + * cleans filename of uploaded file for writing to file system + * + * @param string $str + * @return string $cleaned filename ready for use + */ +function cleanFileName($str) +{ + $str = strtolower($str); + $ext_point = i18n::strrpos($str,"."); + if ( $ext_point === FALSE ) + { + return FALSE; + } + $ext = i18n::substr($str,$ext_point,i18n::strlen($str)); + $str = i18n::substr($str,0,$ext_point); + + return preg_replace("#[^a-z0-9-]#", "_", $str) . $ext; +} + +/** + * use Notification class instead of this + * Deprecated since 4.0: + */ +function getMailFooter() +{ + NOTIFICATION::get_mail_footer(); +} +function isValidMailAddress($address) +{ + return NOTIFICATION::address_validation($address); +} +/** + * use Entity class instead of this + * Deprecated since 4.0: + */ +function highlight($text, $expression, $highlight) +{ + return Entity::highlight($text, $expression, $highlight); +} +function shorten($string, $maxlength, $suffix) +{ + return Entity::shorten($string, $maxlength, $suffix); +} +function stringStripTags ($string) +{ + return Entity::strip_tags($string); +} +function toAscii($string) +{ + return Entity::anchor_footnoting($string); +} +function stringToAttribute ($string) +{ + return Entity::hsc($string); +} +function stringToXML ($string) +{ + return Entity::hen($string); +} +function encode_desc($data) +{ + return Entity::hen($data); +} +/** + * Centralisation of the functions that deals with locales + * This functions is based on the old way to deal with languages + * Deprecated since 4.0: + */ +function getLanguageName() +{ + if( ($language = i18n::convert_locale_to_old_language_file_name(i18n::get_current_locale())) === FALSE ) + { + $language ='english'; + } + return $language; +} +function selectLanguage($language) +{ + global $DIR_LANG; + include($DIR_LANG . preg_replace('#[\\\\|/]#', '', $language) . '.php'); + return; +} +/** + * use i18n class instead of these + * Deprecated since 4.0 + */ +function checkLanguage($lang) +{ + return ( preg_match('#^(.+)_(.+)_(.+)$#', $lang) + || i18n::convert_old_language_file_name_to_locale($lang) ); +} +function formatDate($format, $timestamp, $default_format, &$blog) +{ + $offset = date('Z', $timestamp); + if ( $blog ) + { + $offset += $blog->getTimeOffset() * 3600; + } + return i18n::formatted_datetime($format, $timestamp, $offset, $default_format); +} + +/** + * use DB class instead of these + * Deprecated since 4.0 + */ +function quickQuery($query) +{ + $row = DB::getRow($query); + return $row['result']; +} +function mysqldate($timestamp) +{ + return DB::formatDateTime($timestamp); + } +/** + * Centralisation of the functions that generate links + * Deprecated since 4.0: + * Please use Link::FunctionName(...) instead + */ +function createItemLink($itemid, $extra = '') +{ + return Link::create_item_link($itemid, $extra); +} +function createMemberLink($memberid, $extra = '') +{ + return Link::create_member_link($memberid, $extra); +} +function createCategoryLink($catid, $extra = '') +{ + return Link::create_category_link($catid, $extra); +} +function createArchiveListLink($blogid = '', $extra = '') +{ + return Link::create_archivelist_link($blogid, $extra); +} +function createArchiveLink($blogid, $archive, $extra = '') +{ + return Link::create_archive_link($blogid, $archive, $extra); +} +function createBlogidLink($blogid, $params = '') +{ + return Link::create_blogid_link($blogid, $params = ''); +} +function createLink($type, $params) +{ + return Link::create_link($type, $params); +} +function createBlogLink($url, $params) +{ + return Link::create_blog_link($url, $params); +} +/** + * use ActionLog class instead of this + * Deprecated since 4.0 + */ +function addToLog($level, $msg) +{ + ActionLog::add($level, $msg); +} +/** + * use PHP's implement + * Deprecated since 4.0 + */ +function ifset(&$var) +{ + if ( isset($var) ) + { + return $var; + } + + return NULL; +} +/** + * use Manager::getPluginNameFromPid() instead of this + * Deprecated since 4.0 + */ +function getPluginNameFromPid($pid) +{ + global $manager; + return $manager->getPluginNameFromPid($pid); +} +/** + * use Manager::numberOfEventSubscribers() instead of this + * Deprecated since 4.0 + */ +function numberOfEventSubscribers($event) +{ + global $manager; + return $manager->getNumberOfSubscribers($event); +} + +/** + * PluginAdmin has already the alternative implement + * Deprecated since 4.0 + */ +function ticketForPlugin() +{ + global $CONF, $DIR_LIBS, $DIR_LOCALES, $DIR_PLUGINS, $manager, $member, $ticketforplugin; + + /* initialize */ + $ticketforplugin = array(); + $ticketforplugin['ticket'] = FALSE; + + /* Check if using plugin's php file. */ + $p_translated = serverVar('SCRIPT_FILENAME'); + + if (!file_exists($p_translated) ) + { + header("HTTP/1.0 404 Not Found"); + exit(''); + } + + // check whether this is plugin or not + $p_translated = str_replace('\\', '/', $p_translated); + $d_plugins = str_replace('\\', '/', $DIR_PLUGINS); + if ( i18n::strpos($p_translated, $d_plugins) !== 0 ) + { + return; + } + + // Solve the plugin php file or admin directory + $phppath = i18n::substr($p_translated, i18n::strlen($d_plugins) ); + // Remove the first "/" if exists. + $phppath = preg_replace('#^/#', '', $phppath); + // Remove the first "NP_" and the last ".php" if exists. + $path = preg_replace('#^NP_(.*)\.php$#', '$1', $phppath); + // Remove the "/" and beyond. + $path = preg_replace('#^([^/]*)/(.*)$#', '$1', $path); + + // Solve the plugin name. + $plugins = array(); + $query = sprintf('SELECT pfile FROM %s;', sql_table('plugin')); + $res = DB::getResult($query); + + foreach ( $res as $row ) + { + $name = i18n::substr($row['pfile'], 3); + $plugins[strtolower($name)] = $name; + } + + $res->closeCursor(); + + if ( !array_key_exists($path, $plugins) ) + { + header("HTTP/1.0 404 Not Found"); + exit(''); + } + else + { + $plugin_name = $plugins[$path]; + } + + /* Return if not index.php */ + if ( ($phppath != strtolower($plugin_name) . '/') + && ($phppath != strtolower($plugin_name) . '/index.php') ) + { + return; + } + + /* Exit if not logged in. */ + if ( !$member->isLoggedIn() ) + { + exit('You aren\'t logged in.'); + } + + /* Check if this feature is needed (ie, if "$manager->checkTicket()" is not included in the script). */ + if ( $file = @file($p_translated) ) + { + $prevline = ''; + + foreach($file as $line) + { + if (preg_match('#[\$]manager([\s]*)[\-]>([\s]*)checkTicket([\s]*)[\(]#i', $prevline . $line) ) + { + return; + } + + $prevline = $line; + } + } + + /* Show a form if not valid ticket */ + if ( (i18n::strpos(serverVar('REQUEST_URI'), '?') !== FALSE + || serverVar('QUERY_STRING') + || strtoupper(serverVar('REQUEST_METHOD') ) == 'POST') + && !$manager->checkTicket() ) + { + $oPluginAdmin = new PluginAdmin($plugin_name); + $oPluginAdmin->start(); + + echo '

' . _ERROR_BADTICKET . "

\n"; + + // Resolve URI and QUERY_STRING + if ($uri = serverVar('REQUEST_URI') ) + { + list($uri, $qstring) = preg_split('#\?#', $uri); + } + else + { + if ( !($uri = serverVar('PHP_SELF') ) ) + { + $uri = serverVar('SCRIPT_NAME'); + } + $qstring = serverVar('QUERY_STRING'); + } + if ($qstring) + { + $qstring = '?' . $qstring; + } + + echo '

' . _SETTINGS_UPDATE . ' : ' . _QMENU_PLUGINS . ' ' . Entity::hsc($plugin_name) . " ?

\n"; + + switch(strtoupper(serverVar('REQUEST_METHOD') ) ) + { + case 'POST': + echo '
'; + $manager->addTicketHidden(); + _addInputTags($_POST); + break; + + case 'GET': + echo ''; + $manager->addTicketHidden(); + _addInputTags($_GET); + + default: + break; + } + + echo '    '; + echo ''; + echo "
\n"; + + $oPluginAdmin->end(); + exit; + } + + /* Create new ticket */ + $ticket=$manager->addTicketToUrl(''); + $ticketforplugin['ticket'] = preg_split($ticket, i18n::strpos($ticket, 'ticket=') + 7); + return; +} +======= + * redirect() + * Stops processing the request and redirects to the given URL. + * - no actual contents should have been sent to the output yet + * - the URL will be stripped of illegal or dangerous characters + * + * @param string $uri + * @return void + */ +function redirect($url) +{ + $url = preg_replace('#[^a-z0-9-~+_.?\#=&;,/:@%*]#i', '', $url); + header('Location: ' . $url); + exit; } /** - * Can take either a category ID or a category name (be aware that - * multiple categories can have the same name) + * getBookmarklet() + * Returns the Javascript code for a bookmarklet that works on most modern browsers + * + * @param integer $blogid ID for weblog + * @return script to call Bookmarklet */ -function selectCategory($cat) { - global $catid; - if (is_numeric($cat) ) { - $catid = intval($cat); - } else { - $catid = getCatIDFromName($cat); - } -} - -function selectItem($id) { - global $itemid; - $itemid = intval($id); -} - -// force the use of a language file (warning: can cause warnings) -function selectLanguage($language) { - - global $DIR_LANG; - - # replaced ereg_replace() below with preg_replace(). ereg* functions are deprecated in PHP 5.3.0 - # original ereg_replace: preg_replace( '@\\|/@', '', $language) . '.php') - # important note that '\' must be matched with '\\\\' in preg* expressions - - include($DIR_LANG . preg_replace('#[\\\\|/]#', '', $language) . '.php'); - -} - -function parseFile($filename, $includeMode = 'normal', $includePrefix = '') { - $handler = new ACTIONS('fileparser'); - $parser = new PARSER(SKIN::getAllowedActionsForType('fileparser'), $handler); - $handler->parser =& $parser; - - // set IncludeMode properties of parser - PARSER::setProperty('IncludeMode', $includeMode); - PARSER::setProperty('IncludePrefix', $includePrefix); - - if (!file_exists($filename) ) { - doError('A file is missing'); - } - - $fsize = filesize($filename); - - if ($fsize <= 0) { - return; - } - - // read file - $fd = fopen ($filename, 'r'); - $contents = fread ($fd, $fsize); - fclose ($fd); - - // parse file contents - $parser->parse($contents); +function getBookmarklet($blogid, $width=600, $height=500) +{ + global $CONF; + + $script = "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('{$CONF['AdminURL']}bookmarklet.php?blogid={$blogid}" + . " &logtext=' + encodeURIComponent(Q) +" + . " '&loglink=' + encodeURIComponent(x.location.href) +" + . " '&loglinktitle=' + encodeURIComponent(x.title)," + . " 'nucleusbm'," + . " 'scrollbars=yes,width={$width},height={$height},left=10,top=10,status=yes,resizable=yes');" + . "wingm.focus();"; + + return $script; } /** - * Outputs a debug message - */ -function debug($msg) { - echo '

' . $msg . "

\n"; -} - -// shortcut -function addToLog($level, $msg) { - ACTIONLOG::add($level, $msg); -} - -// shows a link to help file -function help($id) { - echo helpHtml($id); -} - -function helpHtml($id) { - global $CONF; - return helplink($id) . '' . _HELP_TT . '
'; -} - -function helplink($id) { - global $CONF; - return ''; + * cleanFileName() + * cleans filename of uploaded file for writing to file system + * + * @param string $str + * @return string $cleaned filename ready for use + */ +function cleanFileName($str) +{ + $str = strtolower($str); + $ext_point = i18n::strrpos($str,"."); + if ( $ext_point === FALSE ) + { + return FALSE; + } + $ext = i18n::substr($str,$ext_point,i18n::strlen($str)); + $str = i18n::substr($str,0,$ext_point); + + return preg_replace("#[^a-z0-9-]#", "_", $str) . $ext; } /** + * use Notification class instead of this * Deprecated since 4.0: - * Please use functions in MAIL class instead */ function getMailFooter() { @@ -1753,14 +4270,42 @@ function isValidMailAddress($address) { return NOTIFICATION::address_validation($address); } - -/* - * Returns the name of the language to use - * preference priority: member - site - * defaults to english-utf8 when no good language found - * - * NOTE: Deprecated, plugins to use this function should be re-worked as soon as possible! - * TODO: this will be obsoleted soon. +/** + * use Entity class instead of this + * Deprecated since 4.0: + */ +function highlight($text, $expression, $highlight) +{ + return Entity::highlight($text, $expression, $highlight); +} +function shorten($string, $maxlength, $suffix) +{ + return Entity::shorten($string, $maxlength, $suffix); +} +function stringStripTags ($string) +{ + return Entity::strip_tags($string); +} +function toAscii($string) +{ + return Entity::anchor_footnoting($string); +} +function stringToAttribute ($string) +{ + return Entity::hsc($string); +} +function stringToXML ($string) +{ + return Entity::hen($string); +} +function encode_desc($data) +{ + return Entity::hen($data); +} +/** + * Centralisation of the functions that deals with locales + * This functions is based on the old way to deal with languages + * Deprecated since 4.0: */ function getLanguageName() { @@ -1770,301 +4315,133 @@ function getLanguageName() } return $language; } - -/** - * Includes a PHP file. This method can be called while parsing templates and skins - */ -function includephp($filename) { - // make predefined variables global, so most simple scripts can be used here - - // apache (names taken from PHP doc) - global $GATEWAY_INTERFACE, $SERVER_NAME, $SERVER_SOFTWARE, $SERVER_PROTOCOL; - global $REQUEST_METHOD, $QUERY_STRING, $DOCUMENT_ROOT, $HTTP_ACCEPT; - global $HTTP_ACCEPT_CHARSET, $HTTP_ACCEPT_ENCODING, $HTTP_ACCEPT_LANGUAGE; - global $HTTP_CONNECTION, $HTTP_HOST, $HTTP_REFERER, $HTTP_USER_AGENT; - global $REMOTE_ADDR, $REMOTE_PORT, $SCRIPT_FILENAME, $SERVER_ADMIN; - global $SERVER_PORT, $SERVER_SIGNATURE, $PATH_TRANSLATED, $SCRIPT_NAME; - global $REQUEST_URI; - - // php (taken from PHP doc) - global $argv, $argc, $PHP_SELF, $HTTP_COOKIE_VARS, $HTTP_GET_VARS, $HTTP_POST_VARS; - global $HTTP_POST_FILES, $HTTP_ENV_VARS, $HTTP_SERVER_VARS, $HTTP_SESSION_VARS; - - // other - global $PATH_INFO, $HTTPS, $HTTP_RAW_POST_DATA, $HTTP_X_FORWARDED_FOR; - - if (@file_exists($filename) ) { - include($filename); - } +function selectLanguage($language) +{ + global $DIR_LANG; + include($DIR_LANG . preg_replace('#[\\\\|/]#', '', $language) . '.php'); + return; } - /** - * Checks if a certain language exists - * @param string $lang - * @return bool - * - * NOTE: Deprecated, plugins to use this function should be re-worked as soon as possible! - * TODO: this will be obsoleted soon. - **/ + * use i18n class instead of these + * Deprecated since 4.0 + */ function checkLanguage($lang) { return ( preg_match('#^(.+)_(.+)_(.+)$#', $lang) || i18n::convert_old_language_file_name_to_locale($lang) ); } +function formatDate($format, $timestamp, $default_format, &$blog) +{ + $offset = date('Z', $timestamp); + if ( $blog ) + { + $offset += $blog->getTimeOffset() * 3600; + } + return i18n::formatted_datetime($format, $timestamp, $offset, $default_format); +} /** - * Checks if a certain plugin exists - * @param string $plug - * @return bool - **/ -function checkPlugin($plug) { - - global $DIR_PLUGINS; - - # replaced ereg_replace() below with preg_replace(). ereg* functions are deprecated in PHP 5.3.0 - # original ereg_replace: ereg_replace( '[\\|/]', '', $plug) . '.php') - # important note that '\' must be matched with '\\\\' in preg* expressions - - return file_exists($DIR_PLUGINS . preg_replace('#[\\\\|/]#', '', $plug) . '.php'); - + * use DB class instead of these + * Deprecated since 4.0 + */ +function quickQuery($query) +{ + $row = DB::getRow($query); + return $row['result']; } - +function mysqldate($timestamp) +{ + return DB::formatDateTime($timestamp); + } /** - * Centralisation of the functions that generate links - * Deprecated since 3.70: - * Please use Link::FunctionName(...) instead - */ -function createItemLink($itemid, $extra = '') { - return Link::createItemLink($itemid, $extra); + * Centralisation of the functions that generate links + * Deprecated since 4.0: + * Please use Link::FunctionName(...) instead + */ +function createItemLink($itemid, $extra = '') +{ + return Link::create_item_link($itemid, $extra); } - -function createMemberLink($memberid, $extra = '') { - return Link::createMemberLink($memberid, $extra); +function createMemberLink($memberid, $extra = '') +{ + return Link::create_member_link($memberid, $extra); } - -function createCategoryLink($catid, $extra = '') { - return Link::createCategoryLink($catid, $extra); +function createCategoryLink($catid, $extra = '') +{ + return Link::create_category_link($catid, $extra); } - -function createArchiveListLink($blogid = '', $extra = '') { - return Link::createArchiveListLink($blogid, $extra); +function createArchiveListLink($blogid = '', $extra = '') +{ + return Link::create_archivelist_link($blogid, $extra); } - -function createArchiveLink($blogid, $archive, $extra = '') { - return Link::createArchiveLink($blogid, $archive, $extra); +function createArchiveLink($blogid, $archive, $extra = '') +{ + return Link::create_archive_link($blogid, $archive, $extra); } - -function createBlogidLink($blogid, $params = '') { - return Link::createBlogidLink($blogid, $params = ''); +function createBlogidLink($blogid, $params = '') +{ + return Link::create_blogid_link($blogid, $params = ''); } - -function createLink($type, $params) { - return Link::createLink($type, $params); +function createLink($type, $params) +{ + return Link::create_link($type, $params); } - -function createBlogLink($url, $params) { - return Link::createBlogLink($url, $params); +function createBlogLink($url, $params) +{ + return Link::create_blog_link($url, $params); } - - /** - * @param $querystr - * querystring to alter (e.g. foo=1&bar=2&x=y) - * @param $param - * name of parameter to change (e.g. 'foo') - * @param $value - * New value for that parameter (e.g. 3) - * @result - * altered query string (for the examples above: foo=3&bar=2&x=y) + * use ActionLog class instead of this + * Deprecated since 4.0 */ -function alterQueryStr($querystr, $param, $value) { - $vars = i18n::explode('&', $querystr); - $set = false; - - for ($i = 0; $i < count($vars); $i++) { - $v = i18n::explode('=', $vars[$i]); - - if ($v[0] == $param) { - $v[1] = $value; - $vars[$i] = implode('=', $v); - $set = true; - break; - } - } - - if (!$set) { - $vars[] = $param . '=' . $value; - } - - return ltrim(implode('&', $vars), '&'); +function addToLog($level, $msg) +{ + ActionLog::add($level, $msg); } - -// passes one variable as hidden input field (multiple fields for arrays) -// @see passRequestVars in varsx.x.x.php -function passVar($key, $value) { - // array ? - if (is_array($value) ) { - for ($i = 0; $i < sizeof($value); $i++) { - passVar($key . '[' . $i . ']', $value[$i]); - } - - return; - } - - // other values: do stripslashes if needed - ?>getTimeOffset() * 3600 : 0; - $offset = date('Z', $timestamp) + $boffset; - - switch ($format) { - case 'rfc822': - if ($offset >= 0) { - $tz = '+'; - } else { - $tz = '-'; - $offset = -$offset; - } - - $tz .= sprintf("%02d%02d", floor($offset / 3600), round(($offset % 3600) / 60) ); - return date('D, j M Y H:i:s ', $timestamp) . $tz; - - case 'rfc822GMT': - $timestamp -= $offset; - return date('D, j M Y H:i:s ', $timestamp) . 'GMT'; - - case 'utc': - $timestamp -= $offset; - return date('Y-m-d\TH:i:s\Z', $timestamp); - - case 'iso8601': - if ($offset >= 0) { - $tz = '+'; - } else { - $tz = '-'; - $offset = -$offset; - } - $tz .= sprintf("%02d:%02d", floor($offset / 3600), round(($offset % 3600) / 60) ); - return date('Y-m-d\TH:i:s', $timestamp) . $tz; - - default : - return i18n::strftime($format ? $format : $defaultFormat, $timestamp); - } -} - -function checkVars($aVars) { - global $HTTP_GET_VARS, $HTTP_POST_VARS, $HTTP_COOKIE_VARS, $HTTP_ENV_VARS, $HTTP_POST_FILES, $HTTP_SESSION_VARS; - - foreach ($aVars as $varName) { - - if (phpversion() >= '4.1.0') { - - if ( isset($_GET[$varName]) - || isset($_POST[$varName]) - || isset($_COOKIE[$varName]) - || isset($_ENV[$varName]) - || isset($_SESSION[$varName]) - || isset($_FILES[$varName]) - ) { - die('Sorry. An error occurred.'); - } - - } else { - - if ( isset($HTTP_GET_VARS[$varName]) - || isset($HTTP_POST_VARS[$varName]) - || isset($HTTP_COOKIE_VARS[$varName]) - || isset($HTTP_ENV_VARS[$varName]) - || isset($HTTP_SESSION_VARS[$varName]) - || isset($HTTP_POST_FILES[$varName]) - ) { - die('Sorry. An error occurred.'); - } - - } - } +/** + * use Manager::getPluginNameFromPid() instead of this + * Deprecated since 4.0 + */ +function getPluginNameFromPid($pid) +{ + global $manager; + return $manager->getPluginNameFromPid($pid); } - - /** - * Sanitize parameters such as $_GET and $_SERVER['REQUEST_URI'] etc. - * to avoid XSS + * use Manager::numberOfEventSubscribers() instead of this + * Deprecated since 4.0 */ -function sanitizeParams() +function numberOfEventSubscribers($event) { - global $HTTP_SERVER_VARS; - - $array = array(); - $str = ''; - $frontParam = ''; - - // REQUEST_URI of $HTTP_SERVER_VARS - $str =& $HTTP_SERVER_VARS["REQUEST_URI"]; - serverStringToArray($str, $array, $frontParam); - sanitizeArray($array); - arrayToServerString($array, $frontParam, $str); - - // QUERY_STRING of $HTTP_SERVER_VARS - $str =& $HTTP_SERVER_VARS["QUERY_STRING"]; - serverStringToArray($str, $array, $frontParam); - sanitizeArray($array); - arrayToServerString($array, $frontParam, $str); - - if (phpversion() >= '4.1.0') { - // REQUEST_URI of $_SERVER - $str =& $_SERVER["REQUEST_URI"]; - serverStringToArray($str, $array, $frontParam); - sanitizeArray($array); - arrayToServerString($array, $frontParam, $str); - - // QUERY_STRING of $_SERVER - $str =& $_SERVER["QUERY_STRING"]; - serverStringToArray($str, $array, $frontParam); - sanitizeArray($array); - arrayToServerString($array, $frontParam, $str); - } - - // $_GET - convArrayForSanitizing($_GET, $array); - sanitizeArray($array); - revertArrayForSanitizing($array, $_GET); - - // $_REQUEST (only GET param) - convArrayForSanitizing($_REQUEST, $array); - sanitizeArray($array); - revertArrayForSanitizing($array, $_REQUEST); + global $manager; + return $manager->getNumberOfSubscribers($event); } /** - * Check ticket when not checked in plugin's admin page - * to avoid CSRF. - * Also avoid the access to plugin/index.php by guest user. + * PluginAdmin has already the alternative implement + * Deprecated since 4.0 */ function ticketForPlugin() { - global $CONF, $DIR_PLUGINS, $member, $ticketforplugin; + global $CONF, $DIR_LIBS, $DIR_LOCALES, $DIR_PLUGINS, $manager, $member, $ticketforplugin; /* initialize */ $ticketforplugin = array(); $ticketforplugin['ticket'] = FALSE; - /* $_SERVER['PATH_TRANSLATED'] - * http://www.php.net/manual/en/reserved.variables.server.php - * Note: As of PHP 4.3.2, PATH_TRANSLATED is no longer set implicitly - * under the Apache 2 SAPI in contrast to the situation in Apache 1, - * where it's set to the same value as the SCRIPT_FILENAME server variable - * when it's not populated by Apache. - * This change was made to comply with the CGI specification - * that PATH_TRANSLATED should only exist if PATH_INFO is defined. - * Apache 2 users may use AcceptPathInfo = On inside httpd.conf to define PATH_INFO. - */ - /* Check if using plugin's php file. */ $p_translated = serverVar('SCRIPT_FILENAME'); @@ -2074,15 +4451,14 @@ function ticketForPlugin() exit(''); } + // check whether this is plugin or not $p_translated = str_replace('\\', '/', $p_translated); $d_plugins = str_replace('\\', '/', $DIR_PLUGINS); - - // This isn't plugin php file. if ( i18n::strpos($p_translated, $d_plugins) !== 0 ) { return; } - + // Solve the plugin php file or admin directory $phppath = i18n::substr($p_translated, i18n::strlen($d_plugins) ); // Remove the first "/" if exists. @@ -2094,33 +4470,30 @@ function ticketForPlugin() // Solve the plugin name. $plugins = array(); - $query = 'SELECT `pfile` FROM '.sql_table('plugin'); - $res = sql_query($query); + $query = sprintf('SELECT pfile FROM %s;', sql_table('plugin')); + $res = DB::getResult($query); - while($row = sql_fetch_row($res) ) + foreach ( $res as $row ) { - $name = i18n::substr($row[0], 3); + $name = i18n::substr($row['pfile'], 3); $plugins[strtolower($name)] = $name; } - sql_free_result($res); + $res->closeCursor(); - if (array_key_exists($path, $plugins)) - { - $plugin_name = $plugins[$path]; - } - else if (in_array($path, $plugins)) + if ( !array_key_exists($path, $plugins) ) { - $plugin_name = $path; + header("HTTP/1.0 404 Not Found"); + exit(''); } else { - header("HTTP/1.0 404 Not Found"); - exit(''); + $plugin_name = $plugins[$path]; } /* Return if not index.php */ - if ( ($phppath != strtolower($plugin_name) . '/') && ($phppath != strtolower($plugin_name) . '/index.php') ) + if ( ($phppath != strtolower($plugin_name) . '/') + && ($phppath != strtolower($plugin_name) . '/index.php') ) { return; } @@ -2131,21 +4504,14 @@ function ticketForPlugin() exit('You aren\'t logged in.'); } - global $manager, $DIR_LIBS, $DIR_LANG, $HTTP_GET_VARS, $HTTP_POST_VARS; - /* Check if this feature is needed (ie, if "$manager->checkTicket()" is not included in the script). */ - if (!($p_translated = serverVar('PATH_TRANSLATED') ) ) - { - $p_translated = serverVar('SCRIPT_FILENAME'); - } - - if ($file = @file($p_translated) ) + if ( $file = @file($p_translated) ) { $prevline = ''; foreach($file as $line) { - if (preg_match('/[\$]manager([\s]*)[\-]>([\s]*)checkTicket([\s]*)[\(]/i', $prevline . $line) ) + if (preg_match('#[\$]manager([\s]*)[\-]>([\s]*)checkTicket([\s]*)[\(]#i', $prevline . $line) ) { return; } @@ -2155,23 +4521,20 @@ function ticketForPlugin() } /* Show a form if not valid ticket */ - if ( ( strstr(serverVar('REQUEST_URI'), '?') || serverVar('QUERY_STRING') - || strtoupper(serverVar('REQUEST_METHOD') ) == 'POST') - && (!$manager->checkTicket() ) ) + if ( (i18n::strpos(serverVar('REQUEST_URI'), '?') !== FALSE + || serverVar('QUERY_STRING') + || strtoupper(serverVar('REQUEST_METHOD') ) == 'POST') + && !$manager->checkTicket() ) { $oPluginAdmin = new PluginAdmin($plugin_name); $oPluginAdmin->start(); - echo '

' . _ERROR_BADTICKET . "

\n"; - /* Show the form to confirm action */ - // PHP 4.0.x support - $get = (isset($_GET) ) ? $_GET : $HTTP_GET_VARS; - $post = (isset($_POST) ) ? $_POST : $HTTP_POST_VARS; + echo '

' . _ERROR_BADTICKET . "

\n"; // Resolve URI and QUERY_STRING if ($uri = serverVar('REQUEST_URI') ) { - list($uri, $qstring) = i18n::explode('?', $uri); + list($uri, $qstring) = preg_split('#\?#', $uri); } else { @@ -2186,20 +4549,20 @@ function ticketForPlugin() $qstring = '?' . $qstring; } - echo '

' . _SETTINGS_UPDATE . ' : ' . _QMENU_PLUGINS . ' ' . i18n::hsc($plugin_name) . " ?

\n"; + echo '

' . _SETTINGS_UPDATE . ' : ' . _QMENU_PLUGINS . ' ' . Entity::hsc($plugin_name) . " ?

\n"; switch(strtoupper(serverVar('REQUEST_METHOD') ) ) { case 'POST': - echo '
'; + echo ''; $manager->addTicketHidden(); - _addInputTags($post); + _addInputTags($_POST); break; case 'GET': - echo ''; + echo ''; $manager->addTicketHidden(); - _addInputTags($get); + _addInputTags($_GET); default: break; @@ -2215,310 +4578,7 @@ function ticketForPlugin() /* Create new ticket */ $ticket=$manager->addTicketToUrl(''); - $ticketforplugin['ticket']=i18n::substr($ticket,i18n::strpos($ticket,'ticket=')+7); -} - -function _addInputTags(&$keys,$prefix=''){ - foreach($keys as $key=>$value){ - if ($prefix) $key=$prefix.'['.$key.']'; - if (is_array($value)) _addInputTags($value,$key); - else { - if (get_magic_quotes_gpc()) $value=stripslashes($value); - if ($key=='ticket') continue; - echo ''."\n"; - } - } -} - -/** - * Convert the server string such as $_SERVER['REQUEST_URI'] - * to arry like arry['blogid']=1 and array['page']=2 etc. - */ -function serverStringToArray($str, &$array, &$frontParam) -{ - // init param - $array = array(); - $frontParam = ""; - - // split front param, e.g. /index.php, and others, e.g. blogid=1&page=2 - if (strstr($str, "?")){ - list($frontParam, $args) = preg_split("/\?/", $str, 2); - } - else { - $args = $str; - $frontParam = ""; - } - - // If there is no args like blogid=1&page=2, return - if (!strstr($str, "=") && !i18n::strlen($frontParam)) { - $frontParam = $str; - return; - } - - $array = i18n::explode("&", $args); -} - -/** - * Convert array like array['blogid'] to server string - * such as $_SERVER['REQUEST_URI'] - */ -function arrayToServerString($array, $frontParam, &$str) -{ - if (strstr($str, "?")) { - $str = $frontParam . "?"; - } else { - $str = $frontParam; - } - if (count($array)) { - $str .= implode("&", $array); - } -} - -/** - * Sanitize array parameters. - * This function checks both key and value. - * - check key if it inclues " (double quote), remove from array - * - check value if it includes \ (escape sequece), remove remaining string - */ -function sanitizeArray(&$array) -{ - $excludeListForSanitization = array('query'); -// $excludeListForSanitization = array(); - - foreach ($array as $k => $v) { - - // split to key and value - list($key, $val) = preg_split("/=/", $v, 2); - if (!isset($val)) { - continue; - } - - // when magic quotes is on, need to use stripslashes, - // and then addslashes - if (get_magic_quotes_gpc()) { - $val = stripslashes($val); - } - // note that we must use addslashes here because this function is called before the db connection is made - // and sql_real_escape_string needs a db connection - $val = addslashes($val); - - // if $key is included in exclude list, skip this param - if (!in_array($key, $excludeListForSanitization)) { - - // check value - if (i18n::strpos($val, '\\')) { - list($val, $tmp) = i18n::explode('\\', $val); - } - - // remove control code etc. - $val = strtr($val, "\0\r\n<>'\"", " "); - - // check key - if (preg_match('/\"/i', $key)) { - unset($array[$k]); - continue; - } - - // set sanitized info - $array[$k] = sprintf("%s=%s", $key, $val); - } - } -} - -/** - * Convert array for sanitizeArray function - */ -function convArrayForSanitizing($src, &$array) -{ - $array = array(); - foreach ($src as $key => $val) { - if (key_exists($key, $_GET)) { - array_push($array, sprintf("%s=%s", $key, $val)); - } - } -} - -/** - * Revert array after sanitizeArray function - */ -function revertArrayForSanitizing($array, &$dst) -{ - foreach ($array as $v) { - list($key, $val) = preg_split("/=/", $v, 2); - $dst[$key] = $val; - } -} - -/** - * Stops processing the request and redirects to the given URL. - * - no actual contents should have been sent to the output yet - * - the URL will be stripped of illegal or dangerous characters - */ -function redirect($url) { - $url = preg_replace('|[^a-z0-9-~+_.?#=&;,/:@%*]|i', '', $url); - header('Location: ' . $url); - exit; -} - -/** - * Strip HTML tags from a string - * This function is a bit more intelligent than a regular call to strip_tags(), - * because it also deletes the contents of certain tags and cleans up any - * unneeded whitespace. - */ -function stringStripTags ($string) { - $string = preg_replace("/]*>.+<\/del[^>]*>/isU", '', $string); - $string = preg_replace("/]*>.+<\/script[^>]*>/isU", '', $string); - $string = preg_replace("/]*>.+<\/style[^>]*>/isU", '', $string); - $string = str_replace('>', '> ', $string); - $string = str_replace('<', ' <', $string); - $string = strip_tags($string); - $string = preg_replace("/\s+/", " ", $string); - $string = trim($string); - return $string; -} - -/** - * NOTE: Deprecated since 4.0, use i18n::hen() - * - * Make a string containing HTML safe for use in a HTML attribute - * Tags are stripped and entities are normalized - */ -function stringToAttribute ($string) -{ - return i18n::hsc($string); -} - -/** - * NOTE: Deprecated since 4.0, use i18n::hsc() - * - * Make a string containing HTML safe for use in a XML document - * Tags are stripped, entities are normalized and named entities are - * converted to numeric entities. - */ -function stringToXML ($string) -{ - return i18n::hen($string); -} - -// START: functions from the end of file BLOG.php -// used for mail notification (html -> text) -function toAscii($html) { - // strip off most tags - $html = strip_tags($html,''); - $to_replace = "/]*href=[\"\']([^\"^']*)[\"\'][^>]*>([^<]*)<\/a>/i"; - _links_init(); - $ascii = preg_replace_callback ($to_replace, '_links_add', $html); - $ascii .= "\n\n" . _links_list(); - return strip_tags($ascii); -} - -function _links_init() { - global $tmp_links; - $tmp_links = array(); -} - -function _links_add($match) { - global $tmp_links; - array_push($tmp_links, $match[1]); - return $match[2] . ' [' . sizeof($tmp_links) .']'; -} - -function _links_list() { - global $tmp_links; - $output = ''; - $i = 1; - foreach ($tmp_links as $current) { - $output .= "[$i] $current\n"; - $i++; - } - return $output; -} -// END: functions from the end of file BLOG.php - -// START: functions from the end of file ADMIN.php -/** - * - * replace html entities for plugin description, but available for the other strings - * NOTE: we can use i18n::hen() or i18n::hsc() alternatively and this is deprecated. - * @param string $data target string - * @return string - */ -function encode_desc($data) -{ - return i18n::hen($data); -} - -/* - * Returns the Javascript code for a bookmarklet that works on most modern browsers - * @param blogid - */ -function getBookmarklet($blogid) { - global $CONF; - - // normal - $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=550,left=10,top=10,status=yes,resizable=yes');wingm.focus();"; - - return $bookmarkletline; -} -// END: functions from the end of file ADMIN.php - -/** - * Returns a variable or null if not set - * - * @param mixed Variable - * @return mixed Variable - */ -function ifset(&$var) { - if (isset($var)) { - return $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 = sql_fetch_object($res); - return $obj->count; -} - -/** - * sets $special global variable for use in index.php before selector() - * - * @param String id - * @return nothing - */ -function selectSpecialSkinType($id) { - global $special; - $special = strtolower($id); -} - -/** - * cleans filename of uploaded file for writing to file system - * - * @param String str - * @return String cleaned filename ready for use - */ -function cleanFileName($str) { - $str = strtolower($str); - $ext_point = i18n::strrpos($str,"."); - if ($ext_point===false) return false; - $ext = i18n::substr($str,$ext_point,i18n::strlen($str)); - $str = i18n::substr($str,0,$ext_point); - - return preg_replace("/[^a-z0-9-]/","_",$str).$ext; + $ticketforplugin['ticket'] = preg_split($ticket, i18n::strpos($ticket, 'ticket=') + 7); + return; } - -?> \ No newline at end of file +>>>>>>> skinnable-master