Initial commit.

This commit is contained in:
2026-03-10 21:25:26 +08:00
commit 78739bf725
3089 changed files with 472990 additions and 0 deletions

View File

@@ -0,0 +1,142 @@
<?php
// File name: a2html.inc.php
// Description: PHP subroutine to convert a textarea input into HTML content
// Date: 2002-05-23
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2002-2007 Pristine Communications
// This file is in UTF-8 萬國碼
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/htmlchar.inc.php";
require_once "monica/markabbr.inc.php";
require_once "monica/urlregex.inc.php";
// The URL regular-expression pattern
define("_A2HTML_URLREGEX_COMBINED", "(?:" . URLREGEX_EMAIL . "|" . URLREGEX_FTP
. "|" . URLREGEX_FILE . "|" . URLREGEX_HTTP . "|" . URLREGEX_HTTPS
. "|" . URLREGEX_GOPHER . "|" . URLREGEX_MAILTO . "|" . URLREGEX_NEWS
. "|" . URLREGEX_NNTP . "|" . URLREGEX_TELNET . "|" . URLREGEX_WAIS
. "|" . URLREGEX_PROSPERO . ")");
// The substitution ID configuration
define("_A2HTML_SUBST_ID_LEN", 5);
define("_A2HTML_SUBST_ID_MIN", pow(10, _A2HTML_SUBST_ID_LEN - 1));
define("_A2HTML_SUBST_ID_MAX", pow(10, _A2HTML_SUBST_ID_LEN) - 1);
// The punctuation information
$_A2HTML_QUOTES = array(
"\"" => "\"",
"'" => "'",
"`" => "'",
"(" => ")",
"[" => "]",
"{" => "}",
"<" => ">",
"" => "",
"" => "",
"" => "",
"" => "",
"" => "",
"" => "",
"" => "",
"" => "",
"" => "",
"" => "",
);
$_A2HTML_DOTS = array(
"...", ".", ",", ":", ";", "!", "?",
"", "", "", "", "", "", "", "",
);
// a2html: Convert a textarea input into HTML content
function a2html($source)
{
// The punctuation information
global $_A2HTML_QUOTES, $_A2HTML_DOTS;
$result = $source;
// Find and record all the URL's
// Process line by line. PHP PCRE has serial bugs that crashes
// randomly when matching RFC-822 e-mails. The reason is not clear.
// We try to avoid it by reducing the text piece size as possible
// while keeping the integrity of the text. This is not a solution,
// though.
$lines = explode("\n", $result);
for ($i = 0; $i < count($lines); $i++) {
$temp = $lines[$i];
$lines[$i] = "";
if (substr($temp, 0, 1) == " ") {
$lines[$i] .= "&nbsp;";
$temp = substr($temp, 1);
}
$substs = array();
while ( preg_match("/^(.*?)(" . _A2HTML_URLREGEX_COMBINED . ")(.*)$/s",
$temp, $m)) {
// De-quote
foreach (array_keys($_A2HTML_QUOTES) as $start) {
$end = $_A2HTML_QUOTES[$start];
// In a quotation
if ( substr($m[1], -strlen($start)) == $start
&& substr($m[2], -strlen($end)) == $end) {
$m[2] = substr($m[2], 0, -strlen($end));
$m[3] = $end . $m[3];
break;
}
}
// Remove trailing dots
foreach ($_A2HTML_DOTS as $dot) {
// End in this dot
if (substr($m[2], -strlen($dot)) == $dot) {
$m[2] = substr($m[2], 0, -strlen($dot));
$m[3] = $dot . $m[3];
break;
}
}
// Still matched after the above removal
if (preg_match("/^" . _A2HTML_URLREGEX_COMBINED . "$/", $m[2])) {
$lines[$i] .= _a2html_plain_line($m[1]) . _a2html_url2link($m[2]);
} else {
$lines[$i] .= _a2html_plain_line($m[1] . $m[2]);
}
$temp = $m[3];
}
// Add the remains
$lines[$i] .= _a2html_plain_line($temp);
}
$result = implode("\n", $lines);
// Add line breaks
$result = preg_replace("/(\r?\n)/", "<br />\\1", $result);
return $result;
}
// _a2html_plain_line: Convert plain line content to HTML
function _a2html_plain_line($line)
{
// Escape the HTML characters and mark the abbreviation
$line = h_abbr($line);
// Tag non-breaking spaces
$line = str_replace(" ", " &nbsp;", $line);
return $line;
}
// _a2html_url2link: Convert an URL to a link
function _a2html_url2link($url)
{
// There is a scheme
if (preg_match("/^" . URLREGEX_SCHEME . ":/", $url)) {
return "<a href=\"" . h($url) . "\"><samp>" . h($url) . "</samp></a>";
// Schemeless - assumed to be an e-mail address
} else {
return "<a href=\"mailto:" . h($url) . "\"><samp>" . h($url) . "</samp></a>";
}
}
?>

View File

@@ -0,0 +1,87 @@
<?php
// File name: actlog.inc.php
// Description: PHP subroutine to handle activity log
// Date: 2002-04-17
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2002-2013 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/cgiemu.inc.php";
require_once "monica/login.inc.php";
require_once "monica/requri.inc.php";
// Settings
if (!defined("_ACTLOG_DONE_FINDING")) {
_actlog_find_actlog_txt();
define("_ACTLOG_DONE_FINDING", true);
}
// actlog: Log an activity
function actlog($message, $user = null)
{
// ACTLOG must be defined first
if (!defined("ACTLOG")) {
trigger_error("Activity log actlog.txt not found", E_USER_ERROR);
}
$date = date("Y-m-d H:i:s O");
$script = REQUEST_PATH;
$remote = $_SERVER["REMOTE_ADDR"];
if (is_null($user)) {
$user = get_login_id();
if (is_null($user)) {
$user = "anonymous";
}
}
// Escape control characters for safety
$message = str_replace("\t", "\\t", $message);
$message = str_replace("\r", "\\r", $message);
$message = str_replace("\n", "\\n", $message);
$message = preg_replace_callback("/([\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F])/",
function ($matches) {
return sprintf("\\x%02x", ord($matches[1]));
}, $message);
$fp = fopen(ACTLOG, "a");
flock($fp, LOCK_EX);
fwrite($fp, "[$date] $script: ($user from $remote) $message\n");
flock($fp, LOCK_UN);
fclose($fp);
return;
}
// _actlog_find_actlog_txt: Find the activity log file
function _actlog_find_actlog_txt()
{
// It is set
if (defined("ACTLOG")) {
return;
}
// The file location candidates
$cands = array();
if (defined("PACKAGE")) {
$cands[] = "/var/log/apache2/" . PACKAGE . "/actlog.txt";
}
$cands[] = "/var/log/apache2/actlog.txt";
// Find the first available one
$actlog = null;
foreach ($cands as $file) {
if (file_exists($file) && is_file($file) && is_writable($file)) {
$actlog = $file;
break;
}
}
if (!is_null($actlog)) {
define("ACTLOG", $actlog);
}
return;
}
?>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,105 @@
<?php
// File name: addget.inc.php
// Description: PHP subroutines to add a get argument to an url
// Date: 2001-02-13
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2001-2007 Pristine Communications
// Constant symbols
if (!defined("DUP_OK")) {
define("DUP_OK", true);
define("DUP_NO", false);
}
// add_get_arg: Add a get argument to the end of an url
function add_get_arg($cururl, $name, $value, $dup_ok = DUP_NO)
{
// Encode the name and value first
$name = urlencode($name);
$value = urlencode($value);
$pos = strpos($cururl, "?");
// No current arguments were appended yet
if ($pos === false) {
return "$cururl?$name=$value";
}
// It's OK to have duplicated same arguments
if ($dup_ok) {
return "$cururl&$name=$value";
}
// Have arguments already. We need to check if there is already
// a duplicated one and replace it if exists.
// Split the arguments
$script = substr($cururl, 0, $pos);
$argslist = substr($cururl, $pos+1);
$oldargs = explode("&", $argslist);
$newargs = array();
$l = strlen("$name=");
$found = false;
foreach ($oldargs as $arg) {
// Replace existing arguments
if (substr($arg, 0, $l) == "$name=") {
// Replace the first one and discard the rest
if (!$found) {
$newargs[] = "$name=$value";
$found = true;
}
continue;
}
$newargs[] = $arg;
}
// Add it if not found at last
if (!$found) {
$newargs[] = "$name=$value";
}
return "$script?" . implode("&", $newargs);
}
// rem_get_arg: Remove a get argument from the end of an url
function rem_get_arg($cururl, $names)
{
// If $names is not an array, set to an one-element array
if (!is_array($names)) {
$names = array($names);
}
// Parse the names
$lens = array();
for ($i = 0; $i < count($names); $i++) {
// Encode the name first
$names[$i] = urlencode($names[$i]);
// Save its length
$lens[$names[$i]] = strlen($names[$i] . "=");
}
$pos = strpos($cururl, "?");
// No current arguments are appended yet
if ($pos === false) {
return $cururl;
}
// Have arguments already. We need to check if there is already
// a duplicated one and remove it if exists.
// Split the arguments
$script = substr($cururl, 0, $pos);
$argslist = substr($cururl, $pos+1);
$oldargs = explode("&", $argslist);
$newargs = array();
foreach ($oldargs as $arg) {
// Skip found arguments
foreach ($names as $name) {
if (substr($arg, 0, $lens[$name]) == "$name=") {
continue 2;
}
}
$newargs[] = $arg;
}
// No arguments left
if (count($newargs) == 0) {
return $script;
}
return "$script?" . implode("&", $newargs);
}
?>

View File

@@ -0,0 +1,60 @@
<?php
// File name: addslash.inc.php
// Description: PHP subroutine to have addslashes() in different versions
// Date: 2003-03-18
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2003-2007 Pristine Communications
// addslashes_like: addslashes() in like version
// Removed. Replaced with sql_esclike()
// addslashes_re: addslashes() in regular expression version
function addslashes_re($s)
{
// Cache the result
static $cache = array();
// Return the cache
if (array_key_exists($s, $cache)) {
return $cache[$s];
}
$r = $s;
$r = preg_replace("/\\\\/", "\\\\\\\\", $r);
$r = preg_replace("/(\W)/", "\\\\$1", $r);
if (preg_match("/^\w/", $s)) {
$r = "[[:<:]]" . $r;
}
if (preg_match("/\w$/", $s)) {
$r = $r . "[[:>:]]";
}
$cache[$s] = $r;
return $r;
}
// addslashes_re_php: addslashes() in PHP preg_* version
function addslashes_re_php($s)
{
// Cache the result
static $cache = array();
// Return the cache
if (array_key_exists($s, $cache)) {
return $cache[$s];
}
$r = $s;
// ASCII punctuations area
$r = preg_replace("/([\\x21-\\x2F\\x3A-\\x40\\x5B-\\x60\\x7B-\\x7E])/", "\\\\$1", $r);
$r = str_replace("\n", "\\n", $r);
$r = str_replace("\r", "\\r", $r);
$r = str_replace("\t", "\\t", $r);
// Disabled. It may not always be a word piece.
// To be designed a better handling method on this issue.
//if (preg_match("/^\w/", $s)) {
// $r = "\\b" . $r;
//}
//if (preg_match("/\w$/", $s)) {
// $r = $r . "\\b";
//}
$cache[$s] = $r;
return $r;
}
?>

View File

@@ -0,0 +1,205 @@
<?php
// File name: altlang.inc.php
// Description: PHP subroutines to obtain the URL of an alternative language version
// Date: 2004-10-15
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2004-2008 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/cgiemu.inc.php";
require_once "monica/decform.inc.php";
require_once "monica/echoform.inc.php";
require_once "monica/lninfo.inc.php";
require_once "monica/requri.inc.php";
require_once "monica/unicode.inc.php";
// altlang: Obtain the URL of an alternative language version
function altlang($lang, $args)
{
// Obtain the URLs
set_altlang_urls($args);
// Return it
return $args["altlang"][$lang];
}
// set_altlang_urls: Set the URLs of the language variants
function set_altlang_urls(&$args)
{
// Return if already obtained
if (array_key_exists("altlang", $args)) {
return;
}
// Set the path
$path = $args["path"];
if (substr($path, -11) == "/index.html") {
$path = substr($path, 0, -10);
}
// Set the URL parameter
if ($args["static"]) {
$len = strlen(ln($args["lang"], LN_FILENAME)) + 2;
$path = "/%s/" . substr($path, $len);
} else {
// GET arguments not converted to UTF-8 yet
if (!array_key_exists("USER_INPUT", $GLOBALS)) {
decode_forms();
}
global $USER_INPUT;
// Whether we need to specify the character set
$need_charset = !$USER_INPUT["GET_CSERR"]
&& !is_usascii_printable($USER_INPUT["GET_UTF8"]);
$args0 = array();
if ( array_key_exists("QUERY_STRING", $_SERVER)
&& $_SERVER["QUERY_STRING"] != "") {
$args0 = _altlang_parse_qs($_SERVER["QUERY_STRING"], $USER_INPUT["GET_CHARSET"]);
}
// Remove the session ID.
$args0 = _altlang_qsargs_rem_arg($args0, session_name());
// US-ASCII -- we don't need to specify the character set
if (!$need_charset) {
$args0 = _altlang_qsargs_rem_arg($args0, "charset");
}
// Append the referer
if (auto_keep_referer()) {
$args0 = _altlang_qsargs_set_arg($args0, "referer", $_SERVER["HTTP_REFERER"]);
}
}
// Deal with each language
$urls = array();
foreach ($args["all_linguas"] as $lang) {
if ($args["static"]) {
$urls[$lang] = sprintf($path, ln($lang, LN_FILENAME));
} else {
// Make a copy of the variables
$args1 = $args0;
// Set the language
$args1 = _altlang_qsargs_set_arg($args1, "lang", $lang);
// We need to specify the character set
if ($need_charset) {
$charset1 = ln($lang, LN_CHARSET);
$args1 = _altlang_qsargs_set_arg($args1, "charset", $charset1);
for ($i = 0; $i < count($args1); $i++) {
if (is_null($args1[$i]["name"])) {
$args1[$i] = rawurlencode(h_encode($args1[$i]["val"], $charset1));
} else {
$args1[$i] = rawurlencode(h_encode($args1[$i]["name"], $charset1))
. "=" . rawurlencode(h_encode($args1[$i]["val"], $charset1));
}
}
} else {
for ($i = 0; $i < count($args1); $i++) {
if (is_null($args1[$i]["name"])) {
$args1[$i] = rawurlencode($args1[$i]["val"]);
} else {
$args1[$i] = rawurlencode($args1[$i]["name"])
. "=" . rawurlencode($args1[$i]["val"]);
}
}
}
$urls[$lang] = REQUEST_FILE . "?" . implode("&", $args1);
}
$urls[$lang] = $urls[$lang];
}
// Record it
$args["altlang"] = $urls;
return;
}
// _altlang_parse_qs: Parse the query string
function _altlang_parse_qs($qs, $charset)
{
$args = explode("&", $qs);
for ($i = 0; $i < count($args); $i++) {
if (preg_match("/^([^=]*)=(.*)$/", $args[$i], $m)) {
$name = h_decode(urldecode($m[1]), $charset);
if (is_null($name)) {
$name = "";
}
// PHP treats [] as array indices but not part of the names
$phpname = preg_replace("/^([^\[]*)\[.*$/", "$1", $name);
$val = h_decode(urldecode($m[2]), $charset);
if (is_null($val)) {
$val = "";
}
} else {
$name = null;
$phpname = null;
$val = h_decode(urldecode($args[$i]), $charset);
if (is_null($val)) {
$val = "";
}
}
$args[$i] = array(
"name" => $name,
"phpname" => $phpname,
"val" => $val,
);
}
return $args;
}
// _altlang_qsargs_set_arg: Set a query argument
function _altlang_qsargs_set_arg($args, $name, $val)
{
$found = false;
for ($i = 0; $i < count($args); $i++) {
// Not this argument
if ( is_null($args[$i]["phpname"])
|| $args[$i]["phpname"] != $name) {
continue;
}
// The first occurrence
if (!$found) {
$args[$i] = array(
"name" => $name,
"phpname" => $name,
"val" => $val,
);
$found = true;
// Drop the rest of the occurrences
} else {
$args = array_merge(
array_slice($args, 0, $i),
array_slice($args, $i + 1)
);
$i--;
}
}
// Add it if not found
if (!$found) {
$args[] = array(
"name" => $name,
"phpname" => $name,
"val" => $val,
);
}
return $args;
}
// _altlang_qsargs_rem_arg: Remove a query argument
function _altlang_qsargs_rem_arg($args, $name)
{
for ($i = 0; $i < count($args); $i++) {
// Not this argument
if ( is_null($args[$i]["phpname"])
|| $args[$i]["phpname"] != $name) {
continue;
}
// Remove this argument
$args = array_merge(
array_slice($args, 0, $i),
array_slice($args, $i + 1)
);
$i--;
}
return $args;
}
?>

View File

@@ -0,0 +1,99 @@
<?php
// File name: big5.inc.php
// Description: PHP subroutine to deal with Big5 characters
// Date: 2004-04-17
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2004-2007 Pristine Communications
// 編碼規則:
// 高位元組: A1-FE, 8E-A0, 81-8D
// 低位元組: 40-7E, A1-FE
// 常用字: A440-C67E
// 次常用字: C940-F9D5
// 常用符號: A140-A3BF
// 罕用符號: C6A1-C8FE
// 控制碼: A3C0-A3E0
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/xfileio.inc.php";
// Settings
define("_BIG5_VAR", "/tmp/big5.var");
$_BIG5 = null;
// init_big5: Initialize the Big5 characters array
function init_big5()
{
global $_BIG5;
// Already initialized
if (!is_null($_BIG5)) {
return;
}
// Initialize from the existing table
if (file_exists(_BIG5_VAR)) {
eval(xfread(_BIG5_VAR));
return;
}
// Initialize the characters
$_BIG5 = array(
"常用字" => _big5_gen_chars(0xA440, 0xC67E),
"次常用字" => _big5_gen_chars(0xC940, 0xF9D5),
"常用符號" => _big5_gen_chars(0xA140, 0xA3BF),
//"罕用符號" => _big5_gen_chars(0xC6A1, 0xC8FE),
//"控制碼" => _big5_gen_chars(0xA3C0, 0xA3E0),
);
// Save the result
$string = "\$_BIG5 = " . var_export($_BIG5, true) . ";\n";
xfupdate(_BIG5_VAR, $string);
return;
}
// _big5_gen_chars: Generate a range of Big5 characters
function _big5_gen_chars($start, $end)
{
$chars = array();
for ($code = $start; $code <= $end; ) {
$chars[] = pack("n", $code);
# Next character
$hi = $code & 0xFF00;
$lo = $code & 0x00FF;
if ($lo == 0xFE) {
$lo = 0x40;
$hi += 0x0100;
} elseif ($lo == 0x7E) {
$lo = 0xA1;
} else {
$lo++;
}
$code = $hi | $lo;
}
return $chars;
}
// big5_feq_chars: Return the Big5 frequently-used characters
function &big5_feq_chars()
{
init_big5();
return $GLOBALS["_BIG5"]["常用字"];
}
// big5_nonfeq_chars: Return the Big5 non-frequently-used characters
function &big5_nonfeq_chars()
{
init_big5();
return $GLOBALS["_BIG5"]["次常用字"];
}
// big5_punc_chars: Return the Big5 punctuation characters
function &big5_punc_chars()
{
init_big5();
return $GLOBALS["_BIG5"]["常用符號"];
}
?>

View File

@@ -0,0 +1,431 @@
<?php
// File name: callform.inc.php
// Description: PHP subroutine to do API between scripts
// Date: 2002-11-11
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2002-2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/addget.inc.php";
require_once "monica/cgiemu.inc.php";
require_once "monica/formfunc.inc.php";
require_once "monica/formreg.inc.php";
require_once "monica/http.inc.php";
require_once "monica/newsn.inc.php";
require_once "monica/requri.inc.php";
require_once "monica/userhome.inc.php";
// Settings
define("FORMID_LEN", 9);
register_form("FORM_THIS", _callform_form_this());
register_form("FORM_USERS", "/admin/users.php");
register_form("FORM_GROUPS", "/admin/groups.php");
register_form("FORM_USERMEM", "/admin/usermem.php");
register_form("FORM_GROUPMEM", "/admin/groupmem.php");
register_form("FORM_USERPREF", "/admin/userpref.php");
register_form("FORM_SCPTPRIV", "/admin/scpptpriv.php");
register_form("FORM_PIC", "/admin/pic.php");
register_form("FORM_PAGES", "/admin/pages.php");
register_form("FORM_NEWS", "/admin/news.php");
register_form("FORM_LINKCAT", "/admin/linkcat.php");
register_form("FORM_LINKS", "/admin/links.php");
if (!defined("USE_SUSPEND_FORM")) {
define("USE_SUSPEND_FORM", true);
}
// call_form: Suspend the current form and call another selection form
function call_form($form, $args, $import_func)
{
// Only work for defined forms
if (is_null(get_registered_form($form))) {
trigger_error("Calling undefined form \"$form\".\n", E_USER_ERROR);
}
// Record the selection import function
if (!is_null($import_func)) {
// Obtain the form
$FORM =& get_or_post();
$FORM["import_func"] = $import_func;
}
// Suspend the current form
$formid = suspend_form();
// Base URL
$url = get_registered_form($form);
// Initialize as an empty array
if (is_null($args)) {
$args = array();
}
// Add the caller
$args[] = "caller=" . urlencode(REQUEST_PATH);
// Add the caller form ID
$args[] = "cformid=" . urlencode($formid);
// Redirect
http_303($url . "?" . implode("&", $args));
// No need to return
exit;
}
// proc_status_redirect: Save the form status, suspend and redirect
// the form
function proc_status_redirect(&$status)
{
// Obtain the form
$FORM =& get_or_post();
// Set the status
if (!is_null($status)) {
$FORM["status"] = $status;
}
// No more form
if ( is_array($status)
&& array_key_exists("isform", $status)
&& !$status["isform"]) {
// Find the referring script
// Back to the page that refer to this form
if (array_key_exists("referer2", $FORM)) {
$url = $FORM["referer2"];
// Back to the user's home on the calling site
} elseif (array_key_exists("hostport", $FORM)) {
$url = $FORM["hostport"] . userhome();
// Default to the current URL
} else {
$url = REQUEST_FILE;
}
// Do not affect the previous form
unset($status["isform"]);
// Do not suspend the form in this case
// Default to this same script
} else {
$url = _callform_form_this();
// Suspend the current form
$formid = suspend_form();
$url = add_get_arg($url, "formid", $formid);
}
if (!is_null($status)) {
$statid = suspend_status($status);
$url = add_get_arg($url, "statid", $statid);
}
// Redirect
if ($_SERVER["REQUEST_METHOD"] == "POST") {
http_303($url);
} else {
http_307($url);
}
// No need to return
exit;
}
// error_redirect: Shortcut to redirect the error form
function error_redirect(&$status)
{
if (!is_null($status)) {
$status["status"] = "error";
}
proc_status_redirect($status);
// No need to return
exit;
}
// success_redirect: Shortcut to redirect the success form
function success_redirect(&$status)
{
if (!is_null($status)) {
$status["status"] = "success";
}
proc_status_redirect($status);
// No need to return
exit;
}
// goto_form: Goto a specific form
function goto_form(&$FORM, $url = null)
{
// Add the caller infomation
if (is_called_form()) {
// Obtain the current form
$CURFORM =& curform();
// Add the caller infomation
$FORM["caller"] = $CURFORM["caller"];
$FORM["cformid"] = $CURFORM["cformid"];
}
// Suspend the supplied form
$formid = suspend_form($FORM);
// Base URL
// Default to this same script
if (is_null($url)) {
$url = REQUEST_FILE;
}
// Add the form ID
$url = add_get_arg($url, "formid", $formid);
// Redirect
if ($_SERVER["REQUEST_METHOD"] == "POST") {
http_303($url);
} else {
http_307($url);
}
// No need to return
exit;
}
// suspend_form: Suspend the current form to $_SESSION
function suspend_form($FORM = null)
{
// Obtain the form
if (is_null($FORM)) {
$FORM =& get_or_post();
}
// Initialize the form deposit
if (!array_key_exists("saveforms", $_SESSION)) {
$_SESSION["saveforms"] = array();
}
// Generate a new random form ID
$formid = new_sn_assoc($_SESSION["saveforms"]);
// Save the current form
$_SESSION["saveforms"][$formid] = $FORM;
// Save the form ID
$_SESSION["saveforms"][$formid]["formid"] = $formid;
$_SESSION["saveforms"][$formid]["ownerscript"] = REQUEST_PATH;
// Return the form ID
return $formid;
}
// retrieve_form: Retrieve a previously suspended form from $_SESSION
// Return empty array instead of empty, to be merged directly
function &retrieve_form($formid = null)
{
// Cache the result
static $cache = array();
// Return the cache
if (is_null($formid)) {
// $cache[0] is the default (previous form)
if (array_key_exists(0, $cache)) {
return $cache[0];
}
} else {
if (array_key_exists($formid, $cache)) {
return $cache[$formid];
}
}
// Session not in use, return null in all cases
if (!isset($_SESSION)) {
if (is_null($formid)) {
$cache[0] = array();
return $cache[0];
} else {
$cache[$formid] = array();
return $cache[$formid];
}
}
// Initialize the form deposit
if (!array_key_exists("saveforms", $_SESSION)) {
$_SESSION["saveforms"] = array();
if (is_null($formid)) {
$cache[0] = array();
return $cache[0];
} else {
$cache[$formid] = array();
return $cache[$formid];
}
}
// Obtain the previous suspended form if form not specified
if (is_null($formid)) {
// Obtain the form
$FORM =& get_or_post();
// Return empty if not set
if (!array_key_exists("formid", $FORM)) {
$cache[0] = array();
return $cache[0];
}
$formid = $FORM["formid"];
// There is no such previously suspended form
if (!array_key_exists($formid, $_SESSION["saveforms"])) {
$cache[$formid] = array();
$cache[0] = array();
return $cache[0];
}
$cache[$formid] = $_SESSION["saveforms"][$formid];
$cache[0] =& $cache[$formid];
} else {
// There is no such previously suspended form
if (!array_key_exists($formid, $_SESSION["saveforms"])) {
$cache[$formid] = array();
return $cache[$formid];
}
$cache[$formid] = $_SESSION["saveforms"][$formid];
}
// Import the selection if needed
if ( array_key_exists("import_func", $cache[$formid])
&& function_exists($cache[$formid]["import_func"])) {
$cache[$formid] = call_user_func($cache[$formid]["import_func"],
$cache[$formid]);
}
// Return the form
return $cache[$formid];
}
// is_first_form: If it is a first form
function is_first_form()
{
// Obtain the form
$FORM =& get_or_post();
// Return empty if not set
return !array_key_exists("formid", $FORM);
}
// is_called_form: If this is a called form
function is_called_form($FORM = null)
{
if (!USE_SUSPEND_FORM) {
return false;
}
// Obtain the current form
if (is_null($FORM)) {
$FORM =& curform();
}
// Full caller infomation provided
return array_key_exists("caller", $FORM)
&& array_key_exists("cformid", $FORM);
}
// args_addcaller: Add the caller infomation to the GET argument list
function args_addcaller(&$args)
{
if (is_called_form()) {
// Obtain the current form
$FORM =& curform();
// Add the caller infomation
$args[] = "caller=" . urlencode($FORM["caller"]);
$args[] = "cformid=" . urlencode($FORM["cformid"]);
}
return;
}
// suspend_status: Suspend the current status to $_SESSION
function suspend_status($status)
{
// Bounce
if (is_null($status)) {
return null;
}
// Initialize the status deposit
if (!array_key_exists("savestats", $_SESSION)) {
$_SESSION["savestats"] = array();
}
// Generate a new random status ID
$id = new_sn_assoc($_SESSION["savestats"]);
// Save the current status
$_SESSION["savestats"][$id] = $status;
// Save the status ID
$_SESSION["savestats"][$id]["id"] = $id;
// Return the status ID
return $id;
}
// retrieve_status: Retrieve a previously suspended status from $_SESSION
function &retrieve_status($statid = null)
{
// Cache the result
static $cache = array();
// Return the cache
if (is_null($statid)) {
// $cache[0] is the default (previous form)
if (array_key_exists(0, $cache)) {
return $cache[0];
}
} else {
if (array_key_exists($statid, $cache)) {
return $cache[$statid];
}
}
// Session not in use, return null in all cases
if (!isset($_SESSION)) {
if (is_null($statid)) {
$cache[0] = null;
return $cache[0];
} else {
$cache[$statid] = null;
return $cache[$statid];
}
}
// Initialize the status deposit
if (!array_key_exists("savestats", $_SESSION)) {
$_SESSION["savestats"] = array();
if (is_null($statid)) {
$cache[0] = null;
return $cache[0];
} else {
$cache[$statid] = null;
return $cache[$statid];
}
}
// Obtain the previous suspended status if status not specified
if (is_null($statid)) {
// Obtain the form
$FORM =& get_or_post();
// Return empty if not set
if (!array_key_exists("statid", $FORM)) {
$cache[0] = null;
return $cache[0];
}
$statid = $FORM["statid"];
// There is no such previously suspended status
if (!array_key_exists($statid, $_SESSION["savestats"])) {
$cache[$statid] = null;
$cache[0] = null;
return $cache[0];
}
$cache[$statid] = $_SESSION["savestats"][$statid];
$cache[0] =& $cache[$statid];
} else {
// There is no such previously suspended status
if (!array_key_exists($statid, $_SESSION["savestats"])) {
$cache[$statid] = null;
return $cache[$statid];
}
$cache[$statid] = $_SESSION["savestats"][$statid];
}
// Return the status
return $cache[$statid];
}
// _callform_form_this: Find the processing script
function _callform_form_this()
{
static $cache;
if (isset($cache)) {
return $cache;
}
$FORM =& get_or_post();
$cache = (array_key_exists("referer", $FORM)? $FORM["referer"]:
REQUEST_FILE);
return $cache;
}
?>

View File

@@ -0,0 +1,35 @@
<?php
// File name: captitle.inc.php
// Description: PHP subroutines to capitalize a title
// Date: 2006-08-30
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2006-2007 Pristine Communications
// capitalize_title: Capitalize a title
function capitalize_title($title)
{
$title = preg_replace("/\\b(\\w+)\\b/ie", "_captitle_capitalize_word(\"\\1\");", strtolower($title));
$title = preg_replace("/(: +)(\\w+)\\b/ie", "\"\\1\" . ucfirst(\"\\2\");", $title);
$title = preg_replace("/'S /", "'s ", $title);
return ucfirst($title);
}
// _captitle_capitalize_word: Capitalize a word
function _captitle_capitalize_word($word)
{
// Words that should not be capitalized
if (preg_match("/^(a|about|across|after|against|along|among|an|and|around|at|before|below|beneath|beside|besides|between|beyond|but|but|by|concerning|despite|down|during|except|excepting|for|for|from|in|into|like|near|nor|of|off|on|or|past|regarding|since|so|the|through|throughout|thus|till|to|toward|under|underneath|up|upon|with|within|without|yet)$/i", $word)) {
return strtolower($word);
}
// Words without any vowel that look like an abbreviation
if (!preg_match("/[aeiou]/i", $word)) {
return strtoupper($word);
}
// Words that look like a roman number
if (preg_match("/^(?:i|ii|iii|iv|v|vi|vii|viii|ix|x|xi|xii|xiii)$/i", $word)) {
return strtoupper($word);
}
return ucfirst($word);
}
?>

View File

@@ -0,0 +1,78 @@
<?php
// File name: cgiemu.inc.php
// Description: PHP subroutines to set the CGI environment emulation
// Date: 2007-08-31
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2007 Pristine Communications
// Constant symbols
if (!defined("_CGIEMU_SET")) {
_set_cgi_emu();
define("_CGIEMU_SET", true);
}
// add_get_arg: Add a get argument to the end of an url
function _set_cgi_emu()
{
// php-cgi can work on both web and console,
// but only CLI has STDIN and STDERR
define("IS_CGI", getenv("GATEWAY_INTERFACE") !== false);
// Only work if we are not under CGI environment
if (IS_CGI) {
return;
}
// GATEWAY_INTERFACE
if (!array_key_exists("GATEWAY_INTERFACE", $_SERVER)) {
$_SERVER["GATEWAY_INTERFACE"] = "";
putenv("GATEWAY_INTERFACE=" . $_SERVER["GATEWAY_INTERFACE"]);
}
// QUERY_STRING
if (!array_key_exists("QUERY_STRING", $_SERVER)) {
$_SERVER["QUERY_STRING"] = "";
putenv("QUERY_STRING=" . $_SERVER["QUERY_STRING"]);
}
// REMOTE_ADDR
if (!array_key_exists("REMOTE_ADDR", $_SERVER)) {
$_SERVER["REMOTE_ADDR"] = "127.0.0.1";
putenv("REMOTE_ADDR=" . $_SERVER["REMOTE_ADDR"]);
}
// REMOTE_HOST
if (!array_key_exists("REMOTE_HOST", $_SERVER)) {
$_SERVER["REMOTE_HOST"] = "localhost";
putenv("REMOTE_HOST=" . $_SERVER["REMOTE_HOST"]);
}
// REQUEST_METHOD
if (!array_key_exists("REQUEST_METHOD", $_SERVER)) {
$_SERVER["REQUEST_METHOD"] = "GET";
putenv("REQUEST_METHOD=" . $_SERVER["REQUEST_METHOD"]);
}
// SERVER_NAME
if (!array_key_exists("SERVER_NAME", $_SERVER)) {
$_SERVER["SERVER_NAME"] = php_uname("n");
putenv("SERVER_NAME=" . $_SERVER["SERVER_NAME"]);
}
// SERVER_PORT
if (!array_key_exists("SERVER_PORT", $_SERVER)) {
$_SERVER["SERVER_PORT"] = 80;
putenv("SERVER_PORT=" . $_SERVER["SERVER_PORT"]);
}
// SERVER_SOFTWARE
if (!array_key_exists("SERVER_SOFTWARE", $_SERVER)) {
$_SERVER["SERVER_SOFTWARE"] = PHP_OS;
putenv("SERVER_SOFTWARE=" . $_SERVER["SERVER_SOFTWARE"]);
}
// session.save_path
$sessdir = ini_get("session.save_path");
if ($sessdir != "" && !is_writable($sessdir)) {
// Use the temporarily working directory in user's home first
$sessdir = getenv("HOME") . "/tmp";
if (!is_writable($sessdir)) {
// Use system temporarily working directory
$sessdir = sys_get_temp_dir();
}
ini_set("session.save_path", $sessdir);
}
return;
}
?>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,284 @@
<?php
// File name: chkfunc.inc.php
// Description: PHP subroutines to check different things
// Date: 2002-04-17
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2002-2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/errhndl.inc.php";
require_once "monica/gettext.inc.php";
require_once "monica/requri.inc.php";
require_once "monica/sql.inc.php";
require_once "monica/urlregex.inc.php";
// get_has: Check if certain GET fields are submitted
function get_has()
{
// field names are read from the arguments
$fields = func_get_args();
return _form_has($_GET, $fields);
}
// post_has: Check if certain POST fields are submitted
function post_has()
{
// field names are read from the arguments
$fields = func_get_args();
return _form_has($_POST, $fields);
}
// file_has: Check if certain files are submitted
function file_has()
{
// Field names are read from the arguments
$fields = func_get_args();
foreach ($fields as $field) {
// Field recognized as a file field, regardless of whether
// a file uploaded or not
if (array_key_exists($field, $_FILES)) {
continue;
}
// Field presented as an empty POST field when no
// file was submitted
if (array_key_exists($field, $_POST) && $_POST[$field] == "") {
// Present it as the above format
unset($_POST[$field]);
$_FILES[$field] = array("name" => "",
"type" => "application/octet-stream",
"tmp_name" => "",
"error" => 4,
"size" => 0);
continue;
}
// The field was not submitted at all
return array("msg"=>NC_("The following field was not received: \"%s\"."),
"margs"=>array($field),
"init"=>true);
}
// OK
return null;
}
// _form_has: Check if certain form fields are submitted
function _form_has(&$FORM, $fields)
{
foreach ($fields as $field) {
if (!array_key_exists($field, $FORM)) {
return array("msg"=>NC_("The following field was not received: \"%s\"."),
"margs"=>array($field),
"init"=>true);
}
}
// OK
return null;
}
// check_sn: Check if a serial number is valid
// Rule for a serial number:
// An integer of 9 digits within 100000000 - 999999999
function check_sn(&$sn)
{
// Text string
if (is_string($sn)) {
// If it is too long or too short
if (strlen($sn) != 9) {
return false;
}
// If there is any non-digit character
if (preg_match("/\D/", $sn)) {
return false;
}
// Check if it is in the valid range. It is not possible to be
// larger than 999999999 now, due to the previous length check.
if ($sn < 100000000) {
return false;
}
// Convert its type to integer
settype($sn, "integer");
return true;
}
// Integer
if (is_int($sn)) {
// Check if it is in the valid range
return ($sn >= 100000000 && $sn <= 999999999);
}
// Bounce other types
return false;
}
// check_ord: Check if an order is valid
// Rule for an order:
// An integer within 0 - 9999
function check_ord(&$ord)
{
// Text string
if (is_string($ord)) {
// If it is too long or too short
if (strlen($ord) > 4) {
return false;
}
// If there is any non-digit character
if (preg_match("/\D/", $ord)) {
return false;
}
// Check if it is in the valid range. It is not possible to be
// less than 0 now, due to the previous non-digit character check.
if ($ord < 9999) {
return false;
}
// Convert its type to integer
settype($ord, "integer");
return true;
}
// Integer
if (is_int($ord)) {
// Check if it is in the valid range
return ($ord >= 0 && $ord <= 9999);
}
// Bounce other types
return false;
}
// check_date: Check if a submitted date set is valid
function check_date($year, $month, $day)
{
// Check if the year is legal
if (!is_numeric($year)) {
return array("msg"=>NC_("Please select a legal year."));
}
$year += 0;
if (!is_int($year)) {
return array("msg"=>NC_("Please select a legal year."));
}
if (defined("YEAR_START") && $year < YEAR_START) {
return array("msg"=>NC_("Please select a legal year."));
}
if (defined("YEAR_END") && $year > YEAR_END) {
return array("msg"=>NC_("Please select a legal year."));
}
// Check if the month is legal
if (!is_numeric($month)) {
return array("msg"=>NC_("Please select a legal month."));
}
$month += 0;
if (!is_int($month)) {
return array("msg"=>NC_("Please select a legal month."));
}
if ($month < 1 || $month > 12) {
return array("msg"=>NC_("Please select a legal month."));
}
// Check if the day is legal
if (!is_numeric($day)) {
return array("msg"=>NC_("Please select a legal day."));
}
$day += 0;
if (!is_int($day)) {
return array("msg"=>NC_("Please select a legal day."));
}
// Count the last day number of that specified month
$first_day_of_next_month = mktime(0, 0, 0, $month+1, 1, $year);
$last_day_of_this_month = $first_day_of_next_month - 86400;
if ($day < 1 || $day > date("j", $last_day_of_this_month)) {
return array("msg"=>NC_("Please select a legal day."));
}
// OK
return null;
}
// check_sn_in: Check if a serial number exists in a table
function check_sn_in(&$sn, $table)
{
// Check the validity of the serial number first
if (!check_sn($sn)) {
return false;
}
$select = "SELECT * FROM $table WHERE sn=$sn;\n";
$result = sql_query($select);
return (sql_num_rows($result) == 1);
}
// check_script: Check if a script exists
function check_script($path)
{
// Cache the result
static $cache = array();
// Return the cache
if (array_key_exists($path, $cache)) {
return $cache[$path];
}
// Add index.php to directories
if (substr($path, -1) == "/") {
$path .= "index.php";
}
// Not a PHP script
if (substr($path, -4) != ".php") {
$cache[$path] = false;
// Not exists
} elseif (!file_exists(DOC_ROOT . $path)) {
$cache[$path] = false;
// OK
} else {
$cache[$path] = true;
}
return $cache[$path];
}
// check_country: Check if a country exists
function check_country($ct)
{
// Cache the result
static $cache = array();
// Return the cache
if (array_key_exists($ct, $cache)) {
return $cache[$ct];
}
$select = "SELECT id FROM country WHERE id='" . sql_esctext($ct) . "';\n";
$result = sql_query($select);
$cache[$ct] = (sql_num_rows($result) == 1);
return $cache[$ct];
}
// is_url_wellformed: Check if the target of an URL is wellformed
function is_url_wellformed($url)
{
return preg_match("/^" . URLREGEX_URL . "$/", $url)? true: false;
}
// is_url_reachable: Check if the target of an URL is reachable
function is_url_reachable($url)
{
// Cache the result
static $cache = array();
// Return the cache
if (array_key_exists($url, $cache)) {
return $cache[$url];
}
// Check if it is available
set_error_handler("null_error_handler");
$fp = fopen($url, "r");
restore_error_handler();
if ($fp === false) {
$cache[$url] = false;
return false;
}
fclose($fp);
// OK
$cache[$url] = true;
return true;
}
?>

View File

@@ -0,0 +1,335 @@
<?php
// File name: chkpriv.inc.php
// Description: PHP subroutines to check the privileges
// Date: 2001-02-13
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2001-2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/chkfunc.inc.php";
require_once "monica/login.inc.php";
require_once "monica/sql.inc.php";
require_once "monica/username.inc.php";
require_once "monica/usrconst.inc.php";
// Constant symbols
// is_admin: If the user is an administrator (by user sn)
function is_admin($user = null)
{
// Cache the result
static $cache = array();
// Default to the current logged-in user
if (is_null($user) || $user == get_login_sn()) {
return is_su() || in_array(ADMIN_GROUP, get_login_groups());
}
// Return the cache
if (array_key_exists($user, $cache)) {
return $cache[$user];
}
// Super user is always an administrator
if (is_su($user)) {
$cache[$user] = true;
return true;
}
// Obtain the groups
$groups = user_parent_groups($user);
$cache[$user] = in_array(ADMIN_GROUP, $groups);
return $cache[$user];
}
// is_group: If the user belongs to a group
function is_group($group)
{
return in_array($group, get_login_groups());
}
// is_su: If the user is a super user
function is_su($user = null)
{
// Cache the result
static $cache = array();
// Default to check the current user
if (is_null($user)) {
return in_array(SU_GROUP, get_login_groups());
}
// Return the cache
if (array_key_exists($user, $cache)) {
return $cache[$user];
}
// Obtain the groups
$groups = user_parent_groups($user);
$cache[$user] = in_array(SU_GROUP, $groups);
return $cache[$user];
}
// user_parent_groups: Return the full list of groups a user belongs to
function user_parent_groups($sn)
{
// Cache the result
static $cache = array();
// Bounce for null
if (is_null($sn)) {
return array();
}
// Return the cache
if (array_key_exists($sn, $cache)) {
return $cache[$sn];
}
// Check the validity of the user first
if ($sn != get_login_sn()) {
if (!check_sn_in($sn, "users")) {
$cache[$sn] = array();
return $cache[$sn];
}
}
// Find the direct parent groups
$select = "SELECT grp FROM usermem"
. " WHERE member=$sn"
. " ORDER BY grp;\n";
$result = sql_query($select);
$count = sql_num_rows($result);
// Obtain the direct parent groups
for ($i = 0, $current = array(); $i < $count; $i++) {
$row = sql_fetch_assoc($result);
$current[] = $row["grp"];
}
// ALLUSERS_GROUP is automatically added to all logged-in users
$allusers = groupsn(ALLUSERS_GROUP);
if (!is_null($allusers) && !in_array($allusers, $current)) {
$current[] = $allusers;
sort($current);
}
// Trace all their ancester groups
while (true) {
$conds = array();
for ($i = 0; $i < count($current); $i++) {
$conds[] = "member=" . $current[$i];
}
$select = "SELECT grp FROM groupmem"
. " WHERE " . implode(" OR ", $conds)
. " GROUP BY grp ORDER BY grp;\n";
$result = sql_query($select);
$count = sql_num_rows($result);
for ($i = 0, $newfound = array(); $i < $count; $i++) {
$row = sql_fetch_assoc($result);
$newfound[] = $row["grp"];
}
$newfound = array_diff($newfound, $current);
if (count($newfound) == 0) {
break;
}
$current = array_merge($current, $newfound);
}
// Find their ID
$conds = array();
for ($i = 0; $i < count($current); $i++) {
$conds[] = "sn=" . $current[$i];
}
$select = "SELECT id FROM groups"
. " WHERE " . implode(" OR ", $conds)
. " ORDER BY id;\n";
$result = sql_query($select);
$count = sql_num_rows($result);
for ($i = 0, $items = array(); $i < $count; $i++) {
$row = sql_fetch_assoc($result);
$items[] = $row["id"];
}
// Cache it
$cache[$sn] = $items;
return $items;
}
// group_parent_groups: Return the full list of groups a group belongs to
function group_parent_groups($sn)
{
// Cache the result
static $cache = array();
// Bounce for null
if (is_null($sn)) {
return array();
}
// Return the cache
if (array_key_exists($sn, $cache)) {
return $cache[$sn];
}
// Check the validity of the group first
if (!check_sn_in($sn, "groups")) {
$cache[$sn] = array();
return $cache[$sn];
}
$current = array($sn);
// Trace all their ancester groups
while (true) {
$conds = array();
for ($i = 0; $i < count($current); $i++) {
$conds[] = "member=" . $current[$i];
}
$select = "SELECT grp FROM groupmem"
. " WHERE " . implode(" OR ", $conds)
. " GROUP BY grp ORDER BY grp;\n";
$result = sql_query($select);
$count = sql_num_rows($result);
for ($i = 0, $newfound = array(); $i < $count; $i++) {
$row = sql_fetch_assoc($result);
$newfound[] = $row["grp"];
}
$newfound = array_values(array_unique(array_merge($current, $newfound)));
sort($newfound);
if ($newfound == $current) {
break;
}
$current = $newfound;
}
// Remove myself
$current = array_values(array_diff($current, array($sn)));
// Find their ID
$conds = array();
for ($i = 0; $i < count($current); $i++) {
$conds[] = "sn=" . $current[$i];
}
$select = "SELECT id FROM groups"
. " WHERE " . implode(" OR ", $conds)
. " ORDER BY id;\n";
$result = sql_query($select);
$count = sql_num_rows($result);
for ($i = 0, $items = array(); $i < $count; $i++) {
$row = sql_fetch_assoc($result);
$items[] = $row["id"];
}
// Cache it
$cache[$sn] = $items;
return $items;
}
// group_child_users: Return the full list of users in a group
function group_child_users($sn)
{
// Cache the result
static $cache = array();
// Bounce for null
if (is_null($sn)) {
return array();
}
// Return the cache
if (array_key_exists($sn, $cache)) {
return $cache[$sn];
}
$current = array($sn);
// Collect all their lower child groups
while (true) {
$conds = array();
for ($i = 0; $i < count($current); $i++) {
$conds[] = "grp=" . $current[$i];
}
$select = "SELECT member FROM groupmem"
. " WHERE " . implode(" OR ", $conds)
. " GROUP BY member ORDER BY member;\n";
$result = sql_query($select);
$count = sql_num_rows($result);
for ($i = 0, $newfound = array(); $i < $count; $i++) {
$row = sql_fetch_assoc($result);
$newfound[] = $row["member"];
}
$newfound = array_values(array_unique(array_merge($current, $newfound)));
sort($newfound);
if ($newfound == $current) {
break;
}
$current = $newfound;
}
// Find their member users
$conds = array();
for ($i = 0; $i < count($current); $i++) {
$conds[] = "grp=" . $current[$i];
}
$select = "SELECT member FROM usermem"
. " WHERE " . implode(" OR ", $conds)
. " GROUP BY member ORDER BY member;\n";
$result = sql_query($select);
$count = sql_num_rows($result);
for ($i = 0, $current = array(); $i < $count; $i++) {
$row = sql_fetch_assoc($result);
$current[] = $row["member"];
}
// Find their ID
$conds = array();
for ($i = 0; $i < count($current); $i++) {
$conds[] = "sn=" . $current[$i];
}
$select = "SELECT id FROM users"
. " WHERE " . implode(" OR ", $conds)
. " ORDER BY id;\n";
$result = sql_query($select);
$count = sql_num_rows($result);
for ($i = 0, $items = array(); $i < $count; $i++) {
$row = sql_fetch_assoc($result);
$items[] = $row["id"];
}
// Cache it
$cache[$sn] = $items;
return $items;
}
// group_child_groups: Return the full list of groups in a group
function group_child_groups($sn)
{
// Cache the result
static $cache = array();
// Bounce for null
if (is_null($sn)) {
return array();
}
// Return the cache
if (array_key_exists($sn, $cache)) {
return $cache[$sn];
}
$current = array($sn);
// Collect all their lower child groups
while (true) {
$conds = array();
for ($i = 0; $i < count($current); $i++) {
$conds[] = "grp=" . $current[$i];
}
$select = "SELECT member FROM groupmem"
. " WHERE " . implode(" OR ", $conds)
. " GROUP BY member ORDER BY member;\n";
$result = sql_query($select);
$count = sql_num_rows($result);
for ($i = 0, $newfound = array(); $i < $count; $i++) {
$row = sql_fetch_assoc($result);
$newfound[] = $row["member"];
}
$newfound = array_values(array_unique(array_merge($current, $newfound)));
sort($newfound);
if ($newfound == $current) {
break;
}
$current = $newfound;
}
// Remove myself
$current = array_values(array_diff($current, array($sn)));
// Find their ID
$conds = array();
for ($i = 0; $i < count($current); $i++) {
$conds[] = "sn=" . $current[$i];
}
$select = "SELECT id FROM groups"
. " WHERE " . implode(" OR ", $conds)
. " ORDER BY id;\n";
$result = sql_query($select);
$count = sql_num_rows($result);
for ($i = 0, $items = array(); $i < $count; $i++) {
$row = sql_fetch_assoc($result);
$items[] = $row["id"];
}
// Cache it
$cache[$sn] = $items;
return $items;
}
?>

View File

@@ -0,0 +1,63 @@
<?php
// File name: chkwrite.inc.php
// Description: PHP subroutine to check the permission to write to a file
// Date: 2002-04-16
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2002-2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/gettext.inc.php";
require_once "monica/rel2abs.inc.php";
// check_writable: Check the permission to write to a file.
// Input: File full pathname $file.
// Output: true if success, false if failed.
function check_writable($file)
{
// Standardize it
$file = stdpath($file);
// File exists.
if (file_exists($file)) {
// If it is a file
if (!is_file($file)) {
return array("msg"=>NC_("%s: It is not a file."),
"margs"=>array($file));
}
// If it is writable
if (!is_writable($file)) {
return array("msg"=>NC_("%s: You have no permission to overwrite this file."),
"margs"=>array($file));
}
// Not an existing file. See if we can create it.
} else {
$parent = $file;
// Find the nearest existing parent
while ($parent != "" && !file_exists($parent)) {
$parent = dirname($parent);
}
// Creat files from root --- You are insane
if ($parent == "") {
return array("msg"=>NC_("%s: You cannot create anything under the root directory."),
"margs"=>array($file));
}
// This parent is not a directory
if (!is_dir($parent)) {
return array("msg"=>NC_("%s: One of the parents of this file (%s) is not a directory. You cannot create any new file inside."),
"margs"=>array($file, $parent));
}
// If it is possible to create entries in this directory
if (!is_writable($parent)) {
return array("msg"=>NC_("%s: You have no permission to create any file under %s."),
"margs"=>array($file, $parent));
}
}
// OK
return null;
}
?>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,13 @@
<?php
// File name: ISO-8859-1.inc.php
// Description: PHP data of the conversion map of the ISO-8859-1 character set
// Date: 2005-02-02
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2005-2007 Pristine Communications
// ISO-8859-1
$CNVTMAP["ISO-8859-1"] = array(
0x000100, 0x1FFFFF, 0x000000, 0xFFFFFF,
);
?>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,13 @@
<?php
// File name: US-ASCII.inc.php
// Description: PHP data of the conversion map of the US-ASCII character set
// Date: 2005-02-02
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2005-2007 Pristine Communications
// US-ASCII
$CNVTMAP["US-ASCII"] = array(
0x000080, 0x1FFFFF, 0x000000, 0xFFFFFF,
);
?>

View File

@@ -0,0 +1,13 @@
<?php
// File name: invalid.inc.php
// Description: PHP data of the conversion map for invalid unicode characters
// Date: 2008-08-22
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2008 Pristine Communications
// Invalid unicode characters
$CNVTMAP["invalid"] = array(
0x00D800, 0x00DFFF, 0x000000, 0xFFFFFF,
);
?>

View File

@@ -0,0 +1,270 @@
<?php
// File name: simp_to_trad.inc.php
// Description: PHP data of the conversion map from Simplified Chinese to Traditional Chinese
// Date: 2005-05-13
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2005-2007 Pristine Communications
// Simplified Chinese to Traditional Chinese
$CNVTMAP["simp_to_trad"] = array(
0x3005, 0x3005, 0x0000, 0xFFFF,
0x3016, 0x3017, 0x0000, 0xFFFF,
0x2208, 0x2208, 0x0000, 0xFFFF,
0x2237, 0x2237, 0x0000, 0xFFFF,
0x2312, 0x2312, 0x0000, 0xFFFF,
0x224C, 0x224C, 0x0000, 0xFFFF,
0x223D, 0x223D, 0x0000, 0xFFFF,
0x221D, 0x221D, 0x0000, 0xFFFF,
0x226E, 0x226F, 0x0000, 0xFFFF,
0x00A4, 0x00A4, 0x0000, 0xFFFF,
0x2030, 0x2030, 0x0000, 0xFFFF,
0x2116, 0x2116, 0x0000, 0xFFFF,
0x3013, 0x3013, 0x0000, 0xFFFF,
0x2488, 0x249B, 0x0000, 0xFFFF,
0x2474, 0x2487, 0x0000, 0xFFFF,
0x2460, 0x2469, 0x0000, 0xFFFF,
0x3220, 0x3229, 0x0000, 0xFFFF,
0x216A, 0x216B, 0x0000, 0xFFFF,
0xFF07, 0xFF07, 0x0000, 0xFFFF,
0xFF3E, 0xFF3E, 0x0000, 0xFFFF,
0x3041, 0x3093, 0x0000, 0xFFFF,
0x30A1, 0x30F6, 0x0000, 0xFFFF,
0x0410, 0x0415, 0x0000, 0xFFFF,
0x0401, 0x0401, 0x0000, 0xFFFF,
0x0416, 0x0435, 0x0000, 0xFFFF,
0x0451, 0x0451, 0x0000, 0xFFFF,
0x0436, 0x044F, 0x0000, 0xFFFF,
0x0101, 0x0101, 0x0000, 0xFFFF,
0x00E1, 0x00E1, 0x0000, 0xFFFF,
0x01CE, 0x01CE, 0x0000, 0xFFFF,
0x00E0, 0x00E0, 0x0000, 0xFFFF,
0x0113, 0x0113, 0x0000, 0xFFFF,
0x00E9, 0x00E9, 0x0000, 0xFFFF,
0x011B, 0x011B, 0x0000, 0xFFFF,
0x00E8, 0x00E8, 0x0000, 0xFFFF,
0x012B, 0x012B, 0x0000, 0xFFFF,
0x00ED, 0x00ED, 0x0000, 0xFFFF,
0x01D0, 0x01D0, 0x0000, 0xFFFF,
0x00EC, 0x00EC, 0x0000, 0xFFFF,
0x014D, 0x014D, 0x0000, 0xFFFF,
0x00F3, 0x00F3, 0x0000, 0xFFFF,
0x01D2, 0x01D2, 0x0000, 0xFFFF,
0x00F2, 0x00F2, 0x0000, 0xFFFF,
0x016B, 0x016B, 0x0000, 0xFFFF,
0x00FA, 0x00FA, 0x0000, 0xFFFF,
0x01D4, 0x01D4, 0x0000, 0xFFFF,
0x00F9, 0x00F9, 0x0000, 0xFFFF,
0x01D6, 0x01D6, 0x0000, 0xFFFF,
0x01D8, 0x01D8, 0x0000, 0xFFFF,
0x01DA, 0x01DA, 0x0000, 0xFFFF,
0x01DC, 0x01DC, 0x0000, 0xFFFF,
0x00FC, 0x00FC, 0x0000, 0xFFFF,
0x00EA, 0x00EA, 0x0000, 0xFFFF,
0x2504, 0x250B, 0x0000, 0xFFFF,
0x250D, 0x250E, 0x0000, 0xFFFF,
0x2511, 0x2512, 0x0000, 0xFFFF,
0x2515, 0x2516, 0x0000, 0xFFFF,
0x2519, 0x251A, 0x0000, 0xFFFF,
0x251D, 0x2522, 0x0000, 0xFFFF,
0x2525, 0x252A, 0x0000, 0xFFFF,
0x252D, 0x2532, 0x0000, 0xFFFF,
0x2535, 0x253A, 0x0000, 0xFFFF,
0x253D, 0x254A, 0x0000, 0xFFFF,
0x5088, 0x5088, 0x0000, 0xFFFF,
0x9176, 0x9176, 0x0000, 0xFFFF,
0x915E, 0x915E, 0x0000, 0xFFFF,
0x9528, 0x9528, 0x0000, 0xFFFF,
0x4E28, 0x4E28, 0x0000, 0xFFFF,
0x4E3F, 0x4E3F, 0x0000, 0xFFFF,
0x9F17, 0x9F17, 0x0000, 0xFFFF,
0x4E36, 0x4E36, 0x0000, 0xFFFF,
0x5290, 0x5290, 0x0000, 0xFFFF,
0x5182, 0x5182, 0x0000, 0xFFFF,
0x4EEB, 0x4EEB, 0x0000, 0xFFFF,
0x52F9, 0x52F9, 0x0000, 0xFFFF,
0x4EA0, 0x4EA0, 0x0000, 0xFFFF,
0x51AB, 0x51AB, 0x0000, 0xFFFF,
0x5196, 0x5196, 0x0000, 0xFFFF,
0x52D0, 0x52D0, 0x0000, 0xFFFF,
0x5EF4, 0x5EF4, 0x0000, 0xFFFF,
0x57A1, 0x57A1, 0x0000, 0xFFFF,
0x57A7, 0x57A7, 0x0000, 0xFFFF,
0x57B4, 0x57B4, 0x0000, 0xFFFF,
0x57EF, 0x57EF, 0x0000, 0xFFFF,
0x57DD, 0x57DD, 0x0000, 0xFFFF,
0x5844, 0x5844, 0x0000, 0xFFFF,
0x586C, 0x586C, 0x0000, 0xFFFF,
0x589A, 0x589A, 0x0000, 0xFFFF,
0x82CA, 0x82CA, 0x0000, 0xFFFF,
0x82AA, 0x82AA, 0x0000, 0xFFFF,
0x82C4, 0x82C4, 0x0000, 0xFFFF,
0x82F7, 0x82F7, 0x0000, 0xFFFF,
0x82D8, 0x82D8, 0x0000, 0xFFFF,
0x831A, 0x831A, 0x0000, 0xFFFF,
0x836E, 0x836E, 0x0000, 0xFFFF,
0x839C, 0x839C, 0x0000, 0xFFFF,
0x8418, 0x8418, 0x0000, 0xFFFF,
0x841C, 0x841C, 0x0000, 0xFFFF,
0x845C, 0x845C, 0x0000, 0xFFFF,
0x8488, 0x8488, 0x0000, 0xFFFF,
0x84BD, 0x84BD, 0x0000, 0xFFFF,
0x8538, 0x8538, 0x0000, 0xFFFF,
0x85C1, 0x85C1, 0x0000, 0xFFFF,
0x63F8, 0x63F8, 0x0000, 0xFFFF,
0x63DE, 0x63DE, 0x0000, 0xFFFF,
0x7519, 0x7519, 0x0000, 0xFFFF,
0x535F, 0x535F, 0x0000, 0xFFFF,
0x5416, 0x5416, 0x0000, 0xFFFF,
0x544B, 0x544B, 0x0000, 0xFFFF,
0x5421, 0x5421, 0x0000, 0xFFFF,
0x5423, 0x5423, 0x0000, 0xFFFF,
0x5432, 0x5432, 0x0000, 0xFFFF,
0x5494, 0x5494, 0x0000, 0xFFFF,
0x549D, 0x549D, 0x0000, 0xFFFF,
0x54D0, 0x54D0, 0x0000, 0xFFFF,
0x54B4, 0x54B4, 0x0000, 0xFFFF,
0x54A3, 0x54A3, 0x0000, 0xFFFF,
0x54DA, 0x54DA, 0x0000, 0xFFFF,
0x54A4, 0x54A4, 0x0000, 0xFFFF,
0x5523, 0x5523, 0x0000, 0xFFFF,
0x5549, 0x5549, 0x0000, 0xFFFF,
0x553F, 0x553F, 0x0000, 0xFFFF,
0x55B9, 0x55B9, 0x0000, 0xFFFF,
0x55EA, 0x55EA, 0x0000, 0xFFFF,
0x55F5, 0x55F5, 0x0000, 0xFFFF,
0x561E, 0x561E, 0x0000, 0xFFFF,
0x5623, 0x5623, 0x0000, 0xFFFF,
0x562D, 0x562D, 0x0000, 0xFFFF,
0x564D, 0x564D, 0x0000, 0xFFFF,
0x5654, 0x5654, 0x0000, 0xFFFF,
0x567B, 0x567C, 0x0000, 0xFFFF,
0x56AF, 0x56AF, 0x0000, 0xFFFF,
0x5E5E, 0x5E5E, 0x0000, 0xFFFF,
0x5C99, 0x5C99, 0x0000, 0xFFFF,
0x5C9C, 0x5C9C, 0x0000, 0xFFFF,
0x5CC1, 0x5CC1, 0x0000, 0xFFFF,
0x5D3E, 0x5D3E, 0x0000, 0xFFFF,
0x5D74, 0x5D74, 0x0000, 0xFFFF,
0x5F61, 0x5F61, 0x0000, 0xFFFF,
0x72B8, 0x72B8, 0x0000, 0xFFFF,
0x72CD, 0x72CD, 0x0000, 0xFFFF,
0x7339, 0x7339, 0x0000, 0xFFFF,
0x7338, 0x7338, 0x0000, 0xFFFF,
0x5902, 0x5902, 0x0000, 0xFFFF,
0x9987, 0x9987, 0x0000, 0xFFFF,
0x9993, 0x9993, 0x0000, 0xFFFF,
0x9995, 0x9995, 0x0000, 0xFFFF,
0x61B7, 0x61B7, 0x0000, 0xFFFF,
0x6EBB, 0x6EBB, 0x0000, 0xFFFF,
0x6F24, 0x6F24, 0x0000, 0xFFFF,
0x5B80, 0x5B80, 0x0000, 0xFFFF,
0x8FB6, 0x8FB6, 0x0000, 0xFFFF,
0x5F50, 0x5F50, 0x0000, 0xFFFF,
0x59F9, 0x59F9, 0x0000, 0xFFFF,
0x80EC, 0x80EC, 0x0000, 0xFFFF,
0x7EF1, 0x7EF1, 0x0000, 0xFFFF,
0x5DDB, 0x5DDB, 0x0000, 0xFFFF,
0x67A7, 0x67A7, 0x0000, 0xFFFF,
0x6855, 0x6855, 0x0000, 0xFFFF,
0x684A, 0x684A, 0x0000, 0xFFFF,
0x6980, 0x6980, 0x0000, 0xFFFF,
0x6AAB, 0x6AAB, 0x0000, 0xFFFF,
0x8F71, 0x8F71, 0x0000, 0xFFFF,
0x8F77, 0x8F77, 0x0000, 0xFFFF,
0x8ECE, 0x8ECE, 0x0000, 0xFFFF,
0x6657, 0x6657, 0x0000, 0xFFFF,
0x729F, 0x729F, 0x0000, 0xFFFF,
0x728F, 0x728F, 0x0000, 0xFFFF,
0x6BEA, 0x6BEA, 0x0000, 0xFFFF,
0x6535, 0x6535, 0x0000, 0xFFFF,
0x656B, 0x656B, 0x0000, 0xFFFF,
0x809F, 0x809F, 0x0000, 0xFFFF,
0x80BC, 0x80BD, 0x0000, 0xFFFF,
0x80B7, 0x80B7, 0x0000, 0xFFFF,
0x80E8, 0x80E9, 0x0000, 0xFFFF,
0x810E, 0x810E, 0x0000, 0xFFFF,
0x8112, 0x8112, 0x0000, 0xFFFF,
0x8148, 0x8148, 0x0000, 0xFFFF,
0x8159, 0x815A, 0x0000, 0xFFFF,
0x81AA, 0x81AA, 0x0000, 0xFFFF,
0x81C1, 0x81C1, 0x0000, 0xFFFF,
0x98DA, 0x98DA, 0x0000, 0xFFFF,
0x70BB, 0x70BB, 0x0000, 0xFFFF,
0x70C0, 0x70C0, 0x0000, 0xFFFF,
0x7173, 0x7173, 0x0000, 0xFFFF,
0x714A, 0x714A, 0x0000, 0xFFFF,
0x717A, 0x717A, 0x0000, 0xFFFF,
0x7198, 0x7198, 0x0000, 0xFFFF,
0x7818, 0x7818, 0x0000, 0xFFFF,
0x781C, 0x781C, 0x0000, 0xFFFF,
0x7839, 0x7839, 0x0000, 0xFFFF,
0x783C, 0x783C, 0x0000, 0xFFFF,
0x7847, 0x7847, 0x0000, 0xFFFF,
0x78B9, 0x78B9, 0x0000, 0xFFFF,
0x78D9, 0x78D9, 0x0000, 0xFFFF,
0x770D, 0x770D, 0x0000, 0xFFFF,
0x7743, 0x7743, 0x0000, 0xFFFF,
0x7583, 0x7583, 0x0000, 0xFFFF,
0x7F71, 0x7F71, 0x0000, 0xFFFF,
0x949A, 0x949A, 0x0000, 0xFFFF,
0x94B7, 0x94B7, 0x0000, 0xFFFF,
0x94D8, 0x94D8, 0x0000, 0xFFFF,
0x94DE, 0x94DE, 0x0000, 0xFFFF,
0x9503, 0x9503, 0x0000, 0xFFFF,
0x950D, 0x950F, 0x0000, 0xFFFF,
0x9518, 0x9518, 0x0000, 0xFFFF,
0x951D, 0x951D, 0x0000, 0xFFFF,
0x952A, 0x952B, 0x0000, 0xFFFF,
0x953F, 0x953F, 0x0000, 0xFFFF,
0x9545, 0x9545, 0x0000, 0xFFFF,
0x954E, 0x954E, 0x0000, 0xFFFF,
0x9562, 0x9562, 0x0000, 0xFFFF,
0x9565, 0x9565, 0x0000, 0xFFFF,
0x9569, 0x9569, 0x0000, 0xFFFF,
0x9572, 0x9572, 0x0000, 0xFFFF,
0x7A06, 0x7A06, 0x0000, 0xFFFF,
0x9E4B, 0x9E4B, 0x0000, 0xFFFF,
0x9E5B, 0x9E5B, 0x0000, 0xFFFF,
0x9E71, 0x9E71, 0x0000, 0xFFFF,
0x7592, 0x7592, 0x0000, 0xFFFF,
0x75AC, 0x75AC, 0x0000, 0xFFFF,
0x75C3, 0x75C3, 0x0000, 0xFFFF,
0x75D6, 0x75D6, 0x0000, 0xFFFF,
0x7640, 0x7640, 0x0000, 0xFFFF,
0x764D, 0x764D, 0x0000, 0xFFFF,
0x7654, 0x7654, 0x0000, 0xFFFF,
0x766F, 0x766F, 0x0000, 0xFFFF,
0x8020, 0x8020, 0x0000, 0xFFFF,
0x8022, 0x8022, 0x0000, 0xFFFF,
0x8025, 0x8025, 0x0000, 0xFFFF,
0x8031, 0x8031, 0x0000, 0xFFFF,
0x98A5, 0x98A5, 0x0000, 0xFFFF,
0x877D, 0x877D, 0x0000, 0xFFFF,
0x878B, 0x878B, 0x0000, 0xFFFF,
0x87A8, 0x87A8, 0x0000, 0xFFFF,
0x7B7B, 0x7B7B, 0x0000, 0xFFFF,
0x7B62, 0x7B62, 0x0000, 0xFFFF,
0x7BA2, 0x7BA2, 0x0000, 0xFFFF,
0x7BFC, 0x7BFC, 0x0000, 0xFFFF,
0x822D, 0x822D, 0x0000, 0xFFFF,
0x823E, 0x823E, 0x0000, 0xFFFF,
0x9170, 0x9170, 0x0000, 0xFFFF,
0x918C, 0x918C, 0x0000, 0xFFFF,
0x8E3A, 0x8E3A, 0x0000, 0xFFFF,
0x943E, 0x943E, 0x0000, 0xFFFF,
0x9C85, 0x9C86, 0x0000, 0xFFFF,
0x9CB4, 0x9CB4, 0x0000, 0xFFFF,
0x9CBA, 0x9CBA, 0x0000, 0xFFFF,
0x9CBC, 0x9CBC, 0x0000, 0xFFFF,
0x9CCA, 0x9CCB, 0x0000, 0xFFFF,
0x9CD8, 0x9CD9, 0x0000, 0xFFFF,
0x97B2, 0x97B2, 0x0000, 0xFFFF,
0x97B4, 0x97B4, 0x0000, 0xFFFF,
0x9AB6, 0x9AB6, 0x0000, 0xFFFF,
0x9ABA, 0x9ABA, 0x0000, 0xFFFF,
0x9B0F, 0x9B0F, 0x0000, 0xFFFF,
0x9EE2, 0x9EE2, 0x0000, 0xFFFF,
0x9F44, 0x9F44, 0x0000, 0xFFFF,
);
?>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,39 @@
<?php
// File name: commtext.inc.php
// Description: PHP subroutine to obtain common text using gettext
// Date: 2002-04-17
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2002-2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/gettext.inc.php";
// t_notset: Return a localed "(not set)"
function t_notset()
{
return C_("(not set)");
}
// t_none: Return a localed "(none)"
function t_none()
{
return C_("(none)");
}
// t_na: Return a localed "(N/A)"
function t_na()
{
return C_("(N/A)");
}
// t_na: Return a localed "(blank)"
function t_blank()
{
return C_("(blank)");
}
?>

View File

@@ -0,0 +1,27 @@
<?php
// File name: copyyear.inc.php
// Description: PHP subroutine to obtain the copyright year
// Date: 2004-06-05
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2004-2007 Pristine Communications
// copyyear: Return the copyright year
function copyyear($startyear)
{
// Cache the result
static $cache;
// Return the cache
if (isset($cache)) {
return $cache;
}
$thisyear = date("Y");
if ($thisyear == $startyear) {
$cache = $startyear;
} else {
$cache = $startyear . "-" . $thisyear;
}
return $cache;
}
?>

View File

@@ -0,0 +1,78 @@
<?php
// File name: country.inc.php
// Description: PHP subroutine to obtain a country name
// Date: 2002-11-08
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2002-2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/commtext.inc.php";
require_once "monica/echoform.inc.php";
require_once "monica/getlang.inc.php";
require_once "monica/lninfo.inc.php";
require_once "monica/sql.inc.php";
// ctname: Obtain a country name
function ctname($id)
{
// Cache the result
static $cache = array();
// Bounce if there is any problem with $id
if (is_null($id)) {
return t_notset();
}
// Return the cache
if (array_key_exists($id, $cache)) {
return $cache[$id];
}
// Query
// Default language
if (getlang() == DEFAULT_LANG) {
$col = "name_" . getlang(LN_DATABASE) . " AS name";
// Fall back to the default language
} else {
$thiscol = "name_" . getlang(LN_DATABASE);
$defcol = "name_" . ln(DEFAULT_LANG, LN_DATABASE);
$col = "COALESCE($thiscol, $defcol) AS name";
}
$select = "SELECT $col FROM country"
. " WHERE id='" . sql_esctext($id) . "';\n";
$result = sql_query($select);
// Not found
if (sql_num_rows($result) != 1) {
$cache[$id] = t_na();
return $cache[$id];
}
// Found
$row = sql_fetch_assoc($result);
$cache[$id] = $row["name"];
return $cache[$id];
}
// country_options: Obtain a country options list
function country_options($value)
{
// Default language
if (getlang() == DEFAULT_LANG) {
$content = "name_" . getlang(LN_DATABASE) . " AS content";
// Fall back to the default language
} else {
$col = "name_" . getlang(LN_DATABASE);
$defcol = "name_" . ln(DEFAULT_LANG, LN_DATABASE);
$content = "COALESCE($col, $defcol) AS content";
}
$select = "SELECT id AS value, $content FROM country"
. " WHERE " . sql_is_false("special")
. " ORDER BY content;\n";
return opt_list($select, $value);
}
?>

View File

@@ -0,0 +1,54 @@
<?php
// File name: cracklib.inc.php
// Description: PHP subroutine to check password with Cracklib when crack extension does not exist
// Date: 2007-08-08
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2007 Pristine Communications
// Referenced subroutines
require_once "monica/runcmd.inc.php";
// Only do this when Cracklib extension is not loaded
if (!extension_loaded("crack")) {
// The last message
$_CRACKLIB_LASTMMSG = null;
// crack_check: Check password with Cracklib
function crack_check($passwd)
{
// This is faster, but only available with Debian cracklib-runtime
if (file_exists("/usr/sbin/crack_testlib")) {
$cmd = array("/usr/sbin/crack_testlib");
$out = xruncmd($cmd, "$passwd\n");
$toremove = "enter potential passwords, one per line...\n$passwd: ";
if (substr($out, 0, strlen($toremove)) == $toremove) {
$out = substr($out, strlen($toremove));
}
$out = preg_replace("/\s+$/", "", $out);
// This is more portable
} else {
$cmd = array("/usr/bin/perl", "-e",
"use Crypt::Cracklib; print fascist_check(<STDIN>);");
$out = xruncmd($cmd, $passwd);
}
if ($out == "ok") {
$GLOBALS["_CRACKLIB_LASTMMSG"] = "strong password";
return true;
} else {
$GLOBALS["_CRACKLIB_LASTMMSG"] = $out;
return false;
}
}
// crack_getlastmessage: Return the last message from Cracklib
function crack_getlastmessage()
{
return $GLOBALS["_CRACKLIB_LASTMMSG"];
}
}
?>

View File

@@ -0,0 +1,27 @@
<?php
// File name: curtime.inc.php
// Description: PHP current time constants
// Date: 2007-08-08
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/hires.inc.php";
// Settings
if (!defined("NOW")) {
define("NOW", time());
}
if (!defined("TODAY")) {
define("TODAY", date("Y-m-d"));
}
// Log the start time
if (!defined("T_START")) {
define("T_START", time_hires());
}
?>

View File

@@ -0,0 +1,238 @@
<?php
// File name: decform.inc.php
// Description: PHP subroutine to decode user input FORMs to UTF-8
// Date: 2002-04-17
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2002-2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/getlang.inc.php";
require_once "monica/http.inc.php";
require_once "monica/lninfo.inc.php";
require_once "monica/unicode.inc.php";
// Settings
$_DECFORM_TRY = array(
"US-ASCII", "Big5", "GB2312", "GB18030", "Shift-JIS", "UTF-8"
);
// decode_forms: Decode user input FORMs to UTF-8
function decode_forms()
{
// Don't redo
static $done;
if (isset($done)) {
return;
}
global $ALL_LINGUAS;
// Initialize the data deposit
$GLOBALS["USER_INPUT"] = array(
"GET_RAW" => $_GET,
"GET_UTF8" => $_GET,
"GET_CHARSET" => null,
"GET_CSERR" => true,
"GET_KEYS" => array_keys($_GET),
"POST_RAW" => $_POST,
"POST_UTF8" => $_POST,
"FILES_RAW" => $_FILES,
"FILES_UTF8" => $_FILES,
"POST_CHARSET" => null,
"POST_CSERR" => true,
);
global $USER_INPUT;
// The possible character sets of this website
$charsets_site = array();
for ($l = 0; $l < count($ALL_LINGUAS); $l++) {
$charsets_site[] = ln($ALL_LINGUAS[$l], LN_CHARSET);
}
// The GET arguments
// The character set candidates
$charsets = array();
if (array_key_exists("charset", $_GET)) {
$charsets[] = $_GET["charset"];
}
$charsets[] = getlang(LN_CHARSET);
$charsets = array_merge($charsets, $charsets_site);
$charsets = array_merge($charsets, $GLOBALS["_DECFORM_TRY"]);
$charsets = array_values(array_unique($charsets));
// Check each character set
foreach ($charsets as $charset) {
$GET = $USER_INPUT["GET_RAW"];
// In this character set
if (_decform_array2u8($GET, $charset)) {
$_GET = $GET;
$USER_INPUT["GET_UTF8"] = $GET;
$USER_INPUT["GET_CHARSET"] = $charset;
$USER_INPUT["GET_CSERR"] = false;
break;
}
}
// The POSTed form
// The character set candidates
$cands = array();
if (array_key_exists("charset", $_POST)) {
$cands[] = $_POST["charset"];
}
$cands[] = getlang(LN_CHARSET);
$cands = array_merge($cands, $charsets_site);
$cands = array_merge($cands, $GLOBALS["_DECFORM_TRY"]);
$charsets = array();
$lcharsets = array();
foreach ($cands as $charset) {
$lcharset = strtolower($charset);
if (in_array($lcharset, $lcharsets)) {
continue;
}
$charsets[] = $charset;
$lcharsets[] = $lcharset;
switch (strtolower($lcharset)) {
case "big5":
$charsets[] = "CP950";
$lcharsets[] = "cp950";
break;
case "gb2312":
$charsets[] = "GB18030";
$lcharsets[] = "gb18030";
break;
}
}
// Check each character set
foreach ($charsets as $charset) {
$POST = $USER_INPUT["POST_RAW"];
$FILES = $USER_INPUT["FILES_RAW"];
// In this character set
if ( _decform_array2u8($POST, $charset)
&& _decform_files2u8($FILES, $charset)) {
$_POST = $POST;
$_FILES = $FILES;
$USER_INPUT["POST_UTF8"] = $POST;
$USER_INPUT["FILES_UTF8"] = $FILES;
$USER_INPUT["POST_CHARSET"] = $charset;
$USER_INPUT["POST_CSERR"] = false;
break;
}
}
// No valid character set was found
if ($USER_INPUT["GET_CSERR"] || $USER_INPUT["POST_CSERR"]) {
http_400("Unable to detect the character set of your submitted information. Please specify the input character set with charset= parameter.");
}
$done = true;
return;
}
// _decform_array2u8: Convert an array from a specific character set
// to UTF-8
function _decform_array2u8(&$FORM, $charset)
{
// Convert each column value
foreach (array_keys($FORM) as $col) {
// Try to decode the colume name first
$colu8 = h_decode($col, $charset);
// Found something not in this character set
if (is_null($colu8)) {
return false;
}
// Not a piece of valid unicode text
if (!is_valid_unicode($colu8)) {
return false;
}
// Change the key
if ($col != $colu8) {
$FORM[$colu8] =& $FORM[$col];
unset($FORM[$col]);
$col = $colu8;
}
// An array of values
if (is_array($FORM[$col])) {
// Fail to decode this array
if (!_decform_array2u8($FORM[$col], $charset)) {
return false;
}
// A scalar value
} else {
$val = $FORM[$col];
// Remove "\x00". This will cause error with sql_esctext() and sql_esclike().
$val = str_replace("\x00", "", $val);
$val = h_decode($val, $charset);
// Found something not in this character set
if (is_null($val)) {
return false;
}
// Not a piece of valid unicode text
if (!is_valid_unicode($val)) {
return false;
}
$FORM[$col] = $val;
}
}
// Everything OK
return true;
}
// _decform_files2u8: Convert the POSTed files from a specific character set
// to UTF-8
function _decform_files2u8(&$FILES, $charset)
{
// Convert each filename
foreach (array_keys($FILES) as $col) {
// Try to decode the colume name first
$colu8 = h_decode($col, $charset);
// Found something not in this character set
if (is_null($colu8)) {
return false;
}
// Not a piece of valid unicode text
if (!is_valid_unicode($colu8)) {
return false;
}
// Not a piece of valid unicode text
if (!is_valid_unicode($colu8)) {
return false;
}
// Change the key
if ($col != $colu8) {
$FORM[$colu8] =& $FORM[$col];
unset($FORM[$col]);
$col = $colu8;
}
// An array of files
if ( !array_key_exists("tmp_name", $FILES[$col])
|| is_array($FILES[$col]["tmp_name"])) {
// Fail to decode this array
if (!_decform_files2u8($FILES[$col], $charset)) {
return false;
}
// A singular file
} else {
$val = $FILES[$col]["name"];
// Remove "\x00". This will cause error with sql_esctext() and sql_esclike().
$val = str_replace("\x00", "", $val);
$val = h_decode($val, $charset);
// Found something not in this character set
if (is_null($val)) {
return false;
}
// Not a piece of valid unicode text
if (!is_valid_unicode($val)) {
return false;
}
$FILES[$col]["name"] = $val;
}
}
// Everything OK
return true;
}
?>

View File

@@ -0,0 +1,345 @@
<?php
// File name: echoform.inc.php
// Description: PHP subroutines to echo parts of a form
// Date: 2002-05-17
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2002-2007 Pristine Communications
// This file is in UTF-8 萬國碼
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/callform.inc.php";
require_once "monica/commtext.inc.php";
require_once "monica/formfunc.inc.php";
require_once "monica/getlang.inc.php";
require_once "monica/gettext.inc.php";
require_once "monica/htmlchar.inc.php";
require_once "monica/markabbr.inc.php";
require_once "monica/requri.inc.php";
require_once "monica/sql.inc.php";
// locale_date: Obtain a localed date representation
function locale_date($date, $lang = null)
{
if (is_null($lang)) {
$lang = getlang();
}
switch ($lang) {
case "zh-tw":
$d = localtime($date);
return sprintf("%d 年 %d 月 %d 日",
$d[5]+1900-1911, $d[4]+1, $d[3]);
case "de":
return date("F j Y", $date);
case "en":
default:
return date("F j Y", $date);
}
return;
}
// locale_month: Obtain a localed month representation
function locale_month($date, $lang = null)
{
if (is_null($lang)) {
$lang = getlang();
}
switch ($lang) {
case "zh-tw":
$d = localtime($date);
return sprintf("%d 年 %d 月",
$d[5]+1900-1911, $d[4]+1);
case "de":
case "en":
default:
return date("F Y", $date);
}
return;
}
// locale_year: Obtain a localed year representation
function locale_year($date, $lang = null)
{
if (is_null($lang)) {
$lang = getlang();
}
switch ($lang) {
case "zh-tw":
$d = localtime($date);
return sprintf("%d 年", $d[5]+1900-1911);
case "de":
case "en":
default:
return date("Y", $date);
}
return;
}
// locale_amount: Obtain a localed amount representation
function locale_amount($amount, $lang = null)
{
if (is_null($lang)) {
$lang = getlang();
}
switch ($lang) {
case "zh-tw":
// 一萬以下
if (mb_strlen($amount) <= 4) {
return $amount;
// 一億以下
} elseif (mb_strlen($amount) <= 8) {
$sig = mb_substr($amount, 0, -4) . "." . mb_substr($amount, -4);
while (mb_substr($sig, -1) == "0") {
$sig = mb_substr($sig, 0, -1);
}
if (mb_substr($sig, -1) == ".") {
$sig = mb_substr($sig, 0, -1);
}
return sprintf("%s %s 萬)",
$amount, $sig);
// 一兆以下
} elseif (mb_strlen($amount) <= 12) {
$sig = mb_substr($amount, 0, -8) . "." . mb_substr($amount, -8);
while (mb_substr($sig, -1) == "0") {
$sig = mb_substr($sig, 0, -1);
}
if (mb_substr($sig, -1) == ".") {
$sig = mb_substr($sig, 0, -1);
}
return sprintf("%s %s 億)",
$amount, $sig);
// 一兆以上
} else {
$sig = mb_substr($amount, 0, -12) . "." . mb_substr($amount, -12);
while (mb_substr($sig, -1) == "0") {
$sig = mb_substr($sig, 0, -1);
}
if (mb_substr($sig, -1) == ".") {
$sig = mb_substr($sig, 0, -1);
}
return sprintf("%s %s 兆)",
$amount, $sig);
}
case "en":
// Less than one thousand
if (mb_strlen($amount) <= 3) {
return $amount;
// Less than one million
} elseif (mb_strlen($amount) <= 6) {
$sig = mb_substr($amount, 0, -3) . "." . mb_substr($amount, -3);
while (mb_substr($sig, -1) == "0") {
$sig = mb_substr($sig, 0, -1);
}
if (mb_substr($sig, -1) == ".") {
$sig = mb_substr($sig, 0, -1);
}
return sprintf("%s (%s thousands)",
$amount, $sig);
// Less than one billion
} elseif (mb_strlen($amount) <= 9) {
$sig = mb_substr($amount, 0, -6) . "." . mb_substr($amount, -6);
while (mb_substr($sig, -1) == "0") {
$sig = mb_substr($sig, 0, -1);
}
if (mb_substr($sig, -1) == ".") {
$sig = mb_substr($sig, 0, -1);
}
return sprintf("%s (%s millions)",
$amount, $sig);
// More than one billion
} else {
$sig = mb_substr($amount, 0, -9) . "." . mb_substr($amount, -9);
while (mb_substr($sig, -1) == "0") {
$sig = mb_substr($sig, 0, -1);
}
if (mb_substr($sig, -1) == ".") {
$sig = mb_substr($sig, 0, -1);
}
return sprintf("%s (%s billions)",
$amount, $sig);
}
}
return;
}
// report_size: Obtain a human readable size
function report_size($size)
{
// Get the size
$report = sprintf(C_("%s bytes"), number_format($size));
// Try to use KB as the unit
$kb = $size / 1024;
// Bounce if there are fewer than 3 digits in the rounded result
if (round($kb * 100, 0) < 100) {
return $report;
}
// Check the rounded result for each digit
for ($d = 2; $d >= 0; $d--) {
$digits = pow(10, $d);
$rounded = round($kb * $digits, 0);
// There are 3 significient digits in the rounded result
if ($rounded < 1000) {
return sprintf("%s (%.".$d."f KB)",
$report, $rounded / $digits);
}
}
// Try to use MB as the unit
$mb = $kb / 1024;
// Check each digit
for ($d = 2; $d >= 0; $d--) {
$digits = pow(10, $d);
$rounded = round($mb * $digits, 0);
// There are 3 significient digits in the rounded result
if ($rounded < 1000) {
return sprintf("%s (%.".$d."f MB)",
$report, $rounded / $digits);
}
}
// Try to use GB as the unit
$gb = $mb / 1024;
// Check each digit
for ($d = 2; $d >= 0; $d--) {
$digits = pow(10, $d);
$rounded = round($gb * $digits, 0);
// There are 3 significient digits in the rounded result
if ($rounded < 1000) {
return sprintf("%s (%.".$d."f GB)",
$report, $rounded / $digits);
}
}
// Try to use TB as the unit
$tb = $gb / 1024;
// Check each digit
for ($d = 2; $d >= 0; $d--) {
$digits = pow(10, $d);
$rounded = round($tb * $digits, 0);
// There are 3 significient digits in the rounded result
if ($rounded < 1000) {
return sprintf("%s (%.".$d."f TB)",
$report, $rounded / $digits);
}
}
// More than TB
return sprintf("%s (%s TB)",
$report, number_format(round($tb, 0)));
}
// auto_keep_referer: If we should keep the referer information
function auto_keep_referer($auto_keep_referer = null)
{
// Cache the result
static $cache;
// Set the value
if (!is_null($auto_keep_referer)) {
return ($cache = $auto_keep_referer);
}
// Return the cache
if (isset($cache)) {
return $cache;
}
// Only work for forms
if (!is_form()) {
return ($cache = false);
}
// Not for called forms
if (is_called_form()) {
return ($cache = false);
}
// Only work for the first forms
if (!is_first_form()) {
return ($cache = false);
}
// Respect the specified referer
$FORM =& curform();
if (array_key_exists("referer", $FORM)) {
return ($cache = false);
}
// Referer not specified
if (!array_key_exists("HTTP_REFERER", $_SERVER)) {
return ($cache = false);
}
// Only keep referer from the same host
// Check the prefix of the referer
$prefix = REQUEST_HOSTPORT . "/";
return ($cache = (substr($_SERVER["HTTP_REFERER"], 0, strlen($prefix)) == $prefix));
}
// opt_list: Return an options list
function opt_list($select, $curval)
{
// Cache the result
$cache = array();
// Not cached yet
if (!array_key_exists($select, $cache)) {
$result = sql_query($select);
$count = sql_num_rows($result);
for ($i = 0, $opts = array(); $i < $count; $i++) {
$row = sql_fetch_assoc($result);
$opts[] = array(
"value" => $row["value"],
"content" => $row["content"],
);
}
// Obtain the HTML
$cache[$select] = opt_list_array($opts);
}
return preselect_options($cache[$select], $curval);
}
// opt_list_array: Return an options list from an array
function opt_list_array($opts)
{
// Obtain the HTML
ob_start();
?> <option value=""><?php echo h_abbr(t_notset()); ?></option>
<?php
for ($i = 0; $i < count($opts); $i++) {
$value = $opts[$i]["value"];
?> <option value="<?php echo h($value); ?>"><?php
echo h($opts[$i]["content"]); ?></option>
<?php
}
$html = ob_get_contents();
ob_end_clean();
return $html;
}
// preselect_options: Presect an option in an option list
function preselect_options($html, $value)
{
// Not selected if value not set
if (is_null($value)) {
return $html;
}
$value = h($value);
$option = "<option value=\"$value\">";
$pos = strpos($html, $option);
// Not selected if there is no such value in the options
if ($pos === false) {
return $html;
}
$prefix = substr($html, 0, $pos);
$suffix = substr($html, $pos + strlen($option));
$selected = "<option value=\"$value\" selected=\"selected\">";
$html = $prefix . $selected . $suffix;
return $html;
}
?>

View File

@@ -0,0 +1,89 @@
<?php
// File name: email.inc.php
// Description: PHP subroutines for e-mail processing
// Date: 2004-02-11
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2004-2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/rfc822.inc.php";
// Settings
define("ISEMAIL_OK", "ok");
define("ISEMAIL_MALFORMED", "malformed");
define("ISEMAIL_DOMAIN_NOT_FOUND", "baddomain");
define("ISEMAIL_PATTERN",
"/^" . RFC822_LOCAL_PART . "@(" . RFC822_DOMAIN . ")$/");
// is_email: Check the e-mail address validity
function is_email($email)
{
// Malformed
if (!preg_match(ISEMAIL_PATTERN, $email, $m)) {
return ISEMAIL_MALFORMED;
}
$domain = $m[1];
// Domain does not exists
if (!_email_is_domain_exists($domain)) {
return ISEMAIL_DOMAIN_NOT_FOUND;
}
return ISEMAIL_OK;
}
// is_email_wellformed: Check the e-mail address format validity
function is_email_wellformed($email)
{
return preg_match(ISEMAIL_PATTERN, $email)? true: false;
}
// cmp_email: Compare 2 e-mails, to be used with usort()
function cmp_email($a, $b)
{
static $rev = array();
if (!array_key_exists($a, $rev)) {
$rev[$a] = _email_rev_email($a);
}
if (!array_key_exists($b, $rev)) {
$rev[$b] = _email_rev_email($b);
}
return strcmp($rev[$a], $rev[$b]);
}
// _email_is_domain_exists: Check the domain of an e-mail address
function _email_is_domain_exists($domain)
{
// Cache the result
static $cache = array();
// Return the cache
if (array_key_exists($domain, $cache)) {
return $cache[$domain];
}
// Check the MX records
if (getmxrr($domain, $mxhosts)) {
$cache[$domain] = true;
return $cache[$domain];
}
// Check the A or CNAME records
if (gethostbynamel($domain) !== false) {
$cache[$domain] = true;
return $cache[$domain];
}
// Not found at last
$cache[$domain] = false;
return $cache[$domain];
}
// _email_rev_email: Reverse each part of an e-mail
function _email_rev_email($email)
{
$pos = strpos($email, "@");
$local = substr($email, 0, $pos);
$domparts = explode(".", substr($email, $pos+1));
return strtolower(implode(".", array_reverse($domparts)) . "@" . $local);
}
?>

View File

@@ -0,0 +1,40 @@
<?php
// File name: encrypt.inc.php
// Description: Extended PHP subroutine to encrypt/decrypt messages
// Date: 2003-08-19
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2003-2007 Pristine Communications
// Settings
// This should be secret - need to be improved
define("ENCRYPT_KEY", base64_decode("MDJlMDI4MGYyZTZmN2I5ZDNlYTcyMzZiOGI5MzJlZmQ="));
// encrypt: Encrypt a message
function encrypt($s)
{
$s = strlen($s) . " " . $s;
// Pad with spaces
$s = str_pad($s, 32 * ceil(strlen($s) / 32));
// Obtain the IV
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, ENCRYPT_KEY, $s, MCRYPT_MODE_ECB, $iv));
}
// decrypt: Decrypt a message
function decrypt($s)
{
// Obtain the IV
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$s = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, ENCRYPT_KEY, base64_decode($s), MCRYPT_MODE_ECB, $iv);
// Not returning a good formatted decoded text
if (!preg_match("/^(\d+) /", $s, $m)) {
return null;
}
$len = $m[1];
$s = preg_replace("/^(\d+) /", "", $s);
return substr($s, 0, $len);
}
?>

View File

@@ -0,0 +1,16 @@
<?php
// File name: errhndl.inc.php
// Description: PHP subroutine for some error handlers
// Date: 2004-05-28
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2004-2007 Pristine Communications
// null_error_handler: Temporarily disable the normal error handler
// $php_errormsg was set in the original error handler. We have to set it manually.
function null_error_handler($no, $message, $file, $line, $context)
{
$GLOBALS["php_errormsg"] = $message;
return;
}
?>

View File

@@ -0,0 +1,108 @@
<?php
// File name: errmsg.inc.php
// Description: Several PHP subroutines to compose and convert error messages
// Date: 2002-04-30
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2002-2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/gettext.inc.php";
require_once "monica/lninfo.inc.php";
require_once "monica/login.inc.php";
require_once "monica/markabbr.inc.php";
// err2msg: Compose the error message from the $error array
function err2msg($error)
{
$msgs = _errmsg_array_errors_to_msg($error);
switch (count($msgs)) {
case 0:
return "";
case 1:
return $msgs[0];
default:
for ($i = 0; $i < count($msgs); $i++) {
$msgs[$i] = "<li>$msgs[$i]</li>\n";
}
return "<ul>\n" . implode("", $msgs) . "</ul>\n";
}
}
// _errmsg_array_errors_to_msg: Compose error messages from the $errors array
function _errmsg_array_errors_to_msg($errors)
{
$msgs = array();
// A single error
if (!array_key_exists("errors", $errors)) {
$msg = _errmsg_single_error_to_msg($errors);
if (!is_null($msg)) {
$msgs[] = $msg;
}
// An array of errors
} else {
foreach ($errors["errors"] as $error) {
$msgs = array_merge($msgs,
_errmsg_array_errors_to_msg($error));
}
}
return $msgs;
}
// _errmsg_single_error_to_msg: Compose a single error message from the $error array
function _errmsg_single_error_to_msg($error)
{
// Nothing
if (!array_key_exists("msg", $error)) {
return null;
}
// Normal gettext
$msg = $error["msg"];
if (!is_array($msg)) {
$msg = _($msg);
// Complex format
} else {
switch (count($msg)) {
// 2 arguments: dgettext(domain, text)
case 2:
$msg = dgettext($msg[0], $msg[1]);
break;
// 3 arguments: ngettext(singular, plural, number)
case 3:
$msg = ngettext($msg[0], $msg[1], $msg[2]);
break;
// 4 arguments: dngettext(domain, singular, plural, number)
case 4:
$msg = dngettext($msg[0], $msg[1], $msg[2], $msg[3]);
break;
}
}
// Substitute the arguments
if (array_key_exists("margs", $error)) {
$margs = $error["margs"];
// Replace variables
for ($i = 0; $i < count($margs); $i++) {
switch ($margs[$i]) {
case "_USERNAME":
$margs[$i] = get_login_name();
break;
case "_DEFAULT_LANG":
$margs[$i] = ln(DEFAULT_LANG, LN_DESC_CURLC);
break;
default:
$margs[$i] = $margs[$i];
break;
}
}
$msg = vsprintf($msg, $margs);
}
return markabbr($msg);
}
?>

View File

@@ -0,0 +1,38 @@
<?php
// File name: fetchrec.inc.php
// Description: PHP subroutine to fetch items from the database
// Date: 2004-05-26
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2004-2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/chkfunc.inc.php";
require_once "monica/getlang.inc.php";
require_once "monica/lninfo.inc.php";
require_once "monica/sql.inc.php";
// fetchrec: Try to fetch a record by its serial number
function fetchrec(&$sn, $table)
{
if (!check_sn($sn)) {
return false;
}
$select = "SELECT * FROM $table WHERE sn=$sn;\n";
$result = sql_query($select);
if (sql_num_rows($result) != 1) {
return false;
}
$row = sql_fetch_assoc($result);
// Hash the multi-lingual columns
foreach (sql_cols_ml($table) as $col) {
$row[$col] = $row[$col . "_" . getlang(LN_DATABASE)];
}
return $row;
}
?>

6502
lib/php/monica/form.inc.php Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,155 @@
<?php
// File name: formfunc.inc.php
// Description: PHP subroutine to manuplate forms
// Date: 2002-11-11
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2002-2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/callform.inc.php";
require_once "monica/cgiemu.inc.php";
// get_or_post: whether the form data came from $_GET or $_POST
function &get_or_post()
{
if ($_SERVER["REQUEST_METHOD"] == "POST") {
return $_POST;
} else {
return $_GET;
}
}
// curform: Obtain the current form, either from the sent form or
// from the suspended form
function &curform()
{
$FORM =& get_or_post();
if ( defined("USE_SUSPEND_FORM") && USE_SUSPEND_FORM &&
array_key_exists("formid", $FORM)) {
$FORM =& retrieve_form();
}
return $FORM;
}
// is_form: If a form is requested
function is_form($isform = null)
{
// Cache the result
static $cache;
// Use "isform" to alter the cache
if (!is_null($isform)) {
// A status is provided
if (is_array($isform)) {
if (array_key_exists("isform", $isform)) {
$cache = $isform["isform"];
settype($cache, "boolean");
}
// A scalar value
} else {
$cache = $isform;
settype($cache, "boolean");
}
}
// Return the cache
if (isset($cache)) {
return $cache;
}
// Obtain the current form
$FORM =& curform();
// No valid form infomation
if (!array_key_exists("form", $FORM)) {
$cache = false;
return $cache;
}
// "isform" was specified
$status =& retrieve_status();
if (is_array($status) && array_key_exists("isform", $status)) {
$cache = $status["isform"];
return $cache;
}
// Yes, we need a form here
$cache = true;
return $cache;
}
// form_type: Return the form name (new, cur, del, listpref... etc)
function form_type($type = null)
{
// Cache the result
static $cache;
// Set the form type
if (!is_null($type)) {
$cache = $type;
}
// Return the cache
if (isset($cache)) {
return $cache;
}
// Obtain the current form
$FORM =& curform();
// Form type specified in arguments
if (array_key_exists("form", $FORM)) {
$cache = $FORM["form"];
// No form source is found
} else {
$cache = null;
}
return $cache;
}
// form_step: Return the form step number
function form_step($step = null)
{
// Cache the result
static $cache;
// Set the form step
if (!is_null($step)) {
$cache = $step;
}
// Return the cache
if (isset($cache)) {
return $cache;
}
// Obtain the current form
$FORM =& curform();
// Form type specified in arguments
if (array_key_exists("step", $FORM)) {
$cache = $FORM["step"];
// No form source is found
} else {
$cache = 1;
}
// Steps that are not sane are considered as 1
if (!is_int($cache)) {
// Text strings may be convertable
if (is_string($cache)) {
if (preg_match("/^\d+$/", $cache)) {
// Convert its type to integer
settype($cache, "integer");
} else {
$cache = 1;
}
// Others are not convertable
} else {
$cache = 1;
}
}
// "nextstep" specified
$status =& retrieve_status();
if ( is_array($status)
&& array_key_exists("nextstep", $status)
&& $status["nextstep"]) {
$cache++;
}
return $cache;
}
?>

View File

@@ -0,0 +1,37 @@
<?php
// File name: formreg.inc.php
// Description: PHP subroutine to handle form registry
// Date: 2006-11-14
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2004-2007 Pristine Communications
// Settings
$_FORMREG = array();
// register_form: Register a form
function register_form($form, $path)
{
global $_FORMREG;
// The counter
static $n = 0;
// Define the form
if (!defined($form)) {
// Find the next index that is not used
while (array_key_exists($n, $_FORMREG)) {
$n++;
}
define($form, $n);
}
$_FORMREG[$n] = $path;
return;
}
// get_registered_form: Get a registered form
function get_registered_form($form)
{
global $_FORMREG;
return array_key_exists($form, $_FORMREG)?
$_FORMREG[$form]: null;
}
?>

View File

@@ -0,0 +1,134 @@
<?php
// File name: gb2312.inc.php
// Description: PHP subroutine to deal with GB2312 characters
// Date: 2004-04-27
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2004-2007 Pristine Communications
// 編碼規則:
// 區號值: 1-94
// 位號值: 1-94
// 字碼: 最高位元1 + (區號值+0x20(32)), 最高位元1 + (位號值+0x20(32))
// 符號: 1-9區
// 一級字: 16-55區常用漢字
// 二級字: 56-87區次常用漢字
// 空白區: 10-16區, 87-94區
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/xfileio.inc.php";
// Settings
define("_GB2312_VAR", "/tmp/gb2312.var");
$_GB2312 = null;
// init_gb2312: Initialize the GB2312 characters array
function init_gb2312()
{
global $_GB2312;
// Already initialized
if (!is_null($_GB2312)) {
return;
}
// Initialize from the existing table
if (file_exists(_GB2312_VAR)) {
eval(xfread(_GB2312_VAR));
return;
}
// Initialize the characters
$_GB2312 = array(
// 符號
"睫瘍" => _gb2312_gen_chars(1, 9),
// 一級字
"珨撰趼" => _gb2312_gen_chars(16, 55),
// 二級字
"媼撰趼" => _gb2312_gen_chars(56, 87),
);
// Save the result
$string = "\$_GB2312 = " . var_export($_GB2312, true) . ";\n";
xfupdate(_GB2312_VAR, $string);
return;
}
// _gb2312_gen_chars: Generate a range of GB2312 characters
function _gb2312_gen_chars($start, $end)
{
$chars = array();
for ($sec = $start, $pos = 1; $sec <= $end; ) {
$code = ((($sec+0x20)|0x80) << 8) | (($pos+0x20)|0x80);
$chars[] = pack("n", $code);
// Next character
$pos++;
// Carry 進位
if ($pos > 94) {
$pos = 1;
$sec++;
}
// 不用的符號
if ($sec == 2 && $pos == 1) { // 02,01-02,16
$pos = 17;
} elseif ($sec == 2 && $pos == 67) { // 02,67-02,68
$pos = 69;
} elseif ($sec == 2 && $pos == 79) { // 02,79-02,80
$pos = 81;
} elseif ($sec == 2 && $pos == 93) { // 02,93-02,94
$pos = 1;
$sec++;
} elseif ($sec == 4 && $pos == 84) { // 04,84-04,94
$pos = 1;
$sec++;
} elseif ($sec == 5 && $pos == 87) { // 05,87-05,94
$pos = 1;
$sec++;
} elseif ($sec == 6 && $pos == 25) { // 06,25-06,32
$pos = 33;
} elseif ($sec == 6 && $pos == 57) { // 06,57-06,94
$pos = 1;
$sec++;
} elseif ($sec == 7 && $pos == 34) { // 07,34-07,48
$pos = 49;
} elseif ($sec == 7 && $pos == 82) { // 07,82-07,94
$pos = 1;
$sec++;
} elseif ($sec == 8 && $pos == 27) { // 08,27-08,36
$pos = 37;
} elseif ($sec == 8 && $pos == 74) { // 08,74-09,03
$pos = 4;
$sec++;
} elseif ($sec == 9 && $pos == 80) { // 09,80-09,94
break;
}
// 不用的一級字
if ($sec == 55 && $pos == 90) {
break;
}
}
return $chars;
}
// gb2312_punc_chars: Return the GB2312 punctuation characters
function gb2312_punc_chars()
{
init_gb2312();
return $GLOBALS["_GB2312"]["符號"];
}
// gb2312_feq_chars: Return the GB2312 frequently-used characters
function gb2312_feq_chars()
{
init_gb2312();
return $GLOBALS["_GB2312"]["一級字"];
}
// gb2312_nonfeq_chars: Return the GB2312 non-frequently-used characters
function gb2312_nonfeq_chars()
{
init_gb2312();
return $GLOBALS["_GB2312"]["二級字"];
}
?>

View File

@@ -0,0 +1,49 @@
<?php
// File name: geoip.inc.php
// Description: PHP subroutine to query GeoIP
// Date: 2004-11-21
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2004-2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "GeoIP/geoip.inc";
require_once "monica/cgiemu.inc.php";
require_once "monica/ipv4addr.inc.php";
// Settings
define("GEOIP_DAT", "/usr/share/GeoIP/GeoIP.dat");
define("GEOIP_CT_PRIVATE_NETWORK", "AA");
// geoiplookup: Query GeoIP for an IP
function geoiplookup($ip = null)
{
// Default to the client address
if (is_null($ip)) {
$ip = $_SERVER["REMOTE_ADDR"];
}
// Cache the handler
static $gi;
if (!isset($gi)) {
$gi = geoip_open(GEOIP_DAT, GEOIP_STANDARD);
}
// Look up in the GeoIP database
$ct = geoip_country_code_by_addr($gi, $ip);
if ($ct != "") {
return $ct;
}
// Check if it is in a private network
if ( ipv4_in_network("127.0.0.1/8", $ip)
|| ipv4_in_network("10.0.0.0/8", $ip)
|| ipv4_in_network("172.16.0.0/12", $ip)
|| ipv4_in_network("192.168.0.0/16", $ip)) {
return GEOIP_CT_PRIVATE_NETWORK;
}
// Not found at all
return null;
}
?>

View File

@@ -0,0 +1,435 @@
<?php
// File name: getlang.inc.php
// Description: PHP subroutine to get the current user preferred language
// Date: 2002-04-11
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2002-2010 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/cgiemu.inc.php";
require_once "monica/lninfo.inc.php";
require_once "monica/requri.inc.php";
// getlang: Get the appropriate language from the user-agent.
// Input: type: the type of language information to be returned
// See lninfo.inc.php for the most current list of available types.
// LN_NAME: Language name
// LN_CHARSET: It's suggested character set
// LN_FILENAME: It's proper format as part of a file name
// LN_LOCALE: It's locale
// LN_DATABASE: It's proper format as part of a database field name
// LN_HTMLID: It's proper format as part of an HTML ID.
// LN_SPACE_BREAK: If this language break lines at spaces
// LN_IGNORE_CASE: If case can be ignored (can safely do strlower() and strupper())
// LN_COUNTRY_FIRST: If country should be listed first in a mail address
// LN_DESC: It's long description, in English
// LN_DESC_CURLC: It's long description in the current language (UTF-8)
// LN_DESC_SELFLC: It's long description in its own language (UTF-8)
function getlang($type = null)
{
$lang = _getlang_getlang();
// Return in the proper data type
return !is_null($type)? ln($lang, $type): $lang;
}
// getcharset: Get the appropriate character set from the user-agent.
function getcharset()
{
static $charset;
// Obtained before
if (isset($charset)) {
return $charset;
}
// Default character set of this language
$default = getlang(LN_CHARSET);
// Obtain all the available character sets
$all_charsets = _getlang_all_charsets();
// We have no choice
if (count($all_charsets) < 2) {
$charset = $all_charsets[0];
return $charset;
}
// Parse the character set by the Accept-Charset header
$charset = _getlang_getcs_accept();
if (!is_null($charset)) {
return $charset;
}
// Cannot parse - return the default
$lang = $default;
return $lang;
}
// _getlang_getlang: The real subroutine
function _getlang_getlang()
{
static $lang;
// Obtained before
if (isset($lang)) {
return $lang;
}
// Default fallback settings
if (!array_key_exists("ALL_LINGUAS", $GLOBALS)) {
$GLOBALS["ALL_LINGUAS"] = array("en");
}
global $ALL_LINGUAS;
if (!defined("DEFAULT_LANG")) {
define("DEFAULT_LANG", "en");
}
// Uni-lingual
if (count($ALL_LINGUAS) == 1) {
$lang = $ALL_LINGUAS[0];
return $lang;
}
// Check the file name for specified language
// No setting environment in this case
$lang = _getlang_getlang_filename();
if (!is_null($lang)) {
return $lang;
}
// Methods below should set the language in the environment
// Check the environment for specified language
$lang = _getlang_getlang_env();
if (!is_null($lang)) {
_getlang_getlang_setenv($lang);
return $lang;
}
// Parse the language by the Accept-Language header
$lang = _getlang_getlang_accept();
if (!is_null($lang)) {
_getlang_getlang_setenv($lang);
return $lang;
}
// Parse the language by the console locale
$lang = _getlang_getlang_locale();
if (!is_null($lang)) {
_getlang_getlang_setenv($lang);
return $lang;
}
// Cannot parse - return the default
$lang = DEFAULT_LANG;
_getlang_getlang_setenv($lang);
return $lang;
}
// _getlang_getlang_filename: Check the file name for specified language
function _getlang_getlang_filename()
{
global $ALL_LINGUAS;
// Check the file name format
if (!preg_match("/\.([^\.\/]+)\.[^\.\/]+$/", REQUEST_PATH, $m)) {
return null;
}
$langfile = $m[1];
// Check each language for its file name format
for ($l = 0, $map = array(); $l < count($ALL_LINGUAS); $l++) {
$lang = $ALL_LINGUAS[$l];
if ($langfile == ln($lang, LN_FILENAME)) {
return $lang;
}
}
// Not found
return null;
}
// _getlang_getlang_env: Check the environment for specified language
function _getlang_getlang_env()
{
global $ALL_LINGUAS;
// Check the query string
if ( array_key_exists("lang", $_GET)
&& in_array($_GET["lang"], $ALL_LINGUAS)) {
return $_GET["lang"];
// Check the POSTed form
} elseif ( array_key_exists("lang", $_POST)
&& in_array($_POST["lang"], $ALL_LINGUAS)) {
return $_POST["lang"];
// Check the cookies
} elseif ( array_key_exists("lang", $_COOKIE)
&& in_array($_COOKIE["lang"], $ALL_LINGUAS)) {
return $_COOKIE["lang"];
// Check the session
} elseif ( isset($_SESSION)
&& array_key_exists("lang", $_SESSION)
&& in_array($_SESSION["lang"], $ALL_LINGUAS)) {
return $_SESSION["lang"];
}
// Not set
return null;
}
// _getlang_getlang_accept: Parse the language by the Accept-Language header
// Refer to HTTP/1.1 section 14.4 for this algorism
function _getlang_getlang_accept()
{
// Accept-Language not set
if (!array_key_exists("HTTP_ACCEPT_LANGUAGE", $_SERVER)) {
return null;
}
global $ALL_LINGUAS;
// Split into language ranges
$rngs = preg_split("/\s*,\s*/", trim($_SERVER["HTTP_ACCEPT_LANGUAGE"]));
$rngqf = array(); // User Assigned quality factor
foreach ($rngs as $range) {
// Split into attributes
$attrs = preg_split("/\s*;\s*/", trim($range));
// First piece is the language range
$ln = array_shift($attrs);
// Lower-case it
$ln = strtolower($ln);
// Find the quality factor
foreach ($attrs as $attr) {
// A numeric quality factor found
if (strtolower(substr($attr, 0, 2)) == "q="
&& is_numeric(substr($attr, 2))) {
$rngqf[$ln] = substr($attr, 2) + 0;
}
}
// Default quality factor to 1
if (!array_key_exists($ln, $rngqf)) {
$rngqf[$ln] = 1;
}
}
// The default quality factor
if (array_key_exists("*", $rngqf)) {
$defqf = $rngqf["*"];
unset($rngqf["*"]);
} else {
$defqf = 0;
}
// Language tags (what we have)
$tagqf = array(); // Calculated quality factor
for ($l = 0; $l < count($ALL_LINGUAS); $l++) {
$ln = $ALL_LINGUAS[$l];
// Language tag, as specified in ISO
$tag = ln($ln, LN_NAME);
unset($match); // Matched range of the quality factor
// Language ranges (what the user sent to match us)
foreach (array_keys($rngqf) as $range) {
// Exactly match or match a prefix
if ( $tag == $range
|| substr($tag, 0, strlen($range)+1) == "$range-") {
// Not matched yet
if (!isset($match)) {
$tagqf[$ln] = $rngqf[$range]; // Quality Factor
$match = $range; // Record the matched range
// A longer match range
} elseif (strlen($range) > strlen($match)) {
$tagqf[$ln] = $rngqf[$range]; // Quality Factor
$match = $range; // Record the matched range
}
}
}
// Not matched - apply a default quality factor
if (!array_key_exists($ln, $tagqf)) {
$tagqf[$ln] = $defqf;
}
}
// Drop unacceptable languages
foreach (array_keys($tagqf) as $ln) {
if ($tagqf[$ln] <= 0) {
unset($tagqf[$ln]);
}
}
// Nothing acceptable
if (count($tagqf) == 0) {
return null;
}
// Sort by the quality factor
$GLOBALS["_GETLANG_TAGQF"] =& $tagqf;
$GLOBALS["_GETLANG_DEFAULT"] = DEFAULT_LANG;
$ln = array_keys($tagqf);
usort($ln, "_getlang_cmp_tagqf");
unset($GLOBALS["_GETLANG_TAGQF"]);
unset($GLOBALS["_GETLANG_DEFAULT"]);
// A preferred match
return $ln[0];
}
// _getlang_getlang_locale: Parse the language by the console locale
function _getlang_getlang_locale()
{
// Only work on console
if (IS_CGI) {
return null;
}
// Check these environment variables in order
// See http://www.gnu.org/software/libc/manual/html_node/Using-gettextized-software.html
$envs = array("LANGUAGE", "LC_ALL", "LC_MESSAGES", "LANG");
for ($i = 0, $lang = null; $i < count($envs); $i++) {
$locale = getenv($envs[$i]);
// Obtain the first valid one and discard the rest
if ($locale !== false && $locale != "") {
$lang = $locale;
break;
}
}
// No locale setting was found
if (is_null($lang)) {
return null;
}
// Remove the character set
$lang = preg_replace("/\..*$/", "", $lang);
// Lower-case it
$lang = strtolower($lang);
// Replace underscore with dash
$lang = str_replace("_", "-", $lang);
// en-us is en
if ($lang == "en-us") {
$lang = "en";
}
// Not in our available languages list
if (!in_array($lang, $GLOBALS["ALL_LINGUAS"])) {
return null;
}
// Return it
return $lang;
}
// _getlang_getlang_setenv: Set the language in the environment
function _getlang_getlang_setenv($lang)
{
// Set the session variable
if ( isset($_SESSION)
&& (!array_key_exists("lang", $_SESSION)
|| $_SESSION["lang"] != $lang)) {
$_SESSION["lang"] = $lang;
}
// Set the cookie
if ( (!array_key_exists("lang", $_COOKIE)
|| $_COOKIE["lang"] != $lang)
&& !headers_sent()) {
setcookie("lang", $lang, time() + 86400 * 365, "/");
}
return;
}
// _getlang_getcs_accept: Parse the character set by the Accept-Charset header
// Refer to HTTP/1.1 section 14.2 for this algorism
function _getlang_getcs_accept()
{
// Accept-Charset not set
if (!array_key_exists("HTTP_ACCEPT_CHARSET", $_SERVER)) {
return null;
}
// Obtain all the available character sets
$all_charsets = _getlang_all_charsets();
// Split into character set ranges
$rngs = preg_split("/\s*,\s*/", trim($_SERVER["HTTP_ACCEPT_CHARSET"]));
$rngqf = array(); // User Assigned quality factor
foreach ($rngs as $range) {
// Split into attributes
$attrs = preg_split("/\s*;\s*/", trim($range));
// First piece is the character set range
$cs = array_shift($attrs);
// Lower-case it
$cs = strtolower($cs);
// Find the quality factor
foreach ($attrs as $attr) {
// A numeric quality factor found
if (strtolower(substr($attr, 0, 2)) == "q="
&& is_numeric(substr($attr, 2))) {
$rngqf[$cs] = substr($attr, 2) + 0;
}
}
// Default quality factor to 1
if (!array_key_exists($cs, $rngqf)) {
$rngqf[$cs] = 1;
}
}
// The default quality factor
if (array_key_exists("*", $rngqf)) {
$defqf = $rngqf["*"];
unset($rngqf["*"]);
} else {
// Default ISO-8859-1 to 1
if (!array_key_exists("iso-8859-1", $rngqf)) {
$rngqf["iso-8859-1"] = 1;
}
$defqf = 0;
}
$tagqf = array(); // Calculated quality factor
// Character set tags (what we have)
for ($l = 0; $l < count($all_charsets); $l++) {
$cs = $all_charsets[$l];
$tag = strtolower($cs);
// Character set ranges (what the user sent to match us)
foreach (array_keys($rngqf) as $range) {
// Matched
if ($tag == $range) {
$tagqf[$cs] = $rngqf[$range]; // Quality Factor
}
}
// Not matched - apply a default quality factor
if (!array_key_exists($cs, $tagqf)) {
$tagqf[$cs] = $defqf;
}
}
// Drop unacceptable languages
foreach (array_keys($tagqf) as $cs) {
if ($tagqf[$cs] <= 0) {
unset($tagqf[$cs]);
}
}
// Nothing acceptable
if (count($tagqf) == 0) {
return null;
}
// Sort by the quality factor
$GLOBALS["_GETLANG_TAGQF"] =& $tagqf;
$GLOBALS["_GETLANG_DEFAULT"] = getlang(LN_CHARSET);
$cs = array_keys($tagqf);
usort($cs, "_getlang_cmp_tagqf");
unset($GLOBALS["_GETLANG_TAGQF"]);
unset($GLOBALS["_GETLANG_DEFAULT"]);
// A preferred match
return $cs[0];
}
// _getlang_all_charsets: Obtain all the available character sets
// Available character sets are the default character set of this
// language, and UTF-8
function _getlang_all_charsets()
{
static $charsets;
if (isset($charsets)) {
return $charsets;
}
$charsets = array();
$charsets[] = getlang(LN_CHARSET);
$charsets[] = "UTF-8";
$charsets = array_values(array_unique($charsets));
return $charsets;
}
// _getlang_cmp_tagqf: Compare the quality factor of the tags
function _getlang_cmp_tagqf($a, $b)
{
global $_GETLANG_TAGQF, $_GETLANG_DEFAULT;
if ($_GETLANG_TAGQF[$a] != $_GETLANG_TAGQF[$b]) {
return $_GETLANG_TAGQF[$b] < $_GETLANG_TAGQF[$a]? -1: 1;
}
if ($a == $_GETLANG_DEFAULT) {
return -1;
}
if ($b == $_GETLANG_DEFAULT) {
return 1;
}
return 0;
}
?>

View File

@@ -0,0 +1,58 @@
<?php
// File name: gettext.inc.php
// Description: PHP subroutine to implement gettext functions
// Date: 2002-04-11
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2002-2007 Pristine Communications
// Referenced subroutines
require_once "monica/requri.inc.php";
// Settings
if (!defined("COMMONDOMAIN")) {
define("COMMONDOMAIN", "monica");
}
if (!defined("COMMONLOCALEDIR")) {
define("COMMONLOCALEDIR", dirname(dirname(dirname(dirname(__FILE__)))) . "/locale");
}
if (!defined("LOCALEDIR")) {
define("LOCALEDIR", DOC_ROOT . "/admin/locale");
}
// _: gettext implementation
if (!function_exists("_")) {
function _($a)
{
return $a;
}
}
// C_: shortcut to dgettext(COMMONDOMAIN, text)
function C_($a)
{
return dgettext(COMMONDOMAIN, $a);
}
// N_: null gettext implementation
if (!function_exists("N_")) {
function N_($a)
{
return $a;
}
}
// Nn_: null plural gettext implementation
function Nn_($as, $ap, $n)
{
return array($as, $ap, $n);
}
// NC_: null gettext implementation of dgettext(COMMONDOMAIN, text)
function NC_($a)
{
return array(COMMONDOMAIN, $a);
}
// NCn_: null plural gettext implementation of dngettext(COMMONDOMAIN, singular, plural, number)
function NCn_($as, $ap, $n)
{
return array(COMMONDOMAIN, $as, $ap, $n);
}
?>

View File

@@ -0,0 +1,161 @@
<?php
// File name: guest.inc.php
// Description: PHP subroutines to bypass real operations if the user is guest
// Date: 2001-02-13
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2001-2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/actlog.inc.php";
require_once "monica/chkpriv.inc.php";
require_once "monica/login.inc.php";
require_once "monica/mkalldir.inc.php";
require_once "monica/pagefunc.inc.php";
require_once "monica/rmalldir.inc.php";
require_once "monica/rmofile.inc.php";
require_once "monica/runcmd.inc.php";
require_once "monica/sql.inc.php";
require_once "monica/xfileio.inc.php";
// Constant symbols
if (!defined("GUEST_GROUP")) {
define("GUEST_GROUP", "guests");
}
// is_guest: If the user is a guest (by the user id)
function is_guest($user = null)
{
// Cache the result
static $cache = array();
// Default to the current logged-in user
if (is_null($user) || $user == get_login_sn()) {
return !is_su() && in_array(GUEST_GROUP, get_login_groups());
}
// Return the cache
if (array_key_exists($user, $cache)) {
return $cache[$user];
}
// Super user is never a guest
if (is_su($user)) {
$cache[$user] = false;
return false;
}
// Obtain the groups
$groups = user_parent_groups($user);
$cache[$user] = in_array(GUEST_GROUP, $groups);
return $cache[$user];
}
// gunlink: unlink() if the user is not a guest
function gunlink($file)
{
if (!is_guest()) {
unlink($file);
}
}
// gcopy: copy() if the user is not a guest
function gcopy($src, $dst)
{
if (!is_guest()) {
copy($src, $dst);
}
}
// gactlog: actlog() if the user is not a guest
function gactlog($msg, $user = null)
{
if (!is_guest()) {
actlog($msg, $user);
}
}
// gsql_query: sql_query() if the user is not a guest
function gsql_query($query)
{
if (!is_guest()) {
sql_query($query);
}
}
// gmkalldir: mkalldir() if the user is not a guest
function gmkalldir($dir)
{
if (!is_guest()) {
mkalldir($dir);
}
}
// grmalldir: rmalldir() if the user is not a guest
function grmalldir($dir)
{
if (!is_guest()) {
rmalldir($dir);
}
}
// grmoldpage: rmoldpage() if the user is not a guest
function grmoldpage($old, $new = null)
{
if (!is_guest()) {
rmoldpage($old, $new);
}
}
// grmoldfile: rmoldfile() if the user is not a guest
function grmoldfile($old, $new = null)
{
if (!is_guest()) {
rmoldfile($old, $new);
}
}
// goutpage: outpage() if the user is not a guest
function goutpage($html, $path, $lang = null)
{
if (!is_guest()) {
outpage($html, $path, $lang);
}
}
// gxfwrite: xfwrite() if the user is not a guest
function gxfwrite($dest, $content)
{
if (!is_guest()) {
xfwrite($dest, $content);
}
}
// gxfupdate: xfupdate() if the user is not a guest
function gxfupdate($file, $newcontent)
{
if (!is_guest()) {
xfupdate($file, $newcontent);
}
}
// gruncmd: runcmd() if the user is not a guest
function gruncmd($cmd, $stdin, &$stdout, &$stderr)
{
if (!is_guest()) {
return runcmd($cmd, $stdin, $stdout, $stderr);
} else {
return 0;
}
}
// gxruncmd: xruncmd() if the user is not a guest
function gxruncmd($cmd, $stdin)
{
if (!is_guest()) {
return xruncmd($cmd, $stdin);
} else {
return "";
}
}
?>

View File

@@ -0,0 +1,14 @@
<?php
// File name: hires.inc.php
// Description: Extended PHP subroutine to get a high resulution time
// Date: 2002-04-16
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2002-2007 Pristine Communications
// time_hires: Get a high resulution time
function time_hires()
{
return array_sum(explode(" ", microtime()));
}
?>

View File

@@ -0,0 +1,12 @@
<?php
// File name: html401.inc.php
// Description: PHP subroutine for HTML 4.01 patterns
// Date: 2004-02-11
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2004-2007 Pristine Communications
// ID or NAME. Section 6.2.
define("HTML401_ID", "[A-Za-z][A-Za-z\\d\\-_:\\.]*");
?>

View File

@@ -0,0 +1,24 @@
<?php
// File name: htmlchar.inc.php
// Description: PHP subroutines about HTML character entities
// Date: 2002-08-13
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2002-2007 Pristine Communications
// h: Shortcut to htmlspecialchars()
function h($a)
{
return htmlspecialchars($a);
}
// dh: Reverse htmlspecialchars()
function dh($a)
{
$a = str_replace("&lt;", "<", $a);
$a = str_replace("&gt;", ">", $a);
$a = str_replace("&quot;", "\"", $a);
$a = str_replace("&amp;", "&", $a);
return $a;
}
?>

1130
lib/php/monica/http.inc.php Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,79 @@
<?php
// File name: https.inc.php
// Description: Extended PHP subroutine to handle HTTPs operations
// Date: 2004-03-05
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2004-2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/cgiemu.inc.php";
require_once "monica/server.inc.php";
// https_host: The default HTTPs host name
function https_host()
{
// Respect the pre-defined setting
if (defined("HTTPS_HOST")) {
return HTTPS_HOST;
}
// Use the fully-qualified domain name (FQDN)
define("HTTPS_HOST", fqdn());
return HTTPS_HOST;
}
// fqdn: The fully qualified domain name
function fqdn()
{
// Cache the result
static $cache;
// Return the cache
if (isset($cache)) {
return $cache;
}
// Use DNS look-up for the current host name
// Apaches implementation
if (is_apache()) {
$addr = $_SERVER["SERVER_ADDR"];
// Microsoft IIS implementation
} elseif (is_iis()) {
$addr = $_SERVER["LOCAL_ADDR"];
// Else, do DNS query
} else {
$addr = gethostbyname($_SERVER["SERVER_NAME"]);
}
// Reverse-DNS query for a fully-qualified domain name (FQDN)
$cache = gethostbyaddr($addr);
return $cache;
}
// is_https: Check if current scheme is HTTPS
function is_https()
{
// Cache the result
static $cache;
// Return the cache
if (isset($cache)) {
return $cache;
}
// Apache implementation
if (is_apache()) {
$cache = array_key_exists("HTTPS", $_SERVER);
// Microsoft IIS implementation
} elseif (is_iis()) {
$cache = array_key_exists("SERVER_PORT_SECURE", $_SERVER);
// Well, set port 443 to https and others to http.
// This is a bad approach. Avoid it whenever possible.
} else {
$cache = ($_SERVER["SERVER_PORT"] == 443);
}
return $cache;
}
?>

View File

@@ -0,0 +1,31 @@
<?php
// File name: incpath.inc.php
// Description: Extended PHP subroutine to set the include path
// Date: 2007-08-07
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2007 Pristine Communications
// This file is to be included by Monica core files before
// including other Monica core files
// Set the include path
_incpath_set_include_path();
define("INCPATH_SET", true);
// _incpath_set_include_path: Set the include path
function _incpath_set_include_path()
{
$oldpath = get_include_path();
$paths = explode(PATH_SEPARATOR, $oldpath);
$dir = dirname(dirname(__FILE__));
if (!in_array($dir, $paths)) {
$paths[] = $dir;
}
$newpath = implode(PATH_SEPARATOR, $paths);
if ($newpath != $oldpath) {
set_include_path(implode(PATH_SEPARATOR, $paths));
}
return;
}
?>

667
lib/php/monica/init.inc.php Normal file
View File

@@ -0,0 +1,667 @@
<?php
// File name: init.inc.php
// Description: PHP subroutines to initial the environment
// Date: 2002-04-12
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2002-2011 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/altlang.inc.php";
require_once "monica/cgiemu.inc.php";
require_once "monica/chkpriv.inc.php";
require_once "monica/curtime.inc.php";
require_once "monica/decform.inc.php";
require_once "monica/errhndl.inc.php";
require_once "monica/formfunc.inc.php";
require_once "monica/getlang.inc.php";
require_once "monica/gettext.inc.php";
require_once "monica/hires.inc.php";
require_once "monica/http.inc.php";
require_once "monica/https.inc.php";
require_once "monica/lastmodf.inc.php";
require_once "monica/listpref.inc.php";
require_once "monica/lninfo.inc.php";
require_once "monica/login.inc.php";
require_once "monica/logout.inc.php";
require_once "monica/page2rel.inc.php";
require_once "monica/pagefunc.inc.php";
require_once "monica/rel2abs.inc.php";
require_once "monica/requri.inc.php";
require_once "monica/scptpriv.inc.php";
require_once "monica/sql.inc.php";
require_once "monica/sqlconst.inc.php";
require_once "monica/unauth.inc.php";
require_once "monica/unicode.inc.php";
require_once "monica/upload.inc.php";
require_once "monica/xhtml.inc.php";
require_once "monica/xfileio.inc.php";
// Settings
if (!defined("FIELD_HARD_LIMIT")) {
define("FIELD_HARD_LIMIT", 307200);
}
if (!defined("FORM_HARD_LIMIT")) {
define("FORM_HARD_LIMIT", 512000);
}
// initenv: Initialize the script environment
// Input:
// $args: An associative array of arguments, where
// $args["allowed"]: The allowed request methods
// $args["restricted"]: Whether restricted to those permitted here
// $args["session"]: Whether to start a session (boolean)
// $args["sql"]: Which SQL (SQL_NONE, SQL_POSTGRESQL, SQL_MYSQL)
// $args["sql_lock"]: The SQL tables to lock in advance
function initenv($args)
{
// The submitted data
$FORM =& get_or_post();
// Parse the arguments
$session = true;
if (array_key_exists("session", $args)) {
$session = $args["session"];
} elseif (defined("START_SESSION")) {
$session = START_SESSION;
}
settype($session, "boolean");
$sql = SQL_POSTGRESQL;
if ( array_key_exists("sql", $args)
&& in_array($args["sql"], $GLOBALS["VALID_SQLS"])) {
$sql = $args["sql"];
} elseif (defined("START_SQL")
&& in_array(START_SQL, $GLOBALS["VALID_SQLS"])) {
$sql = START_SQL;
}
$GLOBALS["SQL_DBTYPE"] = $sql;
$restricted = false;
if (array_key_exists("restricted", $args)) {
$restricted = $args["restricted"];
}
$lastmod = false;
if (array_key_exists("lastmod", $args)) {
$lastmod = $args["lastmod"];
}
settype($lastmod, "boolean");
$logtime = false;
if (array_key_exists("logtime", $args)) {
$logtime = $args["logtime"];
}
settype($logtime, "boolean");
define("LOGTIME", $logtime);
// Set the custom error handler: http_500(): Standard error handler for Monica
set_error_handler("http500_error_handler");
// Secure the script environment
secure_env();
// Set the multi-byte environment
mb_internal_encoding("UTF-8");
// Initial the gettext locale
_init_initgettext();
// Check the last output buffering level
define("LAST_OB_LEVEL", (ini_get("output_buffering") == "" || !IS_CGI)? 0: 1);
// Start output buffering (till one level more than LAST_OB_LEVEL)
ob_start();
// Block FunWebProduct
// See http://www.networkworld.com/newsletters/web/2003/1208web2.html
if ( array_key_exists("HTTP_USER_AGENT", $_SERVER)
&& strpos($_SERVER["HTTP_USER_AGENT"], "FunWebProduct") !== false) {
http_403(N_("Sorry, browsers with FunWebProduct plugin (Smiley, PopSwatter, Spin4Dough, My Mail Signature, My Mail Stationery, My Mail Stamp, Cursor Mania, etc.) are are not welcome. It duplicates your request and produces high load and even crashes to our server. Please remove it first before you visit us."));
}
// Block bad-behaved e-mail crawlers
// Some bad-behaved e-mail crawlers cannot deal with the parent
// directory ".." and ampersands, and attach them to the URI infinitely
if (strstr(REQUEST_PATH, "/..") !== false || strstr(REQUEST_URI, "&amp;") !== false) {
http_400(false);
}
// Limit the request methods, default to GET, HEAD and POST
// Set to null for no check. Useful for testing and debugging
$allowed = array_key_exists("allowed", $args)?
$args["allowed"]: array("GET", "HEAD", "POST");
if (!is_null($allowed) && !in_array($_SERVER["REQUEST_METHOD"], $allowed)) {
http_405($allowed);
}
// Block bad robots
_init_block_bad_robots();
// Initialize the session
if ($session) {
// Form processed with HTTPs
$https = false;
if (array_key_exists("https", $FORM)) {
$https = $FORM["https"]? true: false;
}
// We are HTTPS, processing a form that came from
// another non-HTTPS virtual host.
// Overriding the session ID. to keep the original session.
if ($https && is_https()) {
// Use the provided session ID
if (array_key_exists(session_name(), $FORM)) {
session_id($FORM[session_name()]);
}
}
// Avoid bad robots producing bad session ID.
$GLOBALS["php_errormsg"] = null;
set_error_handler("null_error_handler");
session_start();
if (!is_null($GLOBALS["php_errormsg"])) {
http_400($GLOBALS["php_errormsg"]);
}
restore_error_handler();
}
// Prevent huge sized request
check_request_size();
// If client has not logged in on restricted area, we can
// bypass SQL connection to save our work
if (IS_CGI && is_null(get_login_sn()) && $restricted !== false) {
unauth();
}
// Initialize the SQL connection
if ($sql) {
if (defined("NODATABASE") && NODATABASE) {
http_503("Database shut down for maintainance.");
}
sql_connect();
}
// Only available on systems with membership turned on
if ($sql && use_users() && $session) {
// Update the log-in infomation
upd_login_info();
// Check the client permission
if ($restricted !== false && !is_script_permitted($restricted)) {
unauth();
}
// Check if this site is closed for policy
_init_check_nologin();
}
// Prepare the SQL tables to lock
if ($sql && array_key_exists("sql_lock", $args)) {
// Read-only on non-POSTed forms
if ($_SERVER["REQUEST_METHOD"] != "POST") {
foreach (array_keys($args["sql_lock"]) as $table) {
$args["sql_lock"][$table] = LOCK_SH;
}
// Add mtime to POSTed forms
} else {
if (in_array("mtime", sql_tables())) {
$args["sql_lock"]["mtime"] = LOCK_EX;
}
}
// Supply the default locks
if (use_users()) {
$default_locks = array("users", "groups", "scptpriv", "userpref",
"users AS createdby", "users AS updatedby");
foreach ($default_locks as $table) {
if (!array_key_exists($table, $args["sql_lock"])) {
$args["sql_lock"][$table] = LOCK_SH;
}
}
}
}
// Check the last modified
if ($lastmod) {
// Set the database tables to check
$tables = array();
if (array_key_exists("lmtables", $args)) {
$tables = array_merge($tables, $args["lmtables"]);
}
// Add the locked tables automatically
if (array_key_exists("sql_lock", $args)) {
$tables = array_merge($tables, array_keys($args["sql_lock"]));
}
// Set the files to check
$files = array();
if (array_key_exists("lmfiles", $args)) {
$files = array_merge($files, $args["lmfiles"]);
}
$callers = debug_backtrace();
if (not_modified($tables, $files,
basename($callers[count($callers)-1]["file"]))) {
http_304();
}
}
// Lock the SQL tables
if ($sql && array_key_exists("sql_lock", $args)) {
sql_lock($args["sql_lock"]);
}
// Fetch the current data
if (function_exists("fetch_current")) {
fetch_current();
}
// Decode user input FORMs to UTF-8
decode_forms();
// Process the list preference form
if (form_type() == "listpref") {
if ( array_key_exists("domain", $_POST)
&& class_exists($_POST["domain"])) {
$LIST = new $_POST["domain"];
$LIST->set_listpref();
} else {
$handler = new ListPreference($_POST);
$handler->main();
}
}
return;
}
// restenv: Restore the script environment
function restenv()
{
// Disconnect SQL
if ($GLOBALS["SQL_DBTYPE"] != SQL_NONE) {
sql_close();
}
// Print the page and end the output buffering, if it exists
if (ob_get_level() > LAST_OB_LEVEL) {
// Return from the innermost level to level 1
while (ob_get_level() > LAST_OB_LEVEL + 1) {
ob_end_flush();
}
// Obtain the final content
$html = ob_get_contents();
ob_end_clean();
// No content -- HTTP 204
if ($html == "") {
http_204();
}
// The content type
$type = array_key_exists("CONTENT_TYPE", $GLOBALS)?
$GLOBALS["CONTENT_TYPE"]: xhtml_content_type();
$is_html = preg_match("/^(?:text\/html|application\/xhtml\+xml)\b/", $type)? true: false;
$is_rss = $type == "application/rss+xml";
// application/rss+xml is not supported yet
if ($is_rss) {
$type = "application/xml";
}
$is_text = preg_match("/^(?:text\/plain)\b/", $type)? true: false;
$is_csv = preg_match("/^(?:text\/csv)\b/", $type)? true: false;
$is_js = preg_match("/^(?:text\/javascript)\b/", $type)? true: false;
$is_attach = array_key_exists("CONTENT_DISPOSITION", $GLOBALS) &&
preg_match("/^attachment\b/", $GLOBALS["CONTENT_DISPOSITION"]);
// Do the run-time replacements
if (($is_html || $is_rss || $is_text || $is_js) && function_exists("page_replacements")) {
$rep = page_replacements();
foreach (array_keys($rep) as $key) {
$html = str_replace("<!--monica:$key-->", $rep[$key]["content"], $html);
}
}
// Fix the HTML output
if ($is_html) {
if (preg_match("/; charset=([^ ;]+)/", $type, $m)) {
$charset = $m[1];
} else {
$charset = getlang(LN_CHARSET);
$type .= "; charset=$charset";
}
// Convert the URLs to relative
if ($is_attach) {
$html = page2abs($html, REQUEST_PATH);
} else {
$html = page2rel($html, REQUEST_PATH);
}
// Mung the e-mail at-signs (@)
$html = str_replace("@", "&#64;", $html);
// Decode the e-mail at-signs (@) of spamtrap
$html = str_replace("spamtrap&#64;", "spamtrap@", $html);
// Convert to the desired character set
$html = page_encode($html, $charset);
// Fix the RSS output
} elseif ($is_rss) {
if (preg_match("/; charset=([^ ;]+)/", $type, $m)) {
$charset = $m[1];
} else {
$charset = getlang(LN_CHARSET);
$type .= "; charset=$charset";
}
// Mung the e-mail at-signs (@)
$html = str_replace("@", "&#64;", $html);
// Decode the e-mail at-signs (@) of spamtrap
$html = str_replace("spamtrap&#64;", "spamtrap@", $html);
// Convert to the desired character set
$html = page_encode($html, $charset);
// Fix the plain text output
} elseif ($is_text) {
if (preg_match("/; charset=([^ ;]+)/", $type, $m)) {
$charset = $m[1];
} else {
$charset = "UTF-8";
$type .= "; charset=$charset";
}
// Mung the e-mail at-signs (@)
$html = str_replace("@", "-at-", $html);
// Decode the e-mail at-signs (@) of spamtrap
$html = str_replace("spamtrap-at-", "spamtrap@", $html);
// Convert to the desired character set
$html = h_encode($html, $charset);
// Fix the comma-seperated values output
} elseif ($is_csv) {
if (preg_match("/; charset=([^ ;]+)/", $type, $m)) {
$charset = $m[1];
} else {
$charset = "UTF-8";
$type .= "; charset=$charset";
}
// Convert to the desired character set
$html = h_encode($html, $charset);
// Fix the javascript output
} elseif ($is_js) {
if (preg_match("/; charset=([^ ;]+)/", $type, $m)) {
$charset = $m[1];
} else {
$charset = getlang(LN_CHARSET);
$type .= "; charset=$charset";
}
// Convert to the desired character set
$html = h_encode($html, $charset);
}
header("Content-Type: $type");
header("Content-Length: " . strlen($html));
if (array_key_exists("CONTENT_DISPOSITION", $GLOBALS)) {
header("Content-Disposition: " . $GLOBALS["CONTENT_DISPOSITION"]);
}
header("Accept-Ranges: none");
if ( substr($type, 0, 5) == "text/"
|| $is_html
|| substr($type, 0, 15) == "application/pdf") {
header("Content-Language: " . getlang(LN_NAME));
}
// Client cache
if (array_key_exists("LAST_MODIFIED", $GLOBALS)) {
if (!is_null(get_login_sn())) {
header("Cache-Control: private");
} else {
header("Cache-Control: public");
}
header("Last-Modified: " . date("r", $GLOBALS["LAST_MODIFIED"]));
} else {
header("Cache-Control: no-cache");
}
// Content negotiation, see HTTP/1.1 section 13.6
if ( count($GLOBALS["ALL_LINGUAS"]) > 1
&& $_SERVER["REQUEST_METHOD"] != "POST"
&& $_SERVER["REQUEST_METHOD"] != "PUT"
&& !array_key_exists("lang", $_GET)) {
header("Content-Location: " . rel2abs(altlang(getlang(), page_param())));
header("Vary: negotiate,accept,accept-language,cookie");
}
// Print the page body
if ($_SERVER["REQUEST_METHOD"] != "HEAD") {
echo $html;
}
}
// Purge the file cache
if (isset($_SESSION) && array_key_exists("savefile", $_SESSION)) {
$FILES =& file_deposit();
$total = 0;
foreach (array_keys($FILES) as $sn) {
// Not a normal record
if ( !is_array($FILES[$sn])
|| !array_key_exists("size", $FILES[$sn])) {
continue;
}
$total += $FILES[$sn]["size"];
// Too larged
if ($total > UPLOAD_DEPOSIT_MAX) {
clear_file_deposit();
break;
}
}
}
// Print the processing time for debugging purpose
if (defined("LOGTIME") && LOGTIME) {
error_log("Process time: " . (time_hires() - T_START) . " sec.");
}
return;
}
// secure_env: Secure the script environment
function secure_env()
{
$ENVLIST = array("PATH", "USER", "MAIL", "HOME", "USERNAME",
"LOGNAME", "PWD", "ENV", "KDEDIR");
foreach ($ENVLIST as $env) {
if (getenv($env) !== false) {
putenv("$env=");
}
}
return;
}
// check_request_size: Prevent huge sized request
function check_request_size()
{
$len = _init_check_array_size($_GET);
if ($len === false) http_413();
if ($len > FORM_HARD_LIMIT) http_413();
$len = _init_check_array_size($_POST);
if ($len === false) http_413();
if ($len > FORM_HARD_LIMIT) http_413();
$len = _init_check_array_size($_COOKIE);
if ($len === false) http_413();
if ($len > FORM_HARD_LIMIT) http_413();
$len = _init_check_array_size($_SERVER);
if ($len === false) http_413();
if ($len > FORM_HARD_LIMIT) http_413();
return;
}
// _init_check_array_size: Recursively check the size of an array
function _init_check_array_size(&$a)
{
// Check the array size
if (gettype($a) != "array") {
$len = strlen($a);
if ($len > FIELD_HARD_LIMIT) {
return false;
}
return $len;
}
// Check the array size
$len = 0;
foreach (array_keys($a) as $k) {
$len += strlen($k);
if (gettype($a[$k]) == "array") {
$len0 = _init_check_array_size($a[$k]);
if ($len0 === false) {
return false;
}
$len += $len0;
} else {
$len0 = strlen($a[$k]);
if ($len0 > FIELD_HARD_LIMIT) {
return false;
}
$len += $len0;
}
}
return $len;
}
// _init_check_nologin: If this site is closed for policy
function _init_check_nologin()
{
// Not logged in - no checks needed
if (is_null(get_login_sn())) {
return;
}
// NOLOGIN: Only super-users can log in now
if (defined("NOLOGIN") && NOLOGIN) {
// Only super-users can log into no-log-in websites
if (is_su()) {
return;
}
logout();
// Deny access to the development site
ob_end_clean();
ob_start();
html_header(_("Log-In Closed"));
html_title(_("Log-In Closed"));
html_message(_("Log-in is temporarily closed for maintainance now. Please come again later. Sorry for the inconvienence."));
html_footer();
$html = ob_get_contents();
ob_end_clean();
if ($_SERVER["REQUEST_METHOD"] != "HEAD") {
echo $html;
}
// No need to return
exit;
// CLOSEDEV: Only developers can log in now
} elseif (defined("CLOSEDEV") && CLOSEDEV) {
if (is_group("dev")) {
return;
}
logout();
// Deny access to the development site
ob_end_clean();
ob_start();
html_header(_("Development Site Closed"));
html_title(_("Development Site Closed"));
html_message(_("Development site is closed. Please work on the live site."));
html_footer();
$html = ob_get_contents();
ob_end_clean();
if ($_SERVER["REQUEST_METHOD"] != "HEAD") {
echo $html;
}
// No need to return
exit;
}
}
// _init_block_bad_robots: Block bad robots
function _init_block_bad_robots()
{
// User-Agent: was sent
if (array_key_exists("HTTP_USER_AGENT", $_SERVER)) {
// Check MSIE 6 and unbalanced brackets
if ($_SERVER["HTTP_USER_AGENT"] == "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1") {
http_403();
}
// Check User-Agent in user-agent identification
if (substr($_SERVER["HTTP_USER_AGENT"], 0, 11) == "User-Agent:") {
http_403();
}
// Check User-Agent in user-agent identification
if (strpos($_SERVER["HTTP_USER_AGENT"], "DTS Agent") !== false) {
http_403(false);
}
// MSIE 6 must be HTTP/1.1
// -- disabled 2006-07-07. Lots of innocent set this way (why?)
// Opera pretends to be MSIE 6, and uses HTTP/1.0 (why?)
//if ( preg_match("/\bMSIE [456]/", $_SERVER["HTTP_USER_AGENT"])
// && strstr($_SERVER["HTTP_USER_AGENT"], "Opera") === false
// && $_SERVER["SERVER_PROTOCOL"] != "HTTP/1.1") {
// http_403();
//}
}
// Check huge amount of requests from a same host in a short time
if (IS_CGI) {
$file = ini_get("session.save_path") . "/ipacct.txt";
$count = 0;
$newrecs = array();
$lastseen = null;
// Check the current records
if (file_exists($file)) {
$fp = fopen($file, "r+");
flock($fp, LOCK_EX);
$size = filesize($file);
// fread() does not allow reading of 0 bytes now
if ($size == 0) {
$content = "";
} else {
$content = fread($fp, $size);
}
$currecs = explode("\n", $content);
foreach ($currecs as $record) {
// Drop invalid
if (!preg_match("/^(\d+) (\d+\.\d+\.\d+\.\d+) /", $record, $m)) {
continue;
}
// We only keep 30 minutes
if (NOW - $m[1] >= 1800) {
continue;
}
$newrecs[] = "$record\n";
if ($m[2] == $_SERVER["REMOTE_ADDR"]) {
if (is_null($lastseen) || $lastseen > $m[1]) {
$lastseen = $m[1];
}
$count++;
}
}
fseek($fp, 0, SEEK_SET);
ftruncate($fp, 0);
// No current records yet
} else {
$fp = fopen($file, "w");
flock($fp, LOCK_EX);
}
// Add this record
if (is_null($lastseen)) {
$lastseen = NOW;
}
$newrecs[] = sprintf("%d %s %s\n", NOW, $_SERVER["REMOTE_ADDR"],
date("Y-m-d H:i:s", NOW));
$count++;
// Update the accounting
fwrite($fp, implode("", $newrecs));
flock($fp, LOCK_UN);
fclose($fp);
/* Debug
if (array_key_exists("debug_reqid", $_GET)) {
error_log(sprintf("req=%s NOW=%d lastseen=%d count=%d avg=%.2f block=%s",
$_GET["debug_reqid"], NOW, $lastseen, $count,
$count / ((NOW == $lastseen)? 1: NOW - $lastseen),
($count / ((NOW == $lastseen)? 1: NOW - $lastseen) > 2? "yes": "no")));
} */
// Averagely 2 script requests in 1 second from a same host - that is too much.
if ($count / ((NOW == $lastseen)? 1: NOW - $lastseen) > 2) {
http_503("Request too fast.");
}
}
}
// _init_initgettext: Initialize the gettext locale
function _init_initgettext()
{
putenv("LANG=" . getlang(LN_LOCALE));
putenv("LANGUAGE=" . getlang(LN_LOCALE));
putenv("LC_ALL=" . getlang(LN_LOCALE));
setlocale(LC_ALL, "");
bindtextdomain(COMMONDOMAIN, COMMONLOCALEDIR);
if (defined("PACKAGE")) {
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
}
}
?>

View File

@@ -0,0 +1,56 @@
<?php
// File name: ipv4addr.inc.php
// Description: PHP subroutine to handle the IPv4 addresses
// Date: 2007-01-30
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2007 Pristine Communications
// ipv4_in_network: If an IP is in a network
function ipv4_in_network($network, $ip)
{
// Network in ddd.ddd.ddd.ddd/mm format
if (preg_match("/^(\d+)\.(\d+)\.(\d+)\.(\d+)\/(\d+)$/", $network, $m)) {
// Sanity check
settype($m[5], "integer");
if ($m[5] > 32) {
return null;
}
for ($i = 1; $i <= 4; $i++) {
settype($m[$i], "integer");
if ($m[$i] > 255) {
return null;
}
}
// Get the subnetwork mask
$masklen = $m[5];
for ($i = 0, $submask = 0; $i < $masklen; $i++) {
$submask |= 1 << (31 - $i);
}
$network = ip2long(sprintf("%d.%d.%d.%d", $m[1], $m[2], $m[3], $m[4]));
$network &= $submask;
// Malformed network
} else {
return null;
}
// IP in ddd.ddd.ddd.ddd format
if (preg_match("/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/", $ip, $m)) {
// Sanity check
for ($i = 1; $i <= 4; $i++) {
settype($m[$i], "integer");
if ($m[$i] > 255) {
return null;
}
}
$ip = ip2long(sprintf("%d.%d.%d.%d", $m[1], $m[2], $m[3], $m[4]));
// Malformed IP
} else {
return null;
}
return (($ip & $submask) == $network);
}
?>

View File

@@ -0,0 +1,154 @@
<?php
// File name: lastmodf.inc.php
// Description: PHP subroutines to calculate the last-modification date
// Date: 2004-11-26
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2004-2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/cgiemu.inc.php";
require_once "monica/getlang.inc.php";
require_once "monica/gettext.inc.php";
require_once "monica/lninfo.inc.php";
require_once "monica/requri.inc.php";
require_once "monica/sql.inc.php";
require_once "monica/sqlconst.inc.php";
// not_modified: Check if we should send "HTTP/1.1 304 Not Modified"
function not_modified($tables, $files, $this_file)
{
// HTTP/1.1 304 only works for GET or HEAD
if (!in_array($_SERVER["REQUEST_METHOD"], array("GET", "HEAD"))) {
return false;
}
// Find the last-modified time
find_last_modified($tables, $files, $this_file);
// If-Modified-Since not supplied. The client had not cached yet.
if (!array_key_exists("HTTP_IF_MODIFIED_SINCE", $_SERVER)) {
return false;
}
// Malformed If-Modified-Since value
$cachemodf = strtotime($_SERVER["HTTP_IF_MODIFIED_SINCE"]);
if ($cachemodf == -1) {
return false;
}
// We are newer than the cache
if ($GLOBALS["LAST_MODIFIED"] > $cachemodf) {
return false;
}
// Yes, use the cache
return true;
return;
}
// find_last_modified: Find the last-modified time
function find_last_modified($tables, $files, $this_file)
{
// Checked before
if (array_key_exists("LAST_MODIFIED", $GLOBALS)) {
return;
}
// Remove duplicates
$tables = array_values(array_unique($tables));
$files = array_values(array_unique($files));
// Start with EPOCH 1970-01-01 00:00:00
$GLOBALS["LAST_MODIFIED"] = 0;
global $LAST_MODIFIED;
// Check myself
updmtime_file($this_file);
// Check mtime from the included modules and gettext MO files
check_inc();
// Check the supplied data files
foreach ($files as $file) {
if (file_exists($file)) {
updmtime_file($file);
}
}
// Check the supplied data tables
updmtime_tables($tables);
}
// check_inc: Check mtime from the included modules and gettext MO files
function check_inc()
{
// Check the included modules
foreach (get_included_files() as $file) {
updmtime_file($file);
}
// Check the header and footer
$incdir = DOC_ROOT . "/admin/include";
$files = array();
$files[] = $incdir . "/header." . getlang(LN_FILENAME) . ".html";
$files[] = $incdir . "/footer." . getlang(LN_FILENAME) . ".html";
$files[] = $incdir . "/header.html";
$files[] = $incdir . "/footer.html";
foreach ($files as $file) {
if (file_exists($file)) {
updmtime_file($file);
}
}
// Check the gettext mo files
if (defined("PACKAGE") && is_dir(LOCALEDIR)) {
$dh = opendir(LOCALEDIR);
while (($ent = readdir($dh)) !== false) {
$file = LOCALEDIR . "/$ent/LC_MESSAGES/" . PACKAGE . ".mo";
if (file_exists($file)) {
updmtime_file($file);
}
}
closedir($dh);
}
$dh = opendir(COMMONLOCALEDIR);
while (($ent = readdir($dh)) !== false) {
$file = COMMONLOCALEDIR . "/$ent/LC_MESSAGES/" . COMMONDOMAIN . ".mo";
if (file_exists($file)) {
updmtime_file($file);
}
}
closedir($dh);
return;
}
// updmtime_tables: Update the $LAST_MODIFIED with the mtime of tables
function updmtime_tables($tables)
{
// Only work when using database
if ($GLOBALS["SQL_DBTYPE"] == SQL_NONE) {
return;
}
$lastupd = sql_lastupd($tables);
if (is_null($lastupd)) {
return;
}
if (!is_numeric($lastupd)) {
$lastupd = preg_replace("/\.\d+$/", "", $lastupd);
$lastupd = strtotime($lastupd);
}
settype($lastupd, "integer");
if ($GLOBALS["LAST_MODIFIED"] < $lastupd) {
$GLOBALS["LAST_MODIFIED"] = $lastupd;
}
return;
}
// updmtime_file: Update the $LAST_MODIFIED with the mtime of a file
function updmtime_file($file)
{
$stat = stat($file);
if ($GLOBALS["LAST_MODIFIED"] < $stat[9]) {
$GLOBALS["LAST_MODIFIED"] = $stat[9];
}
return;
}
?>

View File

@@ -0,0 +1,384 @@
<?php
// File name: links.inc.php
// Description: PHP subroutines to display custom HTTP status messages
// Date: 2004-09-23
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2004-2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/chkfunc.inc.php";
require_once "monica/commtext.inc.php";
require_once "monica/echoform.inc.php";
require_once "monica/getlang.inc.php";
require_once "monica/gettext.inc.php";
require_once "monica/lninfo.inc.php";
require_once "monica/sql.inc.php";
// linkcat_title: Obtain a link category title
function linkcat_title($sn)
{
// Cache the result
static $cache = array();
// Bounce if there is any problem with $sn
if (is_null($sn)) {
return t_notset();
}
// Return the cache
if (array_key_exists($sn, $cache)) {
return $cache[$sn];
}
// Check the serial number first
if (!check_sn($sn)) {
$cache[$sn] = t_na();
return $cache[$sn];
}
// Query
// Unilingual
if (count($GLOBALS["ALL_LINGUAS"]) == 1) {
$col = "linkcat_fulltitle(parent, title) AS title";
// Multilingual
} else {
$thiscol = "title_" . getlang(LN_DATABASE);
$lang = getlang();
// Default language
if ($lang == DEFAULT_LANG) {
$col = "linkcat_fulltitle('$lang', parent, $thiscol) AS title";
// Fall back to the default language
} else {
$defcol = "title_" . ln(DEFAULT_LANG, LN_DATABASE);
$col = "linkcat_fulltitle('$lang', parent, COALESCE($thiscol, $defcol)) AS title";
}
}
$select = "SELECT $col FROM linkcat WHERE sn=$sn;\n";
$result = sql_query($select);
// Not found
if (sql_num_rows($result) != 1) {
$cache[$sn] = t_na();
return $cache[$sn];
}
// Found
$row = sql_fetch_assoc($result);
$cache[$sn] = $row["title"];
return $cache[$sn];
}
// linkcat_path: Obtain a link category path
function linkcat_path($sn)
{
// Cache the result
static $cache = array();
// Bounce if there is any problem with $sn
if (is_null($sn)) {
return t_notset();
}
// Return the cache
if (array_key_exists($sn, $cache)) {
return $cache[$sn];
}
// Check the serial number first
if (!check_sn($sn)) {
$cache[$sn] = t_na();
return $cache[$sn];
}
// Query
$select = "SELECT linkcat_path(sn, id, parent) AS path FROM linkcat"
. " WHERE sn=$sn;\n";
$result = sql_query($select);
// Not found
if (sql_num_rows($result) != 1) {
$cache[$sn] = t_na();
return $cache[$sn];
}
// Found
$row = sql_fetch_assoc($result);
$cache[$sn] = $row["path"];
$cache[$sn] = preg_replace("/(?:\/|\.html)$/", "", $cache[$sn]);
return $cache[$sn];
}
// linkcat_options: Obtain a link category options list
function linkcat_options($value)
{
// Unilingual
if (count($GLOBALS["ALL_LINGUAS"]) == 1) {
$content = "linkcat_fulltitle(parent, title) AS content";
// Multilingual
} else {
$thiscol = "title_" . getlang(LN_DATABASE);
$lang = getlang();
// Default language
if ($lang == DEFAULT_LANG) {
$content = "linkcat_fulltitle('$lang', parent, $thiscol) AS content";
// Fall back to the default language
} else {
$defcol = "title_" . ln(DEFAULT_LANG, LN_DATABASE);
$content = "linkcat_fulltitle('$lang', parent, COALESCE($thiscol, $defcol)) AS content";
}
}
$select = "SELECT sn AS value, $content FROM linkcat"
. " ORDER BY linkcat_fullord(parent, ord);\n";
return opt_list($select, $value);
}
// link_title: Obtain a link title
function link_title($sn)
{
// Cache the result
static $cache = array();
// Bounce if there is any problem with $sn
if (is_null($sn)) {
return t_notset();
}
// Return the cache
if (array_key_exists($sn, $cache)) {
return $cache[$sn];
}
// Check the serial number first
if (!check_sn($sn)) {
$cache[$sn] = t_na();
return $cache[$sn];
}
// Query
// Unilingual
if (count($GLOBALS["ALL_LINGUAS"]) == 1) {
$col = "title";
// Multilingual
} else {
$thiscol = "title_" . getlang(LN_DATABASE);
// Default language
if (getlang() == DEFAULT_LANG) {
$col = "$thiscol AS title";
// Fall back to the default language
} else {
$defcol = "title_" . ln(DEFAULT_LANG, LN_DATABASE);
$col = "COALESCE($thiscol, $defcol) AS title";
}
}
$select = "SELECT $col FROM links WHERE sn=$sn;\n";
$result = sql_query($select);
// Not found
if (sql_num_rows($result) != 1) {
$cache[$sn] = t_na();
return $cache[$sn];
}
// Found
$row = sql_fetch_assoc($result);
$cache[$sn] = $row["title"];
return $cache[$sn];
}
// link_url: Obtain a link URL.
function link_url($sn)
{
// Cache the result
static $cache = array();
// Bounce if there is any problem with $sn
if (is_null($sn)) {
return t_notset();
}
// Return the cache
if (array_key_exists($sn, $cache)) {
return $cache[$sn];
}
// Check the serial number first
if (!check_sn($sn)) {
$cache[$sn] = t_na();
return $cache[$sn];
}
// Query
$select = "SELECT url FROM links WHERE sn=$sn;\n";
$result = sql_query($select);
// Not found
if (sql_num_rows($result) != 1) {
$cache[$sn] = t_na();
return $cache[$sn];
}
// Found
$row = sql_fetch_assoc($result);
$cache[$sn] = $row["url"];
return $cache[$sn];
}
// links_shown_parts: Obtain the shown links parts
function links_shown_parts()
{
$r = array();
// Obtain the shown categories
$path = "linkcat_path(sn, id, parent) AS path";
$select = "SELECT sn, $path FROM linkcat"
. " WHERE linkcat_isshown(sn, hid, parent)"
. " ORDER BY linkcat_fullord(parent, ord);\n";
$result = sql_query($select);
$count = sql_num_rows($result);
for ($i = 0, $r["catspath"] = array(), $r["cats"] = array(); $i < $count; $i++) {
$row = sql_fetch_assoc($result);
$r["cats"][] = $row["sn"];
$r["catspath"][] = $row["path"];
}
sort($r["cats"]);
sort($r["catspath"]);
return $r;
}
/////////////////////////
// Subroutines about link categories
/////////////////////////
// link_tree_full: Get the full page tree of the links
function link_tree_full($lang, $preview = null)
{
// Cache the result
static $cache = array();
// Return the cache
if (array_key_exists($lang, $cache)) {
return $cache[$lang];
}
// Initialize the result
$tree = array();
$lnpref = (count($GLOBALS["ALL_LINGUAS"]) == 1)?
"": "/" . ln($lang, LN_FILENAME);
$tree["index"] = array(
"path" => "$lnpref/links/",
"_path" => "/links/",
"title" => C_("Related Links"),
);
// Get the link tree
$pages =& _link_subtree("/links", null, $lang, $preview);
if (!is_null($pages)) {
$tree["pages"] =& $pages;
}
return $tree;
}
// _link_subtree: Get the page subtree of the links
function &_link_subtree($path, $parent, $lang, $preview = null)
{
// Set the language
$lndb = ln($lang, LN_DATABASE);
$langfile = ln($lang, LN_FILENAME);
// Check if there is any link below this category
$has_links = false;
if (!is_null($parent)) {
$select = "SELECT links.sn FROM links"
. " INNER JOIN linkcatz ON linkcatz.link=links.sn"
. " WHERE linkcatz.cat=$parent"
. " AND " . sql_is_false("links.hid")
. " LIMIT 1;\n";
$result = sql_query($select);
$has_links = (sql_num_rows($result) > 0);
// Check the preview
if (!$has_links && !is_null($preview)) {
$has_links = in_array($parent, $preview["cats"]);
}
}
// Obtain the subcategories
$cols = array();
$cols[] = "sn AS sn";
$cols[] = "id AS id";
if (count($GLOBALS["ALL_LINGUAS"]) > 1) {
if ($lang == DEFAULT_LANG) {
$cols[] = "title_$lndb AS title";
} else {
$lndbdef = ln(DEFAULT_LANG, LN_DATABASE);
$cols[] = "COALESCE(title_$lndb, title_$lndbdef)"
. " AS title";
}
} else {
$cols[] = "title AS title";
}
$cols[] = "ord AS ord";
$conds = array();
if (is_null($parent)) {
$conds[] = "parent IS NULL";
} else {
$conds[] = "parent=$parent";
}
$conds[] = sql_is_false("hid");
if (!is_null($preview) && array_key_exists("sn", $preview)) {
$conds[] = "sn!=" . $preview["sn"];
}
$select = "SELECT " . implode(", ", $cols) . " FROM linkcat"
. " WHERE " . implode(" AND ", $conds)
. " ORDER BY ord;\n";
$result = sql_query($select);
$count = sql_num_rows($result);
$lnpref = (count($GLOBALS["ALL_LINGUAS"]) == 1)?
"": "/" . ln($lang, LN_FILENAME);
for ($i = 0, $pages = array(); $i < $count; $i++) {
$row = sql_fetch_assoc($result);
$subpages =& _link_subtree($path . "/" . $row["id"],
$row["sn"], $lang, $preview);
// Only create subtree that has some content
if (!is_null($subpages)) {
// No subcategories -- create it as a ".html" page
if (count($subpages) == 0) {
$subpath = $path . "/" . $row["id"] . ".html";
$pages[] = array(
"path" => $lnpref . $subpath,
"_path" => $subpath,
"title" => $row["title"],
"ord" => $row["ord"],
);
// There are subcatgories -- create it as a directory
} else {
$subpath = $path . "/" . $row["id"] . "/";
$pages[] = array(
"path" => $lnpref . $subpath,
"_path" => $subpath,
"title" => $row["title"],
"ord" => $row["ord"],
"sub" => array(
"index" => array(
"path" => $lnpref . $subpath,
"_path" => $subpath,
"title" => $row["title"],
),
"pages" => $subpages,
),
);
}
}
}
// No content below
if (!$has_links && count($pages) == 0) {
$pages = null;
return $pages;
}
return $pages;
}
?>

3774
lib/php/monica/list.inc.php Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,136 @@
<?php
// File name: listpref.inc.php
// Description: PHP subroutine to update the list preference
// Date: 2002-11-28
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2002-2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/addget.inc.php";
require_once "monica/addslash.inc.php";
require_once "monica/callform.inc.php";
require_once "monica/checker.inc.php";
require_once "monica/http.inc.php";
require_once "monica/process.inc.php";
require_once "monica/requri.inc.php";
require_once "monica/sql.inc.php";
require_once "monica/userpref.inc.php";
// ListPreference: The list preference handler
class ListPreference
{
protected $_form = array();
protected $_referer = null;
protected $_domain = null;
protected $_listcols = null;
// __construct: Initialize the handler
function __construct(&$form)
{
$this->_form =& $form;
// Set the referer, the domain and the list columns
$this->_set_referer();
$this->_set_domain();
}
// main: Change the list preference
function main()
{
// Lock the necessary tables
$locktable = array("userpref" => LOCK_EX);
sql_lock($locktable);
$error = $this->_check_post();
// If an error occurs
if (!is_null($error)) {
$error["isform"] = false;
error_redirect($error);
// Else, save the data
} else {
$processor = new ListPreferenceProcessor($_POST);
$success = $processor->process();
http_303($this->_referer);
}
}
// _check_post: Check the list preference form
function _check_post()
{
// Run the checker
$checker = new ListPreferenceChecker($this->_form);
$error = $checker->check(array("domain", "listcols", "listsize"));
if (!is_null($error)) {
return $error;
}
// OK
return null;
}
// _set_referer: Obtain the referer to return to
function _set_referer()
{
// Obtained before
if (!is_null($this->_referer)) {
return $this->_referer;
}
// Obtain the source referer
$this->_referer = $this->_source_referer();
// Remove the status from the referer
$this->_referer = rem_get_arg($this->_referer, "statid");
return $this->_referer;
}
// _source_referer: Obtain the source referer
function _source_referer()
{
// Use the POSTed referer
if (array_key_exists("referer", $this->_form)) {
return $this->_form["referer"];
// Use the referer from the request
} elseif (array_key_exists("HTTP_REFERER", $_SERVER)) {
return $_SERVER["HTTP_REFERER"];
// Fall back to the myself
} else {
return REQUEST_FULLURI;
}
}
// _set_domain: Obtain the domain this preference belongs to
function _set_domain()
{
// Obtained before
if (!is_null($this->_domain)) {
return $this->_domain;
}
// Return the supplied domain
if (array_key_exists("domain", $this->_form)) {
$this->_domain = $this->_form["domain"];
return $this->_domain;
}
// Obtain the referer first
$this->_set_referer();
// Return the current script path for the most cases
if ($this->_referer == REQUEST_FULLURI) {
$this->_domain = REQUEST_PATH;
$this->_form["domain"] = $this->_domain;
return $this->_domain;
}
// Parse the referer to get the script path
$url = parse_url($this->_referer);
// Fall back to the root directory if there is no script part
$this->_domain = array_key_exists("path", $url)? $url["path"]: "/";
// Strip the leading root difference
$ROOTDIFF_RE = addslashes_re_php(ROOT_DIFF);
$this->_domain = preg_replace("/^$ROOTDIFF_RE/", "", $this->_domain);
$this->_form["domain"] = $this->_domain;
return $this->_domain;
}
}
?>

View File

@@ -0,0 +1,381 @@
<?php
// File name: lninfo.inc.php
// Description: PHP subroutines to return specific language information
// Date: 2002-07-29
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2002-2018 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Related subroutines
require_once "monica/getlang.inc.php";
require_once "monica/gettext.inc.php";
// Settings
$LNINFO = array(
"en" => array(
"name" => "en-us",
"filename" => "en",
"charset" => "UTF-8",
"db" => "en",
"htmlid" => "en",
"locale" => "en_US",
"sp_break" => true,
"icase" => true,
"ctfirst" => false,
"longdesc" => N_("English")),
"zh-tw" => array(
"name" => "zh-tw",
"filename" => "zh-tw",
"charset" => "UTF-8",
"db" => "zhtw",
"htmlid" => "zhtw",
"locale" => "zh_TW",
"sp_break" => false,
"icase" => false,
"ctfirst" => true,
"longdesc" => N_("Traditional Chinese")),
"zh-cn" => array(
"name" => "zh-cn",
"filename" => "zh-cn",
"charset" => "UTF-8",
"db" => "zhcn",
"htmlid" => "zhcn",
"locale" => "zh_CN",
"sp_break" => false,
"icase" => false,
"ctfirst" => true,
"longdesc" => N_("Simplified Chinese")),
"zh" => array(
"name" => "zh-tw",
"filename" => "zh",
"charset" => "UTF-8",
"db" => "zh",
"htmlid" => "zh",
"locale" => "zh_TW",
"sp_break" => false,
"icase" => false,
"ctfirst" => true,
"longdesc" => N_("Chinese")),
"ja" => array(
"name" => "ja",
"filename" => "ja",
"charset" => "UTF-8",
"db" => "ja",
"htmlid" => "ja",
"locale" => "ja_JP",
"sp_break" => false,
"icase" => false,
"ctfirst" => true,
"longdesc" => N_("Japanese")),
"ko" => array(
"name" => "ko",
"filename" => "ko",
"charset" => "UTF-8",
"db" => "ko",
"htmlid" => "ko",
"locale" => "ko_KR",
"sp_break" => false,
"icase" => false,
"ctfirst" => true,
"longdesc" => N_("Korean")),
"de" => array(
"name" => "de",
"filename" => "de",
"charset" => "UTF-8",
"db" => "de",
"htmlid" => "de",
"locale" => "de_DE",
"sp_break" => true,
"icase" => true,
"ctfirst" => false,
"longdesc" => N_("German")),
"es" => array(
"name" => "es",
"filename" => "es",
"charset" => "UTF-8",
"db" => "es",
"htmlid" => "es",
"locale" => "es_ES",
"sp_break" => true,
"icase" => true,
"ctfirst" => false,
"longdesc" => N_("Spanish"))
);
// Constant symbols
define("LN_NAME", 0);
define("LN_CHARSET", 1);
define("LN_FILENAME", 2);
define("LN_LOCALE", 3);
define("LN_DATABASE", 4);
define("LN_HTMLID", 5);
define("LN_SPACE_BREAK", 6);
define("LN_IGNORE_CASE", 7);
define("LN_COUNTRY_FIRST", 8);
define("LN_DESC", 9);
define("LN_DESC_CURLC", 10);
define("LN_DESC_SELFLC", 11);
define("LN_SWITCH_TITLE", 12);
// Subroutines
// ln: Uniformed wrapper for everything
function ln($lang, $type)
{
switch ($type) {
case LN_NAME:
return _lninfo_name($lang);
case LN_CHARSET:
return _lninfo_charset($lang);
case LN_FILENAME:
return _lninfo_filename($lang);
case LN_LOCALE:
return _lninfo_lc($lang);
case LN_DATABASE:
return _lninfo_db($lang);
case LN_HTMLID:
return _lninfo_htmlid($lang);
case LN_SPACE_BREAK:
return _lninfo_space_break($lang);
case LN_IGNORE_CASE:
return _lninfo_ignore_case($lang);
case LN_COUNTRY_FIRST:
return _lninfo_country_first($lang);
case LN_DESC:
return _lninfo_desc($lang);
case LN_DESC_CURLC:
return _lninfo_desc_curlc($lang);
case LN_DESC_SELFLC:
return _lninfo_desc_selflc($lang);
case LN_SWITCH_TITLE:
return _lninfo_switch_title($lang);
default:
return $lang;
}
}
// selflc: Return the text in its own locale
function selflc($text, $lang)
{
// Cache the result
static $cache = array();
// Obtain the language variants of that text
if (!array_key_exists($text, $cache)) {
global $LNINFO;
$curlc = getenv("LANG");
if ($curlc === false || $curlc == "") {
$curlc = getlang(LN_LOCALE);
}
$cache[$text] = array();
foreach (array_keys($LNINFO) as $l) {
// Switch the locale
$locale = _lninfo_lc($l);
$charset = _lninfo_charset($l);
putenv("LANG=$locale");
putenv("LANGUAGE=$locale");
setlocale(LC_ALL, "");
// Obtain the localed text
$cache[$text][$l] = _($text);
}
// Return the current locale
putenv("LANG=$curlc");
putenv("LANGUAGE=$curlc");
setlocale(LC_ALL, "");
}
// Not found -- return itself instead
if (!array_key_exists($lang, $cache[$text])) {
return $text;
}
// Return the localed text
return $cache[$text][$lang];
}
// _lninfo_name: Language complete name
function _lninfo_name($lang)
{
global $LNINFO;
return array_key_exists($lang, $LNINFO)
&& array_key_exists("name", $LNINFO[$lang])?
$LNINFO[$lang]["name"]: $lang;
}
// _lninfo_charset: Long description
// Most common charset that is used with the specified language
function _lninfo_charset($lang)
{
global $LNINFO;
return array_key_exists($lang, $LNINFO)
&& array_key_exists("charset", $LNINFO[$lang])?
$LNINFO[$lang]["charset"]: $lang;
}
// _lninfo_filename: File system name
function _lninfo_filename($lang)
{
global $LNINFO;
return array_key_exists($lang, $LNINFO)
&& array_key_exists("filename", $LNINFO[$lang])?
$LNINFO[$lang]["filename"]: $lang;
}
// _lninfo_lc: Locale used by GNU glibc and gettext
// Replace hyphens with underscores, and upper-case the district divisions,
// as used in GNU glibc
function _lninfo_lc($lang)
{
global $LNINFO;
if ( array_key_exists($lang, $LNINFO)
&& array_key_exists("locale", $LNINFO[$lang])) {
return $LNINFO[$lang]["locale"];
}
$pos = strpos($lang, "-");
if ($pos !== false) {
return substr($lang, 0, $pos) . "_"
. strtoupper(substr($lang, $pos + 1));
}
return $lang;
}
// _lninfo_db: Database column name
// Hyphens are not allowed, to avoid confusion
// with the substraction operator "-"
function _lninfo_db($lang)
{
global $LNINFO;
if ( array_key_exists($lang, $LNINFO)
&& array_key_exists("db", $LNINFO[$lang])) {
return $LNINFO[$lang]["db"];
}
return str_replace("-", "", $lang);
}
// _lninfo_htmlid: HTML id value
// Hyphens are not allowed, as specified in HTML 4.01 specification
function _lninfo_htmlid($lang)
{
global $LNINFO;
if ( array_key_exists($lang, $LNINFO)
&& array_key_exists("htmlid", $LNINFO[$lang])) {
return $LNINFO[$lang]["htmlid"];
}
return str_replace("-", "", $lang);
}
// _lninfo_space_break: Whether words are seperated at spaces
function _lninfo_space_break($lang)
{
global $LNINFO;
// Default to true, for alphabetic languages
return array_key_exists($lang, $LNINFO)
&& array_key_exists("sp_break", $LNINFO[$lang])?
$LNINFO[$lang]["sp_break"]: true;
}
// _lninfo_ignore_case: Whether case can be ignored
function _lninfo_ignore_case($lang)
{
global $LNINFO;
// Default to true, for European languages
return array_key_exists($lang, $LNINFO)
&& array_key_exists("icase", $LNINFO[$lang])?
$LNINFO[$lang]["icase"]: true;
}
// _lninfo_country_first: Whether country should be listed first in a mail address
function _lninfo_country_first($lang)
{
global $LNINFO;
// Default to false, for European languages
return array_key_exists($lang, $LNINFO)
&& array_key_exists("ctfirst", $LNINFO[$lang])?
$LNINFO[$lang]["ctfirst"]: false;
}
// _lninfo_desc: Long description
function _lninfo_desc($lang)
{
global $LNINFO;
return array_key_exists($lang, $LNINFO)
&& array_key_exists("longdesc", $LNINFO[$lang])?
$LNINFO[$lang]["longdesc"]: $lang;
}
// _lninfo_desc_curlc: Long description in the current locale
function _lninfo_desc_curlc($lang)
{
return C_(_lninfo_desc($lang));
}
// _lninfo_desc_selflc: Long description in its own locale
function _lninfo_desc_selflc($lang)
{
// Cache the result
static $desc;
// Obtain the description list
if (!isset($desc)) {
global $LNINFO;
$curlc = getenv("LANG");
if ($curlc === false || $curlc == "") {
$curlc = getlang(LN_LOCALE);
}
$desc = array();
foreach (array_keys($LNINFO) as $l) {
// Switch the locale
$locale = _lninfo_lc($l);
$charset = _lninfo_charset($l);
putenv("LANG=$locale");
putenv("LANGUAGE=$locale");
setlocale(LC_ALL, "");
// Obtain the long description
$desc[$l] = _lninfo_desc_curlc($l);
}
// Return the current locale
putenv("LANG=$curlc");
putenv("LANGUAGE=$curlc");
setlocale(LC_ALL, "");
}
// Return the proper description
return array_key_exists($lang, $desc)?
$desc[$lang]: $lang;
}
// _lninfo_switch_title: Title of the language switch
function _lninfo_switch_title($lang)
{
// Cache the result
static $title;
// Obtain the title list
if (!isset($title)) {
global $LNINFO;
$curlc = getenv("LANG");
if ($curlc === false || $curlc == "") {
$curlc = getlang(LN_LOCALE);
}
$title = array();
foreach (array_keys($LNINFO) as $l) {
// Switch the locale
$locale = _lninfo_lc($l);
$charset = _lninfo_charset($l);
putenv("LANG=$locale");
putenv("LANGUAGE=$locale");
setlocale(LC_ALL, "");
// Obtain the title
$title[$l] = C_("Switch to the %s version of this page.");
}
// Return the current locale
putenv("LANG=$curlc");
putenv("LANGUAGE=$curlc");
setlocale(LC_ALL, "");
}
// Not found -- use description in its own locale instead
if (!array_key_exists($lang, $title)) {
return _lninfo_desc_selflc($lang);
}
// Return the proper title
return sprintf($title[$lang], _lninfo_desc_selflc($lang));
}
?>

View File

@@ -0,0 +1,209 @@
<?php
// File name: login.inc.php
// Description: PHP subroutines to handle user logins
// Date: 2002-11-13
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2002-2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/cgiemu.inc.php";
require_once "monica/chkpriv.inc.php";
require_once "monica/encrypt.inc.php";
require_once "monica/getlang.inc.php";
require_once "monica/guest.inc.php";
require_once "monica/http.inc.php";
require_once "monica/lninfo.inc.php";
require_once "monica/logout.inc.php";
require_once "monica/scptpriv.inc.php";
require_once "monica/sql.inc.php";
require_once "monica/userhome.inc.php";
require_once "monica/usrconst.inc.php";
if (!defined("REMEMBER_COOKIE")) {
define("REMEMBER_COOKIE", "qySxnXvjNxv0aDAs");
}
if (!defined("FAILURE_DELAY")) {
define("FAILURE_DELAY", 5);
}
// use_users: Use user/membership system
function use_users()
{
// Cache the result
static $cache;
// Return the cache
if (isset($cache)) {
return $cache;
}
// Find in the available tables
$cache = in_array("users", sql_tables());
return $cache;
}
// userinfo_url: The URL to update the user information
function userinfo_url()
{
// Cache the result
static $cache;
// Return the cache
if (isset($cache)) {
return $cache;
}
$is_admin = is_guest()? is_admin_script(): is_admin();
if ($is_admin) {
$args = array();
$args[] = "form=cur";
$args[] = "sn=" . urlencode(get_login_sn());
$cache = userhome() . "users.php?" . implode("&", $args);
} else {
$cache = userhome() . "myinfo.php";
}
return $cache;
}
// get_login_sn: Obtain the user serial number or the current logged-in user
function get_login_sn()
{
return isset($_SESSION) && array_key_exists("usersn", $_SESSION)?
$_SESSION["usersn"]: null;
}
// get_login_id: Obtain the user ID. of the current logged-in user
function get_login_id()
{
return isset($_SESSION) && array_key_exists("userid", $_SESSION)?
$_SESSION["userid"]: null;
}
// get_login_name: Obtain the full name of the current logged-in user
function get_login_name()
{
return isset($_SESSION) && array_key_exists("username", $_SESSION)?
$_SESSION["username"]: null;
}
// get_login_groups: Obtain the groups of the current logged-in user
function get_login_groups()
{
return isset($_SESSION) && array_key_exists("groups", $_SESSION)?
$_SESSION["groups"]: array();
}
// upd_login_info: Update the logged-in infomation
function upd_login_info()
{
// Return if not logged-in from the web yet
if (IS_CGI && is_null(get_login_sn())) {
return;
}
// Lock the necessary tables
$locks = array("users" => LOCK_EX, "groups" => LOCK_SH, "usermem" => LOCK_SH, "groupmem" => LOCK_SH);
sql_lock($locks);
// Begin the SQL transaction
sql_begin();
// Lock the necessary tables
$locks = array("users" => LOCK_EX, "groups" => LOCK_SH, "usermem" => LOCK_SH, "groupmem" => LOCK_SH);
sql_lock($locks);
// Web applications save the login information in session as user S/N
if (IS_CGI) {
// Fetch the user infomation
$found = false;
if (!preg_match("/^[1-9]\d{8}$/", get_login_sn())) {
$found = false;
} else {
$select = "SELECT * FROM users"
. " WHERE sn=" . get_login_sn() . ";\n";
$result = sql_query($select);
$found = (sql_num_rows($result) == 1);
}
// User does not exist anymore
if (!$found) {
logout();
if ($_SERVER["REQUEST_METHOD"] == "POST") {
http_303("/" . getlang(LN_FILENAME) . "/misc/loginchanged.html");
} else {
http_307("/" . getlang(LN_FILENAME) . "/misc/loginchanged.html");
}
// No need to return
exit;
}
// Act as the current user on the console
} else {
$pwent = posix_getpwuid(posix_geteuid());
// Password entry is gone for this user
if ($pwent === false) {
if ($_SERVER["REQUEST_METHOD"] == "POST") {
http_303("/" . getlang(LN_FILENAME) . "/misc/loginchanged.html");
} else {
http_307("/" . getlang(LN_FILENAME) . "/misc/loginchanged.html");
}
}
$userid = $pwent["name"];
// Fetch the user infomation
$select = "SELECT * FROM users"
. " WHERE id='" . sql_esctext($userid) . "';\n";
$result = sql_query($select);
// This user is not in the list of the users for the current package
if (sql_num_rows($result) != 1) {
http_403();
}
}
$row = sql_fetch_assoc($result);
// Remember the user
if (array_key_exists("remember", $_SESSION)) {
// Remember me
if ($_SESSION["remember"]) {
setcookie(REMEMBER_COOKIE, encrypt($row["id"]), time() + 86400 * 365, "/");
// Forget me
} else {
setcookie(REMEMBER_COOKIE, "", time() - 1, "/");
}
unset($_SESSION["remember"]);
// Update the remembered user ID
} elseif (array_key_exists(REMEMBER_COOKIE, $_COOKIE)
&& decrypt($_COOKIE[REMEMBER_COOKIE]) !== $row["id"]) {
setcookie(REMEMBER_COOKIE, encrypt($row["id"]), time() + 86400 * 365, "/");
}
// Update the user ID and full name
$_SESSION["usersn"] = $row["sn"];
$_SESSION["userid"] = $row["id"];
$_SESSION["username"] = $row["name"];
// Update the preferred language
$lang = getlang();
if ($row["lang"] != $lang) {
$update = "UPDATE users SET lang='" . sql_esctext($lang) . "'"
. " WHERE sn=" . get_login_sn() . ";\n";
sql_query($update);
}
// Update the groups
$_SESSION["groups"] = user_parent_groups(get_login_sn());
$_SESSION["guest"] = in_array(GUEST_GROUP, $_SESSION["groups"]);
$_SESSION["admin"] = in_array(ADMIN_GROUP, $_SESSION["groups"]);
// Commit the SQL transaction
sql_commit();
// Unlock the previously locked SQL tables
sql_lock();
return;
}
?>

View File

@@ -0,0 +1,22 @@
<?php
// File name: logout.inc.php
// Description: PHP subroutines to log out a user
// Date: 2002-11-13
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2002-2007 Pristine Communications
// logout: Log out a user
function logout()
{
unset($_SESSION["usersn"]);
unset($_SESSION["userid"]);
unset($_SESSION["username"]);
unset($_SESSION["userpref"]);
unset($_SESSION["groups"]);
unset($_SESSION["admin"]);
unset($_SESSION["guest"]);
unset($_SESSION["bylogin"]);
return;
}
?>

1341
lib/php/monica/mail.inc.php Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,69 @@
<?php
// File name: markabbr.inc.php
// Description: PHP subroutines to mark the abbreviation
// Date: 2006-03-10
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2006-2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/echoform.inc.php";
require_once "monica/htmlchar.inc.php";
// h_abbr: Shortcut to markabbr(h())
function h_abbr($text)
{
return markabbr(h($text));
}
// markabbr: Mark the abbreviation
function markabbr($text)
{
// FAQ
$text = preg_replace("/\b(FAQ)\b(?!<\/abbr>|<\/acronym>)/", "<abbr title=\"frequently asked questions\">$1</abbr>", $text);
$text = preg_replace("/\b(FAQ)s\b(?!<\/abbr>|<\/acronym>)/", "<abbr title=\"frequently asked questions\">$1</abbr>s", $text);
// HTTP
$text = preg_replace("/\b(HTTP)\b(?!<\/abbr>|<\/acronym>)/", "<abbr title=\"HyperText Transfer Protocol\">$1</abbr>", $text);
// HTML
$text = preg_replace("/\b(HTML)\b(?!<\/abbr>|<\/acronym>)/", "<abbr title=\"HyperText Markup Language\">$1</abbr>", $text);
// CGI
$text = preg_replace("/\b(CGI)\b(?!<\/abbr>|<\/acronym>)/", "<abbr title=\"Common Gateway Interface\">$1</abbr>", $text);
// SSL
$text = preg_replace("/\b(SSL)\b(?!<\/abbr>|<\/acronym>)/", "<abbr title=\"Secure Socket Layer\">$1</abbr>", $text);
// PDF
$text = preg_replace("/\b(PDF\b\.?)(?!<\/abbr>|<\/acronym>)/", "<abbr title=\"Portable Document Format\">$1</abbr>", $text);
// IP
$text = preg_replace("/\b(IP)\b(?!<\/abbr>|<\/acronym>)/", "<abbr title=\"Internet Protocol\">$1</abbr>", $text);
// S/N
$text = preg_replace("/\b(S\/N)\b(?!<\/abbr>|<\/acronym>)/", "<abbr title=\"serial number\">$1</abbr>", $text);
// No.
$text = preg_replace("/\b(No\.|Num\.)(?!<\/abbr>|<\/acronym>)/", "<abbr title=\"number\">$1</abbr>", $text);
// ID.
$text = preg_replace("/\b(ID\.)(?!<\/abbr>|<\/acronym>)/", "<abbr title=\"identity\">$1</abbr>", $text);
// Pic.
$text = preg_replace("/\b(Pic\.)(?!<\/abbr>|<\/acronym>)/", "<abbr title=\"picture\">$1</abbr>", $text);
// URL.
$text = preg_replace("/\b(URL\b\.?)(?!<\/abbr>|<\/acronym>)/", "<abbr title=\"Uniform Resource Locator\">$1</abbr>", $text);
// E-mail.
$text = preg_replace("/\b(E-?mail)\b(?!<\/abbr>|<\/acronym>)/i", "<acronym title=\"electronic mail\">$1</acronym>", $text);
// MIME
$text = preg_replace("/\b(MIME\b\.?)(?!<\/abbr>|<\/acronym>)/", "<abbr title=\"Multipurpose Internet Mail Extensions\">$1</abbr>", $text);
// KB/MB/GB/TB from report_size()
$text = preg_replace("/(\d+) KB\)/", "$1 <abbr title=\"kilobyte\">KB</abbr>)", $text);
$text = preg_replace("/(\d+) MB\)/", "$1 <abbr title=\"megabyte\">MB</abbr>)", $text);
$text = preg_replace("/(\d+) GB\)/", "$1 <abbr title=\"gigabyte\">GB</abbr>)", $text);
$text = preg_replace("/(\d+) TB\)/", "$1 <abbr title=\"terabyte\">TB</abbr>)", $text);
// MRTG
$text = preg_replace("/\b(MRTG)\b(?!<\/abbr>|<\/acronym>)/", "<abbr title=\"Multi Router Traffic Grapher\">$1</abbr>", $text);
// Load the local extension
// Load it at last to prevent mark-up recursion
if (function_exists("markabbr_site")) {
$text = markabbr_site($text);
}
return $text;
}
?>

View File

@@ -0,0 +1,24 @@
<?php
// File name: md5.inc.php
// Description: PHP subroutine to calculate MD5 digests
// Date: 2004-07-04
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2004-2007 Pristine Communications
// md5_raw: Return the raw MD5 binary digest
function md5_raw($content)
{
$md5hex = md5($content);
for ($i = 0, $md5 = ""; $i < strlen($md5hex); $i += 2) {
$md5 .= chr(hexdec(substr($md5hex, $i, 2)));
}
return $md5;
}
// md5_base64: Return the Base64-encoded MD5 digest
function md5_base64($content)
{
return base64_encode(md5_raw($content));
}
?>

View File

@@ -0,0 +1,89 @@
<?php
// File name: mimeenc.inc.php
// Description: PHP subroutine to handle MIME encoding/decoding (Base-64 and Quoted-Printable)
// Date: 2004-04-27
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2004-2007 Pristine Communications
// b64encode_header: Encode a piece of header text with Base-64
// Refer to RFC-1522 4.1
function b64encode_header($text, $charset)
{
return "=?$charset?B?" . base64_encode($text) . "?=";
}
// qpencode: Encode a piece of text with Quoted-Printable
// Refer to RFC-1521 5.1
function qpencode($source)
{
// Convert to RFC-822 CRLF (Rule #4)
$source = str_replace("\r\n", "\n", $source);
$source = str_replace("\n", "\r\n", $source);
$result = "";
// Convert each character
for ($i = 0, $linelen = 0; $i < strlen($source); $i++) {
// Rule #4 (Line Breaks)
if (substr($source, $i, 2) == "\r\n") {
$result .= "\r\n";
$linelen = 0;
$i++;
continue;
}
$c = substr($source, $i, 1);
$o = ord($c);
// Rule #2 (Literal representation)
if (($o >= 33 && $o <= 60) || ($o >= 62 && $o <= 126)) {
$char = $c;
// Rule #4 (Line Breaks)
} elseif ($c == "\r" || $c == "\n") {
$char = $c;
// Rule #3 (White Space)
} elseif ($o == 9 || $o == 32) {
// At the end of line
if ($i+1 == strlen($source) || substr($source, $i+1) == "\r") {
$char = sprintf("=%02X", $o);
// Not at the end of line
} else {
$char = $c;
}
// Rule #1 (General 8-bit representation)
} else {
$char = sprintf("=%02X", $o);
}
// Rule #5 (Soft Line Breaks)
if ($linelen + strlen($char) > 75) {
$result .= "=\r\n";
$linelen = 0;
}
$result .= $char;
$linelen += strlen($char);
}
return $result;
}
// qpencode_header: Encode a piece of header text with Quoted-Printable
// Refer to RFC-1522 4.2
function qpencode_header($source, $charset)
{
$result = "";
// Convert each character
for ($i = 0; $i < strlen($source); $i++) {
$c = substr($source, $i, 1);
$o = ord($c);
// 4.2.3
if ($o >= 33 && $o <= 126 && $c != "=" && $c != "?" && $c != "_" && $o != 32) {
$char = $c;
// 4.2.2
} elseif ($o == 32) {
$char = "_";
// 4.2.1
} else {
$char = sprintf("=%02X", $o);
}
$result .= $char;
}
$result = "=?$charset?Q?$result?=";
return $result;
}
?>

View File

@@ -0,0 +1,247 @@
<?php
// File name: mimetype.inc.php
// Description: PHP subroutine to check the MIME type of files
// Date: 2005-12-18
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2005-2009 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/runcmd.inc.php";
require_once "monica/xfileio.inc.php";
// The fileinfo resource
$_MIMETYPE_FINFO = null;
// check_mime_type: Try to decide the MIME type as possible
function check_mime_type($file, $name = null, $sugtype = null)
{
// Default to the name of the file
if (is_null($name)) {
$name = $file;
}
// Obtain the file name suffix
$suffix = null;
if (!is_null($name)) {
$suffix = preg_match("/^.*(\.[^\.]*)$/", $name, $m)? strtolower($m[1]): "";
}
// application/octet-stream is no difference to none
if (!is_null($sugtype) && $sugtype == "application/octet-stream") {
$sugtype = null;
}
// Check the magic number first
if (is_null($GLOBALS["_MIMETYPE_FINFO"])) {
$GLOBALS["_MIMETYPE_FINFO"] = finfo_open(FILEINFO_MIME);
}
$type = preg_replace("/;.*$/", "",
finfo_file($GLOBALS["_MIMETYPE_FINFO"], $file));
// Fix the known errors returned from magic checking
$type = _mimetype_fix_magic($type, $sugtype, $suffix);
// OK
return $type;
}
// check_mime_type_content: Try to decide the MIME type as possible, from the file content
function check_mime_type_content(&$content, $name = null, $sugtype = null)
{
// Obtain the file name suffix
$suffix = null;
if (!is_null($name)) {
$suffix = preg_match("/^.*(\.[^\.]*)$/", $name, $m)? strtolower($m[1]): "";
}
// application/octet-stream is no difference to none
if (!is_null($sugtype) && $sugtype == "application/octet-stream") {
$sugtype = null;
}
// Check the magic number first
if (is_null($GLOBALS["_MIMETYPE_FINFO"])) {
$GLOBALS["_MIMETYPE_FINFO"] = finfo_open(FILEINFO_MIME);
}
$type = preg_replace("/;.*$/", "",
finfo_buffer($GLOBALS["_MIMETYPE_FINFO"], $content));
// Fix the known errors returned from magic checking
$type = _mimetype_fix_magic($type, $sugtype, $suffix);
// OK
return $type;
}
// _mimetype_fix_magic: Fix the known errors returned from magic checking
function _mimetype_fix_magic($type, $sugtype = null, $suffix = null)
{
// Fix known errors
switch ($type) {
// MS-Excel, MS-PowerPoint files are always recognized as application/msword
case "application/msword":
// Starting from Debian Lenny 5.0.0 (libmagic1 4.26-1), they are sometimes
// unrecognizable. By imacat 2009-03-26.
case false:
// There is a suggested type submitted. It should be trusted
if (!is_null($sugtype)) {
switch ($sugtype) {
case "application/msexcell":
case "application/vnd.ms-excel":
return "application/vnd.ms-excel";
break;
case "application/vnd.ms-powerpoint":
return "application/vnd.ms-powerpoint";
break;
case "application/msword":
return "application/msword";
break;
}
}
// Check the file name suffix
if (!is_null($suffix)) {
switch ($suffix) {
case ".xls":
case ".xlt":
return "application/vnd.ms-excel";
break;
case ".ppt":
case ".pot":
return "application/vnd.ms-powerpoint";
break;
case ".doc":
case ".dot":
return "application/msword";
break;
}
}
// We have no choice but to trust the magic number check result
return $type;
break;
// OpenOffice.org documents are always recognized as application/x-zip
case "application/x-zip":
// There is a suggested type submitted. It should be trusted
if (!is_null($sugtype)) {
switch ($sugtype) {
case "application/vnd.oasis.opendocument.text":
case "application/vnd.oasis.opendocument.text-template":
case "application/vnd.oasis.opendocument.spreadsheet":
case "application/vnd.oasis.opendocument.spreadsheet-template":
case "application/vnd.oasis.opendocument.presentation":
case "application/vnd.oasis.opendocument.presentation-template":
case "application/vnd.sun.xml.writer":
case "application/vnd.sun.xml.writer.template":
case "application/vnd.sun.xml.calc":
case "application/vnd.sun.xml.calc.template":
case "application/vnd.sun.xml.impress":
case "application/vnd.sun.xml.impress.template":
case "application/x-zip":
return $sugtype;
break;
}
}
// Check the file name suffix
if (!is_null($suffix)) {
switch ($suffix) {
case ".odt":
return "application/vnd.oasis.opendocument.text";
break;
case ".ott":
return "application/vnd.oasis.opendocument.text-template";
break;
case ".ods":
return "application/vnd.oasis.opendocument.spreadsheet";
break;
case ".ots":
return "application/vnd.oasis.opendocument.spreadsheet-template";
break;
case ".odp":
return "application/vnd.oasis.opendocument.presentation";
break;
case ".otp":
return "application/vnd.oasis.opendocument.presentation-template";
break;
case ".sxw":
return "application/vnd.sun.xml.writer";
break;
case ".stw":
return "application/vnd.sun.xml.writer.template";
break;
case ".stc":
return "application/vnd.sun.xml.calc";
break;
case ".sxc":
return "application/vnd.sun.xml.calc.template";
break;
case ".sxi":
return "application/vnd.sun.xml.impress";
break;
case ".sti":
return "application/vnd.sun.xml.impress.template";
break;
case ".zip":
return "application/x-zip";
break;
}
}
// We have no choice but to trust the magic number check result
return $type;
break;
// Default to trust the magic number check result
default:
return $type;
break;
}
}
// Only do this when fileinfo extension is not loaded
if (!extension_loaded("fileinfo")) {
if (!defined("FILEINFO_MIME")) {
define("FILEINFO_MIME", true);
}
// finfo_open: Create a new fileinfo resource
function finfo_open($options)
{
return null;
}
// finfo_file: Return information about a file
function finfo_file($finfo, $file_name)
{
return mime_content_type($file_name);
}
// finfo_buffer: Return information about a string buffer
function finfo_buffer($finfo, $string)
{
// Check the MIME type from the file content with /usr/bin/file
// The result is not countable with MS-Excel files.
// Use mime_content_type() to obtain a consistent result to fed to
// _mimetype_fix_magic().
//$type = _mimetype_check_content_with_file($content);
$file = tempnam(session_save_path(),
PACKAGE . "-" . basename(__FILE__) . "-finfo_buffer-");
// xfupdate() is not working with files created with tempnam() (why?)
xfupdate($file, $string);
$type = mime_content_type($file);
unlink($file);
}
// _mimetype_check_content_with_file: Check the MIME type from the file content with /usr/bin/file
function _mimetype_check_content_with_file(&$content)
{
// Use the file utility to do this
$cmd = array("/usr/bin/file", "-i", "-");
$output = xruncmd($cmd, $content);
// Remove the filename (should be "standard input:")
$type = preg_replace("/^[^:]+:\s+/", "", $output);
// Remove the trailing space (and maybe a suffix description)
$type = preg_replace("/(?:,.+)?\n$/", "", $type);
return $type;
}
}
?>

View File

@@ -0,0 +1,38 @@
<?php
// File name: mkalldir.inc.php
// Description: PHP subroutine to create all components of a directory
// Date: 2002-04-16
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2002-2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/rel2abs.inc.php";
// mkalldir: Create all the components of a directory
// Input: Directory name $dir. It won't check at all.
// Output: true if success, false if failed
function mkalldir($dir)
{
// Standardize it
$dir = stdpath($dir);
// Directories to create
$dirs = array();
// Find all the directories to create
while ($dir != "" && !file_exists($dir)) {
$dirs[] = $dir;
$dir = dirname($dir);
}
// Create from the last one
for ($i = count($dirs) - 1; $i >= 0; $i--) {
if (mkdir($dirs[$i], 0755) === false) {
return false;
}
}
return true;
}
?>

View File

@@ -0,0 +1,28 @@
<?php
// File name: mkdtemp.inc.php
// Description: PHP subroutine to create a temporarily working directory
// Date: 2002-04-16
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2002-2007 Pristine Communications
// mkdtemp: create a temporarily working directory
function mkdtemp()
{
// Find out our context
$trace = debug_backtrace();
$func = (count($trace) > 1? $trace[1]["function"]: "_GLOBAL");
$file = preg_replace("/\..*$/", "", basename($trace[0]["file"]));
$pkg = (defined("PACKAGE")? PACKAGE: "unknown");
$prefix = sprintf("monica-%s-%s-%s-", $pkg, $file, $func);
$dir = session_save_path();
if ($dir == "") {
$dir = "/tmp";
}
$result = tempnam($dir, $prefix);
unlink($result);
mkdir($result);
chmod($result, 0700);
return $result;
}
?>

View File

@@ -0,0 +1,117 @@
<?php
// File name: monica.inc.php
// Description: PHP meta include file to include the monica system
// Date: 2004-05-26
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2004-2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// All the monica files
require_once "monica/a2html.inc.php";
require_once "monica/actlog.inc.php";
require_once "monica/addcol.inc.php";
require_once "monica/addget.inc.php";
require_once "monica/addslash.inc.php";
require_once "monica/altlang.inc.php";
require_once "monica/big5.inc.php";
require_once "monica/callform.inc.php";
require_once "monica/captitle.inc.php";
require_once "monica/cgiemu.inc.php";
require_once "monica/checker.inc.php";
require_once "monica/chkfunc.inc.php";
require_once "monica/chkpriv.inc.php";
require_once "monica/chkwrite.inc.php";
require_once "monica/commtext.inc.php";
require_once "monica/copyyear.inc.php";
require_once "monica/country.inc.php";
require_once "monica/cracklib.inc.php";
require_once "monica/curtime.inc.php";
require_once "monica/decform.inc.php";
require_once "monica/echoform.inc.php";
require_once "monica/email.inc.php";
require_once "monica/encrypt.inc.php";
require_once "monica/errmsg.inc.php";
require_once "monica/errhndl.inc.php";
require_once "monica/fetchrec.inc.php";
require_once "monica/form.inc.php";
require_once "monica/formfunc.inc.php";
require_once "monica/formreg.inc.php";
require_once "monica/gb2312.inc.php";
require_once "monica/geoip.inc.php";
require_once "monica/getlang.inc.php";
require_once "monica/gettext.inc.php";
require_once "monica/guest.inc.php";
require_once "monica/hires.inc.php";
require_once "monica/htmlchar.inc.php";
require_once "monica/html401.inc.php";
require_once "monica/http.inc.php";
require_once "monica/https.inc.php";
require_once "monica/init.inc.php";
require_once "monica/ipv4addr.inc.php";
require_once "monica/lastmodf.inc.php";
require_once "monica/links.inc.php";
require_once "monica/list.inc.php";
require_once "monica/listpref.inc.php";
require_once "monica/lninfo.inc.php";
require_once "monica/login.inc.php";
require_once "monica/logout.inc.php";
require_once "monica/mail.inc.php";
require_once "monica/markabbr.inc.php";
require_once "monica/md5.inc.php";
require_once "monica/mkalldir.inc.php";
require_once "monica/mkdtemp.inc.php";
require_once "monica/mimetype.inc.php";
require_once "monica/mimeenc.inc.php";
require_once "monica/mysql.inc.php";
require_once "monica/newpass.inc.php";
require_once "monica/news.inc.php";
require_once "monica/newsn.inc.php";
require_once "monica/page.inc.php";
require_once "monica/page2rel.inc.php";
require_once "monica/pagefunc.inc.php";
require_once "monica/parseurl.inc.php";
require_once "monica/passwd.inc.php";
require_once "monica/pic.inc.php";
require_once "monica/pinyin.inc.php";
require_once "monica/postgres.inc.php";
require_once "monica/preview.inc.php";
require_once "monica/process.inc.php";
require_once "monica/rel2abs.inc.php";
require_once "monica/request.inc.php";
require_once "monica/requri.inc.php";
require_once "monica/rfc1521.inc.php";
require_once "monica/rfc1738.inc.php";
require_once "monica/rfc2396.inc.php";
require_once "monica/rfc822.inc.php";
require_once "monica/rmalldir.inc.php";
require_once "monica/rmofile.inc.php";
require_once "monica/runcmd.inc.php";
require_once "monica/scptpriv.inc.php";
require_once "monica/server.inc.php";
require_once "monica/sitesize.inc.php";
require_once "monica/spltline.inc.php";
require_once "monica/sql.inc.php";
require_once "monica/sqlconst.inc.php";
require_once "monica/sqllogin.inc.php";
require_once "monica/timezone.inc.php";
require_once "monica/trimtext.inc.php";
require_once "monica/unauth.inc.php";
require_once "monica/unicode.inc.php";
require_once "monica/upload.inc.php";
require_once "monica/urlregex.inc.php";
require_once "monica/userhome.inc.php";
require_once "monica/username.inc.php";
require_once "monica/userpref.inc.php";
require_once "monica/usrconst.inc.php";
require_once "monica/validate.inc.php";
require_once "monica/xfileio.inc.php";
require_once "monica/xhtml.inc.php";
require_once "monica/zh2py.inc.php";
require_once "monica/zhnum.inc.php";
// Subroutines that are not used
//require_once "monica/unused.inc.php";
?>

View File

@@ -0,0 +1,628 @@
<?php
// File name: mysql.inc.php
// Description: PHP subroutines to handle MySQL operation
// Date: 2001-02-13
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2001-2008 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines with high precedence
require_once "monica/sqlconst.inc.php";
// Referenced subroutines
require_once "monica/errhndl.inc.php";
require_once "monica/getlang.inc.php";
require_once "monica/lninfo.inc.php";
require_once "monica/requri.inc.php";
require_once "monica/sqllogin.inc.php";
// Settings
$_MYSQL_CONN = null;
// xmysql_connect: Connect to the MySQL database
function xmysql_connect($database = null)
{
global $_MYSQL_CONN;
// Connected
if (!is_null($_MYSQL_CONN)) {
return;
}
// Obtain the SQL log-in information
if (is_null($database)) {
if (getenv("MYSQL_DB") !== false) {
$database = getenv("MYSQL_DB");
} elseif (defined("PACKAGE")) {
$database = PACKAGE;
}
}
if (getenv("MYSQL_HOST") !== false) {
$host = getenv("MYSQL_HOST");
} else {
$host = null;
}
// Login with from SQLLOGIN environment variable as a web application
// php-cgi does not have STDIN and STDERR even on console
if (PHP_SAPI != "cli") {
$r = get_sql_login_info(SQL_MYSQL, $database, $host);
// Connect it
$_MYSQL_CONN = mysql_connect($r["MYSQL_HOST"], $r["MYSQL_USER"], $r["MYSQL_PW"]);
if ($_MYSQL_CONN === false) {
$_MYSQL_CONN = null;
trigger_error("Failed connecting to the MySQL server.\n"
. mysql_errno() . " " . mysql_error(), E_USER_ERROR);
}
// Ask the password from the console
} else {
$user = null;
$subseq = false;
set_error_handler("null_error_handler");
$_MYSQL_CONN = mysql_connect();
restore_error_handler();
while ($_MYSQL_CONN === false) {
if ($subseq) {
fprintf(STDERR, "%s\n", $GLOBALS["php_errormsg"]);
sleep(5);
}
// Obtain the current login user
if ( is_null($user)
&& preg_match("/ denied for user '(.+?)'\@'.+?'/", $GLOBALS["php_errormsg"], $m)) {
$user = $m[1];
}
$subseq = true;
// Disable console echo
system("/bin/stty -echo");
fprintf(STDERR, !is_null($user)? "MySQL password for $user: ":
"MySQL password: ");
$passwd = fgets(STDIN);
fprintf(STDERR, "\n");
// Restore console echo status
system("/bin/stty echo");
// STDIN is not available
if ($passwd === false) {
die(THIS_FILE . ": Failed connecting to the PostgreSQL server\n");
}
$passwd = trim($passwd);
set_error_handler("null_error_handler");
$_MYSQL_CONN = mysql_connect(null, null, $passwd);
restore_error_handler();
}
}
// Select the database
$result = mysql_select_db($database);
if ($result === false) {
trigger_error("Failed mysql_select_db(\"$database\").\n"
. mysql_errno() . " " . mysql_error(), E_USER_ERROR);
}
// Set the character set
$charset = defined("SQL_CHARSET")? SQL_CHARSET: "utf8";
$set = "SET NAMES '" . mysql_escape_string($charset) . "';\n";
xmysql_query($set);
return;
}
// xmysql_close: Disconnect from the MySQL database
function xmysql_close()
{
global $_MYSQL_CONN;
if (is_null($_MYSQL_CONN)) {
return;
}
$result = mysql_close($_MYSQL_CONN);
if ($result !== true) {
trigger_error("Failed disconnecting from the MySQL server.\n"
. mysql_errno() . " " . mysql_error(), E_USER_ERROR);
}
$_MYSQL_CONN = null;
return;
}
/////////////////////////
// Concurrency Control: Transactions and Locks
/////////////////////////
$_MYSQL_IN_TRANSACTION = false;
// mysql_begin: Begin a MySQL transaction
function mysql_begin()
{
if (!$GLOBALS["_MYSQL_IN_TRANSACTION"]) {
$begin = "START TRANSACTION;\n";
xmysql_query($begin);
$GLOBALS["_MYSQL_IN_TRANSACTION"] = true;
}
}
// mysql_commit: Commit a MySQL transaction
function mysql_commit()
{
if ($GLOBALS["_MYSQL_IN_TRANSACTION"]) {
$commit = "COMMIT;\n";
xmysql_query($commit);
$GLOBALS["_MYSQL_IN_TRANSACTION"] = false;
}
}
// mysql_rollback: Rollback a MySQL transaction
function mysql_rollback()
{
if ($GLOBALS["_MYSQL_IN_TRANSACTION"]) {
$rollback = "ROLLBACK;\n";
// This generate errors under MyIASM
//xmysql_query($rollback);
mysql_query($rollback);
$GLOBALS["_MYSQL_IN_TRANSACTION"] = false;
}
}
// mysql_lock: MySQL table-locking handler
// We need this to wrok around the stupid MySQL table locking mechanism
// Input: An associative array, where its keys are the tables to lock,
// and its values can be one of the following:
// LOCK_SH: Request a read lock
// LOCK_EX: Request a write lock
// LOCK_UN: Unlock the previously obtained lock
// Or null to unlock everything.
// Return: None. Errors are directed to error handlers
function mysql_lock($newlocks = null)
{
// Keep the current lock table static
static $curlocks = array();
// Save the previous locks
$lastlocks = $curlocks;
// Unlock everything
if (is_null($newlocks)) {
$curlocks = array();
} else {
// Adjust the current lock table
foreach (array_keys($newlocks) as $table) {
switch ($newlocks[$table]) {
case LOCK_SH:
case LOCK_EX:
$curlocks[$table] = $newlocks[$table];
break;
case LOCK_UN:
unset($curlocks[$table]);
break;
default:
trigger_error("Bad SQL lock request: \"$newlocks[$table]\" on table \"$table\".", E_USER_ERROR);
}
}
}
$lockstr = _mysql_locks2str($curlocks);
// Return if nothing is changed
if ($lockstr == _mysql_locks2str($lastlocks)) {
return;
}
// Rollback everything if not committed yet
// LOCK TABLE/UNLOCK TABLE implicitly COMMIT the previous transaction.
// This is bad.
if ($GLOBALS["_MYSQL_IN_TRANSACTION"]) {
mysql_rollback();
}
// Has something to lock
if ($lockstr !== "") {
$locktable = "LOCK TABLES $lockstr;\n";
// Nothing to lock - release all locks
} else {
$locktable = "UNLOCK TABLES;\n";
}
xmysql_query($locktable);
return;
}
// xmysql_query: Do a MySQL query and report the error
function xmysql_query($query)
{
$result = mysql_query($query);
if ($result === false) {
trigger_error("Failed mysql_query().\n$query\n"
. mysql_errno() . " " . mysql_error(), E_USER_ERROR);
}
return $result;
}
// mysql_seek: Move the MySQL result pointer
function mysql_seek($result, $offset)
{
$result = mysql_data_seek($result, $offset);
if ($result === false) {
trigger_error("Failed mysql_data_seek().\n"
. mysql_errno() . " " . mysql_error(), E_USER_ERROR);
}
return $result;
}
// xmysql_fetch_assoc: Return a MySQL row as an associative array
function xmysql_fetch_assoc($result)
{
// Fetch the raw data now
$row = mysql_fetch_assoc($result);
// Return the error
if (!is_array($row)) {
return $row;
}
// Adjust the boolean columns
foreach (mysql_cols_of_type($result, SQL_TYPE_BOOLEAN, SQL_FETCH_ASSOC) as $col) {
$row[$col] = !is_null($row[$col]);
}
// Adjust the integer columns
foreach (mysql_cols_of_type($result, SQL_TYPE_INTEGER, SQL_FETCH_ASSOC) as $col) {
if (!is_null($row[$col])) {
settype($row[$col], "integer");
}
}
// Adjust the big integer columns
foreach (mysql_cols_of_type($result, SQL_TYPE_BIGINT, SQL_FETCH_ASSOC) as $col) {
if ( !is_null($row[$col])
&& $row[$col] >= -2147483647
&& $row[$col] <= 2147483647) {
settype($row[$col], "integer");
}
}
// Adjust the float columns
foreach (mysql_cols_of_type($result, SQL_TYPE_FLOAT, SQL_FETCH_ASSOC) as $col) {
if (!is_null($row[$col])) {
settype($row[$col], "float");
}
}
return $row;
}
// xmysql_fetch_row: Return a MySQL row as an numeric array
function xmysql_fetch_row($result)
{
// Fetch the raw data now
$row = mysql_fetch_row($result);
// Return the error
if (!is_array($row)) {
return $row;
}
// Adjust the boolean columns
foreach (mysql_cols_of_type($result, SQL_TYPE_BOOLEAN, SQL_FETCH_ROW) as $col) {
$row[$col] = !is_null($row[$col]);
}
// Adjust the integer columns
foreach (mysql_cols_of_type($result, SQL_TYPE_INTEGER, SQL_FETCH_ROW) as $col) {
if (!is_null($row[$col])) {
settype($row[$col], "integer");
}
}
// Adjust the big integer columns
foreach (mysql_cols_of_type($result, SQL_TYPE_BIGINT, SQL_FETCH_ROW) as $col) {
if ( !is_null($row[$col])
&& $row[$col] >= -2147483647
&& $row[$col] <= 2147483647) {
settype($row[$col], "integer");
}
}
// Adjust the float columns
foreach (mysql_cols_of_type($result, SQL_TYPE_FLOAT, SQL_FETCH_ROW) as $col) {
if (!is_null($row[$col])) {
settype($row[$col], "float");
}
}
return $row;
}
// mysql_tables: Obtain a list of available MySQL tables
// and report the error
function mysql_tables($db = null)
{
if (is_null($db)) {
$select = "SHOW TABLES;\n";
} else {
$select = "SHOW TABLES FROM $db;\n";
}
$result = xmysql_query($select);
$count = mysql_num_rows($result);
for ($i = 0, $tables = array(); $i < $count; $i++) {
$row = mysql_fetch_row($result);
$tables[] = $row[0];
}
sort($tables);
return $tables;
}
// mysql_cols: Obtain the column list of a MySQL table
function mysql_cols($table)
{
// Cache the result
static $cache = array();
// Return the cache
if (array_key_exists($table, $cache)) {
return $cache[$table];
}
$select = "SHOW COLUMNS FROM $table;\n";
$result = xmysql_query($select);
$count = mysql_num_rows($result);
for ($i = 0, $cache[$table] = array(); $i < $count; $i++) {
$row = mysql_fetch_row($result);
$cache[$table][] = $row[0];
}
return $cache[$table];
}
// mysql_cols_ml: Return a list of multi-lingual columns in a MySQL table
function mysql_cols_ml($table)
{
// Cache the result
static $cache = array();
// Return the cache
if (array_key_exists($table, $cache)) {
return $cache[$table];
}
// Get the columns that have language variants
$cols = mysql_cols($table);
$cache[$table] = array();
$suffix = "_" . getlang(LN_DATABASE);
$len = strlen($suffix);
for ($i = 0; $i < count($cols); $i++) {
// It has a language suffix
if (substr($cols[$i], -$len) == $suffix) {
$cache[$table][] = substr($cols[$i], 0, -$len);
}
}
return $cache[$table];
}
// mysql_cols_nl: Return a list of columns without their multi-lingual
// deviants in a MySQL table
function mysql_cols_nl($table)
{
// Cache the result
static $cache = array();
// Return the cache
if (array_key_exists($table, $cache)) {
return $cache[$table];
}
// Get the columns that have language variants
$cols = mysql_cols($table);
$langcols = mysql_cols_ml($table);
// Remove those language variants
$cache[$table] = array();
for ($i = 0; $i < count($cols); $i++) {
$pos = strrpos($cols[$i], "_");
// No suffix
if ($pos === false) {
$cache[$table][] = $cols[$i];
// Check the prefix
} else {
$prefix = substr($cols[$i], 0, $pos);
// The prefix is one of the language columns
if (in_array($prefix, $langcols)) {
// Not counted yet
if (!in_array($prefix, $cache[$table])) {
$cache[$table][] = $prefix;
}
// An ordinary prefix
} else {
$cache[$table][] = $cols[$i];
}
}
}
return $cache[$table];
}
// mysql_cols_of_type: Return the columns in a certain data type
function mysql_cols_of_type($result, $type, $format = SQL_FETCH_ASSOC)
{
$result_key = _mysql_result_hashkey($result);
// Cache the result
static $cache = array();
// Return the cache
if (array_key_exists($result_key, $cache)) {
return $cache[$result_key][$type][$format];
}
// Check each field type
$count = mysql_num_fields($result);
$cols = array(
SQL_TYPE_BOOLEAN => array(
SQL_FETCH_ASSOC => array(),
SQL_FETCH_ROW => array(),
),
SQL_TYPE_BLOB => array(
SQL_FETCH_ASSOC => array(),
SQL_FETCH_ROW => array(),
),
SQL_TYPE_INTEGER => array(
SQL_FETCH_ASSOC => array(),
SQL_FETCH_ROW => array(),
),
SQL_TYPE_BIGINT => array(
SQL_FETCH_ASSOC => array(),
SQL_FETCH_ROW => array(),
),
SQL_TYPE_FLOAT => array(
SQL_FETCH_ASSOC => array(),
SQL_FETCH_ROW => array(),
),
);
for ($i = 0; $i < $count; $i++) {
$coltype = mysql_field_type($result, $i);
$colname = mysql_field_name($result, $i);
$collen = mysql_field_len($result, $i);
if ($coltype == "string" && $collen == 0) {
$cols[SQL_TYPE_BOOLEAN][SQL_FETCH_ROW][] = $i;
$cols[SQL_TYPE_BOOLEAN][SQL_FETCH_ASSOC][] = $colname;
} elseif ($coltype == "blob") {
$cols[SQL_TYPE_BLOB][SQL_FETCH_ROW][] = $i;
$cols[SQL_TYPE_BLOB][SQL_FETCH_ASSOC][] = $colname;
} elseif ($coltype == "int" && $collen <= 11) {
$cols[SQL_TYPE_INTEGER][SQL_FETCH_ROW][] = $i;
$cols[SQL_TYPE_INTEGER][SQL_FETCH_ASSOC][] = $colname;
} elseif ($coltype == "int" && $collen == 20) {
$cols[SQL_TYPE_BIGINT][SQL_FETCH_ROW][] = $i;
$cols[SQL_TYPE_BIGINT][SQL_FETCH_ASSOC][] = $colname;
} elseif ($coltype == "real") {
$cols[SQL_TYPE_FLOAT][SQL_FETCH_ROW][] = $i;
$cols[SQL_TYPE_FLOAT][SQL_FETCH_ASSOC][] = $colname;
}
}
// Cache it
$cache[$result_key] = $cols;
return $cols[$type][$format];
}
// mysql_col_lens: Obtain the column lengths of a MySQL table
function mysql_col_lens($table)
{
// Cache the result
static $cache = array();
// Return the cache
if (array_key_exists($table, $cache)) {
return $cache[$table];
}
$select = "SELECT * FROM $table LIMIT 1;\n";
$result = xmysql_query($select);
$count = mysql_num_fields($result);
for ($i = 0, $cache[$table] = array(); $i < $count; $i++) {
$cache[$table][mysql_field_name($result, $i)] = mysql_field_len($result, $i);
}
// Hash the multi-lingual columns
$lndb = getlang(LN_DATABASE);
foreach (mysql_cols_ml($table) as $col) {
$cache[$table][$col] = $cache[$table][$col . "_" . $lndb];
}
return $cache[$table];
}
// mysql_strcat: Concatenate strings in MySQL
// MySQL uses the CONCAT() function to concatenate strings
function mysql_strcat()
{
$strs = func_get_args();
return "CONCAT(" . implode(", ", $strs) . ")";
}
// mysql_lastupd: Obtain the last updated time of a list of tables
function mysql_lastupd($tables)
{
// Bounce if no tables supplied
if (is_null($tables) || count($tables) == 0) {
return;
}
// Remove duplicates
$tables = array_values(array_unique($tables));
// Query
$conds = array();
foreach ($tables as $table) {
$conds[] = "tabname='" . mysql_escape_string($table) . "'";
}
$select = "SELECT mtime FROM mtime"
. " WHERE " . implode(" OR ", $conds)
. " ORDER BY mtime DESC LIMIT 1;\n";
$result = xmysql_query($select);
// Bounce if no data found
if (mysql_num_rows($result) != 1) {
return;
}
// Return the result
$row = xmysql_fetch_assoc($result);
return $row["mtime"];
}
// mysql_dbsize: Obtain the size of the database
function mysql_dbsize()
{
$select = "SHOW TABLE STATUS;\n";
$result = xmysql_query($select);
$count = mysql_num_rows($result);
for ($i = 0, $size = 0; $i < $count; $i++) {
$row = xmysql_fetch_row($result);
$size += $row["Data_length"];
}
return $size;
}
// mysql_date: Return date in a predefined format
function mysql_date($expr, $format)
{
switch ($format) {
case SQL_YYYYMMDD:
return "DATE_FORMAT($expr, '%Y%m%d')";
case SQL_YYYY_YYYYMMDD:
return "DATE_FORMAT($expr, '%Y/%Y%m%d')";
case SQL_MM_DD:
return "DATE_FORMAT($expr, '%m-%d')";
case SQL_M_D_EN:
return "DATE_FORMAT($expr, '%c/%e')";
case SQL_M_D_ZHTW:
return "DATE_FORMAT($expr, '%c月%e日')";
case SQL_M_D_DE:
return "DATE_FORMAT($expr, '%e.%c')";
case SQL_HH_MM:
return "TIME_FORMAT($expr, '%H:%i')";
}
}
// mysql_re: Return the MySQL regular expression operator
function mysql_re()
{
return "REGEXP";
}
// _mysql_result_hashkey: Generate a hash key from a MySQL query result
function _mysql_result_hashkey($result)
{
// Use the output of var_dump
ob_start();
var_dump($result);
$key = ob_get_contents();
ob_end_clean();
return $key;
}
// _mysql_locks2str: Convert lock array to SQL text string
function _mysql_locks2str($locks)
{
$reads = array();
$writes = array();
// Adjust the current lock table
foreach (array_keys($locks) as $table) {
switch ($locks[$table]) {
case LOCK_SH:
$reads[] = $table;
break;
case LOCK_EX:
$writes[] = $table;
break;
}
}
sort($reads);
sort($writes);
$phrases = array();
foreach ($writes as $table) {
$phrases[] = "$table WRITE";
}
foreach ($reads as $table) {
$phrases[] = "$table READ";
}
return implode(", ", $phrases);
}
?>

View File

@@ -0,0 +1,114 @@
<?php
// File name: newpass.inc.php
// Description: PHP subroutine to generate a new password
// Date: 2004-03-31
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2004-2009 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/cracklib.inc.php";
require_once "monica/runcmd.inc.php";
// Settings
define("NEWPASS_PRONOUNCABLE", 0);
define("NEWPASS_RANDOM", 1);
define("_NEWPASS_RANDOM_LEN", 8);
$_NEWPASS_APG = array("/usr/bin/apg", "-n", "1", "-d");
$_NEWPASS_BAD_CHARS = array("0", "O", "1", "l", "I", "|");
// newpass: Generate a new password
function newpass($mode = NEWPASS_PRONOUNCABLE)
{
switch ($mode) {
// A random password
case NEWPASS_RANDOM:
return _newpass_random();
break;
// A pronouncable password
case NEWPASS_PRONOUNCABLE:
default:
return _newpass_pronouncable();
break;
}
}
// _newpass_pronouncable: Generate a new pronouncable password
function _newpass_pronouncable()
{
global $_NEWPASS_BAD_CHARS, $_NEWPASS_APG;
// Loop until we get a good password
while (true) {
$passwd = xruncmd($_NEWPASS_APG, "");
// Avoid bad characters
if (_newpass_bad_char($passwd)) {
continue;
}
// Check the password strength with Cracklib
if (!crack_check($passwd)) {
continue;
}
return $passwd;
}
}
// _newpass_random: Generate a new random password
function _newpass_random()
{
global $_NEWPASS_BAD_CHARS;
// Loop until we get a good password
while (true) {
// Generate a password
$passwd = "";
while (strlen($passwd) < _NEWPASS_RANDOM_LEN) {
$type = mt_rand(0, 2);
switch ($type) {
// Number
case 0:
$c = mt_rand(0, 9);
break;
// Lower-case character
case 1:
$c = chr(ord("a") + mt_rand(0, 25));
break;
// Upper-case character
case 2:
$c = chr(ord("A") + mt_rand(0, 25));
break;
}
// Avoid bad characters
if (in_array($c, $_NEWPASS_BAD_CHARS)) {
continue;
}
$passwd .= $c;
}
// Check the password strength with Cracklib
if (!crack_check($passwd)) {
continue;
}
return $passwd;
}
}
// _newpass_bad_char: If the new password contains a bad character
function _newpass_bad_char($passwd)
{
global $_NEWPASS_BAD_CHARS;
for ($i = 0; $i < strlen($passwd); $i++) {
$c = substr($passwd, $i, 1);
// Found
if (in_array($c, $_NEWPASS_BAD_CHARS)) {
return true;
}
}
// Not found
return false;
}
?>

112
lib/php/monica/news.inc.php Normal file
View File

@@ -0,0 +1,112 @@
<?php
// File name: news.inc.php
// Description: PHP subroutines to handle news
// Date: 2006-03-17
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2006-2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/chkfunc.inc.php";
require_once "monica/commtext.inc.php";
require_once "monica/getlang.inc.php";
require_once "monica/lninfo.inc.php";
require_once "monica/sql.inc.php";
// news_title: Obtain the news article title
function news_title($sn)
{
// Cache the result
static $cache = array();
// Bounce if there is any problem with $sn
if (is_null($sn)) {
return t_notset();
}
// Return the cache
if (array_key_exists($sn, $cache)) {
return $cache[$sn];
}
// Check the serial number first
if (!check_sn($sn)) {
$cache[$sn] = t_na();
return $cache[$sn];
}
// Query
$lndb = getlang(LN_DATABASE);
// Default language
if (getlang() == DEFAULT_LANG) {
$title = sql_strcat("to_char(date, 'YYYY-MM-DD')", "' '",
"title_$lndb") . " AS title";
// Fall back to the default language
} else {
$lndbdef = ln(DEFAULT_LANG, LN_DATABASE);
$title = sql_strcat("to_char(date, 'YYYY-MM-DD')", "' '",
"COALESCE(title_$lndb, title_$lndbdef)") . " AS title";
}
$select = "SELECT $title FROM news"
. " WHERE sn=$sn;\n";
$result = sql_query($select);
// Not found
if (sql_num_rows($result) != 1) {
$cache[$sn] = t_na();
return $cache[$sn];
}
// Found
$row = sql_fetch_assoc($result);
$cache[$sn] = $row["title"];
return $cache[$sn];
}
// news_id: Obtain the news article ID.
function news_id($sn)
{
// Cache the result
static $cache = array();
// Bounce if there is any problem with $sn
if (is_null($sn)) {
return t_notset();
}
// Return the cache
if (array_key_exists($sn, $cache)) {
return $cache[$sn];
}
// Check the serial number first
if (!check_sn($sn)) {
$cache[$sn] = t_na();
return $cache[$sn];
}
// Query
$select = "SELECT date, ord FROM news"
. " WHERE sn=$sn;\n";
$result = sql_query($select);
// Not found
if (sql_num_rows($result) != 1) {
$cache[$sn] = t_na();
return $cache[$sn];
}
// Found
$row = sql_fetch_assoc($result);
$cache[$sn] = newsid_compose($row["date"], $row["ord"]);
return $cache[$sn];
}
// newsid_compose: Compose the news article ID
function newsid_compose($date, $ord)
{
return date("Ymd", strtotime($date)) . sprintf("%02d", $ord);
}
?>

View File

@@ -0,0 +1,40 @@
<?php
// File name: newsn.inc.php
// Description: PHP subroutine to generate a new random serial number
// Date: 2002-04-17
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2002-2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/sql.inc.php";
// new_sn: Generate a new random serial number for an SQL table
function new_sn($table)
{
// S/N is always 9 digits
do {
// Generate a random serial number
$sn = mt_rand(100000000, 999999999);
// Check if this serial number exists
$select = "SELECT sn FROM $table WHERE sn=$sn;\n";
$result = sql_query($select);
} while (sql_num_rows($result) > 0);
return $sn;
}
// new_sn_assoc: Generate a new random serial number for an associative array
function new_sn_assoc(&$assoc)
{
// S/N is always 9 digits
do {
// Generate a random serial number
$sn = mt_rand(100000000, 999999999);
} while (array_key_exists($sn, $assoc));
return $sn;
}
?>

329
lib/php/monica/page.inc.php Normal file
View File

@@ -0,0 +1,329 @@
<?php
// File name: page.inc.php
// Description: PHP classes to manage web pages
// Date: 2005-02-27
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2005-2008 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/getlang.inc.php";
require_once "monica/lninfo.inc.php";
require_once "monica/sql.inc.php";
// Page: A web page
class Page
{
protected $_title;
protected $_path;
protected $_ord;
protected $_lang;
protected $_sitemap;
protected $_sub;
// __construct: Initiate the web page
function __construct($args)
{
// An array of arguments
if (is_array($args)) {
// Set the title
if (!array_key_exists("title", $args)) {
trigger_error("Please specify the page title.", E_USER_ERROR);
}
$this->title($args["title"]);
// Set the page path
if (!array_key_exists("path", $args)) {
trigger_error("Please specify the page path.", E_USER_ERROR);
}
$this->path($args["path"]);
// Set the order
$this->ord(array_key_exists("ord", $args)? $args["ord"]: 5000);
// Set the language
$this->lang(array_key_exists("lang", $args)? $args["lang"]: null);
// Set if this page is to be shown on the site map
$this->sitemap(array_key_exists("sitemap", $args)?
$args["sitemap"]: true);
// A Page object
} elseif (strtolower(get_class($args)) == "page") {
$this->title($args->title());
$this->path($args->path());
$this->ord($args->ord());
$this->lang($args->lang());
$this->sitemap($args->sitemap());
// Invalid argument
} else {
trigger_error("Please specify the page arguments.", E_USER_ERROR);
}
}
// title: Set/return the page title
function title($title = null)
{
if (func_num_args() > 0) {
$this->_title = $title;
}
return $this->_title;
}
// path: Set/return the page path
function path($path = null)
{
if (func_num_args() > 0) {
$this->_path = $path;
}
return $this->_path;
}
// ord: Set/return the page order
function ord($ord = null)
{
if (func_num_args() > 0) {
$this->_ord = $ord;
}
return $this->_ord;
}
// lang: Set/return the page language
function lang($lang = null)
{
if (func_num_args() > 0) {
// Delete it
if (is_null($lang)) {
$this->_lang = null;
// Set it
} else {
$this->_lang = $lang;
}
}
return $this->_lang;
}
// sitemap: Set/return if this page is to be shown on the site map
function sitemap($sitemap = true)
{
if (func_num_args() > 0) {
$this->_sitemap = $sitemap;
}
return $this->_sitemap;
}
// sub: Set/return the pages under this page
function sub($pagelist = null)
{
if (func_num_args() > 0) {
// Delete it
if (is_null($pagelist)) {
$this->_sub = null;
// Set it
} else {
// We only accept a PageList object
if (strtolower(get_class($pagelist)) != "pagelist") {
trigger_error("The sub() method of a Page object only accepts a PageList object.", E_USER_ERROR);
}
$this->_sub = $pagelist;
$index = new Page($this);
$index->sub(null);
$this->_sub->index($index);
}
}
return $this->_sub;
}
// compare_to: Compare the order with another page
function compare_to($another)
{
// We only compare to another Selima::Page object
if (strtolower(get_class($another)) != "page") {
trigger_error("The compare_to() method of a Page object only accepts another Page object.", E_USER_ERROR);
}
// Check the page order
if ($this->ord() != $another->ord()) {
return ($this->ord() < $another->ord()? -1: 1);
}
// Check the page path
if ($this->path() != $another->path()) {
return strcmp($this->path(), $another->path());
}
// Check the page title (should not)
if ($this->title() != $another->title()) {
return strcmp($this->title(), $another->title());
}
// Equal
return 0;
}
// fetch_subtree: Fetch the sub page tree from the database
function fetch_subtree()
{
// Not a directory - there is no sub page tree for them
if (substr($this->path(), -1) != "/") {
return;
}
// Compose the SQL statement
$cols = array();
if (count($GLOBALS["ALL_LINGUAS"]) > 1) {
$lndb = ln($this->lang(), LN_DATABASE);
$cols[] = "title_$lndb AS title";
} else {
$cols[] = "title AS title";
}
$cols[] = "ord AS ord";
$cols[] = "path AS path";
if (count($GLOBALS["ALL_LINGUAS"]) > 1) {
$cols[] = "'" . sql_esctext($this->lang()) . "' AS lang";
} else {
$cols[] = "'" . sql_esctext(getlang()) . "' AS lang";
}
$select = "SELECT " . implode(", ", $cols) . " FROM pages"
. " WHERE " . sql_is_false("hid")
. " AND path LIKE '" . sql_esclike($this->path()) . "_%'"
. " AND path NOT LIKE '" . sql_esclike($this->path()) . "_%/_%';\n";
$result = sql_query($select);
$count = sql_num_rows($result);
for ($i = 0, $pages = array(); $i < $count; $i++) {
$row = sql_fetch_assoc($result);
$pages[] = new Page($row);
}
// Recursively fetch the sub page tree
for ($i = 0; $i < count($pages); $i++) {
$pages[$i]->fetch_subtree();
}
// Save it
$this->sub(new PageList($pages));
return;
}
// fetch_full_page_tree: Fetch the full page tree from the database
static function fetch_full_page_tree($lang = null)
{
// Get the available language list
global $ALL_LINGUAS;
// Cache the result
static $tree = null;
// The language
if (is_null($lang)) {
$lang = getlang();
}
// Multi-lingual - obtain each language tree
if (count($ALL_LINGUAS) > 0) {
if (is_null($tree)) {
$tree = array();
}
// Not cached yet
if (!array_key_exists($lang, $tree)) {
$tree[$lang] = new Page(array(
"title" => "",
"path" => "/",
"ord" => 5000,
"lang" => $lang,
));
$tree[$lang]->fetch_subtree();
}
return $tree[$lang];
// Uni-lingual
} else {
// Not cached yet
if (is_null($tree)) {
$tree = new Page(array(
"title" => "",
"path" => "/",
"ord" => 5000,
"lang" => $lang,
));
$tree->fetch_subtree();
}
return $tree;
}
}
// neighbor_pages: Obtain the neighbor pages for a specific page path
static function neighbor_pages($path, $lang = null)
{
// Obtain the full apge tree
$tree = self::fetch_full_page_tree($lang);
// Obtain each level of directories
$dirs = array();
while ($path = preg_replace("/\/[^\/]+\/?$/", "/", $path)) {
array_unshift($dirs, $path);
}
// Nothing - path is "/" (root directory)
if (count($dirs) == 0) {
return $tree->sub();
}
}
}
// PageList: A list of web pages
class PageList
{
protected $_index = null;
protected $_pages = array();
// __construct: Initiate the list of web pages
function __construct($pages)
{
$this->_pages = array();
$this->add($pages);
}
// add: Add web pages to the page list
function add($pages)
{
// Add all the pages
for ($i = 0; $i < count($pages); $i++) {
// We only accept Page objects
if (strtolower(get_class($pages[$i])) != "page") {
trigger_error("The add() method of a PageList object only accepts Page objects.", E_USER_ERROR);
}
// Find the page after the added page
for ($j = 0; $j < count($this->_pages); $j++) {
if ($pages[$i]->compare_to($this->_pages[$j]) < 0) {
break;
}
}
// Insert the page
$this->_pages = array_merge(
array_slice($this->_pages, 0, $j),
array($pages[$i]),
array_slice($this->_pages, $j)
);
}
return;
}
// index: Set/return the index page
function index($page)
{
if (func_num_args() > 0) {
// Delete it
if (is_null($page)) {
$this->_index = null;
// Set it
} else {
// We only accept a Page object
if (strtolower(get_class($page)) != "page") {
trigger_error("The index() method of a PageList object only accepts a Page object.", E_USER_ERROR);
}
$this->_index = $page;
}
}
return $this->_index;
}
// pages: Return the pages
function pages()
{
return $this->_pages;
}
}
?>

View File

@@ -0,0 +1,331 @@
<?php
// File name: page2rel.inc.php
// Description: PHP subroutine to convert URLs in a page to relative
// Date: 2003-09-09
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2003-2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/htmlchar.inc.php";
require_once "monica/rel2abs.inc.php";
// Settings
define("_PAGE2REL_2REL", true);
define("_PAGE2REL_2ABS", false);
// page2rel: Convert URLs in a page to relative
function page2rel($html, $base)
{
return _page2rel_cnvturl($html, $base, _PAGE2REL_2REL, null);
}
// page2abs: Convert URLs in a page to absolute
function page2abs($html, $base, $rdiff = REL2ABS_RDIFF_KEEP)
{
return _page2rel_cnvturl($html, $base, _PAGE2REL_2ABS, $rdiff);
}
// _page2rel_cnvturl: Convert URLs in a page to relative/absolute
function _page2rel_cnvturl($source, $base, $is_rel, $rdiff)
{
$result = "";
while (preg_match("/^(.*?)(<!--.*?-->|<[a-z]+\d?(?:\s+[a-z\-]+=(?:\"[^\"]*\"|'[^']*'|[^\"'\s<>]+))*(?:\s+\/)?>|<\?xml-stylesheet(?:\s+[a-z\-]+=(?:\"[^\"]*\"|'[^']*'|[^\"'\s<>]+))*\s*\?>)(.*)$/is", $source, $m)) {
$result .= $m[1];
$ele = $m[2];
$source = $m[3];
// Skip if not a relevant element
if ( !preg_match("/^<((a|applet|area|base|embed|form|frame|img|input|link|object|param|script|style)\s+)(.+?)>$/is", $ele, $m)
&& !preg_match("/^<((\?xml-stylesheet)\s+)(.+?)\?>$/s", $ele, $m)) {
$result .= $ele;
continue;
}
$elepref = $m[1];
$elename = $m[2];
$elebody = $m[3];
switch (strtolower($elename)) {
case "a":
case "area":
case "base":
case "link":
$elebody = _page2rel_cnvtatt($elebody, "href", $base, $is_rel, $rdiff);
$result .= "<" . $elepref . $elebody . ">";
break;
case "img":
case "input":
case "embed":
case "frame":
$elebody = _page2rel_cnvtatt($elebody, "src", $base, $is_rel, $rdiff);
$result .= "<" . $elepref . $elebody . ">";
break;
case "form":
$elebody = _page2rel_cnvtatt($elebody, "action", $base, $is_rel, $rdiff);
$result .= "<" . $elepref . $elebody . ">";
break;
case "applet":
$elebody = _page2rel_cnvtatt($elebody, "codebase", $base, $is_rel, $rdiff);
$result .= "<" . $elepref . $elebody . ">";
break;
case "object":
$elebody = _page2rel_cnvtatt($elebody, "classid", $base, $is_rel, $rdiff);
$elebody = _page2rel_cnvtatt($elebody, "codebase", $base, $is_rel, $rdiff);
$elebody = _page2rel_cnvtatt($elebody, "data", $base, $is_rel, $rdiff);
$result .= "<" . $elepref . $elebody . ">";
break;
case "script":
$elebody = _page2rel_cnvtatt($elebody, "src", $base, $is_rel, $rdiff);
$result .= "<" . $elepref . $elebody . ">";
$type = strtolower(_page2rel_attval($elebody, "type"));
// Compatibility with the old "language" attribute
if (is_null($type)) {
$scptlang = strtolower(_page2rel_attval($elebody, "language"));
switch ($scptlang) {
case "javascript":
$type = "text/javascript";
break;
case "vbscript":
case "vbs":
$type = "text/vbscript";
break;
case "perlscript":
$type = "text/perlscript";
break;
}
}
switch ($type) {
case "text/javascript":
default:
$m = _page2rel_foreign_js($source);
break;
case "text/vbscript":
case "text/vbs":
$m = _page2rel_foreign_vbs($source);
break;
case "text/perlscript":
$m = _page2rel_foreign_pls($source);
break;
}
$result .= $m[0];
$source = $m[1];
break;
case "style":
$result .= $ele;
$type = strtolower(_page2rel_attval($elebody, "type"));
switch ($type) {
case "text/css":
default:
$m = _page2rel_foreign_css($source, $base, $is_rel, $rdiff);
break;
case "text/javascript":
$m = _page2rel_foreign_jsss($source);
break;
}
$result .= $m[0];
$source = $m[1];
break;
case "param":
$name = strtolower(_page2rel_attval($elebody, "name"));
if (in_array($name, array("src", "movie", "filename"))) {
$elebody = _page2rel_cnvtatt($elebody, "value", $base, $is_rel, $rdiff);
}
$result .= "<" . $elepref . $elebody . ">";
break;
case "?xml-stylesheet":
$elebody = _page2rel_cnvtatt($elebody, "href", $base, $is_rel, $rdiff);
$result .= "<" . $elepref . $elebody . "?>";
break;
}
}
// Append the remains
$result .= $source;
return $result;
}
// _page2rel_cnvtatt: Convert URLs in HTML abbitutes to relative/absolute
function _page2rel_cnvtatt($source, $att, $base, $is_rel, $rdiff)
{
$result = "";
while ($source != "" && preg_match("/^([^\"'\s]*(?:(?:\"[^\"]*\"|'[^']*')[^\"'\s]*)*)(\s*)(.*?)$/s", $source, $m)) {
$piece = $m[1];
$sep = $m[2];
$source = $m[3];
// Skip if not in the attribute="value" format
if ( !(preg_match("/^($att)=(\")([^\"]*)\"$/i", $piece, $m)
|| preg_match("/^($att)=(')([^']*)'$/i", $piece, $m)
|| preg_match("/^($att)=()([^\"']+)$/i", $piece, $m))) {
$result .= $piece . $sep;
continue;
}
$thisatt = $m[1];
$quote = $m[2];
$url = $m[3];
// $url is a variable to be replaces dynamically, as in error pages
if ($url != "\$url") {
$url = $is_rel? abs2rel($url, $base):
rel2abs($url, $base, REL2ABS_SKIP_FRAGMENT, REL2ABS_NO_HOST, $rdiff);
}
$result .= $thisatt . "=" . $quote . $url . $quote. $sep;
}
return $result;
}
// _page2rel_attval: Obtain the value of a attribute
function _page2rel_attval($elebody, $att)
{
$att = strtolower($att);
$val = null;
while ($elebody != "" && preg_match("/^([^\"'\s]*(?:(?:\"[^\"]*\"|'[^']*')[^\"'\s]*)*)(\s*)(.*?)$/s", $elebody, $m)) {
$piece = $m[1];
$elebody = $m[3];
// Skip if not in the attribute="value" format
if ( !(preg_match("/^($att)=(\")([^\"]*)\"$/i", $piece, $m)
|| preg_match("/^($att)=(')([^']*)'$/i", $piece, $m)
|| preg_match("/^($att)=()([^\"']+)$/i", $piece, $m))) {
continue;
}
$thisatt = $m[1];
$thisval = dh($m[3]);
if (strtolower($thisatt) == $att) {
$val = $thisval;
}
}
return $val;
}
// _page2rel_foreign_js: Skip the next javascript block
function _page2rel_foreign_js($html)
{
$block = "";
$ended = false;
while (preg_match("/^(.*?)(\"(?:[^\\\\\"]|\\\\.)*\"|'(?:[^\\\\']|\\\\.)*'|\/\*.*?\*\/|\/\/[^\n]*|<\/script>)(.*)$/is", $html, $m)) {
// The end of the block
if (strtolower($m[2]) == "</script>") {
$block .= $m[1];
$html = $m[2] . $m[3];
$ended = true;
break;
}
// Add this block
$block .= $m[1] . $m[2];
$html = $m[3];
}
// Not ended at last
if (!$ended) {
$block .= $html;
$html = "";
}
return array($block, $html);
}
// _page2rel_foreign_vbs: Skip the next vbscript block
function _page2rel_foreign_vbs($html)
{
$block = "";
$ended = false;
while (preg_match("/^(.*?)(\"(?:[^\"]|\"\")*\"|[:\n]\s*Rem\b[^\n]*|'[^\n]*|<\/script>)(.*)$/is", $html, $m)) {
// The end of the block
if (strtolower($m[2]) == "</script>") {
$block .= $m[1];
$html = $m[2] . $m[3];
$ended = true;
break;
}
// Add this block
$block .= $m[1] . $m[2];
$html = $m[3];
}
// Not ended at last
if (!$ended) {
$block .= $html;
$html = "";
}
return array($block, $html);
}
// _page2rel_foreign_css: Skip the next cascading stylesheet block
function _page2rel_foreign_css($html, $base, $is_rel, $rdiff)
{
$block = "";
$ended = false;
while (preg_match("/^(.*?)(\"(?:[^\\\\\"]|\\\\.)*\"|'(?:[^\\\\']|\\\\.)*'|\/\*.*?\*\/|<\/style>)(.*)$/is", $html, $m)) {
// The end of the block
if (strtolower($m[2]) == "</style>") {
$block .= $m[1];
$html = $m[2] . $m[3];
$ended = true;
break;
}
// Add this block
$block .= $m[1] . $m[2];
$html = $m[3];
}
// Not ended at last
if (!$ended) {
$block .= $html;
$html = "";
}
// Convert URLs in the CSS block
$block = _page2rel_foreign_cssurls($block, $base, $is_rel, $rdiff);
return array($block, $html);
}
// _page2rel_foreign_cssurls: Convert URLs in a CSS block
function _page2rel_foreign_cssurls($source, $base, $is_rel, $rdiff)
{
$result = "";
while (preg_match("/^(.*?)(\burl\([^\"']*\)|\burl\(\"(?:[^\\\\\"]|\\\\.)*\"\)|\burl\('(?:[^\\\\']|\\\\.)*'\)|\"(?:[^\\\\\"]|\\\\.)*\"|'(?:[^\\\\']|\\\\.)*'|\/\*.*?\*\/)(.*)$/is", $source, $m)) {
$result .= $m[1];
$piece = $m[2];
$source = $m[3];
// An URL
if ( preg_match("/^(url\()(\")((?:[^\\\\\"]|\\\\.)*)\"(\))$/i", $piece, $m)
|| preg_match("/^(url\()(')((?:[^\\\\']|\\\\.)*)'(\))$/i", $piece, $m)
|| preg_match("/^(url\()()([^\"']*)(\))$/i", $piece, $m)) {
$m[3] = $is_rel? abs2rel($m[3], $base):
rel2abs($m[3], $base, REL2ABS_SKIP_FRAGMENT, REL2ABS_NO_HOST, $rdiff);
$piece = $m[1] . $m[2] . $m[3] . $m[2] . $m[4];
}
$result .= $piece;
}
// Append the remains
$result .= $source;
return $result;
}
// _page2rel_foreign_jsss: Skip the next javascript stylesheet block
function _page2rel_foreign_jsss($html)
{
$block = "";
$ended = false;
while (preg_match("/^(.*?)(\"(?:[^\\\\\"]|\\\\.)*\"|'(?:[^\\\\']|\\\\.)*'|\/\*.*?\*\/|\/\/[^\n]*|<\/script>)(.*)$/is", $html, $m)) {
// The end of the block
if (strtolower($m[2]) == "</style>") {
$block .= $m[1];
$html = $m[2] . $m[3];
$ended = true;
break;
}
// Add this block
$block .= $m[1] . $m[2];
$html = $m[3];
}
// Not ended at last
if (!$ended) {
$block .= $html;
$html = "";
}
return array($block, $html);
}
?>

View File

@@ -0,0 +1,775 @@
<?php
// File name: pagefunc.inc.php
// Description: PHP subroutines to handle pages
// Date: 2003-07-10
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2003-2009 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/altlang.inc.php";
require_once "monica/chkfunc.inc.php";
require_once "monica/commtext.inc.php";
require_once "monica/echoform.inc.php";
require_once "monica/errhndl.inc.php";
require_once "monica/getlang.inc.php";
require_once "monica/gettext.inc.php";
require_once "monica/lninfo.inc.php";
require_once "monica/mkalldir.inc.php";
require_once "monica/page2rel.inc.php";
require_once "monica/rel2abs.inc.php";
require_once "monica/requri.inc.php";
require_once "monica/rmalldir.inc.php";
require_once "monica/scptpriv.inc.php";
require_once "monica/sql.inc.php";
require_once "monica/unicode.inc.php";
require_once "monica/xfileio.inc.php";
// page_param: Gather the HTML parameters
function page_param($args = null)
{
// Default to an empty array
if (is_null($args)) {
$args = array();
}
// It is already fixed
if (array_key_exists(".fixed", $args)) {
return $args;
}
// Obtain page parameters
if (array_key_exists("PAGE_PARAM", $GLOBALS)) {
$args = array_merge($args, $GLOBALS["PAGE_PARAM"]);
}
if (array_key_exists("ALT_PAGE_PARAM", $GLOBALS)) {
$args = array_merge($args, $GLOBALS["ALT_PAGE_PARAM"]);
}
// Set the path
if (!array_key_exists("path", $args)) {
$args["path"] = REQUEST_PATH;
}
// Set the language
if (!array_key_exists("lang", $args)) {
$args["lang"] = getlang();
}
// Set if static or not
if (!array_key_exists("static", $args)) {
$args["static"] = false;
}
// Set if show a pretty result or not
if (!array_key_exists("clean", $args)) {
$args["clean"] = false;
}
// Set if this page is administrative
if (!array_key_exists("admin", $args)) {
$args["admin"] = is_admin_script($args["path"]);
}
// Set if UTF-8 or not
if (!array_key_exists("utf8", $args)) {
$args["utf8"] = false;
}
// Set if this is a preview page or not
if (!array_key_exists("preview", $args)) {
$args["preview"] = null;
}
// Set if we shoud show the tite in html_header() or not
if (!array_key_exists("no_auto_title", $args)) {
$args["no_auto_title"] = false;
}
// Set if MathML is used or not
if (!array_key_exists("mathml", $args)) {
if ( !is_null($args["preview"])
&& array_key_exists("mathml", $args["preview"])) {
$args["mathml"] = $args["preview"]? true: false;
} else {
$args["mathml"] = false;
}
}
// Set all the available languages
if (!array_key_exists("all_linguas", $args)) {
$args["all_linguas"] = $GLOBALS["ALL_LINGUAS"];
}
// Set the language of the title
if (!array_key_exists("title_lang", $args)) {
$args["title_lang"] = $args["lang"];
}
// The upper level index page
if (!array_key_exists("up", $args)) {
$langfile = ln($args["lang"], LN_FILENAME);
// Certain pages that has no upper level index page
$rootdir = preg_replace("/^\/$langfile\/([^\/]*\/?).*?$/", "$1", $args["path"]);
switch ($rootdir) {
case "errors/":
case "longdesc/":
break;
default:
// See the directory where I belongs
$args["up"] = preg_replace("/[^\/]+\/?$/", "", $args["path"]);
// The home page path
$home = count($GLOBALS["ALL_LINGUAS"]) > 1? "/$langfile/": "/";
// Above the home -- go to the home page
if (substr($args["up"], 0, strlen($home)) != $home) {
$args["up"] = $home;
}
}
}
// Set the URLs of the language variants
if (!array_key_exists("altlang", $args)) {
set_altlang_urls($args);
}
// Load the local extension
if (function_exists("page_param_site")) {
$args = page_param_site($args);
}
if (function_exists("page_param_script")) {
$args = page_param_script($args);
}
// Tag that we have fixed this
$args[".fixed"] = true;
return $args;
}
// page_tree: Get the page tree in a directory
function page_tree($path, $lang, $preview = null)
{
// Get the available language list
global $ALL_LINGUAS;
// Set the language
$langfile = ln($lang, LN_FILENAME);
$lndb = ln($lang, LN_DATABASE);
$islnpre = preg_match("/^\/$langfile\//", $path)? true: false;
$lnpre = $islnpre? "/$langfile": "";
// Obtain the directory
$dir = preg_replace("/[^\/]*$/", "", $path);
if ($islnpre) {
$dir = preg_replace("/^\/$langfile/", "", $dir);
}
// Cache the result
static $cache = array();
// Initialize the directory array
if (!array_key_exists($dir, $cache)) {
$cache[$dir] = array();
}
// Return the cache
if (array_key_exists($lang, $cache[$dir])) {
return $cache[$dir][$lang];
}
// Initialize the result
$tree = array();
// Disable the page tree of error documents
if ($dir == "/errors/") {
$_path = $path;
if ($islnpre) {
$_path = preg_replace("/^\/$langfile/", "", $_path);
}
$title = count($ALL_LINGUAS) > 1? "title_$lndb": "title";
$select = "SELECT $title AS title from pages"
. " WHERE path='" . sql_esctext($_path) . "';\n";
$result = sql_query($select);
$row = sql_fetch_assoc($result);
$tree["index"] = array(
"path" => $path,
"_path" => $_path,
"title" => $row["title"]);
return $tree;
}
// Get the index page
$conds = array();
$conds[] = "path='" . sql_esctext($dir) . "'";
if (count($ALL_LINGUAS) > 1) {
$conds[] = "title_$lndb IS NOT NULL";
}
$conds[] = sql_is_false("hid");
$select = "SELECT * from pages"
. " WHERE " . implode(" AND ", $conds) . ";\n";
$result = sql_query($select);
$count = sql_num_rows($result);
// Index page exists
if ($count == 1) {
$row = sql_fetch_assoc($result);
$tree["index"] = array(
"path" => $lnpre . $dir,
"_path" => $dir,
"title" => count($ALL_LINGUAS) > 1?
$row["title_$lndb"]: $row["title"]);
}
// Get the page tree
$pages = _page_tree($dir, $lang, $lnpre, $preview);
if (!is_null($pages)) {
$tree["pages"] =& $pages;
}
// Nothing found
if ( !array_key_exists("index", $tree)
&& !array_key_exists("pages", $tree)) {
$cache[$dir][$lang] = null;
return null;
}
// Cache it
$cache[$dir][$lang] = $tree;
return $tree;
}
// _page_tree: Get the page tree
function _page_tree($dir, $lang, $lnpre, $preview = null)
{
// Get the available language list
global $ALL_LINGUAS;
// Cache the result
static $cache = array();
// Initialize the directory array
if (!array_key_exists($dir, $cache)) {
$cache[$dir] = array();
}
// Return the cache
if (array_key_exists($lang, $cache[$dir])) {
return $cache[$dir][$lang];
}
// Set the language
$lndb = ln($lang, LN_DATABASE);
// Get the related pages
$tree = array();
// Set the columns list
$cols = array();
if ($lnpre == "") {
$cols[] = "path AS path";
} else {
$cols[] = sql_strcat("'$lnpre'", "path") . " AS path";
}
$cols[] = "path AS _path";
if (count($ALL_LINGUAS) > 1) {
$cols[] = "title_$lndb AS title";
} else {
$cols[] = "title AS title";
}
$cols[] = "ord AS ord";
// Set the criteria
$conds = array();
$conds[] = "path LIKE '" . sql_esclike($dir) . "_%'";
$conds[] = "path NOT LIKE '" . sql_esclike($dir) . "_%/_%'";
if (count($ALL_LINGUAS) > 1) {
$conds[] = "title_$lndb IS NOT NULL";
}
// Skip the original file
if (!is_null($preview) && array_key_exists("sn", $preview)) {
$conds[] = "sn!=" . $preview["sn"];
}
// Set the order key
$orderbys = array();
$orderbys[] = "ord";
if (count($ALL_LINGUAS) > 1) {
$orderbys[] = "title_$lndb";
} else {
$orderbys[] = "title";
}
$orderbys[] = "path";
$conds[] = sql_is_false("hid");
$select = "SELECT " . implode(", ", $cols) . " FROM pages"
. " WHERE " . implode(" AND ", $conds)
. " ORDER BY " . implode(", ", $orderbys) . ";\n";
$result = sql_query($select);
$count = sql_num_rows($result);
for ($i = 0; $i < $count; $i++) {
$tree[] = sql_fetch_assoc($result);
}
// Insert the preview
if (!is_null($preview) && dirname($preview["path"]) . "/" == $dir) {
array_push($tree, array(
"path" => $lnpre . $preview["path"],
"_path" => $preview["path"],
"title" => $preview["title"],
"ord" => $preview["ord"]
));
// Sort again
usort($tree, "cmp_page_tree");
}
// Recur into subdirectories
for ($i = 0; $i < count($tree); $i++) {
if (substr($tree[$i]["path"], -1) != "/") {
continue;
}
$tree[$i]["sub"] = array();
$tree[$i]["sub"]["index"] = array(
"path" => $tree[$i]["path"],
"_path" => $tree[$i]["_path"],
"title" => $tree[$i]["title"]
);
$subtree = _page_tree($tree[$i]["_path"], $lang, $lnpre, $preview);
if (!is_null($subtree)) {
$tree[$i]["sub"]["pages"] = $subtree;
}
}
// Nothing found
if (count($tree) == 0) {
$cache[$dir][$lang] = null;
return null;
}
// Cache it
$cache[$dir][$lang] = $tree;
return $tree;
}
// cmp_page_tree: Sort the page tree again after inserting a preview
function cmp_page_tree($page1, $page2)
{
// Compare the order
if ($page1["ord"] != $page2["ord"]) {
return $page1["ord"] - $page2["ord"];
}
// Compare the title
if ($page1["title"] != $page2["title"]) {
return strcmp($page1["title"], $page2["title"]);
}
// Compare the path
return strcmp($page1["path"], $page2["path"]);
}
// hash_tree: Make a hash of the page tree
function hash_tree(&$tree)
{
$hash = array();
// The index page
if (array_key_exists("index", $tree)) {
$hash[$tree["index"]["path"]] =& $tree;
}
// Track the subdirectories
if (array_key_exists("pages", $tree)) {
for ($i = 0; $i < count($tree["pages"]); $i++) {
// A subdirectory exists
if (array_key_exists("sub", $tree["pages"][$i])) {
$hash = array_merge($hash,
hash_tree($tree["pages"][$i]["sub"]));
}
}
}
return $hash;
}
// hash_page: Make a hash of the page tree
function hash_page(&$tree)
{
$hash = array();
// The index page
if (array_key_exists("index", $tree)) {
$hash[$tree["index"]["path"]] =& $tree["index"];
}
// Track the subdirectories
if (array_key_exists("pages", $tree)) {
for ($i = 0; $i < count($tree["pages"]); $i++) {
// A plain page
if (!array_key_exists("sub", $tree["pages"][$i])) {
$hash[$tree["pages"][$i]["path"]] =& $tree["pages"][$i];
// A subdirectory
} else {
$hash = array_merge($hash,
hash_page($tree["pages"][$i]["sub"]));
}
}
}
return $hash;
}
// page_all_linguas: Get the available languages for this page
function page_all_linguas($page)
{
// Get the available language list
global $ALL_LINGUAS;
// It is specified
if (array_key_exists("all_linguas", $page)) {
return $page["all_linguas"];
}
// Preview
if (array_key_exists("preview", $page) && $page["preview"]) {
// Uni-lingual
if (!sql_is_ml_table(THIS_TABLE)) {
return array(getlang());
}
// Find the page
if (!array_key_exists("sn", $page)) {
return array(getlang());
}
$select = "SELECT * FROM " . THIS_TABLE
. " WHERE sn=" . $page["sn"] . ";\n";
$result = sql_query($select);
// If this record exist
if (sql_num_rows($result) == 0) {
return array(getlang());
}
$row = sql_fetch_assoc($result);
// Check each language
$page_all_linguas = array();
for ($l = 0; $l < count($ALL_LINGUAS); $l++) {
$lang = $ALL_LINGUAS[$l];
$lndb = ln($lang, LN_DATABASE);
// Add it if the content in this language exists
if (!is_null($row["title_$lndb"]) || $lang == getlang()) {
$page_all_linguas[] = $lang;
}
}
return $page_all_linguas;
}
// $page is uni-lingual
if (array_key_exists("title", $page)) {
return array(getlang());
}
// $page is multi-lingual
// Check each language
$page_all_linguas = array();
for ($l = 0; $l < count($ALL_LINGUAS); $l++) {
$lang = $ALL_LINGUAS[$l];
$lndb = ln($lang, LN_DATABASE);
// Add it if the content in this language exists
if (!is_null($page["title_$lndb"])) {
$page_all_linguas[] = $lang;
}
}
return $page_all_linguas;
}
// outpage: Output a page
function outpage($content, $path, $lang = null)
{
if (is_null($lang)) {
$lang = getlang();
}
$langfile = ln($lang, LN_FILENAME);
// An HTML file or directory index
if (substr($path, -5) == ".html" || substr($path, -1) == "/") {
// The page path in multi-lingual context
$lnpath = (count($GLOBALS["ALL_LINGUAS"]) > 1)?
"/$langfile$path": $path;
// Convert the URLs to relative
if (substr($path, 0, 8) == "/errors/") {
$content = page2abs($content, $lnpath, REL2ABS_RDIFF_STRIP);
// $url variable is handled inside of page2abs();
} else {
$content = page2rel($content, $lnpath);
}
// Encode the e-mail at-signs (@)
$content = str_replace("@", "&#64;", $content);
// Decode the e-mail at-signs (@) of spamtrap
$content = str_replace("spamtrap&#64;", "spamtrap@", $content);
// Encode the page to the target character set
$content = page_encode($content, ln($lang, LN_CHARSET));
// Obtain the real file name
$file = DOC_ROOT . $lnpath;
if (substr($file, -1) == "/") {
$file .= "index.html";
}
// Create the necessary directories
mkalldir(dirname($file));
// Write the file
xfupdate_template("$file.xhtml", $content);
// Make the symbolic link for the text/html
$targfile = basename("$file.xhtml");
$linkfile = "$file.html";
if (!is_link($linkfile) || readlink($linkfile) != $targfile) {
if (file_exists($linkfile)) {
if (is_dir($linkfile)) {
rmalldir($linkfile);
} else {
unlink($linkfile);
}
}
symlink($targfile, $linkfile);
}
// An RSS file or OpenSearch description document
} elseif (substr($path, -8) == "/rss.xml" || substr($path, -7) == "osd.xml") {
// The page path in multi-lingual context
$lnpath = (count($GLOBALS["ALL_LINGUAS"]) > 1)?
"/$langfile$path": $path;
// Encode the e-mail at-signs (@)
$content = str_replace("@", "&#64;", $content);
// Decode the e-mail at-signs (@) of spamtrap
$content = str_replace("spamtrap&#64;", "spamtrap@", $content);
// Encode the page to the target character set
// XML is not HTML, so HTML character entity reference should not be used.
$content = page_encode($content, ln($lang, LN_CHARSET), UNICODE_NO_HCEREF);
// Obtain the real file name
$file = DOC_ROOT . $lnpath;
// Create the necessary directories
mkalldir(dirname($file));
// Write the file
xfupdate_template($file, $content);
// A text file
} elseif (substr($path, -4) == ".txt") {
// The page path in multi-lingual context
$lnpath = (count($GLOBALS["ALL_LINGUAS"]) > 1)?
"/$langfile$path": $path;
// We do not encode to a target character set. This is not always
// possible for plain text files and hence not quite useful.
// Hence the output are always in UTF-8.
// Encode the e-mail at-signs (@)
$content = str_replace("@", "-at-", $content);
// Obtain the real file name
$file = DOC_ROOT . $lnpath;
// Create the necessary directories
mkalldir(dirname($file));
// Write the file
xfupdate_template($file, $content);
// A PDF file
} elseif (substr($path, -4) == ".pdf") {
// The page path in multi-lingual context
$lnpath = (count($GLOBALS["ALL_LINGUAS"]) > 1)?
"/$langfile$path": $path;
// Obtain the real file name
$file = DOC_ROOT . $lnpath;
// Create the necessary directories
mkalldir(dirname($file));
// Write the file
xfupdate($file, $content);
// A JavaScript file
} elseif (substr($path, -3) == ".js") {
// The page path in multi-lingual context
$lnpath = (count($GLOBALS["ALL_LINGUAS"]) > 1)?
substr($path, 0, -3) . ".$langfile.js": $path;
// Encode the e-mail at-signs (@)
$content = str_replace("@", "&#64;", $content);
// Encode the page to the target character set
$content = page_encode($content, ln($lang, LN_CHARSET));
// Obtain the real file name
$file = DOC_ROOT . $lnpath;
// Create the necessary directories
mkalldir(dirname($file));
// Write the file
xfupdate_template($file, $content);
}
return;
}
// readpage: Read from an include page
function readpage($path, $lang = null)
{
if (is_null($lang)) {
$lang = getlang();
}
$charset = ln($lang, LN_CHARSET);
$file = DOC_ROOT . $path;
if (count($GLOBALS["ALL_LINGUAS"]) > 1) {
$file = sprintf($file, ln($lang, LN_FILENAME));
}
$content = xfread($file);
// Try to decode with the specified encoding
$GLOBALS["php_errormsg"] = null;
set_error_handler("null_error_handler");
$content = iconv($charset, "UTF-8", $content);
restore_error_handler();
// Wrong encoding
if (!is_null($GLOBALS["php_errormsg"])) {
trigger_error("Failed decoding $file as $charset", E_USER_ERROR);
// In case when error handler is disabled
return null;
}
// An HTML file or XHTML file
if (substr($file, -5) == ".html" || substr($file, -6) == ".xhtml") {
// Decode the HTML character references
$content = a_hcref2char($content);
}
return $content;
}
// array_keys_ml: Return a list of multi-lingual keys in an associative array
function array_keys_ml(&$arr)
{
// Get the columns that have language variants
$suffix = "_" . getlang(LN_DATABASE);
$len = strlen($suffix);
$keys = array_keys($arr);
$mlkeys = array();
for ($i = 0; $i < count($keys); $i++) {
// It has a language suffix
if (substr($keys[$i], -$len) == $suffix) {
$mlkeys[] = substr($keys[$i], 0, -$len);
}
}
return $mlkeys;
}
// array_keys_nl: Return a list of keys without their multi-lingual
// deviants in an associative array
function array_keys_nl(&$arr)
{
$keys = array_keys($arr);
$mlkeys = array_keys_ml($arr);
// Remove those language variants
$nlkeys = array();
for ($i = 0; $i < count($keys); $i++) {
$pos = strrpos($keys[$i], "_");
// No suffix
if ($pos === false) {
$nlkeys[] = $keys[$i];
// Check the prefix
} else {
$prefix = substr($keys[$i], 0, $pos);
// The prefix is one of the language columns
if (in_array($prefix, $mlkeys)) {
// Not counted yet
if (!in_array($prefix, $nlkeys)) {
$nlkeys[] = $prefix;
}
// An ordinary prefix
} else {
$nlkeys[] = $keys[$i];
}
}
}
return $nlkeys;
}
// page_title: Obtain a page title
function page_title($sn)
{
// Cache the result
static $cache = array();
// Bounce if there is any problem with $sn
if (is_null($sn)) {
return t_notset();
}
// Return the cache
if (array_key_exists($sn, $cache)) {
return $cache[$sn];
}
// Check the serial number first
if (!check_sn($sn)) {
$cache[$sn] = t_na();
return $cache[$sn];
}
// Query
// Default language
if (getlang() == DEFAULT_LANG) {
$title = "title_" . getlang(LN_DATABASE) . " AS title";
// Fall back to the default language
} else {
$title = "COALESCE(title_" . getlang(LN_DATABASE) . ","
. " title_" . ln(DEFAULT_LANG, LN_DATABASE) . ") AS title";
}
$select = "SELECT $title FROM pages"
. " WHERE sn=$sn;\n";
$result = sql_query($select);
// Not found
if (sql_num_rows($result) != 1) {
$cache[$sn] = t_na();
return $cache[$sn];
}
// Found
$row = sql_fetch_assoc($result);
$cache[$sn] = $row["title"];
return $cache[$sn];
}
// page_path: Obtain a page path
function page_path($sn)
{
// Cache the result
static $cache = array();
// Bounce if there is any problem with $sn
if (is_null($sn)) {
return t_notset();
}
// Return the cache
if (array_key_exists($sn, $cache)) {
return $cache[$sn];
}
// Check the serial number first
if (!check_sn($sn)) {
$cache[$sn] = t_na();
return $cache[$sn];
}
// Query
$select = "SELECT path FROM pages WHERE sn=$sn;\n";
$result = sql_query($select);
// Not found
if (sql_num_rows($result) != 1) {
$cache[$sn] = t_na();
return $cache[$sn];
}
// Found
$row = sql_fetch_assoc($result);
$cache[$sn] = $row["path"];
return $cache[$sn];
}
// rebuildtype_options: Obtain a rebuild type options list
function rebuildtype_options($value)
{
// The type labels
$labels = array(
"pages" => C_("Web pages"),
"news" => C_("News"),
"links" => C_("Related links"),
"home" => C_("Home page"),
"all" => C_("Whole web site"),
);
if (array_key_exists("REBUILD_LABELS", $GLOBALS)) {
global $REBUILD_LABELS;
foreach (array_keys($REBUILD_LABELS) as $type) {
$labels[$type] = _($REBUILD_LABELS[$type]);
}
}
// Get the available rebuild types
$allfuncs = get_defined_functions();
$opts = array();
foreach ($allfuncs["user"] as $func) {
if (substr($func, 0, 8) == "rebuild_") {
$type = substr($func, 8);
// Skip rebuild_a_page()
// To be removed -- only for DK-Taipei now.
if ($type == "a_page") {
continue;
}
$label = array_key_exists($type, $labels)?
$labels[$type]: $type;
$opts[] = array(
"value" => $type,
"content" => $label,
);
}
}
// Obtain the HTML
$html = opt_list_array($opts);
return preselect_options($html, $value);
}
?>

View File

@@ -0,0 +1,124 @@
<?php
// File name: parseurl.inc.php
// Description: PHP subroutine to parse URL according to RFC 1808
// Date: 2004-12-05
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2004-2010 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/errhndl.inc.php";
// parse_url_rfc1808: Our own parse_url(), in order to confirm to RFC 1808
function parse_url_rfc1808($url)
{
// Try PHP parse_url() first
$GLOBALS["php_errormsg"] = null;
set_error_handler("null_error_handler");
$url_php = parse_url($url);
restore_error_handler();
// Error parsing the URL
if (!is_null($GLOBALS["php_errormsg"])) {
return null;
}
// Compose the network location/login (net_loc)
if (!is_array($url_php)) {
$url_php = array();
}
if (array_key_exists("host", $url_php)) {
$net_loc = $url_php["host"];
// Add the user and password if they exists
if (array_key_exists("user", $url_php)) {
if (array_key_exists("pass", $url_php)) {
$net_loc = $url_php["user"] . ":" . $url_php["pass"] . "@" . $net_loc;
} else {
$net_loc = $url_php["user"] . "@" . $net_loc;
}
}
// Add the port
if (array_key_exists("port", $url_php)) {
$need_port = true;
// Skip the default port
if (array_key_exists("scheme", $url_php)) {
switch (strtolower($url_php["scheme"])) {
case "http":
if ($url_php["port"] == 80) {
$need_port = false;
}
break;
case "https":
if ($url_php["port"] == 443) {
$need_port = false;
}
break;
case "ftp":
if ($url_php["port"] == 21) {
$need_port = false;
}
break;
case "ftps":
if ($url_php["port"] == 990) {
$need_port = false;
}
break;
case "gopher":
if ($url_php["port"] == 70) {
$need_port = false;
}
break;
case "prospero":
if ($url_php["port"] == 191) {
$need_port = false;
}
break;
case "wais":
if ($url_php["port"] == 210) {
$need_port = false;
}
break;
}
}
// We need to specify the port
if ($need_port) {
$net_loc .= ":" . $url_php["port"];
}
}
}
// Seperate the params from the path
if (array_key_exists("path", $url_php)) {
$pos = strpos($url_php["path"], ";");
if ($pos !== false) {
$url_php["params"] = substr($url_php["path"], $pos+1);
$url_php["path"] = substr($url_php["path"], 0, $pos);
}
}
// Compose the URL parts by RFC 1808
$url = array();
if (array_key_exists("scheme", $url_php)) {
$url["scheme"] = $url_php["scheme"];
}
if (isset($net_loc)) {
$url["net_loc"] = $net_loc;
}
if (array_key_exists("path", $url_php)) {
$url["path"] = $url_php["path"];
}
if (array_key_exists("params", $url_php)) {
$url["params"] = $url_php["params"];
}
if (array_key_exists("query", $url_php)) {
$url["query"] = $url_php["query"];
}
if (array_key_exists("fragment", $url_php)) {
$url["fragment"] = $url_php["fragment"];
}
return $url;
}
?>

View File

@@ -0,0 +1,104 @@
<?php
// File name: passwd.inc.php
// Description: Extended PHP subroutine to manuplate passwords
// Date: 2003-08-15
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2003-2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/encrypt.inc.php";
require_once "monica/newsn.inc.php";
// sync_saved_passwd: Set the passwords with the password registry
function sync_saved_passwd(&$FORM, $dummy)
{
// Do not process again
if (array_key_exists("_sync_saved_passwd", $FORM)) {
return;
}
// The passwd field
if (array_key_exists("passwd", $FORM)) {
// Empty password is provided. Restore to the old password.
if ($FORM["passwd"] == "") {
unset($FORM["passid"]);
// A new password is provided
} elseif ($FORM["passwd"] != $dummy) {
$FORM["passid"] = _passwd_suspend($FORM["passwd"]);
// A previous valid password exists
} elseif (_passwd_prev_valid("passid", $FORM)) {
$FORM["passwd"] = _passwd_ret($FORM["passid"]);
// Invalid previous password. Restore to the old password.
} else {
unset($FORM["passid"]);
$FORM["passwd"] = "";
}
}
// The passwd2 field
if (array_key_exists("passwd2", $FORM)) {
// Empty password is provided. Restore to the old password.
if ($FORM["passwd2"] == "") {
unset($FORM["passid2"]);
// A new password is provided
} elseif ($FORM["passwd2"] != $dummy) {
$FORM["passid2"] = _passwd_suspend($FORM["passwd2"]);
// A previous valid password exists
} elseif (_passwd_prev_valid("passid2", $FORM)) {
$FORM["passwd2"] = _passwd_ret($FORM["passid2"]);
// Invalid previous password. Restore to the old password.
} else {
unset($FORM["passid2"]);
$FORM["passwd2"] = "";
}
}
$FORM["_sync_saved_passwd"] = true;
return;
}
// _passwd_suspend: Suspend a password
function _passwd_suspend($password)
{
// Initialize the password registry
if (!array_key_exists("savepass", $_SESSION)) {
$_SESSION["savepass"] = array();
}
// Generate a new random password ID
$passid = new_sn_assoc($_SESSION["savepass"]);
$_SESSION["savepass"][$passid] = encrypt($password);
return $passid;
}
// _passwd_ret: Retrieve a password
function _passwd_ret($passid)
{
return decrypt($_SESSION["savepass"][$passid]);
}
// _passwd_prev_valid: If there is a previously-saved password
function _passwd_prev_valid($col, $FORM)
{
// Password ID does not exist
if (!array_key_exists($col, $FORM)) {
return false;
}
// Password registry not initialized yet
if (!array_key_exists("savepass", $_SESSION)) {
return false;
}
// Password does not exists in the registry
if (!array_key_exists($FORM[$col], $_SESSION["savepass"])) {
return false;
}
// We can't decrypt it
$passwd = decrypt($_SESSION["savepass"][$FORM[$col]]);
if (is_null($passwd)) {
return false;
}
return true;
}
?>

549
lib/php/monica/pic.inc.php Normal file
View File

@@ -0,0 +1,549 @@
<?php
// File name: pic.inc.php
// Description: PHP subroutines to manuplate pictures
// Date: 2002-04-16
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2002-2009 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/chkfunc.inc.php";
require_once "monica/gettext.inc.php";
require_once "monica/htmlchar.inc.php";
require_once "monica/newsn.inc.php";
require_once "monica/requri.inc.php";
require_once "monica/scptpriv.inc.php";
require_once "monica/xfileio.inc.php";
// Settings
if (!defined("PIC_MAX_WIDTH")) {
define("PIC_MAX_WIDTH", 800);
}
if (!defined("PIC_MAX_HEIGHT")) {
define("PIC_MAX_HEIGHT", 1024);
}
if (!defined("PIC_MAX_RATIO")) {
define("PIC_MAX_RATIO", 9.99);
}
$PIC_VALID_TYPES = array("image/png", "image/jpeg", "image/gif");
$PIC_VALID_SUFS = array("png", "jpg", "gif");
$PIC_TYPESUF_MAP = array(
"image/png" => "png",
"image/jpeg" => "jpg",
"image/gif" => "gif");
$PIC_VALID_POS = array("L", "R");
$PIC_POS_LABEL = array(
"L" => N_("Left-aligned"),
"R" => N_("Right-aligned"));
$PIC_POS_CSS = array(
"L" => "float: left;",
"R" => "float: right;");
if (!defined("PIC_POS_DEFAULT")) {
define("PIC_POS_DEFAULT", "L");
}
if (!defined("SHOWPIC_SCRIPT")) {
define("SHOWPIC_SCRIPT", "/admin/showpic.php");
}
if (!defined("SHOWPIC_PUBLIC_SCRIPT")) {
define("SHOWPIC_PUBLIC_SCRIPT", "/showpic.php");
}
// suspend_pic: Suspend a picture to $_SESSION
function suspend_pic(&$pic)
{
$PICS =& pic_deposit();
// Generate a new random picture ID
$picid = new_sn_assoc($PICS);
$pic["sn"] = $picid;
// Save the current picture
$PICS[$picid] =& $pic;
// Return the picture ID
return $picid;
}
// check_picfile: Check the uploaded picture file
function check_picfile($column = "picfile")
{
$picfile =& $_FILES[$column];
// Check the file upload status
switch ($picfile["error"]) {
case UPLOAD_ERR_INI_SIZE:
return array("msg"=>NC_("This picture file is too large (Max %s)."),
"margs"=>array(get_cfg_var("upload_max_filesize")));
case UPLOAD_ERR_FORM_SIZE:
return array("msg"=>NC_("This picture file is too large (Max %s)."),
"margs"=>array(UPLOAD_ERR_FORM_SIZE));
case UPLOAD_ERR_PARTIAL:
return array("msg"=>NC_("Upload not completed. Disk may be full or connection may be closed in the half. You may try to upload again, or contact the system administrator for this problem."));
case UPLOAD_ERR_NO_FILE:
return array("msg"=>NC_("Please upload the picture."));
default:
return array("msg"=>NC_("Upload failed with an unknown error (%d)."),
"margs"=>array($picfile["error"]));
case UPLOAD_ERR_OK:
}
// Check the file type
$picfile["type"] = check_mime_type($picfile["tmp_name"]);
if (!in_array($picfile["type"], $GLOBALS["PIC_VALID_TYPES"])) {
return array("msg"=>NC_("Please upload only PNG, JPEG or GIF files."));
}
// OK
return null;
}
// picurl: Get the picture display URL
function picurl(&$pic, $ratio = null)
{
// Default ratio to the picture ratio
if (is_null($ratio)) {
// Set the default picture ratio to 1
if (!array_key_exists("ratio", $pic)) {
$pic["ration"] = 1;
}
$ratio = $pic["ratio"];
}
$ratio = sprintf("%0.13F", $ratio);
$ratio = preg_replace("/(\.[0-9]*?)0+$/", "$1", $ratio);
$ratio = preg_replace("/\.$/", "", $ratio);
$showpic = is_admin_script()? SHOWPIC_SCRIPT: SHOWPIC_PUBLIC_SCRIPT;
// Compose the fields list
$cols = array();
// Add the columns
$cols[] = "sn=" . urlencode($pic["sn"]);
$cols[] = "ratio=" . urlencode($ratio);
return $showpic . "?" . implode("&", $cols);
}
// pictype_from_content: Get the picture type from its octet content
// Refer to the mime.magic file
function pictype_from_content(&$content)
{
// PNG
if (substr($content, 0, 4) == "\x89PNG") {
return "image/png";
}
// JPEG
if (substr($content, 0, 2) == "\xFF\xD8") {
return "image/jpeg";
}
// GIF
if (substr($content, 0, 4) == "GIF8") {
return "image/gif";
}
// No other formats are supported now
return null;
}
// picinfo: Return the picture infomation
function picinfo(&$pic, $ratio = 1)
{
// Original size not recorded yet
if ( !array_key_exists("width", $pic)
|| !array_key_exists("height", $pic)) {
$img = imagecreatefromstring($pic["content"]);
$pic["width"] = imagesx($img);
$pic["height"] = imagesy($img);
}
$x = newpicx($pic, $ratio);
$y = newpicy($pic, $ratio);
return sprintf(C_("Width: %d, height: %d, ratio: %0.2f"), $x, $y, $ratio);
}
// picstyle: Return the picture style
function picstyle(&$pic, $ratio = 1)
{
// Original size not recorded yet
if ( !array_key_exists("width", $pic)
|| !array_key_exists("height", $pic)) {
$img = imagecreatefromstring($pic["content"]);
$pic["width"] = imagesx($img);
$pic["height"] = imagesy($img);
}
$x = newpicx($pic, $ratio);
$y = newpicy($pic, $ratio);
return sprintf("height: %dpx; width: %dpx;", $y, $x);
}
// check_pic_ratio: Check the sanity of the picture ratio
function check_pic_ratio(&$pic, &$ratio)
{
// Check if the resize ratio is valid
if (!is_numeric($ratio)) {
return array("msg"=>NC_("Please specify a numeric ratio."));
}
settype($ratio, "float");
if ($ratio <= 0) {
return array("msg"=>NC_("Please specify a positive ratio."));
}
if ($ratio > PIC_MAX_RATIO) {
return array("msg"=>NC_("Please specify a ratio less than or equal to %0.2f."),
"margs"=>array(PIC_MAX_RATIO));
}
// The resulted picture is over the limit
if ( newpicx($pic, $ratio) > PIC_MAX_WIDTH
|| newpicy($pic, $ratio) > PIC_MAX_HEIGHT) {
return array("msg"=>NC_("This image is too large to display."));
}
// OK
return null;
}
// best_pic_ratio: Get the best ratio of a picture
function best_pic_ratio(&$pic)
{
// Cache the result
static $cache;
// Return the cache
if (isset($cache)) {
return $cache;
}
// Original size not recorded yet
if ( !array_key_exists("width", $pic)
|| !array_key_exists("height", $pic)) {
$img = imagecreatefromstring($pic["content"]);
$pic["width"] = imagesx($img);
$pic["height"] = imagesy($img);
}
// Good
if ( PIC_MAX_RATIO >= 1
&& $pic["width"] <= PIC_MAX_WIDTH
&& $pic["height"] <= PIC_MAX_HEIGHT) {
$cache = 1;
return $cache;
}
// Too large
// Find the largest proper ratio
$rx = floor(PIC_MAX_WIDTH*100 / $pic["width"])/100;
$ry = floor(PIC_MAX_HEIGHT*100 / $pic["height"])/100;
// Use the smallest among them
$cache = min($rx, $ry, PIC_MAX_RATIO);
return $cache;
}
// newpicx: Calculate the new picture x
function newpicx(&$pic, $ratio = 1)
{
// Original size not recorded yet
if (!array_key_exists("width", $pic)) {
$img = imagecreatefromstring($pic["content"]);
$pic["width"] = imagesx($img);
}
// No calculation needed
if ($ratio == 1) {
return $pic["width"];
}
$x = round($pic["width"] * $ratio);
// Smallest 1
if ($x == 0) {
$x = 1;
}
return $x;
}
// newpicy: Calculate the new picture y
function newpicy(&$pic, $ratio = 1)
{
// Original size not recorded yet
if (!array_key_exists("height", $pic)) {
$img = imagecreatefromstring($pic["content"]);
$pic["height"] = imagesy($img);
}
// No calculation needed
if ($ratio == 1) {
return $pic["height"];
}
$y = round($pic["height"] * $ratio);
// Smallest 1
if ($y == 0) {
$y = 1;
}
return $y;
}
// pic_exists: Check if a picture exists
function pic_exists($sn)
{
// Check the validity of the serial number first
if (!check_sn($sn)) {
return false;
}
if (!array_key_exists($sn, pic_deposit())) {
return false;
}
return true;
}
// echopic: Output a picture
function echopic(&$pic, $alt, $ratio = null)
{
if (is_null($ratio)) {
$ratio = best_pic_ratio($pic);
} else {
$error = check_pic_ratio($pic, $ratio);
if (!is_null($error)) {
$ratio = best_pic_ratio($pic);
}
}
$style = picstyle($pic, $ratio);
$picinfo = picinfo($pic, $ratio);
?><img src="<?php echo h(picurl($pic, $ratio)); ?>"
style="<?php echo h($style); ?>"
alt="<?php echo h($alt); ?>" />
<p class="picinfo"><?php echo h($picinfo); ?></p>
<?php
return;
}
// echopic_thumbnail: Output an picture thumbnail
function echopic_thumbnail(&$pic, $alt)
{
$url = picurl($pic, $pic["ratio"]);
$style = picstyle($pic, $pic["ratio"]);
?><img src="<?php echo h($url); ?>"
style="<?php echo h($style); ?>"
alt="<?php echo h($alt); ?>" /><?php
return;
}
// picpos_label: Output the label of a picture position
function picpos_label($pos)
{
global $PIC_POS_LABEL;
return C_($PIC_POS_LABEL[$pos]);
}
// resize_pic: Resize a picture
function &resize_pic(&$pic, $ratio)
{
// No need to resize it
if ($ratio == 1) {
return $pic;
}
$PICS =& pic_deposit();
// Initialize the cache base
if (!array_key_exists("resized", $pic)) {
$pic["resized"] = array();
}
// Return the cache
$ratio_s = number_format($ratio, 2);
if (array_key_exists($ratio_s, $pic["resized"])) {
return $PICS[$pic["resized"][$ratio_s]];
}
// Resize the picture
$x = $pic["width"];
$y = $pic["height"];
$type = $pic["type"];
$x1 = newpicx($pic, $ratio);
$y1 = newpicy($pic, $ratio);
// Resize it
$img = imagecreatefromstring($pic["content"]);
if (imageistruecolor($img)) {
$img1 = imagecreatetruecolor($x1, $y1);
} else {
$img1 = imagecreate($x1, $y1);
}
imagecopyresized($img1, $img, 0, 0, 0, 0, $x1, $y1, $x, $y);
// Build the new picture object
$pic1 = array();
$pic1["width"] = $x1;
$pic1["height"] = $y1;
$pic1["ratio"] = 1;
// GIF not supported, and should be replaced with PNG
$pic1["type"] = ($type == "image/gif")? "image/png": $type;
// Picture content
ob_start();
switch ($pic1["type"]) {
case "image/png":
imagepng($img1);
break;
case "image/jpeg":
imagejpeg($img1);
break;
}
$pic1["content"] = ob_get_contents();
ob_end_clean();
// Save the result
$sn1 = suspend_pic($pic1);
$pic["resized"][$ratio_s] = $sn1;
return $pic1;
}
// duppic: Duplicate a picture
function duppic($sn)
{
if (!pic_exists($sn)) {
return null;
}
$PICS =& pic_deposit();
// Generate a new random picture ID
$newsn = new_sn_assoc($PICS);
$PICS[$newsn] = $PICS[$sn];
$PICS[$newsn]["sn"] = $newsn;
return $newsn;
}
// pic_deposit: Return the picture deposit
function &pic_deposit()
{
// Session in use
if (isset($_SESSION)) {
if (!array_key_exists("savepics", $_SESSION)) {
$_SESSION["savepics"] = array();
}
return $_SESSION["savepics"];
// Session not in use
} else {
static $PICS = array();
return $PICS;
}
}
// clear_pic_deposit: Clear the picture deposit
function clear_pic_deposit()
{
$PICS =& pic_deposit();
$PICS = array();
return;
}
// piccache: Return an appropriate picture cache
function &piccache($table)
{
$PICS =& pic_deposit();
// Package specified
$package = defined("PACKAGE")? PACKAGE: REQUEST_HOST;
if (!array_key_exists("_cache", $PICS)) {
$PICS["_cache"] = array();
}
if (!array_key_exists($package, $PICS["_cache"])) {
$PICS["_cache"][$package] = array();
}
if (!array_key_exists($table, $PICS["_cache"][$package])) {
$PICS["_cache"][$package][$table] = array();
}
return $PICS["_cache"][$package][$table];
}
/////////////////////////
// Picture source operation in the SQL database
/////////////////////////
// readpic_content: Read a picture from its content into the picture deposit
// and return the picid
function readpic_content($data, $args, $sn, $table)
{
// Check the cache
$PICS =& pic_deposit();
$piccache =& piccache($table);
// Cached
if ( array_key_exists($sn, $piccache)
&& $data == $PICS[$piccache[$sn]]["content"]) {
$picid = $piccache[$sn];
$pic =& $PICS[$picid];
} else {
// Create the picture
$pic = array();
$pic["content"] = $data;
$pic["type"] = pictype_from_content($data);
// Set its width and height value
$img = imagecreatefromstring($pic["content"]);
$pic["width"] = imagesx($img);
$pic["height"] = imagesy($img);
// Suspend the created picture
$picid = suspend_pic($pic);
$piccache[$sn] = $picid;
}
// Check the wanted ratio
$ratio = 1;
if (is_null($args)) {
} elseif (array_key_exists("ratio", $args)) {
$ratio = $args["ratio"];
} elseif (array_key_exists("width", $args)) {
$ratio = $args["width"] / $pic["width"];
} elseif (array_key_exists("height", $args)) {
$ratio = $args["height"] / $pic["height"];
} elseif (array_key_exists("max", $args)) {
$ratio = $args["max"] / max($pic["width"], $pic["height"]);
}
// Check the ratio
// No ratio previously
if (!array_key_exists("ratio", $pic)) {
$pic["ratio"] = $ratio;
return $picid;
// Same ratio -- return the same picture
} elseif($pic["ratio"] == $ratio) {
return $picid;
// Ratio changed
} else {
$newpicid = duppic($picid);
$PICS[$newpicid]["ratio"] = $ratio;
$piccache[$sn] = $newpicid;
return $newpicid;
}
}
/////////////////////////
// Picture source operation on the file system.
// To be removed.
/////////////////////////
// readpic_pathprefix: Read a picture from a file into the picture deposit
// and return the picid
function readpic_pathprefix($prefix)
{
// Check each suffixes
$found = false;
foreach ($GLOBALS["PIC_VALID_SUFS"] as $suf) {
// Check if file exists
$file = "$prefix.$suf";
if ( !file_exists($file)
|| !is_readable($file)) {
continue;
}
// Check the MIME type
$type = check_mime_type($file);
if (!in_array($type, $GLOBALS["PIC_VALID_TYPES"])) {
continue;
}
// Found
$found = true;
break;
}
// Not found
if (!$found) {
return null;
}
// Read the picture
$pic = array();
$pic["content"] = xfread($file);
$pic["type"] = $type;
$img = imagecreatefromstring($pic["content"]);
$pic["width"] = imagesx($img);
$pic["height"] = imagesy($img);
$pic["ratio"] = 1;
$picid = suspend_pic($pic);
return $picid;
}
?>

View File

@@ -0,0 +1,225 @@
<?php
// File name: pinyin.inc.php
// Description: PHP subroutines to convert Traditional Chinese to Pinyin
// Date: 2004-04-14
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2004-2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/chkwrite.inc.php";
require_once "monica/mkalldir.inc.php";
require_once "monica/xfileio.inc.php";
// Settings
if (!defined("DBMDIR")) {
define("DBMDIR", dirname(dirname(dirname(__FILE__))) . "/" . php_uname("m"));
}
define("_PINYIN_PINYIN2BIG5", dirname(__FILE__) . "/pinyin2big5");
define("_PINYIN_B52PY_DB", DBMDIR . "/b52py.db");
$_PINYIN_DB = null;
define("_PINYIN_DBTYPE_DBA", 1);
define("_PINYIN_DBTYPE_ARRAY", 2);
$_PINYIN_SUP = array(
" " => " ",
"" => "#",
"" => "#",
"" => "shi2 ke4",
"" => "qian1 ke4",
"" => "mao2 ke4",
"\" => "fen1 ke4",
"" => "bai3 ke4",
"" => "li2 ke4",
"" => "jia1 lun2",
"" => "qian1 wa3",
"" => "li2 mi3",
);
// b52py: Convert Traditional Chinese to Pinyin
function b52py($big5)
{
global $_PINYIN_DB;
// Initialize the database
_init_b52py();
// Split into pieces
$pieces = array();
$remains = $big5;
while (preg_match("/^([\\x01-\\x7F]+|(?:[\\x80-\\xFE].)+)(.*)$/s", $remains, $m)) {
$pieces[] = $m[1];
$remains = $m[2];
}
// Process each piece
switch (_PINYIN_DBTYPE) {
// Using a DB file
case _PINYIN_DBTYPE_DBA:
for ($i = 0; $i < count($pieces); $i++) {
// Big5 piece
if (preg_match("/^[\\x80-\\xFF]/", $pieces[$i])) {
for ($j = 0, $words = array(); $j < strlen($pieces[$i]); $j += 2) {
$char = substr($pieces[$i], $j, 2);
if (dba_exists($char, $_PINYIN_DB)) {
$words[] = dba_fetch($char, $_PINYIN_DB);
} else {
$words[] = $char;
}
}
$pieces[$i] = implode(" ", $words);
}
}
break;
// Using an array
case _PINYIN_DBTYPE_ARRAY:
for ($i = 0; $i < count($pieces); $i++) {
// Big5 piece
if (preg_match("/^[\\x80-\\xFF]/", $pieces[$i])) {
for ($j = 0, $words = array(); $j < strlen($pieces[$i]); $j += 2) {
$char = substr($pieces[$i], $j, 2);
if (array_key_exists($char, $_PINYIN_DB)) {
$words[] = $_PINYIN_DB[$char];
} else {
$words[] = $char;
}
}
$pieces[$i] = implode(" ", $words);
}
}
break;
}
$pinyin = $pieces[0];
for ($i = 1; $i < count($pieces); $i++) {
// Insert a space
if ( !preg_match("/\s$/", $pieces[$i-1])
&& !preg_match("/^\s/", $pieces[$i])) {
$pinyin .= " ";
}
$pinyin .= $pieces[$i];
}
return $pinyin;
}
// _init_b52py: Initialize the Big5 to Pinyin database
function _init_b52py()
{
global $_PINYIN_DB, $_PINYIN_SUP;
// Already initialized
if (defined("_PINYIN_DBTYPE")) {
return;
}
// Decide the action to do
if (file_exists(_PINYIN_B52PY_DB)) {
// Not a file
if (!is_file(_PINYIN_B52PY_DB)) {
define("_PINYIN_DBTYPE", _PINYIN_DBTYPE_ARRAY);
// Not readable
} elseif (!is_readable(_PINYIN_B52PY_DB)) {
define("_PINYIN_DBTYPE", _PINYIN_DBTYPE_ARRAY);
// Not writable -- read only
} elseif (!is_writable(_PINYIN_B52PY_DB)) {
$_PINYIN_DB = dba_open(_PINYIN_B52PY_DB, "r", "gdbm");
// No data
if (dba_firstkey($_PINYIN_DB) === false) {
dba_close($_PINYIN_DB);
define("_PINYIN_DBTYPE", _PINYIN_DBTYPE_ARRAY);
// OK
} else {
define("_PINYIN_DBTYPE", _PINYIN_DBTYPE_DBA);
return;
}
// Writable
} else {
$_PINYIN_DB = dba_open(_PINYIN_B52PY_DB, "w", "gdbm");
// No data - initialize the data
if (dba_firstkey($_PINYIN_DB) === false) {
define("_PINYIN_DBTYPE", _PINYIN_DBTYPE_DBA);
// OK
} else {
define("_PINYIN_DBTYPE", _PINYIN_DBTYPE_DBA);
return;
}
}
// File does not exist
} else {
// Not creatable
$error = check_writable(_PINYIN_B52PY_DB);
if (!is_null($error)) {
define("_PINYIN_DBTYPE", _PINYIN_DBTYPE_ARRAY);
// Creatable
} else {
mkalldir(dirname(_PINYIN_B52PY_DB));
$_PINYIN_DB = dba_open(_PINYIN_B52PY_DB, "c", "gdbm");
define("_PINYIN_DBTYPE", _PINYIN_DBTYPE_DBA);
}
}
// Initialize the database
switch (_PINYIN_DBTYPE) {
// Initialize it as a DB file
case _PINYIN_DBTYPE_DBA:
$lines = explode("\n", xfread(_PINYIN_PINYIN2BIG5));
foreach ($lines as $line) {
// Skip comments
if (substr($line, 0, 1) == "#") {
continue;
}
// Skip empty lines
if (!preg_match("/\S/", $line)) {
continue;
}
$chars = explode(" ", $line);
// First item is pinyin
$pinyin = array_shift($chars);
foreach ($chars as $char) {
if (!dba_exists($char, $_PINYIN_DB)) {
dba_insert($char, $pinyin, $_PINYIN_DB);
}
}
}
// Special meta characters
foreach (array_keys($_PINYIN_SUP) as $char) {
if (!dba_exists($char, $_PINYIN_DB)) {
dba_insert($char, $_PINYIN_SUP[$char], $_PINYIN_DB);
}
}
break;
// Initialize it as an array
case _PINYIN_DBTYPE_ARRAY:
$_PINYIN_DB = array();
$lines = explode("\n", xfread(_PINYIN_PINYIN2BIG5));
foreach ($lines as $line) {
// Skip comments
if (substr($line, 0, 1) == "#") {
continue;
}
// Skip empty lines
if (!preg_match("/\S/", $line)) {
continue;
}
$chars = explode(" ", $line);
// First item is pinyin
$pinyin = array_shift($chars);
foreach ($chars as $char) {
$_PINYIN_DB[$char] = $pinyin;
}
}
// Special meta characters
foreach (array_keys($_PINYIN_SUP) as $char) {
$_PINYIN_DB[$char] = $_PINYIN_SUP[$char];
}
break;
}
return;
}
?>

1555
lib/php/monica/pinyin2big5 Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,708 @@
<?php
// File name: postgres.inc.php
// Description: PHP subroutines to handle PostgreSQL operation
// Date: 2004-05-22
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2004-2008 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines with high precedence
require_once "monica/sqlconst.inc.php";
// Referenced subroutines
require_once "monica/errhndl.inc.php";
require_once "monica/getlang.inc.php";
require_once "monica/lninfo.inc.php";
require_once "monica/requri.inc.php";
require_once "monica/sqllogin.inc.php";
// Settings
$_PG_CONN = null;
// xpg_connect: Connect to the PostgreSQL database
function xpg_connect($database = null)
{
global $_PG_CONN;
// Connected
if (!is_null($_PG_CONN)) {
return;
}
// Obtain the SQL log-in information
if (is_null($database)) {
if (getenv("PGDATABASE") !== false) {
$database = getenv("PGDATABASE");
} elseif (defined("PACKAGE")) {
$database = PACKAGE;
}
}
if (getenv("PGHOST") !== false) {
$host = getenv("PGHOST");
} else {
$host = null;
}
// Login with from SQLLOGIN environment variable as a web application
// php-cgi does not have STDIN and STDERR even on console
if (PHP_SAPI != "cli") {
$r = get_sql_login_info(SQL_POSTGRESQL, $database, $host);
// Connect it
$_PG_CONN = pg_connect(sprintf("host=%s dbname=%s user=%s password=%s",
$r["PGHOST"], $r["PGDATABASE"], $r["PGUSER"], $r["PGPASSWORD"]));
if ($_PG_CONN === false) {
$_PG_CONN = null;
trigger_error("Failed connecting to the PostgreSQL server.\n"
. $GLOBALS["php_errormsg"], E_USER_ERROR);
}
// Ask the password from the console
} else {
$user = null;
$subseq = false;
set_error_handler("null_error_handler");
$_PG_CONN = pg_connect("dbname=$database");
restore_error_handler();
while ($_PG_CONN === false) {
global $php_errormsg;
if ($subseq) {
fprintf(STDERR, "%s\n", $GLOBALS["php_errormsg"]);
sleep(5);
}
$subseq = true;
// Obtain the current login user
if ( is_null($user)
&& preg_match("/ failed for user \"(.+?)\"/", $GLOBALS["php_errormsg"], $m)) {
$user = $m[1];
}
// Disable console echo
system("/bin/stty -echo");
fprintf(STDERR, !is_null($user)? "PostgreSQL password for $user: ":
"PostgreSQL password: ");
$passwd = fgets(STDIN);
fprintf(STDERR, "\n");
// Restore console echo status
system("/bin/stty echo");
// STDIN is not available
if ($passwd === false) {
die(THIS_FILE . ": Failed connecting to the PostgreSQL server\n");
}
$passwd = trim($passwd);
set_error_handler("null_error_handler");
$_PG_CONN = pg_connect("dbname=$database password=$passwd");
restore_error_handler();
}
}
// Set the client encoding
$chaset = defined("SQL_CHARSET")? SQL_CHARSET: "utf8";
$result = pg_set_client_encoding($_PG_CONN, $chaset);
if ($result == -1) {
trigger_error("Failed setting client encoding to $chaset.\n"
. (pg_last_error()? pg_last_error(): $GLOBALS["php_errormsg"]), E_USER_ERROR);
}
return;
}
// xpg_close: Disconnect from the PostgreSQL database
function xpg_close()
{
global $_PG_CONN;
if (is_null($_PG_CONN)) {
return;
}
$result = pg_close($_PG_CONN);
if ($result !== true) {
trigger_error("Failed disconnecting from the PostgreSQL server.\n"
. (pg_last_error()? pg_last_error(): $GLOBALS["php_errormsg"]), E_USER_ERROR);
}
$_PG_CONN = null;
return;
}
/////////////////////////
// Concurrency Control: Transactions and Locks
/////////////////////////
$_PG_IN_TRANSACTION = false;
// pg_begin: Begin a PostgreSQL transaction
function pg_begin()
{
if (!$GLOBALS["_PG_IN_TRANSACTION"]) {
$begin = "START TRANSACTION;\n";
xpg_query($begin);
$GLOBALS["_PG_IN_TRANSACTION"] = true;
}
}
// pg_commit: Commit a PostgreSQL transaction
function pg_commit()
{
if ($GLOBALS["_PG_IN_TRANSACTION"]) {
$commit = "COMMIT;\n";
xpg_query($commit);
$GLOBALS["_PG_IN_TRANSACTION"] = false;
}
}
// pg_rollback: Rollback a PostgreSQL transaction
function pg_rollback()
{
if ($GLOBALS["_PG_IN_TRANSACTION"]) {
$rollback = "ROLLBACK;\n";
xpg_query($rollback);
$GLOBALS["_PG_IN_TRANSACTION"] = false;
}
}
// pg_lock: PostgreSQL table-locking handler
// PostgreSQL has no unlock
// Input: An associative array, where its keys are the tables to lock,
// and its values can be one of the following:
// LOCK_SH: Request a read lock
// LOCK_EX: Request a write lock
// LOCK_UN: No effect
// null has no effect here.
// Return: None. Errors are directed to error handlers
function pg_lock($locks = null)
{
// Bounce for nothing
if (is_null($locks) || count($locks) == 0) {
return;
}
// Remove the table aliases - compatibility with stupid MySQL
$abslocks = array();
foreach (array_keys($locks) as $origtable) {
// Remove the table aliases
$abstable = preg_replace("/\s+AS\s+.+?$/i", "", $origtable);
// No override previous write lock
if ( array_key_exists($abstable, $abslocks)
&& $abslocks[$abstable] == LOCK_EX) {
continue;
}
// Set the lock
$abslocks[$abstable] = $locks[$origtable];
}
$locks = $abslocks;
// Split into different lock modes
$reads = array();
$writes = array();
foreach (array_keys($locks) as $table) {
switch ($locks[$table]) {
case LOCK_SH:
$reads[] = $table;
break;
case LOCK_EX:
$writes[] = $table;
break;
default:
trigger_error("Bad SQL lock request: \"$locks[$table]\" on table \"$table\".", E_USER_ERROR);
}
}
// Start transaction if not started yet. Table locks cannot
// live outside of transactions at all.
if (!$GLOBALS["_PG_IN_TRANSACTION"]) {
pg_begin();
}
// Request the locks
if (count($reads) > 0) {
$locktable = "LOCK TABLE " . implode(", ", $reads)
. " IN SHARE MODE;\n";
xpg_query($locktable);
}
if (count($writes) > 0) {
$locktable = "LOCK TABLE " . implode(", ", $writes)
. " IN ACCESS EXCLUSIVE MODE;\n";
xpg_query($locktable);
}
return;
}
// xpg_query: Do a PostgreSQL query and report the error
function xpg_query($query)
{
set_error_handler("null_error_handler");
$result = pg_query($query);
restore_error_handler();
if ($result === false) {
trigger_error("Failed pg_query().\n$query\n"
. (pg_last_error()? pg_last_error(): $GLOBALS["php_errormsg"]), E_USER_ERROR);
}
return $result;
}
// pg_seek: Move the PostgreSQL result pointer
function pg_seek($result, $offset)
{
$result = pg_result_seek($result, $offset);
if ($result === false) {
trigger_error("Failed pg_result_seek().\n"
. (pg_last_error()? pg_last_error(): $GLOBALS["php_errormsg"]), E_USER_ERROR);
}
return $result;
}
// xpg_fetch_assoc: Return a PostgreSQL row as an associative array
function xpg_fetch_assoc($result)
{
// Fetch the raw data now
$row = pg_fetch_assoc($result);
// Return the error
if (!is_array($row)) {
return $row;
}
// Adjust the boolean columns
foreach (pg_cols_of_type($result, SQL_TYPE_BOOLEAN, SQL_FETCH_ASSOC) as $col) {
if (!is_null($row[$col])) {
$row[$col] = ($row[$col] == "t");
}
}
// Adjust the bytea columns
foreach (pg_cols_of_type($result, SQL_TYPE_BLOB, SQL_FETCH_ASSOC) as $col) {
if (!is_null($row[$col])) {
$row[$col] = pg_unescape_bytea($row[$col]);
}
}
// Adjust the integer columns
foreach (pg_cols_of_type($result, SQL_TYPE_INTEGER, SQL_FETCH_ASSOC) as $col) {
if (!is_null($row[$col])) {
settype($row[$col], "integer");
}
}
// Adjust the big integer columns
foreach (pg_cols_of_type($result, SQL_TYPE_BIGINT, SQL_FETCH_ASSOC) as $col) {
if ( !is_null($row[$col])
&& $row[$col] >= -2147483647
&& $row[$col] <= 2147483647) {
settype($row[$col], "integer");
}
}
// Adjust the float columns
foreach (pg_cols_of_type($result, SQL_TYPE_FLOAT, SQL_FETCH_ASSOC) as $col) {
if (!is_null($row[$col])) {
settype($row[$col], "float");
}
}
return $row;
}
// xpg_fetch_row: Return a PostgreSQL row as an numeric array
function xpg_fetch_row($result)
{
// Fetch the raw data now
$row = pg_fetch_row($result);
// Return the error
if (!is_array($row)) {
return $row;
}
// Adjust the boolean columns
foreach (pg_cols_of_type($result, SQL_TYPE_BOOLEAN, SQL_FETCH_ROW) as $col) {
if (!is_null($row[$col])) {
$row[$col] = ($row[$col] == "t");
}
}
// Adjust the bytea columns
foreach (pg_cols_of_type($result, SQL_TYPE_BLOB, SQL_FETCH_ROW) as $col) {
if (!is_null($row[$col])) {
$row[$col] = pg_unescape_bytea($row[$col]);
}
}
// Adjust the integer columns
foreach (pg_cols_of_type($result, SQL_TYPE_INTEGER, SQL_FETCH_ROW) as $col) {
if (!is_null($row[$col])) {
settype($row[$col], "integer");
}
}
// Adjust the big integer columns
foreach (pg_cols_of_type($result, SQL_TYPE_BIGINT, SQL_FETCH_ROW) as $col) {
if ( !is_null($row[$col])
&& $row[$col] >= -2147483647
&& $row[$col] <= 2147483647) {
settype($row[$col], "integer");
}
}
// Adjust the float columns
foreach (pg_cols_of_type($result, SQL_TYPE_FLOAT, SQL_FETCH_ROW) as $col) {
if (!is_null($row[$col])) {
settype($row[$col], "float");
}
}
return $row;
}
// pg_tables: Obtain a list of available PostgreSQL tables
// and report the error
function pg_tables($schema = null)
{
// Default to the current schema
if (is_null($schema)) {
$schema = _pg_current_schema();
}
$select = "SELECT tablename FROM pg_tables"
. " WHERE schemaname='" . pg_escape_string($schema) . "'"
. " ORDER BY tablename;\n";
$result = xpg_query($select);
$count = pg_num_rows($result);
for ($i = 0, $tables = array(); $i < $count; $i++) {
$row = pg_fetch_row($result);
$tables[] = $row[0];
}
return $tables;
}
// pg_cols: Obtain the column list of a PostgreSQL table
function pg_cols($table)
{
// Cache the result
static $cache = array();
// Return the cache
if (array_key_exists($table, $cache)) {
return $cache[$table];
}
global $_PG_CONN;
// Use pg_meta_data(). This is marked as experimental in PHP documentation yet.
$result = pg_meta_data($_PG_CONN, $table);
if ($result === false) {
trigger_error("Failed pg_meta_data(\$PG_CONN, \"$table\").\n"
. (pg_last_error()? pg_last_error(): $GLOBALS["php_errormsg"]), E_USER_ERROR);
}
$cache[$table] = array_keys($result);
return $cache[$table];
}
// pg_cols_ml: Return a list of multi-lingual columns in a PostgreSQL table
function pg_cols_ml($table)
{
// Cache the result
static $cache = array();
// Return the cache
if (array_key_exists($table, $cache)) {
return $cache[$table];
}
// Get the columns that have language variants
$cols = pg_cols($table);
$cache[$table] = array();
$suffix = "_" . getlang(LN_DATABASE);
$len = strlen($suffix);
for ($i = 0; $i < count($cols); $i++) {
// It has a language suffix
if (substr($cols[$i], -$len) == $suffix) {
$cache[$table][] = substr($cols[$i], 0, -$len);
}
}
return $cache[$table];
}
// pg_cols_nl: Return a list of columns without their multi-lingual
// deviants in a PostgreSQL table
function pg_cols_nl($table)
{
// Cache the result
static $cache = array();
// Return the cache
if (array_key_exists($table, $cache)) {
return $cache[$table];
}
// Get the columns that have language variants
$cols = pg_cols($table);
$langcols = pg_cols_ml($table);
// Remove those language variants
$cache[$table] = array();
for ($i = 0; $i < count($cols); $i++) {
$pos = strrpos($cols[$i], "_");
// No suffix
if ($pos === false) {
$cache[$table][] = $cols[$i];
// Check the prefix
} else {
$prefix = substr($cols[$i], 0, $pos);
// The prefix is one of the language columns
if (in_array($prefix, $langcols)) {
// Not counted yet
if (!in_array($prefix, $cache[$table])) {
$cache[$table][] = $prefix;
}
// An ordinary prefix
} else {
$cache[$table][] = $cols[$i];
}
}
}
return $cache[$table];
}
// pg_cols_of_type: Return the columns in a certain data type
function pg_cols_of_type($result, $type, $format = SQL_FETCH_ASSOC)
{
$result_key = _pg_result_hashkey($result);
// Cache the result
static $cache = array();
// Return the cache
if (array_key_exists($result_key, $cache)) {
return $cache[$result_key][$type][$format];
}
// Check each field type
$count = pg_num_fields($result);
$cols = array(
SQL_TYPE_BOOLEAN => array(
SQL_FETCH_ASSOC => array(),
SQL_FETCH_ROW => array(),
),
SQL_TYPE_BLOB => array(
SQL_FETCH_ASSOC => array(),
SQL_FETCH_ROW => array(),
),
SQL_TYPE_INTEGER => array(
SQL_FETCH_ASSOC => array(),
SQL_FETCH_ROW => array(),
),
SQL_TYPE_BIGINT => array(
SQL_FETCH_ASSOC => array(),
SQL_FETCH_ROW => array(),
),
SQL_TYPE_FLOAT => array(
SQL_FETCH_ASSOC => array(),
SQL_FETCH_ROW => array(),
),
);
for ($i = 0; $i < $count; $i++) {
$coltype = pg_field_type($result, $i);
$colname = pg_field_name($result, $i);
switch ($coltype) {
case "bool":
$cols[SQL_TYPE_BOOLEAN][SQL_FETCH_ROW][] = $i;
$cols[SQL_TYPE_BOOLEAN][SQL_FETCH_ASSOC][] = $colname;
break;
case "bytea":
$cols[SQL_TYPE_BLOB][SQL_FETCH_ROW][] = $i;
$cols[SQL_TYPE_BLOB][SQL_FETCH_ASSOC][] = $colname;
break;
case "int2":
case "int4":
$cols[SQL_TYPE_INTEGER][SQL_FETCH_ROW][] = $i;
$cols[SQL_TYPE_INTEGER][SQL_FETCH_ASSOC][] = $colname;
break;
case "int8":
$cols[SQL_TYPE_BIGINT][SQL_FETCH_ROW][] = $i;
$cols[SQL_TYPE_BIGINT][SQL_FETCH_ASSOC][] = $colname;
break;
case "float4":
case "float8":
$cols[SQL_TYPE_FLOAT][SQL_FETCH_ROW][] = $i;
$cols[SQL_TYPE_FLOAT][SQL_FETCH_ASSOC][] = $colname;
break;
}
}
// Cache it
$cache[$result_key] = $cols;
return $cols[$type][$format];
}
// pg_col_lens: Obtain the column lengths of a PostgreSQL table
function pg_col_lens($table)
{
// Cache the result
static $cache = array();
// Return the cache
if (array_key_exists($table, $cache)) {
return $cache[$table];
}
$schema = _pg_current_schema();
$select = "SELECT pg_attribute.attname AS col,"
. " pg_type.typname AS type,"
. " pg_attribute.attlen AS len,"
. " pg_attribute.atttypmod AS typmod"
. " FROM pg_attribute"
. " INNER JOIN pg_class ON pg_attribute.attrelid=pg_class.oid"
. " INNER JOIN pg_type ON pg_attribute.atttypid=pg_type.oid"
. " INNER JOIN pg_namespace ON pg_class.relnamespace=pg_namespace.oid"
. " WHERE pg_namespace.nspname='" . pg_escape_string($schema) . "'"
. " AND pg_class.relname='" . pg_escape_string($table) . "'"
. " AND pg_class.relkind='r'"
. " AND pg_attribute.attnum>0"
. " ORDER BY pg_attribute.attnum;\n";
$result = xpg_query($select);
$count = pg_num_rows($result);
for ($i = 0, $cache[$table] = array(); $i < $count; $i++) {
$row = pg_fetch_assoc($result);
switch ($row["type"]) {
// Integer -- Digits of the largest number - 1
case "int2":
case "int4":
case "int8":
$cache[$table][$row["col"]] = floor(log10(pow(256, $row["len"])));
settype($cache[$table][$row["col"]], "integer");
break;
// Refer to typmod for char and varchar
case "varchar":
case "bpchar":
$cache[$table][$row["col"]] = $row["typmod"] - 4;
break;
// Set text and bytea to 4294967296 (2^32) (infinite actually)
case "text":
case "bytea":
$cache[$table][$row["col"]] = 4294967296;
break;
// Set timestamp to 19
case "timestamp":
$cache[$table][$row["col"]] = 26;
break;
// Set date to 10
case "date":
$cache[$table][$row["col"]] = 10;
break;
// Set time to 8
case "time":
$cache[$table][$row["col"]] = 8;
break;
// Set numeric to precision + 1 decimal point
// Refer to http://archives.postgresql.org/pgsql-hackers/1999-01/msg00127.php
case "numeric":
$typmod = $row["typmod"] - 4;
$scale = $typmod & 0xFFFF;
$precision = $typmod >> 16;
$cache[$table][$row["col"]] = $precision + 1;
break;
// Set boolean to 1
case "bool":
$cache[$table][$row["col"]] = 1;
break;
// Set inet to 18 (nnn.nnn.nnn.nnn/nn)
case "inet":
$cache[$table][$row["col"]] = 18;
break;
// Bounce for other columns, so that we know to fix it here
default:
trigger_error("Unknown column type " . $row["type"]
. " for table $table", E_USER_ERROR);
break;
}
}
// Hash the multi-lingual columns
$lndb = getlang(LN_DATABASE);
foreach (pg_cols_ml($table) as $col) {
$cache[$table][$col] = $cache[$table][$col . "_" . $lndb];
}
return $cache[$table];
}
// pg_strcat: Concatenate strings in PostgreSQL
// PostgreSQL uses the || operator to concatenate strings
function pg_strcat()
{
$strs = func_get_args();
return implode(" || ", $strs);
}
// pg_lastupd: Obtain the last updated time of a list of tables
function pg_lastupd($tables)
{
// Bounce if no tables supplied
if (is_null($tables) || count($tables) == 0) {
return;
}
// Remove the table aliases
for ($i = 0; $i < count($tables); $i++) {
$tables[$i] = preg_replace("/\s+AS\s+.+?$/i", "", $tables[$i]);
}
// Remove duplicates
$tables = array_values(array_unique($tables));
// Query
$conds = array();
foreach ($tables as $table) {
$conds[] = "tabname='" . pg_escape_string($table) . "'";
}
$select = "SELECT mtime FROM mtime"
. " WHERE " . implode(" OR ", $conds)
. " ORDER BY mtime DESC LIMIT 1;\n";
$result = xpg_query($select);
// Bounce if no data found
if (pg_num_rows($result) != 1) {
return;
}
// Return the result
$row = xpg_fetch_assoc($result);
return $row["mtime"];
}
// pg_dbsize: Obtain the size of the database
function pg_dbsize()
{
$select = "SELECT pg_database_size(datname) FROM pg_database"
. " WHERE datname=current_database();\n";
$result = xpg_query($select);
$row = xpg_fetch_row($result);
return $row[0];
}
// pg_date: Return date in a predefined format format
function pg_date($expr, $format)
{
switch ($format) {
case SQL_YYYYMMDD:
return "to_char($expr, 'YYYYMMDD')";
case SQL_YYYY_YYYYMMDD:
return "to_char($expr, 'YYYY/YYYYMMDD')";
case SQL_MM_DD:
return "to_char($expr, 'MM-DD')";
case SQL_M_D_EN:
return "to_char($expr, 'FMMM/FMDD')";
case SQL_M_D_ZHTW:
return "to_char($expr, 'FMMM月FMDD日')";
case SQL_M_D_DE:
return "to_char($expr, 'FMDD.FMMM')";
case SQL_HH_MM:
return "to_char($expr, 'HH24:MI')";
}
}
// pg_re: Return the PostgreSQL regular expression operator
function pg_re()
{
return "~";
}
// _pg_result_hashkey: Generate a hash key from a PostgreSQL query result
function _pg_result_hashkey($result)
{
// Use the output of var_dump
ob_start();
var_dump($result);
$key = ob_get_contents();
ob_end_clean();
return $key;
}
// _pg_current_schema: Obtain the current schema
function _pg_current_schema()
{
// Cache the result
static $cache;
// Return the cache
if (isset($cache)) {
return $cache;
}
$select = "SELECT current_schema();\n";
$result = xpg_query($select);
$row = pg_fetch_row($result);
$cache = $row[0];
return $cache;
}
?>

View File

@@ -0,0 +1,155 @@
<?php
// File name: preview.inc.php
// Description: PHP subroutine to handle page previews
// Date: 2004-10-28
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2004-2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/callform.inc.php";
require_once "monica/getlang.inc.php";
require_once "monica/gettext.inc.php";
require_once "monica/htmlchar.inc.php";
require_once "monica/lninfo.inc.php";
require_once "monica/page2rel.inc.php";
require_once "monica/pagefunc.inc.php";
require_once "monica/requri.inc.php";
require_once "monica/sql.inc.php";
// fetch_preview: Retrieve a previously suspended preview from,
// from $_SESSION or database
function fetch_preview()
{
// S/N not specified
if (!array_key_exists("sn", $_GET)) {
return array("msg"=>NC_("The following field was not received: \"%s\"."),
"margs"=>array("sn"),
"isform"=>false);
}
// Check the source to retrieve the preview form
$source = "session";
if (array_key_exists("source", $_GET)) {
switch ($_GET["source"]) {
// Retrieve from the database
case "db":
$source = "db";
break;
// Retrieve from the $_SESSION saveform
case "session":
$source = "session";
break;
// Other preview sources
default:
return array("msg"=>NC_("Unknown preview source: \"%s\"."),
"margs"=>array($_GET["source"]),
"isform"=>false);
break;
}
}
// Retrieve the preview form
switch ($source) {
// Retrieve from the database
case "db":
// Fetch with fetch_curitem()
fetch_curitem();
$GLOBALS["PREVIEW"] =& $GLOBALS["CURRENT"];
break;
// Retrieve from the $_SESSION saveform
case "session":
$GLOBALS["PREVIEW"] =& retrieve_form($_GET["sn"]);
if (count($GLOBALS["PREVIEW"]) == 0) {
unset($GLOBALS["PREVIEW"]);
return array("msg"=>NC_("Unknown preview form: %d."),
"margs"=>array($_GET["sn"]),
"isform"=>false);
}
break;
}
// Tag that this is a preview content
$GLOBALS["PREVIEW"]["preview"] = true;
// OK
return null;
}
// html_preview: Display the preview
function html_preview()
{
// Lock the required tables
if (array_key_exists("REBUILD_TABLES", $GLOBALS)) {
$sql_lock = array();
foreach ($GLOBALS["REBUILD_TABLES"] as $table) {
$sql_lock[$table] = LOCK_SH;
}
}
sql_lock($sql_lock);
global $PREVIEW;
$html = compose_page($PREVIEW);
$path = $PREVIEW["path"];
// A multi-lingual website
if (count($GLOBALS["ALL_LINGUAS"]) > 1 && !preg_match("/\.php\?/", $path)) {
$path = "/" . getlang(LN_FILENAME) . $path;
}
$html = page2rel(page2abs($html, $path), REQUEST_PATH);
echo $html;
return;
}
// html_preview_mark: Print the HTML preview mark
function html_preview_mark($args = null)
{
// Obtain page parameters
$args = page_param($args);
// This is only for the preview
if (is_null($args["preview"])) {
return;
}
// Decide the data source
$source = "session";
if (array_key_exists("source", $_GET)) {
switch ($_GET["source"]) {
// Retrieve from the database
case "db":
$source = "db";
break;
// Retrieve from the $_SESSION saveform
case "session":
$source = "session";
break;
// Other preview sources
default:
trigger_error("Unknown preview source: \"" . $_GET["source"] . "\"",
E_USER_ERROR);
break;
}
}
// Set the query arguments
switch ($source) {
// Retrieve from the database
case "db":
$url = REQUEST_PATH . "?form=cur&sn=" . $_GET["sn"];
break;
// Retrieve from the $_SESSION saveform
case "session":
$url = REQUEST_PATH . "?formid=" . $_GET["sn"];
break;
}
$areatitle = C_("Preview Mark Area");
?><div class="previewmark" title="<?php echo h($areatitle); ?>">
<h2><?php echo h(C_("Preview")); ?></h2>
<p><a href="<?php echo h($url); ?>"><?php
echo h(C_("Finish preview and return.")); ?></a></p>
</div>
<?php
return;
}
?>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,309 @@
<?php
// File name: rel2abs.inc.php
// Description: PHP subroutine to convert a relative URL to an absolute URL
// Date: 2002-06-10
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2002-2007 Pristine Communications
// Refer to RFC 1808
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/parseurl.inc.php";
require_once "monica/requri.inc.php";
// Settings
define("REL2ABS_SKIP_FRAGMENT", true);
define("REL2ABS_NO_HOST", true);
define("REL2ABS_RDIFF_KEEP", true);
define("REL2ABS_RDIFF_STRIP", false);
// rel2abs: Conver a relative URL to an absolute URL
// Refer to RFC 1808
function rel2abs($rel, $base = null, $skip_fragment = false, $no_host = false, $rdiff = true)
{
// Keep the original. We may need to bounce intact later.
$rel_o = $rel;
// Make the base absolute first
if (!is_null($base)) {
$base = rel2abs($base);
// Default base to the current URL
} else {
$base = REQUEST_FULLURI;
}
// Skip the fragment
if (substr($rel, 0, 1) == "#" && $skip_fragment) {
return $rel;
}
// Return if it is completely empty (RFC 1808, 4, step 2, a)
if ($rel == "") {
return $base;
}
// Parse the URL first
$rel_a = parse_url_rfc1808($rel);
// Fail to parse - bounce intact
if (is_null($rel_a)) {
return $rel_o;
}
if ( !array_key_exists("net_loc", $rel_a)
&& array_key_exists("path", $rel_a)
&& substr($rel_a["path"], 0, 1) == "/"
&& $rdiff) {
$rel_a["path"] = ROOT_DIFF . $rel_a["path"];
}
$base_a = parse_url_rfc1808($base);
// Fail to parse - bounce intact
if (is_null($base_a)) {
return $rel_o;
}
if (!array_key_exists("path", $base_a)) {
$base_a["path"] = "/";
}
if (!array_key_exists("scheme", $base_a)) {
$base_a["scheme"] = "http";
}
// Return if it starts with a scheme (RFC 1808, 4, step 2, b)
if (array_key_exists("scheme", $rel_a)) {
return $rel;
}
// Inherit the scheme of the base URL (RFC 1808, 4, step 2, c)
$rel_a["scheme"] = $base_a["scheme"];
$skip_to_7 = false;
// The net_loc is not empty (RFC 1808, 4, step 3)
if (array_key_exists("net_loc", $rel_a)) {
$skip_to_7 = true;
// Inherit the net_loc of the base URL (if any)
} else {
if (array_key_exists("net_loc", $base_a)) {
$rel_a["net_loc"] = $base_a["net_loc"];
}
// The path is not relative (RFC 1808, 4, step 4)
if ( array_key_exists("path", $rel_a)
&& substr($rel_a["path"], 0, 1) == "/") {
$skip_to_7 = true;
} else {
// The path is empty (RFC 1808, 4, step 5)
if (!array_key_exists("path", $rel_a)) {
$rel_a["path"] = $base_a["path"];
// The params is not empty (RFC 1808, 4, step 5, a)
if (array_key_exists("params", $rel_a)) {
$skip_to_7 = true;
} else {
if (array_key_exists("params", $base_a)) {
$rel_a["params"] = $base_a["params"];
}
// The query is not empty (RFC 1808, 4, step 5, b)
if (array_key_exists("query", $rel_a)) {
$skip_to_7 = true;
} else {
if (array_key_exists("query", $base_a)) {
$rel_a["query"] = $base_a["query"];
}
$skip_to_7 = true;
}
}
}
}
}
// Resolve the path (RFC 1808, 4, step 6)
if (!$skip_to_7) {
$rel_a["path"] = preg_replace("/[^\/]+$/", "", $base_a["path"])
. $rel_a["path"];
$rel_a["path"] = stdpath($rel_a["path"]);
}
// Compose the URL (RFC 1808, 4, step 7)
$abs = "";
if (!$no_host) {
$abs .= $rel_a["scheme"] . ":";
if (array_key_exists("net_loc", $rel_a)) {
$abs .= "//" . $rel_a["net_loc"];
}
}
$abs .= $rel_a["path"];
if (array_key_exists("params", $rel_a)) {
$abs .= ";" . $rel_a["params"];
}
if (array_key_exists("query", $rel_a)) {
$abs .= "?" . $rel_a["query"];
}
if (array_key_exists("fragment", $rel_a)) {
$abs .= "#" . $rel_a["fragment"];
}
return $abs;
}
// abs2rel: Conver an absolute URL to a relative URL
function abs2rel($abs, $base = null)
{
// Keep the original. We may need to bounce intact later.
$abs_o = $abs;
// Make the base absolute first
if (!is_null($base)) {
$base = rel2abs($base);
// Default base to the current URL
} else {
$base = REQUEST_FULLURI;
}
$abs = rel2abs($abs, $base);
// Parse the URL first
$abs_a = parse_url_rfc1808($abs);
// Fail to parse - bounce intact
if (is_null($abs_a)) {
return $abs_o;
}
if (!array_key_exists("path", $abs_a)) {
$abs_a["path"] = "/";
}
$base_a = parse_url_rfc1808($base);
// Fail to parse - bounce intact
if (is_null($base_a)) {
return $abs_o;
}
// Return if not the same scheme
if ($abs_a["scheme"] != $base_a["scheme"]) {
return $abs;
}
unset($abs_a["scheme"]);
// Return if not the same network location (net_loc)
if ( !((!array_key_exists("net_loc", $abs_a)
&& !array_key_exists("net_loc", $base_a))
|| (array_key_exists("net_loc", $abs_a)
&& array_key_exists("net_loc", $base_a)
&& $abs_a["net_loc"] == $base_a["net_loc"]))) {
return $abs;
}
unset($abs_a["net_loc"]);
if (!array_key_exists("path", $abs_a)) {
$abs_a["path"] = "/";
}
// Different path -- find the path difference
if ($abs_a["path"] != $base_a["path"]) {
// Remove the last segment from the base URL
$base_path = preg_replace("/[^\/]+$/", "", $base_a["path"]);
$abs_path = $abs_a["path"];
// Remove the leading absolute slash
$base_path = preg_replace("/^\//", "", $base_path);
$abs_path = preg_replace("/^\//", "", $abs_path);
// Check each path segment from the left
while (preg_match("/^([^\/]+\/)(.*)$/", $base_path, $m)) {
// Not sharing the same path segment
if (substr($abs_path, 0, strlen($m[1])) != $m[1]) {
break;
}
$base_path = $m[2];
$abs_path = substr($abs_path, strlen($m[1]));
// Nothing left, but false is not what we want
if ($abs_path === false) {
$abs_path = "";
break;
}
}
// Turn each remaining segment to ".." and prepend it to the path
$abs_a["path"] = preg_replace("/[^\/]+/", "..", $base_path) . $abs_path;
// Remove the trailing slash of the ancestor directories
if ( $abs_a["path"] == "../"
|| preg_match("/\/\.\.\/$/", $abs_a["path"])) {
$abs_a["path"] = substr($abs_a["path"], 0, -1);
}
// Nothing left means the current directory
if ($abs_a["path"] == "") {
$abs_a["path"] = ".";
}
// Same path
} else {
// Different params
if ( !((!array_key_exists("params", $abs_a)
&& !array_key_exists("params", $base_a))
|| (array_key_exists("params", $abs_a)
&& array_key_exists("params", $base_a)
&& $abs_a["params"] == $base_a["params"]))) {
// No further checks
// Keep the last segment of the path
$abs_a["path"] = preg_replace("/^\/(?:[^\/]+\/)*/", "", $abs_a["path"]);
if ($abs_a["path"] == "") {
$abs_a["path"] = ".";
}
// Same params
} else {
// Different query
if ( !((!array_key_exists("query", $abs_a)
&& !array_key_exists("query", $base_a))
|| (array_key_exists("query", $abs_a)
&& array_key_exists("query", $base_a)
&& $abs_a["query"] == $base_a["query"]))) {
// No further checks
// Keep the last segment of the path
$abs_a["path"] = preg_replace("/^\/(?:[^\/]+\/)*/", "", $abs_a["path"]);
if ($abs_a["path"] == "") {
$abs_a["path"] = ".";
}
// Same query
} else {
// Everything is the same (fragment not counted)
// Keep only the fragment if there is a fragment
if (array_key_exists("fragment", $abs_a)) {
unset($abs_a["path"]);
unset($abs_a["params"]);
unset($abs_a["query"]);
// No fragment
} else {
// Keep the last segment of the path
$abs_a["path"] = preg_replace("/^\/(?:[^\/]+\/)*/", "", $abs_a["path"]);
if ($abs_a["path"] == "") {
$abs_a["path"] = ".";
}
}
}
}
}
// Compose the URL
$rel = "";
if (array_key_exists("path", $abs_a)) {
$rel .= $abs_a["path"];
}
if (array_key_exists("params", $abs_a)) {
$rel .= ";" . $abs_a["params"];
}
if (array_key_exists("query", $abs_a)) {
$rel .= "?" . $abs_a["query"];
}
if (array_key_exists("fragment", $abs_a)) {
$rel .= "#" . $abs_a["fragment"];
}
return $rel;
}
// stdpath: Standardize a path name
// Refer to RFC 1808, 4, step 6
function stdpath($path)
{
// Remove all the "./" (RFC 1808, 4, step 6, a)
$path = preg_replace("/(?<=\/)\.\//", "", $path);
$path = preg_replace("/^\.\//", "", $path);
// Remove the trailing "." (RFC 1808, 4, step 6, b)
$path = preg_replace("/(?<=\/)\.$/", "", $path);
// Remove all the "<segment>/../" (RFC 1808, 4, step 6, c)
while ( preg_match("/^(.*?)([^\/]+)\/\.\.\/(.*)$/", $path, $m)
&& $m[2] != "..") {
$path = $m[1] . $m[3];
}
// Remove the trailing "<segment>/.." (RFC 1808, 4, step 6, d)
while ( preg_match("/^(.*?)([^\/]+)\/\.\.$/", $path, $m)
&& $m[2] != "..") {
$path = $m[1];
}
return $path;
}
?>

View File

@@ -0,0 +1,139 @@
<?php
// File name: request.inc.php
// Description: PHP subroutine to handle the user requests
// Date: 2006-04-03
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2006-2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/callform.inc.php";
require_once "monica/chkfunc.inc.php";
require_once "monica/formfunc.inc.php";
require_once "monica/gettext.inc.php";
require_once "monica/guest.inc.php";
require_once "monica/sql.inc.php";
// Settings
if (!defined("USER_REQ_EXPIRE")) {
define("USER_REQ_EXPIRE", 72);
}
// fetch_curreq: Fetch the current request
function fetch_curreq()
{
// The error status
static $error = null;
// Fetched before
if (array_key_exists("REQUEST", $GLOBALS)) {
return $error;
}
// Obtain the current form
$FORM =& curform();
// No item specified
if (!array_key_exists("req", $FORM)) {
$error = array("msg"=>NC_("Please specify the request."),
"isform"=>false);
return $error;
}
$sn =& $FORM["req"];
// Find the record
if (!check_sn($sn)) {
$error = array("msg"=>NC_("Invalid request S/N: %s."),
"margs"=>array($FORM["req"]),
"isform"=>false);
return $error;
}
$cols = array();
$select = "SELECT * FROM userreq WHERE sn=$sn;\n";
$result = sql_query($select);
if (sql_num_rows($result) != 1) {
$error = array("msg"=>NC_("Invalid request S/N: %s."),
"margs"=>array($FORM["req"]),
"isform"=>false);
return $error;
}
$row = sql_fetch_assoc($result);
// Obtain the request arguments
$row["_args"] = $row["args"];
parse_str($row["_args"], $row["args"]);
// Obtain the user information
if (!is_null($row["usr"])) {
$row["_usr"] = $row["usr"];
$select = "SELECT * FROM users WHERE sn=" . $row["_usr"] . ";\n";
$result = sql_query($select);
$row["usr"] = sql_fetch_assoc($result);
}
// Local extension
if (function_exists("fetch_curreq_script")) {
$row = fetch_curreq_script($row);
}
$GLOBALS["REQUEST"] = $row;
is_form(true);
if ( !array_key_exists("step", curform())
&& array_key_exists("step", $row["args"])) {
form_step($row["args"]["step"]);
}
// OK
return null;
}
// is_userreq: If a request is requested
function is_userreq($isreq = null)
{
// Cache the result
static $cache;
// Use "isreq" to alter the cache
if (!is_null($isreq)) {
// A status is provided
if (is_array($isreq)) {
if (array_key_exists("isreq", $isreq)) {
$cache = $isreq["isreq"];
settype($cache, "boolean");
}
// A scalar value
} else {
$cache = $isreq;
settype($cache, "boolean");
}
}
// Return the cache
if (isset($cache)) {
return $cache;
}
// Obtain the current form
$FORM =& curform();
// No valid form infomation
if (!array_key_exists("req", $FORM)) {
$cache = false;
return $cache;
}
// "isreq" was specified
$status =& retrieve_status();
if (is_array($status) && array_key_exists("isreq", $status)) {
$cache = $status["isreq"];
return $cache;
}
// Yes, we have a request here
$cache = true;
return $cache;
}
// expire_userreq: Expire user requests
function expire_userreq()
{
$delete = "DELETE FROM userreq"
. " WHERE expire IS NOT NULL"
. " AND expire<now();\n";
gsql_query($delete);
return;
}
?>

View File

@@ -0,0 +1,216 @@
<?php
// File name: requri.inc.php
// Description: PHP subroutines to set the Request-URI variables
// Date: 2002-04-12
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2002-2008 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/cgiemu.inc.php";
require_once "monica/https.inc.php";
require_once "monica/parseurl.inc.php";
require_once "monica/server.inc.php";
// Initialize it
if (!defined("REQUEST_URI")) {
_requri_init();
}
// _requri_init: Obtain the REQUEST_URI
function _requri_init()
{
// Get the name of the script
// The last calling stack
$callers = debug_backtrace();
define("THIS_FILE", basename($callers[count($callers)-1]["file"]));
// Build the document root
// config.inc.php should always be put at /admin/lib/php/config.inc.php
if (defined("CONFIG_INC")) {
if (substr(CONFIG_INC, -29) == "/admin/lib/php/config.inc.php") {
define("DOC_ROOT", substr(CONFIG_INC, 0, -29));
}
}
if (!defined("DOC_ROOT")) {
define("DOC_ROOT", $_SERVER["DOCUMENT_ROOT"]);
}
// Find the root difference
// Apache's implementation
if (is_apache()) {
// Both mod_php5 and CGI use SCRIPT_FILENAME now
$file = $_SERVER["SCRIPT_FILENAME"];
// Microsoft IIS' implementation
} elseif (is_iis()) {
$file = $_SERVER["PATH_TRANSLATED"];
}
if (isset($file)) {
$len = strlen(DOC_ROOT);
if (substr($file, 0, $len) == DOC_ROOT) {
$script = substr($file, $len);
}
}
if (isset($script)) {
$len = strlen($script);
// Both mod_php5 and CGI use SCRIPT_NAME now
$script_name = is_apache()? $_SERVER["SCRIPT_NAME"]:
$_SERVER["PATH_INFO"];
if (substr($script_name, -$len) == $script) {
define("ROOT_DIFF", substr($script_name, 0, -$len));
} elseif (substr($script_name, -($len-4)) . ".php" == $script) {
define("ROOT_DIFF", substr($script_name, 0, -($len-4)));
}
}
// Assume no root difference if that is not available
if (!defined("ROOT_DIFF")) {
define("ROOT_DIFF", "");
}
// Build the REQUEST_PATH first
// Apache REQUEST_URI exists. Use it for simplicity and accuracy.
if (array_key_exists("REQUEST_URI", $_SERVER)) {
define("REQUEST_URI", $_SERVER["REQUEST_URI"]);
// If $_SERVER["REQUEST_URI"] contains a ":" somewhere (in query,
// for example), PHP's parse_url() will treat it as a port seperator
// and make a wrong parse result. We prevent this by adding a dummy
// scheme and net_loc to avoid this kinds of mistakes.
if (substr(REQUEST_URI, 0, 1) == "/") {
$url = parse_url_rfc1808("http://somewhere" . REQUEST_URI);
unset($url["scheme"]);
unset($url["net_loc"]);
} else {
$url = parse_url_rfc1808(REQUEST_URI);
}
$path = array_key_exists("path", $url)? $url["path"]: "/";
// Construct the REQUEST_PATH from scratches
// Avoid it whenever possible, since its result is not always right,
// especially for directory indices, like index.php.
} else {
$path = $_SERVER["SCRIPT_NAME"];
if ( !_requri_path_info_is_broken()
&& array_key_exists("PATH_INFO", $_SERVER)
&& $_SERVER["PATH_INFO"] != "") {
$path .= $_SERVER["PATH_INFO"];
}
$url = array();
}
$len = strlen(ROOT_DIFF);
define("REQUEST_PATH", $path == ""? "/":
(substr($path, 0, $len) == ROOT_DIFF?
substr($path, $len): $path));
// Set the REQUEST_FILE from REQUEST_PATH
$file = preg_replace("/^.*\//", "", REQUEST_PATH);
// Set to "." for directories, since we do not know what
// exact file name it should be
define("REQUEST_FILE", ($file == "")? ".": $file);
// Construct the REQUEST_URI
// REQUEST_URI is raw. All arguments are kept.
if (!defined("REQUEST_URI")) {
define("REQUEST_URI", REQUEST_PATH
. ((array_key_exists("QUERY_STRING", $_SERVER)
&& $_SERVER["QUERY_STRING"] != "")?
"?" . $_SERVER["QUERY_STRING"]: ""));
}
// Strip the unwanted arguments from the query string
$query = "";
if ( array_key_exists("QUERY_STRING", $_SERVER)
&& $_SERVER["QUERY_STRING"] != "") {
$query = _requri_clean_qs($_SERVER["QUERY_STRING"]);
}
// Construct the REQUEST_URI
define("REQUEST_FILEQS", REQUEST_FILE . $query);
// Construct the REQUEST_FULLURI, with the scheme and the host name
define("REQUEST_SCHEME", array_key_exists("scheme", $url)? $url["scheme"]:
(is_https()? "https": "http"));
if ( array_key_exists("net_loc", $url)) {
$net_loc = $url["net_loc"];
define("REQUEST_HOST", preg_replace("/:\d+$/", "", $net_loc));
} else {
define("REQUEST_HOST", array_key_exists("HTTP_HOST", $_SERVER)?
preg_replace("/:\d+$/", "", $_SERVER["HTTP_HOST"]):
$_SERVER["SERVER_NAME"]);
$net_loc = REQUEST_HOST;
if (is_https()) {
if ($_SERVER["SERVER_PORT"] != 443) {
$net_loc .= ":" . $_SERVER["SERVER_PORT"];
}
} else {
if ($_SERVER["SERVER_PORT"] != 80) {
$net_loc .= ":" . $_SERVER["SERVER_PORT"];
}
}
}
define("REQUEST_HOSTPORT", REQUEST_SCHEME . "://$net_loc" . ROOT_DIFF);
define("REQUEST_HOSTPATH", REQUEST_HOSTPORT . REQUEST_PATH);
if (substr(REQUEST_URI, 0, 1) != "/") {
define("REQUEST_FULLURI", REQUEST_URI);
} else {
define("REQUEST_FULLURI", REQUEST_SCHEME . "://$net_loc" . REQUEST_URI);
}
// Construct the cononical server name
if (!defined("CANONICAL_SERVER_NAME")) {
$host = (is_https()? "https": "http") . "://"
. preg_replace("/:\d+$/", "", $_SERVER["SERVER_NAME"]);
if (is_https()) {
if ($_SERVER["SERVER_PORT"] != 443) {
$host .= ":" . $_SERVER["SERVER_PORT"];
}
} else {
if ($_SERVER["SERVER_PORT"] != 80) {
$host .= ":" . $_SERVER["SERVER_PORT"];
}
}
define("CANONICAL_SERVER_NAME", $host);
}
return;
}
// _requri_clean_qs: Remove "lang" and session_name() from the query string
function _requri_clean_qs($qs)
{
$args = explode("&", $qs);
for ($i = 0; $i < count($args); $i++) {
// Only check well-formed query strings
if (preg_match("/^([^=]*)=(.*)$/", $args[$i], $m)) {
$name = urldecode($m[1]);
$val = urldecode($m[2]);
switch ($name) {
case "lang":
case session_name():
$args = array_merge(
array_slice($args, 0, $i),
array_slice($args, $i + 1)
);
$i--;
break;
default:
$args[$i] = rawurlencode($name) . "=" . rawurlencode($val);
break;
}
} else {
$args[$i] = rawurlencode(urldecode($args[$i]));
}
}
if (count($args) == 0) {
return "";
}
return "?" . implode("&", $args);
}
// _requri_path_info_is_broken: If PATH_INFO is broken
function _requri_path_info_is_broken()
{
// PATH_INFO is broken in Microsoft-IIS
return is_iis();
}
?>

View File

@@ -0,0 +1,29 @@
<?php
// File name: rfc1521.inc.php
// Description: PHP subroutine for RFC 1521 MIME related patterns
// Date: 2004-07-04
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2004-2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/rfc822.inc.php";
define("RFC1521_TSPECIALS", "[()<>@,;:\\\\\"\\/\\[\\]?=]");
define("RFC1521_TOKEN", "[^()<>@,;:\\\\\"\\/\\[\\]?= \\x01-\\x1F\\x7F]");
define("RFC1521_ATTRIBUTE", RFC1521_TOKEN);
define("RFC1521_VALUE", "(?:" . RFC1521_TOKEN . "|" . RFC822_QUOTED_STR . ")");
define("RFC1521_PARAMETER", RFC1521_ATTRIBUTE . "=" . RFC1521_VALUE);
// rfc1521_value_need_quoting: Whether a value need to be quoted by RFC-1521
function rfc1521_value_need_quoting($a)
{
return preg_match("/[()<>@,;:\\\\\"\\/\\[\\]?= \\x01-\\x1F\\x7F]/", $a)?
true: false;
}
?>

View File

@@ -0,0 +1,110 @@
<?php
// File name: rfc1738.inc.php
// Description: PHP regular expressions for RFC 1738 URL patterns
// Date: 2004-02-11
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2004-2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/rfc822.inc.php";
require_once "monica/html401.inc.php";
define("RFC1738_ALPHA", "[A-Za-z]");
define("RFC1738_DIGIT", "\\d");
define("RFC1738_DIGITS", "\\d+");
define("RFC1738_HEX", "[\\dA-Fa-f]");
define("RFC1738_ALPHADIGIT", "[A-Za-z\\d]");
define("RFC1738_SAFE", "[$\\-_\\.+]");
define("RFC1738_EXTRA", "[!*'(),]");
define("RFC1738_ESCAPE", "%" . RFC1738_HEX . "{2}");
define("RFC1738_RESERVED", "[;\\/?:@&=]");
// Alpha, digit, safe, extra
define("RFC1738_UNRESERVED", "[A-Za-z\\d$\\-_\\.+!*'(),]");
// Unreserved, reserved, escape
define("RFC1738_XCHAR", "(?:[A-Za-z\\d$\\-_\\.+!*'(),;\\/?:@&=]|" . RFC1738_ESCAPE . ")");
define("RFC1738_UCHAR", "(?:" . RFC1738_UNRESERVED . "|" . RFC1738_ESCAPE . ")");
define("RFC1738_SCHEME", "[A-Za-z\\d+\\-\\.]+");
define("RFC1738_DOMAINLABEL", "(?:" . RFC1738_ALPHADIGIT . "|"
. RFC1738_ALPHADIGIT . "(?:" . RFC1738_ALPHADIGIT . "|-)*" . RFC1738_ALPHADIGIT . ")");
define("RFC1738_TOPLABEL", "(?:" . RFC1738_ALPHA . "(?:" . RFC1738_ALPHADIGIT . "|-)*" . RFC1738_ALPHADIGIT . "|"
. RFC1738_ALPHA . ")");
define("RFC1738_HOSTNAME", "(?:" . RFC1738_DOMAINLABEL . "\\.)*" . RFC1738_TOPLABEL);
define("RFC1738_HOSTNUMBER", "\\d+\\.\\d+\\.\\d+\\.\\d+");
define("RFC1738_HOST", "(?:" . RFC1738_HOSTNAME . "|" . RFC1738_HOSTNUMBER . ")");
define("RFC1738_PORT", RFC1738_DIGITS);
define("RFC1738_USER", "(?:" . RFC1738_UCHAR . "|[;?&=])*");
define("RFC1738_PASSWORD", "(?:" . RFC1738_UCHAR . "|[;?&=])*");
define("RFC1738_HOSTPORT", RFC1738_HOST . "(?::" . RFC1738_PORT . ")?");
define("RFC1738_LOGIN", "(?:" . RFC1738_USER . "(?::" . RFC1738_PASSWORD . ")?@)?" . RFC1738_HOSTPORT);
// FTP, also section 3.2
define("RFC1738_FTPTYPE", "[AIDaid]");
define("RFC1738_FSEGMENT", "(?:" . RFC1738_UCHAR . "|[?:@&=])*");
define("RFC1738_FPATH", RFC1738_FSEGMENT . "(?:\\/" . RFC1738_FSEGMENT . ")*");
define("RFC1738_FTPURL", "[fF][tT][pP]:\\/\\/" . RFC1738_LOGIN . "(?:\\/" . RFC1738_FPATH . "(?:;type=" . RFC1738_FTPTYPE . ")?)?");
// FILE
define("RFC1738_FILEURL", "[fF][iI][lL][eE]:\\/\\/(?:" . RFC1738_HOST . "|localhost)?\\/" . RFC1738_FPATH);
// HTTP, also section 3.3
define("RFC1738_HSEGMENT", "(?:" . RFC1738_UCHAR . "|[;:@&=])*");
define("RFC1738_SEARCH", "(?:" . RFC1738_UCHAR . "|[;:@&=])*");
define("RFC1738_HPATH", RFC1738_HSEGMENT . "(?:\\/" . RFC1738_HSEGMENT . ")*");
// hostport should be login
define("RFC1738_HTTPURL", "[hH][tT][tT][pP]:\\/\\/" . RFC1738_HOSTPORT . "(?:\\/" . RFC1738_HPATH . "(?:\\?" . RFC1738_SEARCH . ")?)?");
// Local fix to HTTP URL
// hsegment does not include the tide "~" character (users' home direcories).
// It is a common practice now.
define("RFC1738_LOCAL_HSEGMENT", "(?:" . RFC1738_UCHAR . "|[;:@&=~])*");
// hostport should be login
define("RFC1738_LOCAL_HTTPURL", str_replace(RFC1738_HOSTPORT, RFC1738_LOGIN,
str_replace(RFC1738_HSEGMENT, RFC1738_LOCAL_HSEGMENT, RFC1738_HTTPURL))
. "(?:#" . HTML401_ID . ")?");
// HTTPS does not exist in RFC 1738
define("RFC1738_LOCAL_HTTPSURL", str_replace("[hH][tT][tT][pP]:", "[hH][tT][tT][pP][sS]:", RFC1738_HTTPURL));
// GOPHER
define("RFC1738_GTYPE", RFC1738_XCHAR);
define("RFC1738_SELECTOR", RFC1738_XCHAR . "*");
define("RFC1738_GOPHERP_STRING", RFC1738_XCHAR . "*");
define("RFC1738_GOPHERURL", "[gG][oO][pP][hH][eE][rR]:\\/\\/" . RFC1738_HOSTPORT . "(?:\\/(?:" . RFC1738_GTYPE . "(?:" . RFC1738_SELECTOR . "(?:%09" . RFC1738_SEARCH . "(?:" . RFC1738_GOPHERP_STRING . ")?)?)?)?)?");
// MAILTO
define("RFC1738_MAILTOURL", "[mM][aA][iI][lL][tT][oO]:" . RFC822_ADDR_SPEC);
// NEWS
define("RFC1738_GROUP", RFC1738_ALPHA . "[A-Za-z\\d\\-\\.+_]*");
define("RFC1738_ARTICLE", "(?:" . RFC1738_UCHAR . "|[;\\/?:&=])+@" . RFC1738_HOST);
define("RFC1738_GROUPPART", "(?:\\*|" . RFC1738_GROUP . "|" . RFC1738_ARTICLE . ")");
define("RFC1738_NEWSURL", "[nN][eE][wW][sS]:" . RFC1738_GROUPPART);
// NNTP
define("RFC1738_NNTPURL", "[nN][nN][tT][pP]:\\/\\/" . RFC1738_HOSTPORT . "\\/" . RFC1738_GROUP . "(?:\\/\\d+)?");
// TELNET
define("RFC1738_TELNETURL", "[tT][eE][lL][nN][eE][tT]:\\/\\/" . RFC1738_LOGIN . "\\/?");
// WAIS
define("RFC1738_DATABASE", RFC1738_UCHAR . "*");
define("RFC1738_WTYPE", RFC1738_UCHAR . "*");
define("RFC1738_WPATH", RFC1738_UCHAR . "*");
define("RFC1738_WAISDATABASE", "[wW][aA][iI][sS]:\\/\\/" . RFC1738_HOSTPORT . "\\/" . RFC1738_DATABASE);
define("RFC1738_WAISINDEX", "[wW][aA][iI][sS]:\\/\\/" . RFC1738_HOSTPORT . "\\/" . RFC1738_DATABASE . "\\?" . RFC1738_SEARCH);
define("RFC1738_WAISDOC", "[wW][aA][iI][sS]:\\/\\/" . RFC1738_HOSTPORT . "\\/" . RFC1738_DATABASE . "\\/" . RFC1738_WTYPE . "\\/" . RFC1738_WPATH);
define("RFC1738_WAISURL", "(?:" . RFC1738_WAISDOC . "|" . RFC1738_WAISINDEX . "|" . RFC1738_WAISDATABASE . ")");
// PROSPERO
define("RFC1738_FIELDNAME", "(?:" . RFC1738_UCHAR . "|[?:@&])*");
define("RFC1738_FIELDVALUE", "(?:" . RFC1738_UCHAR . "|[?:@&])*");
define("RFC1738_FIELDSPEC", ";" . RFC1738_FIELDNAME . "=" . RFC1738_FIELDVALUE);
define("RFC1738_PSEGMENT", "(?:" . RFC1738_UCHAR . "|[?:@&=])*");
define("RFC1738_PPATH", RFC1738_PSEGMENT . "(?:\\/" . RFC1738_PSEGMENT . ")*");
define("RFC1738_PROSPEROURL", "[pP][rR][oO][sS][pP][eE][rR][oO]:\\/\\/" . RFC1738_HOSTPORT . "\\/" . RFC1738_PPATH . "(?:" . RFC1738_FIELDSPEC . ")*");
?>

View File

@@ -0,0 +1,63 @@
<?php
// File name: rfc2396.inc.php
// Description: PHP regular expressions for RFC 2396 URL patterns
// Date: 2005-02-28
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2005-2007 Pristine Communications
// Section 1.6
define("RFC2396_LOWALPHA", "[a-z]");
define("RFC2396_UPALPHA", "[A-Z]");
define("RFC2396_ALPHA", "[A-Za-z]");
define("RFC2396_DIGIT", "\\d");
define("RFC2396_ALPHANUM", "[A-Za-z\\d]");
// Section 2.2
define("RFC2396_RESERVED", "[;\\/?:@&=+$,]");
// Section 2.3
define("RFC2396_MARK", "[\\-_\\.!~*'()]");
// alphanum, mark
define("RFC2396_UNRESERVED", "[A-Za-z\\d\\-_\\.!~*'()]");
// Section 2.4.1
define("RFC2396_HEX", "[\\dA-Fa-f]");
define("RFC2396_ESCAPED", "%" . RFC2396_HEX . "{2}");
// Chapter 2
define("RFC2396_URIC", "(?:" . RFC2396_RESERVED . "|" . RFC2396_UNRESERVED . "|" . RFC2396_ESCAPED . ")");
// Section 2.4.3
define("RFC2396_CONTROL", "[\\x00-\\x1F\\x7F]");
define("RFC2396_SPACE", " ");
define("RFC2396_DELIMS", "[<>#%\"]");
define("RFC2396_UNWISE", "[{}|\\\\^\\[\\]`]");
// Section 3.1
define("RFC2396_SCHEME", "[A-Za-z][A-Za-z+\\-\\.]*");
// Section 3.2.1
define("RFC2396_REG_NAME", "(?:" . RFC2396_UNRESERVED . "|" . RFC2396_ESCAPED . "|[$,;:@&=+])+");
// Section 3.2.2
define("RFC2396_DOMAINLABEL", RFC2396_ALPHANUM . "(?:[A-Za-z\\d\\-]*" . RFC2396_ALPHANUM . ")?");
define("RFC2396_TOPLABEL", RFC2396_ALPHA . "(?:[A-Za-z\\d\\-]*" . RFC2396_ALPHANUM . ")?");
define("RFC2396_HOSTNAME", "(?:" . RFC2396_DOMAINLABEL . "\\.)*" . RFC2396_TOPLABEL . "\\.?");
define("RFC2396_IPV4ADDRESS", "\\d+\\.\\d+\\.\\d+\\.\\d+");
define("RFC2396_HOST", "(?:" . RFC2396_HOSTNAME . "|" . RFC2396_IPV4ADDRESS . ")");
define("RFC2396_PORT", "\\d*");
define("RFC2396_HOSTPORT", RFC2396_HOST . "(?::" . RFC2396_PORT . ")?");
define("RFC2396_USERINFO", "(?:" . RFC2396_UNRESERVED . "|" . RFC2396_ESCAPED . "|[;:&=+$,])*");
define("RFC2396_SERVER", "(?:(?:" . RFC2396_USERINFO . ")?" . RFC2396_HOSTPORT . ")?");
// Section 3.2
define("RFC2396_AUTHORITY", "(?:" . RFC2396_SERVER . "|" . RFC2396_REG_NAME . ")");
// Section 3.3
define("RFC2396_PCHAR", "(?:" . RFC2396_UNRESERVED . "|" . RFC2396_ESCAPED . "|[:@&=+$,])");
define("RFC2396_PARAM", RFC2396_PCHAR . "*");
define("RFC2396_SEGMENT", RFC2396_PCHAR . "*(?:;" . RFC2396_PARAM . ")*");
define("RFC2396_PATH_SEGMENTS", RFC2396_SEGMENT . "(?:\\/" . RFC2396_SEGMENT . ")*");
// Section 3.4
define("RFC2396_QUERY", RFC2396_URIC . "*");
// Chapter 3
define("RFC2396_URIC_NO_SLASH", "(?:" . RFC2396_UNRESERVED . "|" . RFC2396_ESCAPED . "|[;?:@&=+$,])");
define("RFC2396_OPAQUE_PART", RFC2396_URIC_NO_SLASH . "(?:" . RFC2396_URIC . "*)");
define("RFC2396_ABS_PATH", "\\/" . RFC2396_PATH_SEGMENTS);
define("RFC2396_NET_PATH", "\\/\\/" . RFC2396_AUTHORITY . "(?:" . RFC2396_ABS_PATH . ")?");
define("RFC2396_HIER_PART", "(?:" . RFC2396_NET_PATH . "|" . RFC2396_ABS_PATH . ")");
define("RFC2396_ABSOLUTEURI", RFC2396_SCHEME . ":(?:" . RFC2396_HIER_PART . "|" . RFC2396_OPAQUE_PART .")(?:\\?" . RFC2396_QUERY . ")?");
// Section 3.3
define("RFC2396_PATH", "(?:" . RFC2396_ABS_PATH . "|" . RFC2396_OPAQUE_PART . ")?");
?>

View File

@@ -0,0 +1,31 @@
<?php
// File name: rfc822.inc.php
// Description: PHP subroutine for RFC 822 address related patterns
// Date: 2004-02-11
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2004-2007 Pristine Communications
define("RFC822_CTL", "[\\x01-\\x1F\\x7F]");
define("RFC822_SPECIALS", "[()<>@,;:\\\\\".\\[\\]]");
define("RFC822_ATOM", "[\\x21\\x23-\\x27\\x2A-\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x41-\\x5A\\x5E-\\x7E]+");
define("RFC822_DTEXT", "[^\"\\\\\r]");
define("RFC822_QUOTED_PAIR", "\\\\[\\x01-\\xFF]");
define("RFC822_DOMAIN_REF", RFC822_ATOM);
define("RFC822_DOMAIN_LITERAL", "\\[(?:" . RFC822_DTEXT . "|" . RFC822_QUOTED_PAIR . ")*\\]");
define("RFC822_SUB_DOMAIN", "(?:" . RFC822_DOMAIN_REF . "|" . RFC822_DOMAIN_LITERAL . ")");
define("RFC822_DOMAIN", RFC822_SUB_DOMAIN . "(?:\." . RFC822_SUB_DOMAIN . ")*");
define("RFC822_QUOTED_STR", "\"(?:" . RFC822_DTEXT . "|" . RFC822_QUOTED_PAIR . ")*\"");
define("RFC822_WORD", "(?:" . RFC822_ATOM . "|" . RFC822_QUOTED_STR . ")");
define("RFC822_LOCAL_PART", RFC822_WORD . "(?:\." . RFC822_WORD . ")*");
define("RFC822_ADDR_SPEC", RFC822_LOCAL_PART . "@" . RFC822_DOMAIN);
// rfc822_phrase_need_quoting: Whether a phrase need to be quoted by RFC-822
function rfc822_phrase_need_quoting($a)
{
return preg_match("/[()<>@,;:\\\\\".\\[\\]\\x01-\\x1F\\x7F]/", $a)?
true: false;
}
?>

View File

@@ -0,0 +1,40 @@
<?php
// File name: rmalldir.inc.php
// Description: PHP subroutine to remove a whole directory
// Date: 2004-03-01
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2004-2007 Pristine Communications
// rmalldir: Remove a whole directory
// Input: The directory $dir to be removed. It won't check at all
// Output: none
function rmalldir($dir)
{
// Non-existing
if (!file_exists($dir)) {
return;
}
// Get everything inside
$ents = array();
$dh = opendir($dir);
while (($ent = readdir($dh)) !== false) {
// Not a real entry
if ($ent == "." || $ent == "..") {
continue;
}
$ents[] = "$dir/$ent";
}
closedir($dh);
// Remove them
foreach ($ents as $ent) {
if (is_dir($ent)) {
rmalldir($ent);
} else {
unlink($ent);
}
}
rmdir($dir);
return;
}
?>

View File

@@ -0,0 +1,134 @@
<?php
// File name: rmofile.inc.php
// Description: PHP subroutine to remove the old page before creating a new one
// Date: 2003-03-28
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2003-2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/lninfo.inc.php";
require_once "monica/rel2abs.inc.php";
require_once "monica/requri.inc.php";
require_once "monica/xfileio.inc.php";
// rmoldpage: Remove the old page before creating a new one
// Input: The old page path $oldpage to be removed, and an optional new page
// path $newpage to be compared with. It won't check at all.
// Path is without DOC_ROOT
function rmoldpage($oldpage, $newpage = null)
{
// Get the available languages list
global $ALL_LINGUAS;
// Standardize it
$oldpage = stdpath($oldpage);
if (substr($oldpage, -1) == "/") {
$oldpage .= "index.html";
}
// The new file is supplied to be compared with
if (!is_null($newpage)) {
// Standardize it
$newpage = stdpath($newpage);
if (substr($newpage, -1) == "/") {
$newpage .= "index.html";
}
// Return if unchanged
if ($oldpage == $newpage) {
return;
}
}
// Unilingual
if (count($ALL_LINGUAS) == 1) {
$oldfile = DOC_ROOT . $oldpage;
if (!is_null($newpage)) {
$newfile = DOC_ROOT . $newpage;
rmoldfile($oldfile, $newfile);
} else {
rmoldfile($oldfile);
}
// Multilingual
} else {
for ($l = 0; $l < count($ALL_LINGUAS); $l++) {
$langfile = ln($ALL_LINGUAS[$l], LN_FILENAME);
$oldfile = DOC_ROOT . "/$langfile$oldpage";
if (!is_null($newpage)) {
$newfile = DOC_ROOT . "/$langfile$newpage";
rmoldfile($oldfile, $newfile);
} else {
rmoldfile($oldfile);
}
}
}
}
// rmoldfile: the real function
function rmoldfile($oldfile, $newfile = null)
{
// Obtain the parent directory
$parent = dirname($oldfile);
// Return if its parent is not a directory
if (!is_dir($parent)) {
return;
}
// Remove the file and its variants
$files = preg_match("/\.html$/", $oldfile)?
array($oldfile, "$oldfile.html", "$oldfile.xhtml"): array($oldfile);
foreach ($files as $file) {
if (!is_file($file) && !is_link($file)) {
continue;
}
// We can delete this file
if (is_writable($parent)) {
unlink($file);
// We cannot delete the file -- Empty it if possible
} else {
if (is_file($file) && is_writable($file)) {
xfwrite($file, "");
}
}
}
// Remove the parents as much as possible and necessary
while ($parent != "/") {
$dir = $parent;
// Coincident with the new path ends
if (!is_null($newfile) && substr($newfile, 0, strlen($dir) + 1) == $dir . "/") {
return;
}
// Obtain the parent directory
$parent = dirname($dir);
// Skip to the next parent if directory not exists
if (!file_exists($dir)) {
continue;
}
// We cannot remove, or the directory is not empty
if (!is_writable($parent) || !is_dir($dir) || _rmofile_dir_not_empty($dir)) {
return;
}
// Remove this directory
rmdir($dir);
}
}
// _rmofile_dir_not_empty: Check if a directory is empty
function _rmofile_dir_not_empty($dir)
{
$dh = opendir($dir);
while (($ent = readdir($dh)) !== false) {
// A real entry is found
if ($ent != "." && $ent != "..") {
closedir($dh);
return true;
}
}
// No real entry was found
closedir($dh);
return false;
}
?>

View File

@@ -0,0 +1,77 @@
<?php
// File name: runcmd.inc.php
// Description: PHP subroutine to run a command
// Date: 2004-03-31
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2004-2007 Pristine Communications
// xruncmd: Entended runcmd, which produce error when errno != 0
// Output: STDOUT
function xruncmd($cmd, $stdin)
{
// Deal with shell argument escapes
if (is_array($cmd)) {
$args = array();
foreach ($cmd as $arg) {
$args[] = escapeshellarg($arg);
}
$cmd = implode(" ", $args);
}
// Run the command
$exitno = runcmd($cmd, $stdin, $stdout, $stderr);
if ($exitno != 0) {
trigger_error("Failed executing command:\n$cmd\n"
. $stdout . $stderr . "exit no: $exitno", E_USER_ERROR);
}
return $stdout;
}
// runcmd: Run a command, return the exit code, STDOUT and STDERR
// Output: The exit return number
function runcmd($cmd, $stdin, &$stdout, &$stderr)
{
// Deal with shell argument escapes
if (is_array($cmd)) {
$args = array();
foreach ($cmd as $arg) {
$args[] = escapeshellarg($arg);
}
$cmd = implode(" ", $args);
}
// Run the command
$descriptorspec = array(
0 => array("pipe", "r"), // STDIN
1 => array("pipe", "w"), // STDOUT
2 => array("pipe", "w"), // STDERR
);
$proc = proc_open($cmd, $descriptorspec, $pipes);
// Send to STDIN
if (!is_null($stdin) && $stdin !== "") {
fwrite($pipes[0], $stdin);
}
fclose($pipes[0]);
// Read from STDOUT
$stdout = "";
while(!feof($pipes[1])) {
$stdout .= fread($pipes[1], 1024);
}
fclose($pipes[1]);
// Read from STDERR
$stderr = "";
while(!feof($pipes[2])) {
$stderr .= fread($pipes[2], 1024);
}
fclose($pipes[2]);
// Get the return code
$retval = proc_close($proc);
return $retval;
}
?>

View File

@@ -0,0 +1,105 @@
<?php
// File name: scptpriv.inc.php
// Description: PHP subroutines to check the script privilege
// Date: 2002-11-13
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2002-2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/chkpriv.inc.php";
require_once "monica/guest.inc.php";
require_once "monica/login.inc.php";
require_once "monica/requri.inc.php";
require_once "monica/server.inc.php";
require_once "monica/sql.inc.php";
// is_script_permitted: Check the script privilege
function is_script_permitted($script = null)
{
// Cache the result
static $cache = array();
// Default to the current script
if (is_null($script) || $script === true) {
// If Apache SCRIPT_FILENAME exists, use it with DOC_ROOT to decide the current script
if ( is_apache()
&& array_key_exists("SCRIPT_FILENAME", $_SERVER)
&& substr($_SERVER["SCRIPT_FILENAME"], 0, strlen(DOC_ROOT)) == DOC_ROOT) {
$script = substr($_SERVER["SCRIPT_FILENAME"], strlen(DOC_ROOT));
if (substr($script, -10) == "/index.php") {
$script = substr($script, 0, -9);
}
} else {
$script = REQUEST_PATH;
}
}
// Return the cache
if (array_key_exists($script, $cache)) {
return $cache[$script];
}
// Always true for super users
if (is_su()) {
$cache[$script] = true;
return $cache[$script];
}
// Obtain the permitted groups
$select = "SELECT groups.id AS grp FROM scptpriv"
. " INNER JOIN groups ON scptpriv.grp=groups.sn"
. " WHERE scptpriv.script='" . sql_esctext($script) . "';\n";
$result = sql_query($select);
$count = sql_num_rows($result);
for ($i = 0, $permgroups = array(); $i < $count; $i++) {
$row = sql_fetch_assoc($result);
$permgroups[] = $row["grp"];
}
// Only true for guests to act like ordinary administrators
if (is_guest() && count($permgroups) > 0) {
$cache[$script] = true;
return $cache[$script];
}
// Obtain the belonged groups
$curgroups = get_login_groups();
// If there is any intersection
if (count(array_intersect($curgroups, $permgroups)) > 0) {
$cache[$script] = true;
return $cache[$script];
}
// Default to false
$cache[$script] = false;
return $cache[$script];
}
// is_admin_script: If this is an administrative script
function is_admin_script($script = null)
{
// Cache the result
static $cache = array();
// Default to the current script
if (is_null($script)) {
$script = REQUEST_PATH;
}
// Return the cache
if (array_key_exists($script, $cache)) {
return $cache[$script];
}
// Respect the local checker
if (function_exists("is_admin_script_local")) {
$cache[$script] = is_admin_script_local($script);
// Else, check the "/admin/" prefix
} else {
$cache[$script] = substr($script, 0, 7) == "/admin/";
}
return $cache[$script];
}
?>

View File

@@ -0,0 +1,29 @@
<?php
// File name: server.inc.php
// Description: PHP subroutine to identify the server
// Date: 2004-03-05
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2004-2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/cgiemu.inc.php";
// is_apache: If this server is Apache
function is_apache()
{
return array_key_exists("SERVER_SOFTWARE", $_SERVER)
&& preg_match("/^Apache\b/", $_SERVER["SERVER_SOFTWARE"]);
}
// is_iis: If this server is Microsoft IIS
function is_iis()
{
return array_key_exists("SERVER_SOFTWARE", $_SERVER)
&& preg_match("/^Microsoft-(IIS|PWS)\b/", $_SERVER["SERVER_SOFTWARE"]);
}
?>

View File

@@ -0,0 +1,89 @@
<?php
// File name: sitesize.inc.php
// Description: PHP subroutines to calculate the size of the web site
// Date: 2007-08-09
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/echoform.inc.php";
require_once "monica/gettext.inc.php";
require_once "monica/htmlchar.inc.php";
require_once "monica/markabbr.inc.php";
require_once "monica/requri.inc.php";
require_once "monica/sql.inc.php";
// Settings
// This is true for almost all the cases
define("_SITESIZE_BLKSIZE", 512);
// sitesize: Calculate and return the size of the website
function sitesize()
{
$files = _sitesize_dirsize(DOC_ROOT);
$data = sql_dbsize();
return array(
"files" => $files,
"data" => $data,
"total" => $files + $data,
);
}
// html_sitesize: Print the size usage of the website
function html_sitesize()
{
$size = sitesize();
if ($size["data"] == 0) {
?><p class="sitesize"><?php printf(h(C_("Currently using files %s.\n")),
h_abbr(report_size($size["files"]))); ?></p>
<?php
} else {
?><p class="sitesize"><?php printf(h(C_("Currently using files %s, database %s, total %s.\n")),
h_abbr(report_size($size["files"])),
h_abbr(report_size($size["data"])),
h_abbr(report_size($size["total"]))); ?></p>
<?php
}
return;
}
// _sitesize_dirsize: Calculate the size of a directory
function _sitesize_dirsize($dir)
{
// Get everything inside
$ents = array();
$dh = opendir($dir);
while (($ent = readdir($dh)) !== false) {
// Not a real entry
if ($ent == "." || $ent == "..") {
continue;
}
$ents[] = "$dir/$ent";
}
closedir($dh);
$size = 0;
// Add the size of this directory
$stat = lstat($dir);
$size += $stat[12] * _SITESIZE_BLKSIZE;
for ($i = 0; $i < count($ents); $i++) {
// Directory - recursive into inside
if (is_dir($ents[$i]) && !is_link($ents[$i])) {
$size += _sitesize_dirsize($ents[$i]);
// Non-directory - add its size
} else {
$stat = lstat($ents[$i]);
$size += $stat[12] * _SITESIZE_BLKSIZE;
}
}
return $size;
}
?>

View File

@@ -0,0 +1,46 @@
<?php
// File name: spltline.inc.php
// Description: PHP subroutine to split long lines
// Date: 2004-07-04
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2004-2007 Pristine Communications
// split_long_lines: Split long lines (English only)
function split_long_lines($source, $line_width)
{
$pos = 0;
$result = "";
while (preg_match("/^(\S+[^\n\S]*|[^\n\S]+|\n+)/s", $source, $m)) {
$piece = $m[1];
// Text token
if (preg_match("/^\S/", $piece)) {
// Split line
if ($pos + strlen($piece) > $line_width) {
$result .= "\n";
$pos = 0;
}
$result .= $piece;
$pos += strlen($piece);
// Space token -- skip if over $line_width
} elseif (preg_match("/^[^\n\S]/", $piece)) {
// Split line
if ($pos + strlen($piece) > $line_width) {
$result .= "\n";
$pos = 0;
} else {
$result .= $piece;
$pos += strlen($piece);
}
// New-line token -- add it and reset the position
} else {
$result .= $piece;
$pos = 0;
}
$source = substr($source, strlen($piece));
}
return $result;
}
?>

439
lib/php/monica/sql.inc.php Normal file
View File

@@ -0,0 +1,439 @@
<?php
// File name: sql.inc.php
// Description: PHP meta subroutines to handle SQL actions
// Date: 2004-05-22
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2004-2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines with high precedence
require_once "monica/sqlconst.inc.php";
// Referenced subroutines
require_once "monica/mysql.inc.php";
require_once "monica/postgres.inc.php";
// Settings
// Settings are moved to sqlconst.inc.php
// sql_connect: Connect to the SQL database
function sql_connect()
{
switch ($GLOBALS["SQL_DBTYPE"]) {
case SQL_POSTGRESQL:
return xpg_connect();
break;
case SQL_MYSQL:
return xmysql_connect();
break;
}
}
// sql_close: Disconnect from the SQL database
function sql_close()
{
switch ($GLOBALS["SQL_DBTYPE"]) {
case SQL_POSTGRESQL:
return xpg_close();
case SQL_MYSQL:
return xmysql_close();
}
}
/////////////////////////
// Concurrency Control: Transactions and Locks
/////////////////////////
// sql_begin: Begin an SQL transaction
function sql_begin()
{
switch ($GLOBALS["SQL_DBTYPE"]) {
case SQL_POSTGRESQL:
return pg_begin();
case SQL_MYSQL:
return mysql_begin();
}
}
// sql_commit: Commit an SQL transaction
function sql_commit()
{
switch ($GLOBALS["SQL_DBTYPE"]) {
case SQL_POSTGRESQL:
return pg_commit();
case SQL_MYSQL:
return mysql_commit();
}
}
// sql_rollback: Rollback an SQL transaction
function sql_rollback()
{
switch ($GLOBALS["SQL_DBTYPE"]) {
case SQL_POSTGRESQL:
return pg_rollback();
case SQL_MYSQL:
return mysql_rollback();
}
}
// sql_lock: Lock and unlock the SQL tables
function sql_lock($locks = null)
{
switch ($GLOBALS["SQL_DBTYPE"]) {
case SQL_POSTGRESQL:
return pg_lock($locks);
case SQL_MYSQL:
return mysql_lock($locks);
}
}
// sql_query: Do an SQL query and report the error
function sql_query($query)
{
static $use_mtime;
switch ($GLOBALS["SQL_DBTYPE"]) {
case SQL_POSTGRESQL:
if (!isset($use_mtime)) {
$use_mtime = in_array("mtime", pg_tables());
}
$result = xpg_query($query);
// Update the mtime
if ($use_mtime) {
if (preg_match("/^(?:INSERT\s+INTO|UPDATE|DELETE\s+FROM)\s+(\S+)/i", $query, $m)) {
$table = $m[1];
$select_mtime = "SELECT * FROM mtime"
. " WHERE tabname='" . pg_escape_string($table) . "';\n";
$result_mtime = xpg_query($select_mtime);
// Found
if (pg_num_rows($result_mtime) == 1) {
// Update the mtime
$update = "UPDATE mtime SET mtime=now()"
. " WHERE tabname='" . pg_escape_string($table) . "';\n";
xpg_query($update);
// Not found
} else {
// Set the mtime
$insert = "INSERT INTO mtime (tabname, mtime) VALUES"
. "('" . pg_escape_string($table) . "', now());\n";
xpg_query($insert);
}
}
}
return $result;
case SQL_MYSQL:
if (!isset($use_mtime)) {
$use_mtime = in_array("mtime", mysql_tables());
}
$result = xmysql_query($query);
// Update the mtime
if ($use_mtime) {
if (preg_match("/^(?:INSERT\s+INTO|UPDATE|DELETE\s+FROM)\s+(\S+)/i", $query, $m)) {
$table = $m[1];
$select_mtime = "SELECT * FROM mtime"
. " WHERE tabname='" . mysql_escape_string($table) . "';\n";
$result_mtime = xmysql_query($select_mtime);
// Found
if (mysql_num_rows($result_mtime) == 1) {
// Update the mtime
$update = "UPDATE mtime SET mtime=now()"
. " WHERE tabname='" . mysql_escape_string($table) . "';\n";
xmysql_query($update);
// Not found
} else {
// Set the mtime
$insert = "INSERT INTO mtime (tabname, mtime) VALUES"
. "('" . mysql_escape_string($table) . "', now());\n";
xmysql_query($insert);
}
}
}
return $result;
}
}
// sql_seek: Move the SQL result pointer
function sql_seek($query, $offset)
{
switch ($GLOBALS["SQL_DBTYPE"]) {
case SQL_POSTGRESQL:
return pg_seek($query, $offset);
case SQL_MYSQL:
return mysql_seek($query, $offset);
}
}
// sql_num_rows: Return the number of rows
function sql_num_rows($result)
{
switch ($GLOBALS["SQL_DBTYPE"]) {
case SQL_POSTGRESQL:
return pg_num_rows($result);
case SQL_MYSQL:
return mysql_num_rows($result);
}
}
// sql_fetch_assoc: Return a row as an associative array
function sql_fetch_assoc($result)
{
switch ($GLOBALS["SQL_DBTYPE"]) {
case SQL_POSTGRESQL:
return xpg_fetch_assoc($result);
case SQL_MYSQL:
return xmysql_fetch_assoc($result);
}
}
// sql_fetch_row: Return a row as an numeric array
function sql_fetch_row($result)
{
switch ($GLOBALS["SQL_DBTYPE"]) {
case SQL_POSTGRESQL:
return xpg_fetch_row($result);
case SQL_MYSQL:
return xmysql_fetch_row($result);
}
}
// sql_tables: Return a list of available tables
function sql_tables($schema = null)
{
switch ($GLOBALS["SQL_DBTYPE"]) {
case SQL_POSTGRESQL:
return pg_tables($schema);
case SQL_MYSQL:
return mysql_tables($schema);
}
}
// sql_is_ml_table: Return if a table is multi-lingual
function sql_is_ml_table($table)
{
return (count(sql_cols_ml($table)) > 0);
}
// sql_cols: Return a list of available columns in a table
function sql_cols($table)
{
switch ($GLOBALS["SQL_DBTYPE"]) {
case SQL_POSTGRESQL:
return pg_cols($table);
case SQL_MYSQL:
return mysql_cols($table);
}
}
// sql_cols_ml: Return a list of multi-lingual columns in a table
function sql_cols_ml($table)
{
switch ($GLOBALS["SQL_DBTYPE"]) {
case SQL_POSTGRESQL:
return pg_cols_ml($table);
case SQL_MYSQL:
return mysql_cols_ml($table);
}
}
// sql_cols_nl: Return a list of columns without their multi-lingual
// deviants in a table
function sql_cols_nl($table)
{
switch ($GLOBALS["SQL_DBTYPE"]) {
case SQL_POSTGRESQL:
return pg_cols_nl($table);
case SQL_MYSQL:
return mysql_cols_nl($table);
}
}
// sql_cols_of_type: Return the columns in a certain data type
function sql_cols_of_type($result, $type, $format = SQL_FETCH_ASSOC)
{
switch ($GLOBALS["SQL_DBTYPE"]) {
case SQL_POSTGRESQL:
return pg_cols_of_type($result, $type, $format);
case SQL_MYSQL:
return mysql_cols_of_type($result, $type, $format);
}
}
// sql_col_lens: Return the column length in a table
function sql_col_lens($table)
{
switch ($GLOBALS["SQL_DBTYPE"]) {
case SQL_POSTGRESQL:
return pg_col_lens($table);
case SQL_MYSQL:
return mysql_col_lens($table);
}
}
// sql_strcat: Concatenate strings
function sql_strcat()
{
$strs = func_get_args();
switch ($GLOBALS["SQL_DBTYPE"]) {
case SQL_POSTGRESQL:
return call_user_func_array("pg_strcat", $strs);
case SQL_MYSQL:
return call_user_func_array("mysql_strcat", $strs);
}
}
// sql_lastupd: Obtain the last updated time of a list of tables
function sql_lastupd($tables)
{
switch ($GLOBALS["SQL_DBTYPE"]) {
case SQL_POSTGRESQL:
return pg_lastupd($tables);
case SQL_MYSQL:
return mysql_lastupd($tables);
}
}
// sql_dbsize: Obtain the size of the database
function sql_dbsize()
{
switch ($GLOBALS["SQL_DBTYPE"]) {
case SQL_NONE:
return 0;
case SQL_POSTGRESQL:
return pg_dbsize();
case SQL_MYSQL:
return mysql_dbsize();
}
}
// sql_date: Return date in a predefined format
function sql_date($expr, $format)
{
$strs = func_get_args();
switch ($GLOBALS["SQL_DBTYPE"]) {
case SQL_POSTGRESQL:
return pg_date($expr, $format);
case SQL_MYSQL:
return mysql_date($expr, $format);
}
}
// sql_re: Return the SQL regular expression operator
function sql_re()
{
$strs = func_get_args();
switch ($GLOBALS["SQL_DBTYPE"]) {
case SQL_POSTGRESQL:
return pg_re();
case SQL_MYSQL:
return mysql_re();
}
}
// sql_escblob: Escape a piece of BLOB octet
function sql_escblob($blob)
{
switch ($GLOBALS["SQL_DBTYPE"]) {
case SQL_POSTGRESQL:
return pg_escape_bytea($blob);
case SQL_MYSQL:
return mysql_escape_string($blob);
}
}
// sql_esctext: Escape a piece of text
function sql_esctext($text)
{
switch ($GLOBALS["SQL_DBTYPE"]) {
case SQL_POSTGRESQL:
return pg_escape_string($text);
case SQL_MYSQL:
return mysql_escape_string($text);
}
}
// sql_strlen: Calculate the length of a text string
// MySQL once used strlen(), but now mb_strlen() since 4.1
function sql_strlen($text)
{
switch ($GLOBALS["SQL_DBTYPE"]) {
case SQL_POSTGRESQL:
case SQL_MYSQL:
return mb_strlen($text);
}
}
// sql_support: Return if this SQL supports views
function sql_support($feature)
{
switch ($feature) {
// If view is supported
// MySQL once did not support, but support now since 5.0
case SQL_FEATURE_VIEW:
return true;
// If boolean data type is supported
case SQL_FEATURE_BOOLEAN:
if ($GLOBALS["SQL_DBTYPE"] == SQL_MYSQL) {
return false;
}
return true;
// Default to yes. ^^; We assume everyone is a good guy
default:
return true;
}
}
// sql_is_true: Return the expression for a boolean true
function sql_is_true($expr)
{
if (!sql_support(SQL_FEATURE_BOOLEAN)) {
return "$expr IS NOT NULL";
}
return $expr;
}
// sql_is_false: Return the expression for a boolean false
function sql_is_false($expr)
{
if (!sql_support(SQL_FEATURE_BOOLEAN)) {
return "$expr IS NULL";
}
return "NOT $expr";
}
// sql_true: Return the boolean true value
function sql_true()
{
if (!sql_support(SQL_FEATURE_BOOLEAN)) {
return "''";
}
return "TRUE";
}
// sql_false: Return the boolean false value
function sql_false()
{
if (!sql_support(SQL_FEATURE_BOOLEAN)) {
return "NULL";
}
return "FALSE";
}
// sql_esclike: Escape a phrase by the LIKE matching rule
// Double quote should never be used, according to
// the column name rules in the SQL standard.
function sql_esclike($phrase)
{
$phrase = str_replace("\\", "\\\\\\\\", $phrase);
$phrase = str_replace("%", "\\\\%", $phrase);
$phrase = str_replace("_", "\\\\_", $phrase);
// By the SQL standard
$phrase = str_replace("'", "''", $phrase);
// Loose way that works for some overly-simple, non-standard DBMS, like MySQL
//$phrase = str_replace("'", "\\\\\\'", $phrase);
return $phrase;
}
?>

View File

@@ -0,0 +1,38 @@
<?php
// File name: sqlconst.inc.php
// Description: PHP SQL constants
// Date: 2006-01-11
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2006-2007 Pristine Communications
// Settings
// SQL types
define("SQL_NONE", false);
define("SQL_POSTGRESQL", "PostgreSQL");
define("SQL_MYSQL", "MySQL");
$VALID_SQLS = array(SQL_NONE, SQL_POSTGRESQL, SQL_MYSQL);
$SQL_DBTYPE = SQL_NONE;
define("SQL_MLCOLS_NONE", false);
define("SQL_MLCOLS_SET", 1);
// SQL features
define("SQL_FEATURE_VIEW", "view");
define("SQL_FEATURE_BOOLEAN", "boolean");
// SQL data types
define("SQL_TYPE_BOOLEAN", "boolean");
define("SQL_TYPE_BLOB", "blob");
define("SQL_TYPE_INTEGER", "integer");
define("SQL_TYPE_BIGINT", "big_integer");
define("SQL_TYPE_FLOAT", "float");
// SQL fetch format
define("SQL_FETCH_ASSOC", "assoc");
define("SQL_FETCH_ROW", "row");
// SQL date format
define("SQL_YYYYMMDD", "YYYYMMDD");
define("SQL_YYYY_YYYYMMDD", "YYYY/YYYYMMDD");
define("SQL_MM_DD", "MM-DD");
define("SQL_M_D_EN", "M/D en");
define("SQL_M_D_ZHTW", "M/D zh-tw");
define("SQL_M_D_DE", "M/D de");
define("SQL_HH_MM", "HH:MM");
?>

View File

@@ -0,0 +1,139 @@
<?php
// File name: sqllogin.inc.php
// Description: PHP meta subroutines to obtain the SQL log-in information
// Date: 2006-02-02
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2006-2007 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/sqlconst.inc.php";
// get_sql_login_info: Obtain the SQL log-in information
function get_sql_login_info($type, $database = null, $host = null, $user = null)
{
// DBMS naming convension
switch ($type) {
case SQL_POSTGRESQL:
$names = array("PGHOST", "PGUSER", "PGPASSWORD", "PGDATABASE");
break;
case SQL_MYSQL:
$names = array("MYSQL_HOST", "MYSQL_USER", "MYSQL_PW", "MYSQL_DB");
break;
}
// Initialize the return values
$login = array(
$names[0] => null,
$names[1] => null,
$names[2] => null,
$names[3] => null,
);
// Obtain the SQL log-in information from the environment
$sqllogin = getenv("SQLLOGIN");
if ($sqllogin !== false) {
// Parse the SQL log-in information
// The first matched line is used, so put the default first
$sqllogin = base64_decode($sqllogin);
// Find all the matching records
$matches = array();
$lineno = 0;
$lines = explode("\n", $sqllogin);
foreach ($lines as $line) {
$cols = explode("\t", $line);
if (count($cols) == 4) {
$cols[] = "";
}
// Skip malformed lines
if (count($cols) != 5) {
continue;
}
// Not this DBMS type
if ($cols[0] != $type) {
continue;
}
for ($i = 0; $i < count($cols); $i++) {
if ($cols[$i] == "") {
$cols[$i] = null;
}
}
$count = 0;
$score = 0;
// Match this database?
if (is_null($database) || is_null($cols[4])) {
} elseif ($cols[4] == $database) {
$count++;
$score += 3;
} else {
continue;
}
// Match this user?
if (is_null($user) || is_null($cols[2])) {
} elseif ($cols[2] == $user) {
$count++;
$score += 2;
} else {
continue;
}
// Match this host?
if (is_null($host) || is_null($cols[1])) {
} elseif ($cols[1] == $host) {
$count++;
$score += 1;
} else {
continue;
}
$matches[] = array(
"host" => $cols[1],
"user" => $cols[2],
"password" => $cols[3],
"database" => $cols[4],
"matches" => $count,
"score" => $score,
"lineno" => ++$lineno,
);
}
if (count($matches) > 0) {
usort($matches, "_sqllogin_sort_matches");
$login[$names[0]] = $matches[0]["host"];
$login[$names[1]] = $matches[0]["user"];
$login[$names[2]] = $matches[0]["password"];
$login[$names[3]] = $matches[0]["database"];
}
}
// Apply the specified information
if (!is_null($database) && is_null($login[$names[3]])) {
$login[$names[3]] = $database;
}
if (!is_null($host) && is_null($login[$names[0]])) {
$login[$names[0]] = $host;
}
if (!is_null($user) && is_null($login[$names[1]])) {
$login[$names[1]] = $user;
}
// PostgreSQL database name cannot be empty
if ($type == SQL_POSTGRESQL && is_null($login[$names[3]])) {
$login[$names[3]] = "test";
}
return $login;
}
// _sqllogin_sort_matches: sort the matching lines
function _sqllogin_sort_matches($a, $b)
{
if ($a["matches"] != $b["matches"]) {
return $b["matches"] - $a["matches"];
}
if ($a["score"] != $b["score"]) {
return $b["score"] - $a["score"];
}
return $a["lineno"] - $b["lineno"];
}
?>

View File

@@ -0,0 +1,32 @@
<?php
// File name: timezone.inc.php
// Description: PHP subroutines to deal with time zone information
// Date: 2004-04-05
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2004-2007 Pristine Communications
// timezone_iso: Return the timezone in ISO 8601 format
function timezone_iso()
{
// Cache the result
static $cache;
// Return the cache
if (isset($cache)) {
return $cache;
}
// Calculate the time zone string
$tzsec = date("Z");
$tzsign = ($tzsec >= 0? "+": "-");
$tzsec = abs($tzsec);
$tzmin = floor($tzsec / 60);
$tzsec = $tzsec % 60;
$tzhr = floor($tzmin / 60);
$tzmin = $tzmin % 60;
$tz = sprintf("%s%02d:%02d", $tzsign, $tzhr, $tzmin);
// Cache it
$cache = $tz;
return $tz;
}
?>

View File

@@ -0,0 +1,22 @@
<?php
// File name: trimtext.inc.php
// Description: PHP subroutine to trim a textarea input
// Date: 2004-06-10
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2004-2007 Pristine Communications
// trimtext: Trim a textarea input, remove excess spaces
function trimtext($a)
{
// Format the textarea input to UNIX text format
$a = str_replace("\r\n", "\n", $a);
// Trim the excess leading and trailing lines and spaces
// This is not working. Long articles may overload the PCRE limit.
//$a = preg_replace("/^(?:[^\S\n]*\n)*(.*?)\s*$/us", "\\1", $a);
$a = preg_replace("/^(?:[^\S\n]*\n)+/s", "", rtrim($a));
// Remove the excess spaces at the end of each line
$a = preg_replace("/[^\S\n]+\n/", "\n", $a);
return $a;
}
?>

Some files were not shown because too many files have changed in this diff Show More