// Copyright: Copyright (C) 2004-2013 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/addget.inc.php"; require_once "monica/callform.inc.php"; require_once "monica/cgiemu.inc.php"; require_once "monica/chkfunc.inc.php"; require_once "monica/chkpriv.inc.php"; require_once "monica/chkwrite.inc.php"; require_once "monica/cracklib.inc.php"; require_once "monica/echoform.inc.php"; require_once "monica/email.inc.php"; require_once "monica/getlang.inc.php"; require_once "monica/gettext.inc.php"; require_once "monica/guest.inc.php"; require_once "monica/http.inc.php"; require_once "monica/lninfo.inc.php"; require_once "monica/login.inc.php"; require_once "monica/mimetype.inc.php"; require_once "monica/passwd.inc.php"; require_once "monica/pic.inc.php"; require_once "monica/request.inc.php"; require_once "monica/requri.inc.php"; require_once "monica/rfc2396.inc.php"; require_once "monica/sql.inc.php"; require_once "monica/trimtext.inc.php"; require_once "monica/upload.inc.php"; require_once "monica/userhome.inc.php"; require_once "monica/username.inc.php"; require_once "monica/usrconst.inc.php"; require_once "monica/xfileio.inc.php"; require_once "monica/zh2py.inc.php"; // BaseChecker: Base form checker class class BaseChecker { protected $_form; protected $_iscur = null; protected $_isreq = null; protected $_sn = null; protected $_table; public $maxlens; public $minlens; // __construct: Initialize the checker function __construct(&$form, $table) { $this->_form =& $form; $this->_table = $table; if (!is_null($table)) { $this->maxlens = sql_col_lens($table); } $this->minlens = array(); $this->minlens["id"] = 3; $this->_iscur = array_key_exists("CURRENT", $GLOBALS); if ($this->_iscur && array_key_exists("sn", $form)) { $this->_sn = $form["sn"]; } $this->_isreq = is_userreq(); } // check: Run a list of checks function check($cols) { // Check the list itself first foreach ($cols as $col) { if (!method_exists($this, "_check_$col")) { trigger_error("Called an undefined check \"$col\"", E_USER_ERROR); } } // Run each checker foreach ($cols as $col) { $error = call_user_func(array(&$this, "_check_$col")); if (!is_null($error)) { return $error; } } return null; } // redir: Check and redirect to another form function redir($cols) { // Check the list itself first foreach ($cols as $col) { if (!method_exists($this, "_redir_$col")) { trigger_error("Called an undefined redirection \"$col\"", E_USER_ERROR); } } // Check each redirection foreach ($cols as $col) { call_user_func(array(&$this, "_redir_$col")); } return; } // save_uploaded: Check and save the uploaded file function save_uploaded($cols) { // Check the list itself first foreach ($cols as $col) { if (!method_exists($this, "_save_uploaded_$col")) { trigger_error("Called an undefined uploaded file handler \"$col\"", E_USER_ERROR); } } // Check each uploaded file $errors = array(); foreach ($cols as $col) { $error = call_user_func(array(&$this, "_save_uploaded_$col")); if (!is_null($error)) { // A list of errors if (array_key_exists(0, $error)) { $errors = array_merge($errors, $error); } else { $errors[] = $error; } } } switch (count($errors)) { // OK case 0: return null; case 1: return $errors[0]; default: return array("errors"=>$errors); } } ///////////////////////// // Private column checkers. Do not call them directly. // Add or override the column checkers when needed. // Method names must be in the following format: // function _check_{column}() { ... } // Columns started with underlines are reserved for internal use, as usual. ///////////////////////// // _check_usr: The default user checker function _check_usr() { // Check if it exists $error = $this->_missing("usr"); if (!is_null($error)) { return $error; } // Regularize it $this->_form["usr"] = trim($this->_form["usr"]); // Check if it is filled if ($this->_form["usr"] == "") { return array("msg"=>NC_("Please select a user.")); } // Check if this user exists if (!check_sn_in($this->_form["usr"], "users")) { return array("msg"=>NC_("This user does not exist anymore. Please select another one.")); } // OK return null; } // _check_grp: The default group checker function _check_grp() { // Check if it exists $error = $this->_missing("grp"); if (!is_null($error)) { return $error; } // Regularize it $this->_form["grp"] = trim($this->_form["grp"]); // Check if it is filled if ($this->_form["grp"] == "") { return array("msg"=>NC_("Please select a group.")); } // Check if the group exists if (!check_sn_in($this->_form["grp"], "groups")) { return array("msg"=>NC_("This group does not exist anymore. Please select another one.")); } // OK return null; } // _check_script: The default script checker function _check_script() { // Check if it exists $error = $this->_missing("script"); if (!is_null($error)) { return $error; } // Regularize it $this->_form["script"] = trim($this->_form["script"]); // Check if it is filled if ($this->_form["script"] == "") { return array("msg"=>NC_("Please fill in the script.")); } // Check the length if (sql_strlen($this->_form["script"]) > $this->maxlens["script"]) { return array("msg"=>NC_("This script is too long. (Max. length %d)"), "margs"=>array($this->maxlens["script"])); } // Check if this script exists if (!check_script($this->_form["script"])) { return array("msg"=>NC_("This script is not a valid script. Please specify another one.")); } // OK return null; } // _check_date: The default date checker function _check_date() { // Check if it exists $error = $this->_missing("date"); if (!is_null($error)) { return $error; } // Regularize it $this->_form["date"] = trim($this->_form["date"]); // Check if it is filled if ($this->_form["date"] == "") { return array("msg"=>NC_("Please fill in the date.")); } // Check the length if (sql_strlen($this->_form["date"]) != $this->maxlens["date"]) { return array("msg"=>NC_("Please fill in a valid date in YYYY-MM-DD format.")); } // Check the date format if (!preg_match("/^(\d{4})-(\d{2})-(\d{2})$/", $this->_form["date"], $m)) { return array("msg"=>NC_("Please fill in a valid date in YYYY-MM-DD format.")); } if (!checkdate($m[2], $m[3], $m[1])) { return array("msg"=>NC_("Please fill in a valid date in YYYY-MM-DD format.")); } // OK return null; } // _check_id: The default ID. checker function _check_id() { // Check if it exists $error = $this->_missing("id"); if (!is_null($error)) { return $error; } // Regularize it $this->_form["id"] = trim($this->_form["id"]); // Check if it is filled if ($this->_form["id"] == "") { return array("msg"=>NC_("Please fill in the ID.")); } // Check the length if (sql_strlen($this->_form["id"]) > $this->maxlens["id"]) { return array("msg"=>NC_("This ID. is too long. (Max. length %d)"), "margs"=>array($this->maxlens["id"])); } if (sql_strlen($this->_form["id"]) < $this->minlens["id"]) { return array("msg"=>NC_("This ID. is too short. (Min. length %d)"), "margs"=>array($this->minlens["id"])); } // Check if the characters used are valid if (!preg_match("/^[a-z][a-z0-9_]*$/", $this->_form["id"])) { return array("msg"=>NC_("Only lower-case English letters, numbers and underscores are allowed for the ID.")); } // OK return null; } // _check_ord: The default order checker function _check_ord() { // Check if it exists $error = $this->_missing("ord"); if (!is_null($error)) { return $error; } $min = 0; $max = pow(10, $this->maxlens["ord"]) - 1; // Text string if (is_string($this->_form["ord"])) { // Regularize it $this->_form["ord"] = trim($this->_form["ord"]); // Check if it is filled if ($this->_form["ord"] == "") { return array("msg"=>NC_("Please fill in the order.")); } // Check the length if (sql_strlen($this->_form["ord"]) > $this->maxlens["ord"]) { return array("msg"=>NC_("This order is too long. (Max. length %d)"), "margs"=>array($this->maxlens["ord"])); } // If there is any non-digit character if (preg_match("/\D/", $this->_form["ord"])) { return array("msg"=>NC_("Please fill in a positive integer order.")); } // Check if it is in the valid range if ($this->_form["ord"] < $min) { return array("msg"=>NC_("The order is too small. Please fill in a larger order between %d and %d."), "margs"=>array($min, $max)); } // It is not possible to be too large now. // Convert its type to integer settype($this->_form["ord"], "integer"); // Integer } elseif (is_int($this->_form["ord"])) { // Check if it is in the valid range if ($this->_form["ord"] < $min) { return array("msg"=>NC_("The order is too small. Please fill in a larger order between %d and %d."), "margs"=>array($min, $max)); } if ($this->_form["ord"] > $max) { return array("msg"=>NC_("The order is too large. Please fill in a smaller order between %d and %d."), "margs"=>array($min, $max)); } // Other types are non-sense } else { trigger_error("Unknown type for column \"ord\"", E_USER_ERROR); } // OK return null; } // _check_path: The default page order checker function _check_path() { // Get the available languages list global $ALL_LINGUAS; // Check if it exists $error = $this->_missing("path"); if (!is_null($error)) { return $error; } // Regularize it $this->_form["path"] = trim($this->_form["path"]); // Remove the trailing excess "index.html" $this->_form["path"] = preg_replace("/\/index\.html?$/i", "/", $this->_form["path"]); // Check if it is filled if ($this->_form["path"] == "") { return array("msg"=>NC_("Please fill in the page path.")); } // Check the length if (sql_strlen($this->_form["path"]) > $this->maxlens["path"]) { return array("msg"=>NC_("This page path is too long. (Max. length %d)"), "margs"=>array($this->maxlens["path"])); } // Check if this item is duplicated $conds = array(); $conds[] = "path='" . sql_esctext($this->_form["path"]) . "'"; if ($this->_iscur) { $conds[] = "sn!=" . $this->_sn; } $select = "SELECT * FROM " . $this->_table . " WHERE " . implode(" AND ", $conds) . ";\n"; $result = sql_query($select); if (sql_num_rows($result) != 0) { return array("msg"=>NC_("This page already exists. You cannot create a duplicated one.")); } // Check if the path is absolute if (substr($this->_form["path"], 0, 1) != "/") { return array("msg"=>NC_("Please fill in an absolute page path.")); } // Check if the path is legal if (!preg_match("/^\\/" . RFC2396_PATH_SEGMENTS . "$/", $this->_form["path"])) { return array("msg"=>NC_("Please fill in a valid page path.")); } // Check if it is the cover home page if ($this->_form["path"] == "/") { return array("msg"=>NC_("You cannot overwrite the cover home page.")); } // Check if it is *.html if (!preg_match("/(?:\/|\.html)$/", $this->_form["path"])) { return array("msg"=>NC_("You can only fill in an HTML page path (*.html).")); } // Check if we are permitted to write files there if (count($ALL_LINGUAS) > 1) { $pathpat = DOC_ROOT . "/%s" . $this->_form["path"]; if (substr($pathpat, -1, 1) == "/") { $pathpat .= "index.html"; } for ($l = 0; $l < count($ALL_LINGUAS); $l++) { $langfile = ln($ALL_LINGUAS[$l], LN_FILENAME); $error = check_writable(sprintf($pathpat, $langfile)); if (!is_null($error)) { return $error; } } } else { $path = DOC_ROOT . $this->_form["path"]; if (substr($path, -1, 1) == "/") { $path .= "index.html"; } $error = check_writable(DOC_ROOT . $path); if (!is_null($error)) { return $error; } } // OK return null; } // _check_attdsc: The default attachment description checker function _check_attdsc() { // Skip if there is no file to check $error = $this->_missing("att"); if (!is_null($error)) { return null; } // Check if it exists $error = $this->_missing("attdsc"); if (!is_null($error)) { // No attdsc will be sent when uploading an attachment from nothing return array("msg"=>NC_("Please fill in the attachment description.")); } // Regularize it $this->_form["attdsc"] = trim($this->_form["attdsc"]); // Check if it is filled if ($this->_form["attdsc"] == "") { return array("msg"=>NC_("Please fill in the attachment description.")); } // Check the length if (sql_strlen($this->_form["attdsc"]) > $this->maxlens["attdsc"]) { return array("msg"=>NC_("This attachment description is too long. (Max. length %d)"), "margs"=>array($this->maxlens["attdsc"])); } // OK return null; } // _check_pdf: The default PDF. file checker function _check_pdf() { // Skip if there is no file to check $error = $this->_missing("pdf"); if (!is_null($error)) { return null; } // Check if this file exists if (!savefile_exists($this->_form["pdf"])) { return array("msg"=>NC_("This PDF. file does not exist anymore. Please upload another one.")); } // Obtain the file deposit $FILES =& file_deposit(); $file =& $FILES[$this->_form["pdf"]]; // Check if this size is too large if ($file["size"] > $this->maxlens["pdf"]) { return array("msg"=>NC_("This PDF. file is too large. (Max. size %s)"), "margs"=>array(report_size($this->maxlens["pdf"]))); } // Check if the file type is valid if ($file["type"] != "application/pdf") { return array("msg"=>NC_("Please upload only PDF. file.")); } // OK return null; } // _check_title: The default title checker function _check_title() { // Check if it exists $error = $this->_missing("title"); if (!is_null($error)) { return $error; } // Regularize it $this->_form["title"] = trim($this->_form["title"]); // Check if it is filled if ($this->_form["title"] == "") { return array("msg"=>NC_("Please fill in the title.")); } // Check the length if (sql_strlen($this->_form["title"]) > $this->maxlens["title"]) { return array("msg"=>NC_("This title is too long. (Max. length %d)"), "margs"=>array($this->maxlens["title"])); } // OK return null; } // _check_subject: Check the subject function _check_subject() { // Check if it exists $error = $this->_missing("subject"); if (!is_null($error)) { return $error; } // Regularize it $this->_form["subject"] = trim($this->_form["subject"]); // Check if it is filled if ($this->_form["subject"] == "") { return array("msg"=>NC_("Please fill in the subject.")); } // Check the length if (sql_strlen($this->_form["subject"]) > $this->maxlens["subject"]) { return array("msg"=>NC_("This subject is too long. (Max. length %d)"), "margs"=>array($this->maxlens["subject"])); } // OK return null; } // _check_body: The default content body checker function _check_body() { // Check if it exists $error = $this->_missing("body"); if (!is_null($error)) { return $error; } // Regularize it $this->_form["body"] = trimtext($this->_form["body"]); // Check if it is filled if ($this->_form["body"] == C_("Fill in the content here.")) { $this->_form["body"] = ""; } if ($this->_form["body"] == "") { return array("msg"=>NC_("Please fill in the content.")); } // Check the length if (sql_strlen($this->_form["body"]) > $this->maxlens["body"]) { return array("msg"=>NC_("This content is too long. (Max. length %d)"), "margs"=>array($this->maxlens["body"])); } // OK return null; } // _check_kw: The default keyword list checker function _check_kw() { // Check if it exists $error = $this->_missing("kw"); if (!is_null($error)) { return $error; } // Regularize it $this->_form["kw"] = trim($this->_form["kw"]); // Check if it is filled if ($this->_form["kw"] == "") { return array("msg"=>NC_("Please fill in the keywords.")); } // Check the length if (sql_strlen($this->_form["kw"]) > $this->maxlens["kw"]) { return array("msg"=>NC_("This keyword list is too long. (Max. length %d)"), "margs"=>array($this->maxlens["kw"])); } // OK return null; } // _check_pinyin: The default pinyin checker function _check_pinyin() { // Skip if there is no Chinese if ($this->_missing("chinese")) { return null; } // Check if it exists $error = $this->_missing("pinyin"); if (!is_null($error)) { return array("msg"=>NC_("Please select a proper pinyin.")); } // Regularize it $this->_form["pinyin"] = trim($this->_form["pinyin"]); // Check the length if (sql_strlen($this->_form["pinyin"]) > $this->maxlens["pinyin"]) { return array("msg"=>NC_("This pinyin is too long. (Max. length %d)"), "margs"=>array($this->maxlens["pinyin"])); } // Check if the pinyin is in our safe list if (!in_array($this->_form["pinyin"], zh2pys($this->_form["chinese"]))) { return array("msg"=>NC_("This pinyin does not match the Chinese. Please select a proper pinyin from the list.")); } // OK return null; } // _check_pic: The default picture checker function _check_pic() { // Check if it exists $error = $this->_missing("pic"); if (!is_null($error)) { // Check against the default language // Only check if multilingual, not in the default language and column is multilingual if ( ($this->_iscur || $this->_isreq) && count($GLOBALS["ALL_LINGUAS"]) > 1 && getlang() != DEFAULT_LANG && in_array("pic", sql_cols_ml($this->_table))) { $lndbdef = ln(DEFAULT_LANG, LN_DATABASE); if ($this->_isreq) { $defpic = $GLOBALS["REQUEST"]["args"]["pic_$lndbdef"]; } else { $defpic = $GLOBALS["CURRENT"]["pic_$lndbdef"]; } // Check if there is a matching column to the default language if (!is_null($defpic)) { return array("msg"=>N_("Please upload the picture.")); } } return null; } // Check if this picture exists if (!pic_exists($this->_form["pic"])) { return array("msg"=>NC_("This picture does not exist anymore. Please upload another one.")); } // Obtain the picture deposit $PICS =& pic_deposit(); // Check the length if (strlen($PICS[$this->_form["pic"]]["content"]) > $this->maxlens["pic"]) { return array("msg"=>NC_("This picture is too large. Please upload another one. (Max. size %d)"), "margs"=>array($this->maxlens["pic"])); } // Check against the default language // Only check if multilingual, not in the default language and column is multilingual if ( ($this->_iscur || $this->_isreq) && count($GLOBALS["ALL_LINGUAS"]) > 1 && getlang() != DEFAULT_LANG && in_array("pic", sql_cols_ml($this->_table))) { $lndbdef = ln(DEFAULT_LANG, LN_DATABASE); if ($this->_isreq) { $defpic = $GLOBALS["REQUEST"]["args"]["pic_$lndbdef"]; } else { $defpic = $GLOBALS["CURRENT"]["pic_$lndbdef"]; } // Check if we start from the default language if (!pic_exists($defpic)) { return array("msg"=>NC_("Please upload a new picture from %s."), "margs"=>array("_DEFAULT_LANG")); } } // OK return null; } // _check_piccap: The default picture caption checker function _check_piccap() { // Skip if there is no picture now if ($this->_missing("pic")) { unset($this->_form["piccap"]); return null; } // Check if it exists $error = $this->_missing("piccap"); if (!is_null($error)) { return $error; } // Regularize it $this->_form["piccap"] = trim($this->_form["piccap"]); // Check if it is filled if ($this->_form["piccap"] == "") { return array("msg"=>NC_("Please fill in the picture caption.")); } // Check the length if (sql_strlen($this->_form["piccap"]) > $this->maxlens["piccap"]) { return array("msg"=>NC_("This picture caption is too long. (Max. length %d)"), "margs"=>array($this->maxlens["piccap"])); } // OK return null; } // _check_picpos: The default picture position checker function _check_picpos() { // Skip if there is no picture now if ($this->_missing("pic")) { unset($this->_form["picpos"]); return null; } // Check if it exists $error = $this->_missing("picpos"); if (!is_null($error)) { return array("msg"=>NC_("Please select the picture position.")); } // Regularize it $this->_form["picpos"] = trim($this->_form["picpos"]); // Check if the picture position is legal if (!in_array($this->_form["picpos"], $GLOBALS["PIC_VALID_POS"])) { return array("msg"=>NC_("This picture position is invalid. Please choose a proper picture position.")); } // OK return null; } // _check_called_form: Check if this form is a called form function _check_called_form() { // Check if it exists $error = $this->_missing("caller", "cformid"); if (!is_null($error)) { return $error; } // OK return null; } // _check_cap: The default picture caption checker function _check_cap() { // Skip if there is no picture now if ($this->_missing("pic")) { unset($this->_form["cap"]); return null; } // Check if it exists $error = $this->_missing("cap"); if (!is_null($error)) { return $error; } // Regularize it $this->_form["cap"] = trim($this->_form["cap"]); // Check if it is filled if ($this->_form["cap"] == "") { return array("msg"=>NC_("Please fill in the picture caption.")); } // Check the length if (sql_strlen($this->_form["cap"]) > $this->maxlens["cap"]) { return array("msg"=>NC_("This picture caption is too long. (Max. length %d)"), "margs"=>array($this->maxlens["cap"])); } // OK return null; } // _check_pos: The default picture position checker function _check_pos() { // Skip if there is no picture now if ($this->_missing("pic")) { unset($this->_form["pos"]); return null; } // Check if it exists $error = $this->_missing("pos"); if (!is_null($error)) { return array("msg"=>NC_("Please select the picture position.")); } // Regularize it $this->_form["pos"] = trim($this->_form["pos"]); // Check if the picture position is legal if (!in_array($this->_form["pos"], $GLOBALS["PIC_VALID_POS"])) { return array("msg"=>NC_("This picture position is invalid. Please choose a proper picture position.")); } // OK return null; } // __check_upload: The default file checker function __check_upload($col) { // Skip if multi-lingual and not in the default language if ( ($this->_iscur || $this->_isreq) && count($GLOBALS["ALL_LINGUAS"]) > 1 && getlang() != DEFAULT_LANG && in_array($col, sql_cols_ml($this->_table))) { $defcol = $col . "_" . ln(DEFAULT_LANG, LN_DATABASE); $deffile = $this->_isreq? $GLOBALS["REQUEST"]["args"][$defcol]: $GLOBALS["CURRENT"][$defcol]; if (!savefile_exists($deffile)) { return null; } } // Check if it exists $error = file_has("up$col"); if (!is_null($error)) { return $error; } // Check the file upload status switch ($_FILES["up$col"]["error"]) { // Success case UPLOAD_ERR_OK: return null; // Nothing uploaded case UPLOAD_ERR_NO_FILE: return null; // Below are errors case UPLOAD_ERR_INI_SIZE: return array("msg"=>NC_("Your uploaded file is too large (Max %s)."), "margs"=>array(get_cfg_var("upload_max_filesize"))); case UPLOAD_ERR_FORM_SIZE: return array("msg"=>NC_("Your uploaded 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.")); default: return array("msg"=>NC_("Upload failed with an unknown error (%d)."), "margs"=>array($_FILES["up$col"]["error"])); } } ///////////////////////// // Private form redirectors. Do not call them directly. // Add redirector definitions here. // Method names must be in the following format: // function _redir_{column}() { ... } // Columns started with underlines are reserved for internal use, as usual. ///////////////////////// // _redir_del: Suspend and move to the deletion form function _redir_del() { // Skip if not requested if ($this->_missing("del")) { return; } $args = array(); $args[] = "form=del"; if (!$this->_missing("sn")) { $args[] = "sn=" . $this->_form["sn"]; } elseif (!$this->_missing("req")) { $args[] = "req=" . $this->_form["req"]; } call_form(FORM_THIS, $args, null); } // _redir_cancel: Cancel the form and return to the originator function _redir_cancel() { // Skip if not requested if ($this->_missing("cancel")) { return; } // A calling form -- return to the caller if (!$this->_missing("caller", "cformid")) { $url = $this->_form["caller"]; if (!$this->_missing("hostport")) { $url = $this->_form["hostport"] . $url; } $url = add_get_arg($url, "formid", $this->_form["cformid"]); if ($_SERVER["REQUEST_METHOD"] == "POST") { http_303($url); } else { http_307($url); } } // Referer2 specified -- return to referer2 if (!$this->_missing("referer2")) { $url = $this->_form["referer2"]; // Return to the hostport } elseif (!$this->_missing("hostport")) { $url = $this->_form["hostport"] . userhome(); } else { $url = userhome(); } if ($_SERVER["REQUEST_METHOD"] == "POST") { http_303($url); } else { http_307($url); } } // _redir_selgrp: Suspend and move to the group selection form function _redir_selgrp() { // Skip if not requested if ($this->_missing("selgrp")) { return; } call_form(FORM_GROUPS, null, "import_selgrp"); } // _redir_delgrp: Remove the group function _redir_delgrp() { // Skip if not requested if ($this->_missing("delgrp")) { return; } // Remove the item unset($this->_form["grp"]); $status = null; success_redirect($status); } // _redir_setpic: Suspend and move to the picture manager function _redir_setpic() { // Skip if not requested if ($this->_missing("setpic")) { return; } // There is a current picture if (!$this->_missing("pic")) { $args = array(); $args[] = "form=cur"; $args[] = "sn=" . urlencode($this->_form["pic"]); call_form(FORM_PIC, $args, "import_setpic"); // There is no current picture } else { $args = array(); $args[] = "form=new"; call_form(FORM_PIC, $args, "import_setpic"); } } // _redir_delpic: Remove the picture function _redir_delpic() { // Skip if not requested if ($this->_missing("delpic")) { return; } // Remove the item unset($this->_form["pic"]); unset($this->_form["piccap"]); unset($this->_form["picpos"]); $status = null; success_redirect($status); } // _redir_delfile: Remove the file function _redir_delfile() { // Skip if not requested if ($this->_missing("delfile")) { return; } // Remove the file unset($this->_form["file"]); $status = null; success_redirect($status); } // _redir_delatt: Remove the attachment file function _redir_delatt() { // Skip if not requested if ($this->_missing("delatt")) { return; } // Remove the file unset($this->_form["att"]); $status = null; success_redirect($status); } // _redir_delpdf: Remove the PDF. file function _redir_delpdf() { // Skip if not requested if ($this->_missing("delpdf")) { return; } // Remove the file unset($this->_form["pdf"]); $status = null; success_redirect($status); } // _redir_selpage: Suspend and move to the page selection form function _redir_selpage() { // Skip if not requested if ($this->_missing("selpage")) { return; } call_form(FORM_PAGES, null, "import_selpage"); } // _redir_selnews: Suspend and move to the news article selection form function _redir_selnews() { // Skip if not requested if ($this->_missing("selnews")) { return; } call_form(FORM_NEWS, null, "import_selnews"); } // _redir_delnews: Remove the news article function _redir_delnews() { // Skip if not requested if ($this->_missing("delnews")) { return; } // Remove the item unset($this->_form["news"]); $status = null; success_redirect($status); } // _redir_sellink: Suspend and move to the related link selection form function _redir_sellink() { // Skip if not requested if ($this->_missing("sellink")) { return; } call_form(FORM_LINKS, null, "import_sellink"); } // _redir_dellink: Remove the link function _redir_dellink() { // Skip if not requested if ($this->_missing("dellink")) { return; } // Remove the item unset($this->_form["link"]); $status = null; success_redirect($status); } // _redir_selparent: Suspend and move to the parent selection form function _redir_selparent() { // Skip if not requested if ($this->_missing("selparent")) { return; } call_form(FORM_THIS, null, "import_selparent"); } // _redir_delparent: Remove the parent function _redir_delparent() { // Skip if not requested if ($this->_missing("delparent")) { return; } // Remove the item unset($this->_form["parent"]); $status = null; success_redirect($status); } ///////////////////////// // Private uploaded file handlers. Do not call them directly. // Add uploaded file handlers definitions here. // Method names must be in the following format: // function _save_uploaded_{column}() { ... } // Columns started with underlines are reserved for internal use, as usual. ///////////////////////// // _save_uploaded_pdf: Check and save the uploaded PDF. file function _save_uploaded_pdf() { // Skip if multi-lingual and not in the default language if ( ($this->_iscur || $this->_isreq) && count($GLOBALS["ALL_LINGUAS"]) > 1 && getlang() != DEFAULT_LANG && in_array("pdf", sql_cols_ml($this->_table))) { $defcol = "pdf_" . ln(DEFAULT_LANG, LN_DATABASE); $deffile = $this->_isreq? $GLOBALS["REQUEST"]["args"][$defcol]: $GLOBALS["CURRENT"][$defcol]; if (!savefile_exists($deffile)) { return null; } } // Check with the basic upload checker $error = $this->__check_upload("pdf"); if (!is_null($error)) { return $error; } // Skip if no new file was submitted if ($_FILES["uppdf"]["error"] == UPLOAD_ERR_NO_FILE) { return null; } $type = check_mime_type($_FILES["uppdf"]["tmp_name"], $_FILES["uppdf"]["name"], $_FILES["uppdf"]["type"]); // Save the file $file = array(); $file["content"] = xfread($_FILES["uppdf"]["tmp_name"]); $file["name"] = $_FILES["uppdf"]["name"]; $file["type"] = $type; $file["size"] = strlen($file["content"]); $fileid = suspend_file($file); $this->_form["pdf"] = $fileid; // Do not confirm now if (!$this->_missing("confirm")) { unset($this->_form["confirm"]); } // OK return null; } // _save_uploaded_att: Check and save the uploaded attachment file function _save_uploaded_att() { // Skip if multi-lingual and not in the default language if ( ($this->_iscur || $this->_isreq) && count($GLOBALS["ALL_LINGUAS"]) > 1 && getlang() != DEFAULT_LANG && in_array("att", sql_cols_ml($this->_table))) { $defcol = "att_" . ln(DEFAULT_LANG, LN_DATABASE); $deffile = $this->_isreq? $GLOBALS["REQUEST"]["args"][$defcol]: $GLOBALS["CURRENT"][$defcol]; if (!savefile_exists($deffile)) { return null; } } // Check with the basic upload checker $error = $this->__check_upload("att"); if (!is_null($error)) { return $error; } // Skip if no new file was submitted if ($_FILES["upatt"]["error"] == UPLOAD_ERR_NO_FILE) { return null; } $type = check_mime_type($_FILES["upatt"]["tmp_name"], $_FILES["upatt"]["name"], $_FILES["upatt"]["type"]); // Save the file $file = array(); $file["content"] = xfread($_FILES["upatt"]["tmp_name"]); $file["name"] = $_FILES["upatt"]["name"]; $file["type"] = $type; $file["size"] = strlen($file["content"]); $fileid = suspend_file($file); $this->_form["att"] = $fileid; // Do not confirm now if (!$this->_missing("confirm")) { unset($this->_form["confirm"]); } // OK return null; } // _save_uploaded_file: Check and save the uploaded file function _save_uploaded_file() { // Skip if multi-lingual and not in the default language if ( ($this->_iscur || $this->_isreq) && count($GLOBALS["ALL_LINGUAS"]) > 1 && getlang() != DEFAULT_LANG && in_array("file", sql_cols_ml($this->_table))) { $defcol = "file_" . ln(DEFAULT_LANG, LN_DATABASE); $deffile = $this->_isreq? $GLOBALS["REQUEST"]["args"][$defcol]: $GLOBALS["CURRENT"][$defcol]; if (!savefile_exists($deffile)) { return null; } } // Check with the basic upload checker $error = $this->__check_upload("file"); if (!is_null($error)) { return $error; } // Skip if no new file was submitted if ($_FILES["upfile"]["error"] == UPLOAD_ERR_NO_FILE) { return null; } $type = check_mime_type($_FILES["upfile"]["tmp_name"], $_FILES["upfile"]["name"], $_FILES["upfile"]["type"]); // Save the file $file = array(); $file["content"] = xfread($_FILES["upfile"]["tmp_name"]); $file["name"] = $_FILES["upfile"]["name"]; $file["type"] = $type; $file["size"] = strlen($file["content"]); $fileid = suspend_file($file); $this->_form["file"] = $fileid; // Do not confirm now if (!$this->_missing("confirm")) { unset($this->_form["confirm"]); } // OK return null; } ///////////////////////// // Private utility methods. Do not override them. ///////////////////////// // _missing: Check if a column is submitted function _missing() { $cols = func_get_args(); foreach ($cols as $col) { if (!array_key_exists($col, $this->_form)) { return array("msg"=>NC_("The following field was not received: \"%s\"."), "margs"=>array($col), "isform"=>false); } } // OK return null; } } ///////////////////////// // Account Checkers: Checkers for the account management system ///////////////////////// // UserChecker: User form checker class class UserChecker extends BaseChecker { protected $_is_guest = null; // __construct: Initialize the checker function __construct(&$form, $table = "users") { parent::__construct($form, $table); $this->maxlens["passwd"] = 100; $this->minlens["passwd"] = 6; } // check: Run a list of checks function check($cols) { // Check the guest flag first $this->_is_guest(); // Run the parent method $error = parent::check($cols); if (!is_null($error)) { return $error; } return null; } // _is_guest: If the user being edited is a guest function _is_guest() { // Checked before if (!is_null($this->_is_guest)) { return $this->_is_guest; } for ($i = 0; !$this->_missing("supgroup$i" . "sn"); $i++) { // Skip unselected groups if ($this->_missing("supgroup$i")) { continue; } // Check if this is the guest group if (groupid($this->_form["supgroup$i" . "sn"]) == GUEST_GROUP) { $this->_is_guest = true; return true; } } // No guest group was found $this->_is_guest = false; return false; } // _check_id: Check the user ID. function _check_id() { // Skip for a non-super-user editing a super-user if ($this->_iscur && !is_su() && is_su($this->_sn)) { return null; } // Check if it exists $error = $this->_missing("id"); if (!is_null($error)) { return $error; } // Regularize it $this->_form["id"] = trim($this->_form["id"]); // Check if it is filled if ($this->_form["id"] == "") { return array("msg"=>NC_("Please fill in the user ID.")); } // Check the length if (sql_strlen($this->_form["id"]) > $this->maxlens["id"]) { return array("msg"=>NC_("This user ID. is too long. (Max. length %d)"), "margs"=>array($this->maxlens["id"])); } if (sql_strlen($this->_form["id"]) < $this->minlens["id"]) { return array("msg"=>NC_("This user ID. is too short. (Min. length %d)"), "margs"=>array($this->minlens["id"])); } // Check if the characters used are valid if (!preg_match("/^[a-z][a-z0-9@.\-_]*$/", $this->_form["id"])) { return array("msg"=>NC_("Only lower-case English letters, numbers, at-signs, dots, dashes and underscores are allowed for the user ID.")); } // Check if this item is duplicated $conds = array(); $conds[] = "id='" . sql_esctext($this->_form["id"]) . "'"; if ($this->_iscur) { $conds[] = "sn!=" . $this->_sn; } $select = "SELECT * FROM " . $this->_table . " WHERE " . implode(" AND ", $conds) . ";\n"; $result = sql_query($select); if (sql_num_rows($result) != 0) { return array("msg"=>NC_("This user already has an account. You cannot create a duplicated one.")); } // OK return null; } // _check_passwd: Check the user password function _check_passwd() { // Skip for a non-super-user editing a super-user if ($this->_iscur && !is_su() && is_su($this->_sn)) { return null; } // Set the passwords with the password registry $dummy = str_repeat("*", 16); sync_saved_passwd($this->_form, $dummy); // Skip password checking for guests if ($this->_is_guest()) { return null; } // Check if it exists $error = $this->_missing("passwd", "passwd2"); if (!is_null($error)) { return $error; } // Regularize it $this->_form["passwd"] = trim($this->_form["passwd"]); $this->_form["passwd2"] = trim($this->_form["passwd2"]); // Check if it is filled if (!$this->_iscur && $this->_form["passwd"] == "") { return array("msg"=>NC_("Please fill in the password.")); } if ($this->_form["passwd"] != "" && $this->_form["passwd2"] == "") { return array("msg"=>NC_("Please confirm the password.")); } // Check the length if (sql_strlen($this->_form["passwd"]) > $this->maxlens["passwd"]) { return array("msg"=>NC_("This password is too long. (Max. length %d)"), "margs"=>array($this->maxlens["passwd"])); } if ( $this->_form["passwd"] != "" && sql_strlen($this->_form["passwd"]) < $this->minlens["passwd"]) { return array("msg"=>NC_("This password is too short. (Min. length %d)"), "margs"=>array($this->minlens["passwd"])); } // Check if two passwords are consistent if ($this->_form["passwd"] != $this->_form["passwd2"]) { return array("msg"=>NC_("The 2 passwords are different. Please fill in the password again.")); } if ($this->_form["passwd"] != "") { // Check the password strength with cracklib if (!crack_check($this->_form["passwd"])) { // See the message from cracklib/fscist.c switch (crack_getlastmessage()) { // FascistGecos() /* case "you are not registered in the password file": return array("msg"=>NC_("You are not registered.")); */ case "it is based on your username": return array("msg"=>NC_("This password is based on the user ID.")); /* case "it is based upon your password entry": return array("msg"=>NC_("This password is based upon the personal information.")); case "it is derived from your password entry": case "it's derived from your password entry": return array("msg"=>NC_("This password is derived from the personal information.")); case "it is derivable from your password entry": case "it's derivable from your password entry": return array("msg"=>NC_("This password is derivable from the personal information.")); */ // FascistLook() /* case "it's WAY too short": case "it is too short": return array("msg"=>NC_("This password is too short. (Min. length %d)"), "margs"=>array($this->minlens["passwd"])); */ case "it does not contain enough DIFFERENT characters": return array("msg"=>NC_("This password does not contain enough different characters.")); /* case "it is all whitespace": return array("msg"=>NC_("This password is all whitespace.")); */ case "it is too simplistic/systematic": return array("msg"=>NC_("This password is too simplistic/systematic.")); /* case "it looks like a National Insurance number": return array("msg"=>NC_("This password looks like a National Insurance number.")); */ case "it is based on a dictionary word": return array("msg"=>NC_("This password is based on a dictionary word.")); case "it is based on a (reversed) dictionary word": return array("msg"=>NC_("This password is based on a (reversed) dictionary word.")); default: return array("msg"=>NC_("This password is too simple.")); } } // Check if the password is based on the user ID. if ( !$this->_missing("id") && strpos(strtolower($this->_form["passwd"]), strtolower($this->_form["id"])) !== false) { return array("msg"=>NC_("You cannot use a password that is based on the user ID.")); } } // OK return null; } // _check_name: Check the user name function _check_name() { // Check if it exists $error = $this->_missing("name"); if (!is_null($error)) { return $error; } // Regularize it $this->_form["name"] = trim($this->_form["name"]); // Check if it is filled if ($this->_form["name"] == "") { return array("msg"=>NC_("Please fill in the name.")); } // Check the length if (sql_strlen($this->_form["name"]) > $this->maxlens["name"]) { return array("msg"=>NC_("This name is too long. (Max. length %d)"), "margs"=>array($this->maxlens["name"])); } // OK return null; } // _check_email: Check the user e-mail function _check_email($col = "email") { // Check if it exists $error = $this->_missing($col); if (!is_null($error)) { return $error; } // Regularize it $this->_form[$col] = trim($this->_form[$col]); // Check if it is filled if ($this->_form[$col] == "") { return array("msg"=>NC_("Please fill in the e-mail.")); } // Check the length if (sql_strlen($this->_form[$col]) > $this->maxlens[$col]) { return array("msg"=>NC_("This e-mail is too long. (Max. length %d)"), "margs"=>array($this->maxlens[$col])); } if (sql_strlen($this->_form[$col]) < $this->minlens[$col]) { return array("msg"=>NC_("This e-mail is too short. (Min. length %d)"), "margs"=>array($this->minlens[$col])); } // Check the e-mail validity switch (is_email($this->_form[$col])) { case ISEMAIL_OK: break; case ISEMAIL_MALFORMED: default: return array("msg"=>NC_("Please fill in a valid e-mail address.")); case ISEMAIL_DOMAIN_NOT_FOUND: return array("msg"=>NC_("The domain of this e-mail does not exists. Check if there is any typo in it.")); } // OK return null; } // _check_supgroup: Check the belonging groups function _check_supgroup() { // Skip for a non-super-user editing herself if ($this->_iscur && !is_su() && $this->_sn == get_login_sn()) { return null; } for ($i = 0, $items = array(); !$this->_missing("supgroup$i" . "sn"); $i++) { // Skip unselected ones if ($this->_missing("supgroup$i")) { continue; } // Regularize it $this->_form["supgroup$i" . "sn"] = trim($this->_form["supgroup$i" . "sn"]); // Check if this selection is duplicated if (in_array($this->_form["supgroup$i" . "sn"], $items)) { return array("msg"=>NC_("This belonging group is duplicated. You cannot set duplicated ones.")); } $items[] = $this->_form["supgroup$i" . "sn"]; // Check with the subform checker $form = array(); $form["grp"] =& $this->_form["supgroup$i" . "sn"]; if ($this->_iscur) { $form["member"] =& $this->_sn; } $checker = new UserMembershipChecker($form); $error = $checker->check(array("grp")); if (!is_null($error)) { return $error; } // Check if a special group is submitted switch (groupid($this->_form["supgroup$i" . "sn"])) { case SU_GROUP: return array("msg"=>NC_("You cannot submit the super-user group along with other groups.")); case ADMIN_GROUP: return array("msg"=>NC_("You cannot set the administrators group.")); case ALLUSERS_GROUP: return array("msg"=>NC_("You cannot set the all-users group.")); } } // OK return null; } } // GroupChecker: Group form checker class class GroupChecker extends BaseChecker { // __construct: Initialize the checker function __construct(&$form, $table = "groups") { parent::__construct($form, $table); } // _check_id: Check the group ID. function _check_id() { // Skip for a non-super-user editing a super-user group if ($this->_iscur && !is_su() && $this->_sn == su_group_sn()) { return null; } // Check if it exists $error = $this->_missing("id"); if (!is_null($error)) { return $error; } // Regularize it $this->_form["id"] = trim($this->_form["id"]); // Check if it is filled if ($this->_form["id"] == "") { return array("msg"=>NC_("Please fill in the group ID.")); } // Check the length if (sql_strlen($this->_form["id"]) > $this->maxlens["id"]) { return array("msg"=>NC_("This group ID. is too long. (Max. length %d)"), "margs"=>array($this->maxlens["id"])); } if (sql_strlen($this->_form["id"]) < $this->minlens["id"]) { return array("msg"=>NC_("This group ID. is too short. (Min. length %d)"), "margs"=>array($this->minlens["id"])); } // Check if the characters used are valid if (!preg_match("/^[a-z][a-z0-9_]*$/", $this->_form["id"])) { return array("msg"=>NC_("Only lower-case English letters, numbers and underscores are allowed for the group ID.")); } // Check if this item is duplicated $conds = array(); $conds[] = "id='" . sql_esctext($this->_form["id"]) . "'"; if ($this->_iscur) { $conds[] = "sn!=" . $this->_sn; } $select = "SELECT * FROM " . $this->_table . " WHERE " . implode(" AND ", $conds) . ";\n"; $result = sql_query($select); if (sql_num_rows($result) != 0) { return array("msg"=>NC_("This group already exists. You cannot create a duplicated one.")); } // OK return null; } // _check_dsc: Check the group description function _check_dsc() { // Check if it exists $error = $this->_missing("dsc"); if (!is_null($error)) { return $error; } // Regularize it $this->_form["dsc"] = trim($this->_form["dsc"]); // Check if it is filled if ($this->_form["dsc"] == "") { return array("msg"=>NC_("Please fill in the privilege description.")); } // Check the length if (sql_strlen($this->_form["dsc"]) > $this->maxlens["dsc"]) { return array("msg"=>NC_("This privilege description is too long. (Max. length %d)"), "margs"=>array($this->maxlens["dsc"])); } // OK return null; } // _check_subuser: Check the user members function _check_subuser() { // Skip for a non-super-user editing a super-user group if ($this->_iscur && !is_su() && $this->_sn == su_group_sn()) { return null; } for ($i = 0, $items = array(); !$this->_missing("subuser$i" . "sn"); $i++) { // Skip unselected ones if ($this->_missing("subuser$i")) { continue; } // Regularize it $this->_form["subuser$i" . "sn"] = trim($this->_form["subuser$i" . "sn"]); // Check if this selection is duplicated if (in_array($this->_form["subuser$i" . "sn"], $items)) { return array("msg"=>NC_("This user member is duplicated. You cannot set duplicated ones.")); } $items[] = $this->_form["subuser$i" . "sn"]; // Check with the subform checker $form = array(); $form["member"] =& $this->_form["subuser$i" . "sn"]; if ($this->_iscur) { $form["grp"] =& $this->_sn; } $checker = new UserMembershipChecker($form); $error = $checker->check(array("member")); if (!is_null($error)) { return $error; } } // OK return null; } // _check_subgroup: Check the group members function _check_subgroup() { // Skip for a non-super-user editing a super-user group if ($this->_iscur && !is_su() && $this->_sn == su_group_sn()) { return null; } for ($i = 0, $items = array(); !$this->_missing("subgroup$i" . "sn"); $i++) { // Skip unselected ones if ($this->_missing("subgroup$i")) { continue; } // Regularize it $this->_form["subgroup$i" . "sn"] = trim($this->_form["subgroup$i" . "sn"]); // Check if this selection is duplicated if (in_array($this->_form["subgroup$i" . "sn"], $items)) { return array("msg"=>NC_("This group member is duplicated. You cannot set duplicated ones.")); } $items[] = $this->_form["subgroup$i" . "sn"]; // Check with the subform checker $form = array(); $form["member"] =& $this->_form["subgroup$i" . "sn"]; if ($this->_iscur) { $form["grp"] =& $this->_sn; } $checker = new GroupMembershipChecker($form); $error = $checker->check(array("member")); if (!is_null($error)) { return $error; } } // OK return null; } // _check_supgroup: Check the belonging groups function _check_supgroup() { // Skip for a non-super-user editing a super-user group if ($this->_iscur && !is_su() && $this->_sn == su_group_sn()) { return null; } for ($i = 0, $items = array(); !$this->_missing("supgroup$i" . "sn"); $i++) { // Skip unselected ones if ($this->_missing("supgroup$i")) { continue; } // Regularize it $this->_form["supgroup$i" . "sn"] = trim($this->_form["supgroup$i" . "sn"]); // Check if this selection is duplicated if (in_array($this->_form["supgroup$i" . "sn"], $items)) { return array("msg"=>NC_("This belonging group is duplicated. You cannot set duplicated ones.")); } $items[] = $this->_form["supgroup$i" . "sn"]; // Check with the subform checker $form = array(); $form["grp"] =& $this->_form["supgroup$i" . "sn"]; if ($this->_iscur) { $form["member"] =& $this->_sn; } $checker = new GroupMembershipChecker($form); $error = $checker->check(array("grp")); if (!is_null($error)) { return $error; } } // OK return null; } // _redir_selsubuser: Suspend and move to the subordinate user selection form function _redir_selsubuser() { // Skip if not requested if ($this->_missing("selsubuser")) { return; } call_form(FORM_USERS, null, "import_selsubuser"); } // _redir_selsubgroup: Suspend and move to the subordinate group selection form function _redir_selsubgroup() { // Skip if not requested if ($this->_missing("selsubgroup")) { return; } call_form(FORM_GROUPS, null, "import_selsubgroup"); } // _redir_selsupgroup: Suspend and move to the superordinate group selection form function _redir_selsupgroup() { // Skip if not requested if ($this->_missing("selsupgroup")) { return; } call_form(FORM_GROUPS, null, "import_selsupgroup"); } } // UserMembershipChecker: User membership form checker class class UserMembershipChecker extends BaseChecker { // __construct: Initialize the checker function __construct(&$form, $table = "usermem") { parent::__construct($form, $table); } // check: Run a list of checks function check($cols) { // Run the parent method $error = parent::check($cols); if (!is_null($error)) { return $error; } // See if we need to check the duplicates. Check it in the end. if (in_array("grp", $cols) && in_array("member", $cols)) { $error = $this->__check_dup(); if (!is_null($error)) { return $error; } } return null; } // _check_grp: Check the group // Use the default group checker // _check_member: Check the member function _check_member() { // Check if it exists $error = $this->_missing("member"); if (!is_null($error)) { return $error; } // Regularize it $this->_form["member"] = trim($this->_form["member"]); // Check if it is filled if ($this->_form["member"] == "") { return array("msg"=>NC_("Please select a member.")); } // Check if this member exists if (!check_sn_in($this->_form["member"], "users AS usrmembers")) { return array("msg"=>NC_("This member does not exist anymore. Please select another one.")); } // OK return null; } // __check_dup: Check if this item is duplicated function __check_dup() { $conds = array(); $conds[] = "grp=" . $this->_form["grp"]; $conds[] = "member=" . $this->_form["member"]; if ($this->_iscur) { $conds[] = "sn!=" . $this->_sn; } $select = "SELECT * FROM " . $this->_table . " WHERE " . implode(" AND ", $conds) . ";\n"; $result = sql_query($select); if (sql_num_rows($result) != 0) { return array("msg"=>NC_("This membership record already exists. You cannot create a duplicated one.")); } return null; } // _redir_selmember: Suspend and move to the member selection form function _redir_selmember() { // Skip if not requested if ($this->_missing("selmember")) { return; } call_form(FORM_USERS, null, "import_selmember"); } // _redir_delmember: Remove the member function _redir_delmember() { // Skip if not requested if ($this->_missing("delmember")) { return; } // Remove the item unset($this->_form["member"]); $status = null; success_redirect($status); } } // GroupMembershipChecker: Group membership form checker class class GroupMembershipChecker extends BaseChecker { // __construct: Initialize the checker function __construct(&$form, $table = "groupmem") { parent::__construct($form, $table); } // check: Run a list of checks function check($cols) { // Run the parent method $error = parent::check($cols); if (!is_null($error)) { return $error; } // See if we need to check the duplicates. Check it in the end. if (in_array("grp", $cols) && in_array("member", $cols)) { $error = $this->__check_dup(); if (!is_null($error)) { return $error; } } return null; } // _check_grp: Check the group function _check_grp() { // Run the default group checker $error = parent::_check_grp(); if (!is_null($error)) { return $error; } // Check if the group and the member are different if ( !$this->_missing("member") && $this->_form["grp"] == $this->_form["member"]) { return array("msg"=>NC_("Please select a different belonging group.")); } // OK return null; } // _check_member: Check the member function _check_member() { // Check if it exists $error = $this->_missing("member"); if (!is_null($error)) { return $error; } // Regularize it $this->_form["member"] = trim($this->_form["member"]); // Check if it is filled if ($this->_form["member"] == "") { return array("msg"=>NC_("Please select a member.")); } // Check if this member exists if (!check_sn_in($this->_form["member"], "groups AS grpmembers")) { return array("msg"=>NC_("This member does not exist anymore. Please select another one.")); } // Check if the group and the member are different if ( !$this->_missing("grp") && $this->_form["grp"] == $this->_form["member"]) { return array("msg"=>NC_("Please select a different group member.")); } // OK return null; } // __check_dup: Check if this item is duplicated function __check_dup() { $conds = array(); $conds[] = "grp=" . $this->_form["grp"]; $conds[] = "member=" . $this->_form["member"]; if ($this->_iscur) { $conds[] = "sn!=" . $this->_sn; } $select = "SELECT * FROM " . $this->_table . " WHERE " . implode(" AND ", $conds) . ";\n"; $result = sql_query($select); if (sql_num_rows($result) != 0) { return array("msg"=>NC_("This membership record already exists. You cannot create a duplicated one.")); } return null; } // _redir_selmember: Suspend and move to the member selection form function _redir_selmember() { // Skip if not requested if ($this->_missing("selmember")) { return; } call_form(FORM_GROUPS, null, "import_selmember"); } // _redir_delmember: Remove the member function _redir_delmember() { // Skip if not requested if ($this->_missing("delmember")) { return; } // Remove the item unset($this->_form["member"]); $status = null; success_redirect($status); } } // ScriptPrivilegeChecker: Script privilege form checker class class ScriptPrivilegeChecker extends BaseChecker { // __construct: Initialize the checker function __construct(&$form, $table = "scptpriv") { parent::__construct($form, $table); } // check: Run a list of checks function check($cols) { // Run the parent method $error = parent::check($cols); if (!is_null($error)) { return $error; } // See if we need to check the duplicates. Check it in the end. if (in_array("script", $cols) && in_array("grp", $cols)) { $error = $this->__check_dup(); if (!is_null($error)) { return $error; } } return null; } // _check_script: Check the script // Use the default script checker // _check_grp: Check the group // Use the default group checker // __check_dup: Check if this item is duplicated function __check_dup() { $conds = array(); $conds[] = "script='" . sql_esctext($this->_form["script"]) . "'"; $conds[] = "grp=" . $this->_form["grp"]; if ($this->_iscur) { $conds[] = "sn!=" . $this->_sn; } $select = "SELECT * FROM " . $this->_table . " WHERE " . implode(" AND ", $conds) . ";\n"; $result = sql_query($select); if (sql_num_rows($result) != 0) { return array("msg"=>NC_("This script privilege already exists. You cannot create a duplicated one.")); } return null; } } // UserPreferenceChecker: User preference form checker class class UserPreferenceChecker extends BaseChecker { // __construct: Initialize the checker function __construct(&$form, $table = "userpref") { parent::__construct($form, $table); } // check: Run a list of checks function check($cols) { // Run the parent method $error = parent::check($cols); if (!is_null($error)) { return $error; } // See if we need to check the duplicates. Check it in the end. if (in_array("usr", $cols) && in_array("domain", $cols) && in_array("name", $cols)) { $error = $this->__check_dup(); if (!is_null($error)) { return $error; } } return null; } // _check_usr: Check the user function _check_usr() { // "everyone not set" has a different form context if ($this->_missing("everyone")) { return array("msg"=>NC_("Please select the user.")); } // Regularize it $this->_form["everyone"] = trim($this->_form["everyone"]); // Check the option value if (!in_array($this->_form["everyone"], array("true", "false"))) { return array("msg"=>NC_("This option is invalid. Please select a proper user.")); } // Run the default user checker if not everyone if ($this->_form["everyone"] == "false") { $error = parent::_check_usr(); if (!is_null($error)) { return $error; } } // OK return null; } // _check_domain: Check the preference domain function _check_domain() { // "everywhere not set" has a different form context if ($this->_missing("everywhere")) { return array("msg"=>NC_("Please set the preference domain.")); } // Regularize it $this->_form["everywhere"] = trim($this->_form["everywhere"]); // Check the option value if (!in_array($this->_form["everywhere"], array("true", "false"))) { return array("msg"=>NC_("This option is invalid. Please set a proper preference domain.")); } // Check the domain if not everywhere if ($this->_form["everywhere"] == "false") { // Check if it exists $error = $this->_missing("domain"); if (!is_null($error)) { return $error; } // Regularize it $this->_form["domain"] = trim($this->_form["domain"]); // Check if it is filled if ($this->_form["domain"] == "") { return array("msg"=>NC_("Please fill in the preference domain.")); } // Check the length if (sql_strlen($this->_form["domain"]) > $this->maxlens["domain"]) { return array("msg"=>NC_("This preference domain is too long. (Max. length %d)"), "margs"=>array($this->maxlens["domain"])); } } // OK return null; } // _check_name: Check the preference name function _check_name() { // Check if it exists $error = $this->_missing("name"); if (!is_null($error)) { return $error; } // Regularize it $this->_form["name"] = trim($this->_form["name"]); // Check if it is filled if ($this->_form["name"] == "") { return array("msg"=>NC_("Please fill in the preference name.")); } // Check the length if (sql_strlen($this->_form["name"]) > $this->maxlens["name"]) { return array("msg"=>NC_("This preference name is too long. (Max. length %d)"), "margs"=>array($this->maxlens["name"])); } // OK return null; } // _check_value: Check the preference value function _check_value() { // Check if it exists $error = $this->_missing("value"); if (!is_null($error)) { return $error; } // Regularize it $this->_form["value"] = trim($this->_form["value"]); // Check if it is filled if ($this->_form["value"] == "") { return array("msg"=>NC_("Please fill in the preference value.")); } // Check the length if (sql_strlen($this->_form["value"]) > $this->maxlens["value"]) { return array("msg"=>NC_("This preference value is too long. (Max. length %d)"), "margs"=>array($this->maxlens["value"])); } // OK return null; } // __check_dup: Check if this item is duplicated function __check_dup() { $conds = array(); if ($this->_form["everyone"] == "true") { $conds[] = "usr IS NULL"; } else { $conds[] = "usr=" . $this->_form["usr"]; } if ($this->_form["everywhere"] == "true") { $conds[] = "domain IS NULL"; } else { $conds[] = "domain='" . sql_esctext($this->_form["domain"]) . "'"; } $conds[] = "name='" . sql_esctext($this->_form["name"]) . "'"; if ($this->_iscur) { $conds[] = "sn!=" . $this->_sn; } $select = "SELECT * FROM " . $this->_table . " WHERE " . implode(" AND ", $conds) . ";\n"; $result = sql_query($select); if (sql_num_rows($result) != 0) { return array("msg"=>NC_("This user preference already exists. You cannot create a duplicated one.")); } return null; } // _redir_selusr: Suspend and move to the user selection form function _redir_selusr() { // Skip if not requested if ($this->_missing("selusr")) { return; } call_form(FORM_USERS, null, "import_selusr"); } // _redir_delusr: Remove the user function _redir_delusr() { // Skip if not requested if ($this->_missing("delusr")) { return; } // Remove the item unset($this->_form["usr"]); $status = null; success_redirect($status); } } // UserRequestChecker: user requests form checker class class UserRequestChecker extends UserChecker { protected $_types = array(); // __construct: Initialize the checker function __construct(&$form, $table = "userreq") { parent::__construct($form, $table); $this->minlens["email"] = 5; $this->_types = array("join", "chgeml", "rstpwd"); } // _check_type: Check the request type function _check_type() { // "type not set" has a different form context $error = $this->_missing("type"); if (!is_null($error)) { return array("msg"=>NC_("Please select the request type.")); } // Regularize it $this->_form["type"] = trim($this->_form["type"]); // Check the option value if (!in_array($this->_form["type"], $this->_types)) { return array("msg"=>NC_("This option is invalid. Please select a proper request type.")); } // OK return null; } // _check_usr: Check the user function _check_usr() { // "anonymous not set" has a different form context if ($this->_missing("anonymous")) { return array("msg"=>NC_("Please select the user.")); } // Regularize it $this->_form["anonymous"] = trim($this->_form["anonymous"]); // Check the option value if (!in_array($this->_form["anonymous"], array("true", "false"))) { return array("msg"=>NC_("This option is invalid. Please select a proper user.")); } // Anonymous option depends on the request type if ($this->_form["type"] == "join" && $this->_form["anonymous"] == "false") { return array("msg"=>NC_("You must choose anonymous for join requests.")); } if ($this->_form["type"] != "join" && $this->_form["anonymous"] == "true") { return array("msg"=>NC_("You cannot choose anonymous for non-join requests.")); } // Run the default user checker if not anonymous if ($this->_form["anonymous"] == "false") { $error = parent::_check_usr(); if (!is_null($error)) { return $error; } } // OK return null; } // _check_args: Check the arguments function _check_args() { // Check if it exists $error = $this->_missing("args"); if (!is_null($error)) { return $error; } // Regularize it $this->_form["args"] = trimtext($this->_form["args"]); // Skip if it is not filled if ($this->_form["args"] == C_("Please fill in the request arguments list here.")) { $this->_form["args"] = ""; } if ($this->_form["args"] == "") { return null; } // Check the length if (sql_strlen($this->_form["args"]) > $this->maxlens["args"]) { return array("msg"=>NC_("This request arguments list is too long. (Max. length %d)"), "margs"=>array($this->maxlens["args"])); } // OK return null; } // _redir_selusr: Suspend and move to the user selection form function _redir_selusr() { // Skip if not requested if ($this->_missing("selusr")) { return; } call_form(FORM_USERS, null, "import_selusr"); } // _redir_delusr: Remove the user function _redir_delusr() { // Skip if not requested if ($this->_missing("delusr")) { return; } // Remove the item unset($this->_form["usr"]); $status = null; success_redirect($status); } } // ListPreferenceChecker: List preference form checker class class ListPreferenceChecker extends BaseChecker { // Maximum list size is 1000, to prevent processing timeout. const MAX_LISTSIZE = 1000; // __construct: Initialize the checker function __construct(&$form, $table = "userpref") { if (func_num_args() < 2) { if (!is_guest()) { $table = "userpref"; } else { $table = null; } } parent::__construct($form, $table); if (is_null($table)) { $this->maxlens = array(); $this->maxlens["domain"] = 64; $this->maxlens["name"] = 16; $this->maxlens["value"] = 65536; } $this->maxlens["listsize"] = 4; } // _check_domain: Check the preference domain function _check_domain() { // Check if it exists $error = $this->_missing("domain"); if (!is_null($error)) { return $error; } // Regularize it $this->_form["domain"] = trim($this->_form["domain"]); // Check if it is filled if ($this->_form["domain"] == "") { return array("msg"=>NC_("Please fill in the preference domain.")); } // Check the length if (sql_strlen($this->_form["domain"]) > $this->maxlens["domain"]) { return array("msg"=>NC_("This preference domain is too long. (Max. length %d)"), "margs"=>array($this->maxlens["domain"])); } // OK return null; } // _check_listcols: Check the list columns function _check_listcols() { // No need to check the validility. Invalids are simply ignored. $cols = array(); foreach (array_keys($this->_form) as $key) { if (preg_match("/^listcols_(.+)$/", $key, $m)) { $cols[] = $m[1]; } } // Obtain the preference value $listcols = implode(" ", $cols); // Check the length if (sql_strlen("listcols") > $this->maxlens["name"]) { $errmsg = sprintf("Maximum preference name length too short (%d for \"%s\" %d)", $this->maxlens["name"], "listcols", sql_strlen("listcols")); trigger_error($errmsg, E_USER_ERROR); } if (sql_strlen($listcols) > $this->maxlens["value"]) { $errmsg = sprintf("Maximum preference value length too short (%d for \"%s\" %d)", $this->maxlens["value"], $listcols, sql_strlen($listcols)); trigger_error($errmsg, E_USER_ERROR); } // OK return null; } // _check_listsize: Check the list size function _check_listsize() { // Check if it exists $error = $this->_missing("listsize"); if (!is_null($error)) { return $error; } $min = 0; //$max = pow(10, $this->maxlens["listsize"]) - 1; // Text string if (is_string($this->_form["listsize"])) { // Regularize it $this->_form["listsize"] = trim($this->_form["listsize"]); // Check if it is filled if ($this->_form["listsize"] == "") { return array("msg"=>NC_("Please fill in the number of rows per page.")); } // Check the length if (sql_strlen($this->_form["listsize"]) > $this->maxlens["listsize"]) { return array("msg"=>NC_("This number of rows per page is too long. (Max. length %d)"), "margs"=>array($this->maxlens["listsize"])); } // If there is any non-digit character if (preg_match("/\D/", $this->_form["listsize"])) { return array("msg"=>NC_("Please fill in a positive integer number of rows per page.")); } // Check if it is in the valid range if ($this->_form["listsize"] < $min) { return array("msg"=>NC_("The number of rows per page is too small. Please fill in a larger number of rows per page between %d and %d."), "margs"=>array($min, self::MAX_LISTSIZE)); } if ($this->_form["listsize"] > self::MAX_LISTSIZE) { return array("msg"=>NC_("The number of rows per page is too large. Please fill in a smaller number of rows per page between %d and %d."), "margs"=>array($min, self::MAX_LISTSIZE)); } // Convert its type to integer settype($this->_form["listsize"], "integer"); // Integer } elseif (is_int($this->_form["listsize"])) { // Check if it is in the valid range if ($this->_form["listsize"] < $min) { return array("msg"=>NC_("The number of rows per page is too small. Please fill in a larger number of rows per page between %d and %d."), "margs"=>array($min, self::MAX_LISTSIZE)); } if ($this->_form["listsize"] > self::MAX_LISTSIZE) { return array("msg"=>NC_("The number of rows per page is too large. Please fill in a smaller number of rows per page between %d and %d."), "margs"=>array($min, self::MAX_LISTSIZE)); } // Other types are non-sense } else { trigger_error("Unknown type for column \"listsize\"", E_USER_ERROR); } // Check the length if (sql_strlen("listsize") > $this->maxlens["name"]) { $errmsg = sprintf("Maximum preference name length too short (%d for \"%s\" %d)", $this->maxlens["name"], "listsize", sql_strlen("listsize")); trigger_error($errmsg, E_USER_ERROR); } if (sql_strlen($this->_form["listsize"]) > $this->maxlens["value"]) { $errmsg = sprintf("Maximum preference value length too short (%d for \"%s\" %d)", $this->maxlens["value"], $this->_form["listsize"], sql_strlen($this->_form["listsize"])); trigger_error($errmsg, E_USER_ERROR); } // OK return null; } } // LogInChecker: Log in form checker class class LogInChecker extends UserChecker { public $row = null; protected $_allcols; protected $_login = null; // __construct: Initialize the checker function __construct(&$form, $table = "users") { parent::__construct($form, $table); $this->row = null; $this->_allcols = sql_cols($table); // Always confirmed $this->_form["confirm"] = true; } // check: Run a list of checks function check($cols) { // See if a log in is attemped. if (is_null($this->_login)) { $this->_login = (in_array("id", $cols) && in_array("passwd", $cols)); } // Run the parent method $error = parent::check($cols); if (!is_null($error)) { return $error; } return null; } // _check_id: Check the user ID. function _check_id() { // Check if it exists $error = $this->_missing("id"); if (!is_null($error)) { return $error; } // Regularize it $this->_form["id"] = trim($this->_form["id"]); // Check if it is filled if ($this->_form["id"] == "") { return array("msg"=>NC_("Please fill in your user ID.")); } // Check the length if (sql_strlen($this->_form["id"]) > $this->maxlens["id"]) { if ($this->_login) { actlog("Log in failed for user " . $this->_form["id"] . " because user ID is too long."); } return array("msg"=>NC_("Log in failed. Either your user ID or your password is incorrect.")); } if (sql_strlen($this->_form["id"]) < $this->minlens["id"]) { if ($this->_login) { actlog("Log in failed for user " . $this->_form["id"] . " because user ID is too short."); } return array("msg"=>NC_("Log in failed. Either your user ID or your password is incorrect.")); } // Check if this user exists $conds = array(); $conds[] = "id='" . sql_esctext($this->_form["id"]) . "'"; if (in_array("deleted", $this->_allcols)) { $conds[] = sql_is_false("deleted"); } $select = "SELECT * FROM " . $this->_table . " WHERE " . implode(" AND ", $conds) . ";\n"; $result = sql_query($select); if (sql_num_rows($result) != 1) { if ($this->_login) { actlog("Log in failed for user " . $this->_form["id"] . " because user ID does not exist."); } return array("msg"=>NC_("Log in failed. Either your user ID or your password is incorrect.")); } // Save it for further reference $this->row = sql_fetch_assoc($result); $this->_sn = $this->row["sn"]; // Check if log-in is closed if (defined("NOLOGIN") && NOLOGIN && !is_su($this->_sn)) { if ($this->_login) { actlog("Log in failed for user " . $this->_form["id"] . " website is temporarily closed."); } // This message is duplicated return array(); } // Check if this user is disabled if ($this->row["disabled"]) { if ($this->_login) { actlog("Log in failed for user " . $this->_form["id"] . " because account is disabled."); } return array("msg"=>NC_("Your account is disabled. Contact our system administrator for assistence.")); } // Check if we have exceed the maximum number of fail logins // Skip super users - super users are invincible if ( defined("MAX_FAIL_LOGINS") && MAX_FAIL_LOGINS !== false && !is_su($this->_sn) && $this->row["fails"] >= MAX_FAIL_LOGINS) { if ($this->_login) { actlog("Log in failed for user " . $this->_form["id"] . " because too many bad logins (" . $this->row["fails"] . ")."); } $this->_update_fails(); return array("msg"=>NC_("Log in failed. Either your user ID or your password is incorrect.")); } // OK return null; } // _check_passwd: Check the user password function _check_passwd() { // Skip password checks for guests if ( !is_null($this->_sn) && is_guest($this->_sn)) { return null; } // Check if it exists $error = $this->_missing("passwd"); if (!is_null($error)) { return $error; } // Regularize it $this->_form["passwd"] = trim($this->_form["passwd"]); // Check if it is filled if ($this->_form["passwd"] == "") { return array("msg"=>NC_("Please fill in your password.")); } // Check the length if (sql_strlen($this->_form["passwd"]) > $this->maxlens["passwd"]) { if ($this->_login) { actlog("Log in failed for user " . $this->_form["id"] . " because password is too long."); } $this->_update_fails(); return array("msg"=>NC_("Log in failed. Either your user ID or your password is incorrect.")); } if (sql_strlen($this->_form["passwd"]) < $this->minlens["passwd"]) { if ($this->_login) { actlog("Log in failed for user " . $this->_form["id"] . " because password is too short."); } $this->_update_fails(); return array("msg"=>NC_("Log in failed. Either your user ID or your password is incorrect.")); } // Check if the password is correct if ( !is_null($this->row) && md5($this->_form["passwd"]) != $this->row["passwd"]) { if ($this->_login) { actlog("Log in failed for user " . $this->_form["id"] . " because password is incorrect."); } $this->_update_fails(); return array("msg"=>NC_("Log in failed. Either your user ID or your password is incorrect.")); } // OK return null; } // _check_admin: Check if the user is an administrator function _check_admin() { // Skip checking for guests if (is_guest($this->_sn)) { return null; } // Skip checking for super users if (is_su($this->_sn)) { return null; } // Check if this user is an administrator if (!is_admin($this->_sn)) { if ($this->_login) { actlog("Log in failed for user " . $this->_form["id"] . " because user is not an administrator."); } return array("msg"=>NC_("You are not an administrator so may not log in here.")); } // OK return null; } // _check_nonadmin: Check if the user is not an administrator function _check_nonadmin() { // Skip checking for guests if (is_guest($this->_sn)) { return null; } // Check if this user is an administrator if (is_admin($this->_sn)) { if ($this->_login) { actlog("Log in failed for user " . $this->_form["id"] . " because user is an administrator."); } return array("msg"=>NC_("You are an administrator so may not log in here.")); } // OK return null; } // _update_fails: Add one to the number of failed logins function _update_fails() { // We need the user information if (is_null($this->_sn)) { return; } sql_begin(); $update = "UPDATE users SET fails=fails+1," . " updated=now()" . " WHERE sn=" . $this->_sn . ";\n"; sql_query($update); sql_commit(); $this->row["fails"]++; return; } } ///////////////////////// // Content Checkers: Checkers for the content management system ///////////////////////// // PageChecker: Page form checker class class PageChecker extends BaseChecker { // __construct: Initialize the checker function __construct(&$form, $table = "pages") { parent::__construct($form, $table); } // _check_path: Check the page path // Use the default page path checker // _check_ord: Check the order // Use the default order checker // _check_title: Check the title // Use the default title checker // _check_body: Check the content body // Use the default content body checker // _check_kw: Check the keyword list // Use the default keyword list checker // _check_pic: Check the picture // Use the default picture checker // _check_piccap: Check the picture caption // Use the default picture captio checker // _check_picpos: Check the picture position // Use the default picture position checker } // NewsChecker: News form checker class class NewsChecker extends BaseChecker { // __construct: Initialize the checker function __construct(&$form, $table = "news") { parent::__construct($form, $table); } // _check_date: Check the date // Use the default date checker // _check_ord: Check the order // Actually this is to set the order, but not to check the order function _check_ord() { // Current form if ($this->_iscur) { global $CURRENT; // Same day -- inherit the same order if ($this->_form["date"] == $CURRENT["date"]) { $this->_form["ord"] = $CURRENT["ord"]; return; } } // Create a new order for this new day $this->_form["ord"] = $this->_new_ord(); return; } // _check_title: Check the title // Use the default title checker // _check_body: Check the content body // Use the default content body checker // _check_kw: Check the keyword list // Use the default keyword list checker // _check_pic: Check the picture // Use the default picture checker // _new_ord: Create a new news order function _new_ord() { // Cache the result static $cache; // Return the cache if (isset($cache)) { return $cache; } // Get the largest or der $select = "SELECT ord FROM " . $this->_table . " WHERE date='" . $this->_form["date"] . "'" . " ORDER BY ord DESC LIMIT 1;\n"; $result = sql_query($select); $count = sql_num_rows($result); // No record yet if ($count == 0) { $cache = 1; // Largest plus 1 } else { $row = sql_fetch_assoc($result); $cache = $row["ord"] + 1; } return $cache; } } // CountryChecker: Country form checker class class CountryChecker extends BaseChecker { // __construct: Initialize the checker function __construct(&$form, $table = "country") { parent::__construct($form, $table); $this->minlens["id"] = 2; } // _check_id: Check the country code function _check_id() { // Check if it exists $error = $this->_missing("id"); if (!is_null($error)) { return $error; } // Regularize it $this->_form["id"] = trim($this->_form["id"]); // Check if it is filled if ($this->_form["id"] == "") { return array("msg"=>NC_("Please fill in the code.")); } // Check the length if (sql_strlen($this->_form["id"]) != $this->maxlens["id"]) { return array("msg"=>NC_("You must fill in a %d-letters code."), "margs"=>array($this->maxlens["id"])); } // Check if the characters used are valid if (!preg_match("/^(?:[A-Z][A-Z0-9]|==)$/", $this->_form["id"])) { return array("msg"=>NC_("You can only use upper letters and for the code.")); } // Check if this item is duplicated $conds = array(); $conds[] = "id='" . sql_esctext($this->_form["id"]) . "'"; if ($this->_iscur) { $conds[] = "sn!=" . $this->_sn; } $select = "SELECT * FROM " . $this->_table . " WHERE " . implode(" AND ", $conds) . ";\n"; $result = sql_query($select); if (sql_num_rows($result) != 0) { return array("msg"=>NC_("This code is duplicated. You cannot create a duplicated one.")); } // OK return null; } // _check_name: Check the country name function _check_name() { // Check if it exists $error = $this->_missing("name"); if (!is_null($error)) { return $error; } // Regularize it $this->_form["name"] = trim($this->_form["name"]); // Check if it is filled if ($this->_form["name"] == "") { return array("msg"=>NC_("Please fill in the country name.")); } // Check the length if (sql_strlen($this->_form["name"]) > $this->maxlens["name"]) { return array("msg"=>NC_("This country name is too long. (Max. length %d)"), "margs"=>array($this->maxlens["name"])); } // OK return null; } } ///////////////////////// // Link Checkers: Checkers for the related links ///////////////////////// // LinkCategoryChecker: Link category form checker class class LinkCategoryChecker extends BaseChecker { // __construct: Initialize the checker function __construct(&$form, $table = "linkcat") { parent::__construct($form, $table); $this->maxlens["ord"] = 2; $this->minlens["id"] = 2; } // _check_parent: Check the parent category function _check_parent() { // "topmost not set" has a different form context $error = $this->_missing("topmost"); if (!is_null($error)) { return array("msg"=>NC_("Please select a parent category.")); } // Regularize it $this->_form["topmost"] = trim($this->_form["topmost"]); // Check the option value if (!in_array($this->_form["topmost"], array("true", "false"))) { return array("msg"=>NC_("This option is invalid. Please select a proper parent category.")); } // Check the parent category if not a topmost category if ($this->_form["topmost"] == "false") { // Check if it exists $error = $this->_missing("parent"); if (!is_null($error)) { return $error; } // Regularize it $this->_form["parent"] = trim($this->_form["parent"]); // Check if it is filled if ($this->_form["parent"] == "") { return array("msg"=>NC_("Please select a parent category.")); } // Check if this category exists if (!check_sn_in($this->_form["parent"], "linkcat")) { return array("msg"=>NC_("This parent category does not exist anymore. Please select another one.")); } if ($this->_iscur) { // Check if the parent category is itself if ($this->_form["parent"] == $this->_sn) { return array("msg"=>NC_("A category cannot belong to itself. Please select another one.")); } // Check if the parent directory is its descendant $select = "SELECT linkcat_ischild(" . $this->_sn . ", " . $this->_form["parent"] . ") AS is_child;\n"; $result = sql_query($select); $row = sql_fetch_assoc($result); if ($row["is_child"]) { return array("msg"=>NC_("A category cannot belong to its descendant. Please select another one.")); } } } // OK return null; } // _check_id: Check the ID. function _check_id() { // Run the default ID. checker $error = parent::_check_id(); if (!is_null($error)) { return $error; } // ID. cannot be "index" to avoid overriding index.html if ($this->_form["id"] == "index") { return array("msg"=>NC_("\"index\" is dedicated to the index file index.html. You cannot set the ID. as \"index\".")); } // Check if this item is duplicated if (!$this->_missing("topmost", "parent")) { $conds = array(); $conds[] = "id='" . sql_esctext($this->_form["id"]) . "'"; if ($this->_iscur) { $conds[] = "sn!=" . $this->_sn; } if ($this->_form["topmost"] == "true") { $conds[] = "parent IS NULL"; } else { $conds[] = "parent=" . $this->_form["parent"]; } $select = "SELECT * FROM " . $this->_table . " WHERE " . implode(" AND ", $conds) . ";\n"; $result = sql_query($select); if (sql_num_rows($result) != 0) { return array("msg"=>NC_("This category already exists. You cannot create a duplicated one.")); } } // OK return null; } // _check_ord: Check the order // Use the default order checker // _check_title: Check the title // Use the default title checker // _check_kw: Check the keyword list // Use the default keyword list checker // _redir_selparent: Suspend and move to the parent selection form // Use the default parent redirector // _redir_delparent: Remove the parent // Use the default parent remover } // LinkChecker: Link form checker class class LinkChecker extends BaseChecker { // __construct: Initialize the checker function __construct(&$form, $table = "links") { parent::__construct($form, $table); } // _check_title: Check the title // Use the default title checker // _check_url: Check the URL. function _check_url() { // Check if it exists $error = $this->_missing("url"); if (!is_null($error)) { return $error; } // Regularize it $this->_form["url"] = trim($this->_form["url"]); // Check if it is filled if ($this->_form["url"] == "" || $this->_form["url"] == "http://") { return array("msg"=>NC_("Please fill in the URL..")); } // Check the length if (sql_strlen($this->_form["url"]) > $this->maxlens["url"]) { return array("msg"=>NC_("This URL. is too long. (Max. length %d)"), "margs"=>array($this->maxlens["url"])); } // Check its format if (!is_url_wellformed($this->_form["url"])) { return array("msg"=>NC_("Please fill in a valid URL..")); } // Check if this item is duplicated $conds = array(); $conds[] = "url='" . sql_esctext($this->_form["url"]) . "'"; if ($this->_iscur) { $conds[] = "sn!=" . $this->_sn; } $select = "SELECT * FROM " . $this->_table . " WHERE " . implode(" AND ", $conds) . ";\n"; $result = sql_query($select); if (sql_num_rows($result) != 0) { return array("msg"=>NC_("This related link already exists. You cannot create a duplicated one.")); } // Check if it is available if ( $this->_missing("hid") && !is_url_reachable($this->_form["url"])) { return array("msg"=>NC_("This URL. is not reachable. Check if there is any typo in it.")); } // OK return null; } // _check_dsc: Check the description function _check_dsc() { // Check if it exists $error = $this->_missing("dsc"); if (!is_null($error)) { return $error; } // Regularize it $this->_form["dsc"] = trimtext($this->_form["dsc"]); // Check if it is filled if ($this->_form["dsc"] == C_("Fill in the description here.")) { $this->_form["dsc"] = ""; } if ($this->_form["dsc"] == "") { return array("msg"=>NC_("Please fill in the description.")); } // Check the length if (sql_strlen($this->_form["dsc"]) > $this->maxlens["dsc"]) { return array("msg"=>NC_("This description is too long. (Max. length %d)"), "margs"=>array($this->maxlens["dsc"])); } // OK return null; } // _check_cats: Check the categories list function _check_cats() { // Loop each category for ($i = 0, $items = array(); !$this->_missing("cat$i"); $i++) { // Regularize it $this->_form["cat$i"] = trim($this->_form["cat$i"]); // Skip if it is not filled if ($this->_form["cat$i"] == "") { continue; } // Check if this selection is duplicated if (in_array($this->_form["cat$i"], $items)) { return array("msg"=>NC_("This category is duplicated. You cannot set duplicated ones.")); } // Check if the category exists if (!check_sn_in($this->_form["cat$i"], "linkcat")) { return array("msg"=>NC_("This category does not exist anymore. Please select another one.")); } $items[] = $this->_form["cat$i"]; } // Check if there is any category selected if (count($items) == 0) { return array("msg"=>NC_("Please select a category.")); } // OK return null; } } // LinkCategorizationChecker: Link categorization form checker class class LinkCategorizationChecker extends BaseChecker { // __construct: Initialize the checker function __construct(&$form, $table = "linkcatz") { parent::__construct($form, $table); } // check: Run a list of checks function check($cols) { // Run the parent method $error = parent::check($cols); if (!is_null($error)) { return $error; } // See if we need to check the duplicates. Check it in the end. if (in_array("cat", $cols) && in_array("link", $cols)) { $error = $this->__check_dup(); if (!is_null($error)) { return $error; } } return null; } // _check_cat: Check the category function _check_cat() { // Check if it exists $error = $this->_missing("cat"); if (!is_null($error)) { return $error; } // Regularize it $this->_form["cat"] = trim($this->_form["cat"]); // Check if it is filled if ($this->_form["cat"] == "") { return array("msg"=>NC_("Please select a category.")); } // Check if this category exists if (!check_sn_in($this->_form["cat"], "linkcat")) { return array("msg"=>NC_("This category does not exist anymore. Please select another one.")); } // OK return null; } // _check_link: Check the link function _check_link() { // Check if it exists $error = $this->_missing("link"); if (!is_null($error)) { return $error; } // Regularize it $this->_form["link"] = trim($this->_form["link"]); // Check if it is filled if ($this->_form["link"] == "") { return array("msg"=>NC_("Please select a related link.")); } // Check if this link exists if (!check_sn_in($this->_form["link"], "links")) { return array("msg"=>NC_("This link does not exist anymore. Please select another one.")); } // OK return null; } // __check_dup: Check if this item is duplicated function __check_dup() { $conds = array(); $conds[] = "cat=" . $this->_form["cat"]; $conds[] = "link=" . $this->_form["link"]; if ($this->_iscur) { $conds[] = "sn!=" . $this->_sn; } $select = "SELECT * FROM " . $this->_table . " WHERE " . implode(" AND ", $conds) . ";\n"; $result = sql_query($select); if (sql_num_rows($result) != 0) { return array("msg"=>NC_("This link categorization already exists. You cannot create a duplicated one.")); } return null; } // _redir_sellink: Suspend and move to the link selection form function _redir_sellink() { // Skip if not requested if ($this->_missing("sellink")) { return; } call_form(FORM_LINKS, null, "import_sellink"); } } ///////////////////////// // Miscellaneous Checkers: Checkers for various data ///////////////////////// // RebuildChecker: Rebuild form checker class class RebuildChecker extends BaseChecker { // __construct: Initialize the checker function __construct(&$form, $table = null) { parent::__construct($form, $table); } // _check_type: Check the page type function _check_type() { // Check if it exists $error = $this->_missing("type"); if (!is_null($error)) { return $error; } // Regularize it $this->_form["type"] = trim($this->_form["type"]); // Check if it is filled if ($this->_form["type"] == "") { return array("msg"=>NC_("Please select the type.")); } // Check if this link exists if (!function_exists("rebuild_" . $this->_form["type"])) { return array("msg"=>NC_("This type does not exist anymore. Please select another one.")); } // OK return null; } } // QueryChecker: Query form checker class class QueryChecker extends BaseChecker { // __construct: Initialize the checker function __construct(&$form, $table = null) { parent::__construct($form, $table); } // _check_query: Check the query phrase function _check_query() { // Skip if there is no query phrase if ($this->_missing("query")) { return null; } // Regularize it $this->_form["query"] = trim($this->_form["query"]); // Check if it is filled if ($this->_form["query"] == "") { return array("msg"=>NC_("Please fill in your query.")); } // OK return null; } } // PictureChecker: Picture form checker class // This is specially for the pic.php picture handler class PictureChecker extends BaseChecker { protected $_newpic = null; // __construct: Initialize the checker function __construct(&$form, $table = null) { parent::__construct($form, $table); } // _check_pic: Check the picture function _check_pic() { // Check if it exists $error = $this->_missing("pic"); if (!is_null($error)) { return array("msg"=>NC_("Please submit the picture.")); } // Check if this picture exists if (!pic_exists($this->_form["pic"])) { return array("msg"=>NC_("This picture does not exist anymore. Please upload another one.")); } // Obtain the picture $PICS =& pic_deposit(); $this->_newpic =& $PICS[$this->_form["pic"]]; // OK return null; } // _check_ratio: Check the picture ratio function _check_ratio() { // Check if it exists $error = $this->_missing("ratio"); if (!is_null($error)) { return $error; } // Regularize it if (is_string($this->_form["ratio"])) { $this->_form["ratio"] = trim($this->_form["ratio"]); } // Check if it is filled if ($this->_form["ratio"] == "") { return array("msg"=>NC_("Please fill in the resize ratio.")); } // Check if the resize ratio is valid if (!is_null($this->_newpic)) { $error = check_pic_ratio($this->_newpic, $this->_form["ratio"]); if (!is_null($error)) { return $error; } } } // _save_uploaded_pic: Check and save the uploaded picture function _save_uploaded_pic() { // Check if it exists $error = file_has("uppic"); if (!is_null($error)) { return $error; } // Skip if no new file was submitted if ($_FILES["uppic"]["error"] == UPLOAD_ERR_NO_FILE) { return null; } // Check the upload error $error = check_picfile("uppic"); if (!is_null($error)) { return $error; } // Save the picture $pic = array(); $pic["content"] = xfread($_FILES["uppic"]["tmp_name"]); $pic["type"] = $_FILES["uppic"]["type"]; $img = imagecreatefromstring($pic["content"]); $pic["width"] = imagesx($img); $pic["height"] = imagesy($img); $picid = suspend_pic($pic); $this->_form["pic"] = $picid; $this->_form["ratio"] = best_pic_ratio($pic); // Do not confirm now if (!$this->_missing("confirm")) { unset($this->_form["confirm"]); } // OK return null; } } // ShowPictureChecker: Show picture form checker class class ShowPictureChecker extends BaseChecker { protected $_pic = null; // __construct: Initialize the checker function __construct(&$form, $table = null) { parent::__construct($form, $table); } // _check_sn: Check the picture S/N function _check_sn() { // Check if it exists $error = $this->_missing("sn"); if (!is_null($error)) { return $error; } // Check if the picture is valid if (!pic_exists($this->_form["sn"])) { return array("msg"=>NC_("Please specify a valid picture.")); } // Obtain the picture $PICS =& pic_deposit(); $this->_pic =& $PICS[$this->_form["sn"]]; // OK return null; } // _check_ratio: Check the picture ratio function _check_ratio() { // Check if it exists $error = $this->_missing("ratio"); if (!is_null($error)) { return $error; } // Regularize it if (is_string($this->_form["ratio"])) { $this->_form["ratio"] = trim($this->_form["ratio"]); } // Check if it is filled if ($this->_form["ratio"] == "") { return array("msg"=>NC_("Please fill in the resize ratio.")); } // Check if the resize ratio is valid if (!is_null($this->_pic)) { $error = check_pic_ratio($this->_pic, $this->_form["ratio"]); if (!is_null($error)) { return $error; } } } } ?>