// 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/lninfo.inc.php"; require_once "monica/login.inc.php"; require_once "monica/pic.inc.php"; require_once "monica/sql.inc.php"; require_once "monica/sqlconst.inc.php"; require_once "monica/upload.inc.php"; // Settings define("ADDCOL_INSERT", 1); define("ADDCOL_UPDATE", 2); define("_ADDCOL_TYPE_NULL", "_ADDCOL_TYPE_NULL"); define("_ADDCOL_TYPE_NUM", "_ADDCOL_TYPE_NUM"); define("_ADDCOL_TYPE_STR", "_ADDCOL_TYPE_STR"); define("_ADDCOL_TYPE_DATE", "_ADDCOL_TYPE_DATE"); define("_ADDCOL_TYPE_IPADDR", "_ADDCOL_TYPE_IPADDR"); define("_ADDCOL_TYPE_FILE", "_ADDCOL_TYPE_FILE"); define("_ADDCOL_TYPE_BOOL", "_ADDCOL_TYPE_BOOL"); define("_ADDCOL_TYPE_EXPR", "_ADDCOL_TYPE_EXPR"); define("ADDCOL_NOTIMESTAMP", false); // AddCol: Prepare columns for SQL updates class AddCol { // Run as this user public $login = null; private $_cols; private $_table; private $_optype; private $_allcols; private $_mlcols; // __construct: Initialize the columns deposit function __construct($table, $optype = ADDCOL_UPDATE) { $this->_cols = array(); $this->_table = $table; $this->_optype = $optype; if ($GLOBALS["SQL_DBTYPE"] != SQL_NONE) { $this->_allcols = sql_cols($table); $this->_mlcols = sql_cols_ml($table); } else { $this->_allcols = array(); $this->_mlcols = array(); } } // addstr: Add a modified string column to the columns deposit // Input: $name: The column name. // $val: The column value. // $curval: The current value to be compared. // Output: None. function addstr($name, $val) { // Set the 3rd argument as the current value $cur_exists = false; if (func_num_args() == 3) { $cur_exists = true; $curval = func_get_arg(2); } // Adjust the column name for multi-lingual columns if (in_array($name, $this->_mlcols)) { $name .= "_" . getlang(LN_DATABASE); } // The new column value $col = array(); $col["name"] = $name; $col["mod"] = false; // No value is supplied if (is_null($val) || $val === "") { $col["type"] = _ADDCOL_TYPE_NULL; $col["value"] = null; // A valid value } else { $col["type"] = _ADDCOL_TYPE_STR; $col["value"] = $val; } // Check if we should set it switch ($this->_optype) { case ADDCOL_INSERT: // Always set the value for INSERT $col["mod"] = true; break; case ADDCOL_UPDATE: default: // A current value is supplied if ($cur_exists) { // This column had a value previously if (!is_null($curval)) { // It has no value now. Remove it. if ($col["type"] == _ADDCOL_TYPE_NULL) { $col["mod"] = true; // A different new value. Modify it. } elseif ($col["value"] !== $curval) { $col["mod"] = true; } // This column had no value previously } else { // But it has a value now. if ($col["type"] != _ADDCOL_TYPE_NULL) { $col["mod"] = true; } } // No current value to compare with. } else { // Set it anyway $col["mod"] = true; } break; } // Add this column $this->_cols[] = $col; return; } // addstr_empty: Add a modified string column to the columns deposit, // where empty string is allowed // Input: $name: The column name. // $val: The column value. // $curval: The current value to be compared. // Output: None. function addstr_empty($name, $val) { // Set the 3rd argument as the current value $cur_exists = false; if (func_num_args() == 3) { $cur_exists = true; $curval = func_get_arg(2); } // Adjust the column name for multi-lingual columns if (in_array($name, $this->_mlcols)) { $name .= "_" . getlang(LN_DATABASE); } // The new column value $col = array(); $col["name"] = $name; $col["mod"] = false; // No value is supplied if (is_null($val)) { $col["type"] = _ADDCOL_TYPE_NULL; $col["value"] = null; // A valid value } else { $col["type"] = _ADDCOL_TYPE_STR; $col["value"] = $val; } // Check if we should set it switch ($this->_optype) { case ADDCOL_INSERT: // Always set the value for INSERT $col["mod"] = true; break; case ADDCOL_UPDATE: default: // A current value is supplied if ($cur_exists) { // This column had a value previously if (!is_null($curval)) { // It has no value now. Remove it. if ($col["type"] == _ADDCOL_TYPE_NULL) { $col["mod"] = true; // A different new value. Modify it. } elseif ($col["value"] !== $curval) { $col["mod"] = true; } // This column had no value previously } else { // But it has a value now. if ($col["type"] != _ADDCOL_TYPE_NULL) { $col["mod"] = true; } } // No current value to compare with. } else { // Set it anyway $col["mod"] = true; } break; } // Add this column $this->_cols[] = $col; return; } // addurl: Add a modified URL to the columns deposit, // where "http://" also means empty // Input: $name: The column name. // $val: The column value. // $curval: The current value to be compared. // Output: None. function addurl($name, $val) { // Set the 3rd argument as the current value $cur_exists = false; if (func_num_args() == 3) { $cur_exists = true; $curval = func_get_arg(2); } // Adjust the column name for multi-lingual columns if (in_array($name, $this->_mlcols)) { $name .= "_" . getlang(LN_DATABASE); } // The new column value $col = array(); $col["name"] = $name; $col["mod"] = false; // No value is supplied if (is_null($val) || $val === "" || $val == "http://") { $col["type"] = _ADDCOL_TYPE_NULL; $col["value"] = null; // A valid value } else { $col["type"] = _ADDCOL_TYPE_STR; $col["value"] = $val; } // Check if we should set it switch ($this->_optype) { case ADDCOL_INSERT: // Always set the value for INSERT $col["mod"] = true; break; case ADDCOL_UPDATE: default: // A current value is supplied if ($cur_exists) { // This column had a value previously if (!is_null($curval)) { // It has no value now. Remove it. if ($col["type"] == _ADDCOL_TYPE_NULL) { $col["mod"] = true; // A different new value. Modify it. } elseif ($col["value"] !== $curval) { $col["mod"] = true; } // This column had no value previously } else { // But it has a value now. if ($col["type"] != _ADDCOL_TYPE_NULL) { $col["mod"] = true; } } // No current value to compare with. Modify it anyway } else { // Set it anyway $col["mod"] = true; } break; } // Add this column $this->_cols[] = $col; return; } // addpass: Add a modified password to the columns deposit, // where "" means "not changed". Passwords are never empty. // Input: $name: The column name. // $purge: If we should purge the password. // $val: The column value. // $curval: The current value to be compared. // Output: None. function addpass($name, $purge, $val) { // Set the 4nd argument as the current value $cur_exists = false; if (func_num_args() == 4) { $cur_exists = true; $curval = func_get_arg(3); } // Adjust the column name for multi-lingual columns if (in_array($name, $this->_mlcols)) { $name .= "_" . getlang(LN_DATABASE); } // The new column value $col = array(); $col["name"] = $name; $col["mod"] = false; // Purge the password with a dummy one if ($purge) { $col["type"] = _ADDCOL_TYPE_STR; $col["value"] = str_repeat("x", 32); // No value is supplied } elseif (is_null($val) || $val === "") { // There is always a value. This means no change $col["type"] = _ADDCOL_TYPE_NULL; $col["value"] = null; // A valid value } else { $col["type"] = _ADDCOL_TYPE_STR; $col["value"] = md5($val); } // Check if we should set it switch ($this->_optype) { case ADDCOL_INSERT: // Always set the value for INSERT $col["mod"] = true; break; case ADDCOL_UPDATE: default: // A current value is supplied if ($cur_exists) { // A different new value. Modify it. if ($col["type"] != _ADDCOL_TYPE_NULL && $col["value"] != $curval) { $col["mod"] = true; } // No current value to compare with. Modify it anyway } else { // Set it anyway $col["mod"] = true; } break; } // Add this column $this->_cols[] = $col; return; } // addpic: Add a picture to the columns deposit // Input: $name: The column name. // $val: The column value. // $curval: The current value to be compared. // Output: None. function addpic($name, $val) { $PICS =& pic_deposit(); // Set the 3rd argument as the current value $cur_exists = false; if (func_num_args() == 3) { $cur_exists = true; $curval = func_get_arg(2); // Get the picture content if (!is_null($curval)) { $curval = $PICS[$curval]["content"]; } } // Adjust the column name for multi-lingual columns if (in_array($name, $this->_mlcols)) { $name .= "_" . getlang(LN_DATABASE); } // The new column value $col = array(); $col["name"] = $name; $col["mod"] = false; // No value is supplied if (is_null($val)) { $col["type"] = _ADDCOL_TYPE_NULL; $col["value"] = null; // A valid value } else { $col["type"] = _ADDCOL_TYPE_FILE; $col["value"] = $PICS[$val]["content"]; } // Check if we should set it switch ($this->_optype) { case ADDCOL_INSERT: // Always set the value for INSERT $col["mod"] = true; break; case ADDCOL_UPDATE: default: // A current value is supplied if ($cur_exists) { // This column had a value previously if (!is_null($curval)) { // It has no value now. Remove it. if ($col["type"] == _ADDCOL_TYPE_NULL) { $col["mod"] = true; // A different new value. Modify it. } elseif ($col["value"] !== $curval) { $col["mod"] = true; } // This column had no value previously } else { // But it has a value now. if ($col["type"] != _ADDCOL_TYPE_NULL) { $col["mod"] = true; } } // No current value to compare with. Modify it anyway } else { // Set it anyway $col["mod"] = true; } break; } // Add this column $this->_cols[] = $col; return; } // addfile: Add a file to the columns deposit // Input: $name: The column name. // $val: The column value. // $curval: The current value to be compared. // Output: None. function addfile($name, $val) { $FILES =& file_deposit(); // Set the 3rd argument as the current value $cur_exists = false; if (func_num_args() == 3) { $cur_exists = true; $curval = func_get_arg(2); // Get the picture content if (!is_null($curval)) { $curval = $FILES[$curval]["content"]; } } // Adjust the column name for multi-lingual columns if (in_array($name, $this->_mlcols)) { $name .= "_" . getlang(LN_DATABASE); } // The new column value $col = array(); $col["name"] = $name; $col["mod"] = false; // No value is supplied if (is_null($val)) { $col["type"] = _ADDCOL_TYPE_NULL; $col["value"] = null; // A valid value } else { $col["type"] = _ADDCOL_TYPE_FILE; $col["value"] = $FILES[$val]["content"]; } // Check if we should set it switch ($this->_optype) { case ADDCOL_INSERT: // Always set the value for INSERT $col["mod"] = true; break; case ADDCOL_UPDATE: default: // A current value is supplied if ($cur_exists) { // This column had a value previously if (!is_null($curval)) { // It has no value now. Remove it. if ($col["type"] == _ADDCOL_TYPE_NULL) { $col["mod"] = true; // A different new value. Modify it. } elseif ($col["value"] !== $curval) { $col["mod"] = true; } // This column had no value previously } else { // But it has a value now. if ($col["type"] != _ADDCOL_TYPE_NULL) { $col["mod"] = true; } } // No current value to compare with. Modify it anyway } else { // Set it anyway $col["mod"] = true; } break; } // Add this column $this->_cols[] = $col; return; } // addnum: Add a modified numeric column to the columns deposit // Input: $name: The column name. // $val: The column value. // $curval: The current value to be compared. function addnum($name, $val) { // Set the 3rd argument as the current value $cur_exists = false; if (func_num_args() == 3) { $cur_exists = true; $curval = func_get_arg(2); } // Adjust the column name for multi-lingual columns if (in_array($name, $this->_mlcols)) { $name .= "_" . getlang(LN_DATABASE); } // The new column value $col = array(); $col["name"] = $name; $col["mod"] = false; // No value is supplied if (is_null($val) || $val === "") { $col["type"] = _ADDCOL_TYPE_NULL; $col["value"] = null; // A valid value } else { $col["type"] = _ADDCOL_TYPE_NUM; $col["value"] = $val; } // Check if we should set it switch ($this->_optype) { case ADDCOL_INSERT: // Always set the value for INSERT $col["mod"] = true; break; case ADDCOL_UPDATE: default: // A current value is supplied if ($cur_exists) { // This column had a value previously if (!is_null($curval)) { // It has no value now. Remove it. if ($col["type"] == _ADDCOL_TYPE_NULL) { $col["mod"] = true; // A different new value. Modify it. } elseif ($col["value"] != $curval) { $col["mod"] = true; } // This column had no value previously } else { // But it has a value now. if ($col["type"] != _ADDCOL_TYPE_NULL) { $col["mod"] = true; } } // No current value to compare with. } else { // Set it anyway $col["mod"] = true; } break; } // Add this column $this->_cols[] = $col; return; } // adddate: Add a modified date column to the columns deposit // Mostly the same as addstr(). Different when out. // Input: $name: The column name. // $val: The column value. // $curval: The current value to be compared. // Output: None. function adddate($name, $val) { // Set the 3rd argument as the current value $cur_exists = false; if (func_num_args() == 3) { $cur_exists = true; $curval = func_get_arg(2); } // Adjust the column name for multi-lingual columns if (in_array($name, $this->_mlcols)) { $name .= "_" . getlang(LN_DATABASE); } // The new column value $col = array(); $col["name"] = $name; $col["mod"] = false; // No value is supplied if (is_null($val) || $val === "") { $col["type"] = _ADDCOL_TYPE_NULL; $col["value"] = null; // A valid value } else { $col["type"] = _ADDCOL_TYPE_DATE; $col["value"] = $val; } // Check if we should set it switch ($this->_optype) { case ADDCOL_INSERT: // Always set the value for INSERT $col["mod"] = true; break; case ADDCOL_UPDATE: default: // A current value is supplied if ($cur_exists) { // This column had a value previously if (!is_null($curval)) { // It has no value now. Remove it. if ($col["type"] == _ADDCOL_TYPE_NULL) { $col["mod"] = true; // A different new value. Modify it. } elseif ($col["value"] !== $curval) { $col["mod"] = true; } // This column had no value previously } else { // But it has a value now. if ($col["type"] != _ADDCOL_TYPE_NULL) { $col["mod"] = true; } } // No current value to compare with. } else { // Set it anyway $col["mod"] = true; } break; } // Add this column $this->_cols[] = $col; return; } // addipaddr: Add a modified IP address column to the columns deposit // Mostly the same as addstr(). Different when out. // Input: $name: The column name. // $val: The column value. // $curval: The current value to be compared. // Output: None. function addipaddr($name, $val) { // Set the 3rd argument as the current value $cur_exists = false; if (func_num_args() == 3) { $cur_exists = true; $curval = func_get_arg(2); } // Adjust the column name for multi-lingual columns if (in_array($name, $this->_mlcols)) { $name .= "_" . getlang(LN_DATABASE); } // The new column value $col = array(); $col["name"] = $name; $col["mod"] = false; // No value is supplied if (is_null($val) || $val === "") { $col["type"] = _ADDCOL_TYPE_NULL; $col["value"] = null; // A valid value } else { $col["type"] = _ADDCOL_TYPE_IPADDR; $col["value"] = $val; } // Check if we should set it switch ($this->_optype) { case ADDCOL_INSERT: // Always set the value for INSERT $col["mod"] = true; break; case ADDCOL_UPDATE: default: // A current value is supplied if ($cur_exists) { // This column had a value previously if (!is_null($curval)) { // It has no value now. Remove it. if ($col["type"] == _ADDCOL_TYPE_NULL) { $col["mod"] = true; // A different new value. Modify it. } elseif ($col["value"] !== $curval) { $col["mod"] = true; } // This column had no value previously } else { // But it has a value now. if ($col["type"] != _ADDCOL_TYPE_NULL) { $col["mod"] = true; } } // No current value to compare with. } else { // Set it anyway $col["mod"] = true; } break; } // Add this column $this->_cols[] = $col; return; } // addbool: Add a modified boolean column to the columns deposit // Input: $name: The column name. // $val: The column value. // $curval: The current value to be compared. function addbool($name, $val) { // Set the 3rd argument as the current value $cur_exists = false; if (func_num_args() == 3) { $cur_exists = true; $curval = func_get_arg(2); } // Adjust the column name for multi-lingual columns if (in_array($name, $this->_mlcols)) { $name .= "_" . getlang(LN_DATABASE); } // The new column value $col = array(); $col["name"] = $name; $col["mod"] = false; // No value supplied means "false" $col["type"] = _ADDCOL_TYPE_BOOL; $col["value"] = !is_null($val) && $val; // Check if we should set it switch ($this->_optype) { case ADDCOL_INSERT: // Always set the value for INSERT $col["mod"] = true; break; case ADDCOL_UPDATE: default: // A current value is supplied if ($cur_exists) { // This column is previously true if ($curval) { // New value is false. Disable it. if (!$col["value"]) { $col["mod"] = true; } // The current value is false } else { // But it is true now. if ($col["value"]) { $col["mod"] = true; } } // No current value to compare with. } else { // set it anyway $col["mod"] = true; } break; } // Add this column $this->_cols[] = $col; return; } // addboolnull: Add a modified boolean column to the columns deposit // Input: $name: The column name. // $val: The column value. // $curval: The current value to be compared. function addboolnull($name, $val) { // Set the 3rd argument as the current value $cur_exists = false; if (func_num_args() == 3) { $cur_exists = true; $curval = func_get_arg(2); } // Adjust the column name for multi-lingual columns if (in_array($name, $this->_mlcols)) { $name .= "_" . getlang(LN_DATABASE); } // The new column value $col = array(); $col["name"] = $name; $col["mod"] = false; // No value is supplied if (is_null($val) || $val === "") { $col["type"] = _ADDCOL_TYPE_NULL; $col["value"] = null; // A valid value } else { $col["type"] = _ADDCOL_TYPE_BOOL; switch ($val) { case "yes": case "true": $col["value"] = true; break; case "no": case "false": $col["value"] = false; break; } } // Check if we should set it switch ($this->_optype) { case ADDCOL_INSERT: // Always set the value for INSERT $col["mod"] = true; break; case ADDCOL_UPDATE: default: // A current value is supplied if ($cur_exists) { // This column had a value previously if (!is_null($curval)) { // It has no value now. Remove it. if ($col["type"] == _ADDCOL_TYPE_NULL) { $col["mod"] = true; // A different new value. Modify it. } elseif ($col["value"] !== $curval) { $col["mod"] = true; } // This column had no value previously } else { // But it has a value now. if ($col["type"] != _ADDCOL_TYPE_NULL) { $col["mod"] = true; } } // No current value to compare with. } else { // Set it anyway $col["mod"] = true; } break; } // Add this column $this->_cols[] = $col; return; } // addexpr: Add a expression column value to the columns deposit // Input: $name: The column name. // $val: The column value. function addexpr($name, $expr) { // Adjust the column name for multi-lingual columns if (in_array($name, $this->_mlcols)) { $name .= "_" . getlang(LN_DATABASE); } // The new column value // Always set it, since it is not possible to compare the current value $col = array(); $col["name"] = $name; $col["mod"] = true; $col["type"] = _ADDCOL_TYPE_EXPR; $col["value"] = $expr; // Add this column $this->_cols[] = $col; return; } // modified: Return if this record is modified function modified() { // Find any column that is modified foreach ($this->_cols as $col) { if ($col["mod"]) { return true; } } return false; } // ret: Retrieve the columns deposit in an SQL statement // Input: $timestamp: Whether we should record timestamps or not // Log in forms should not update their timestamps. // Output: An SQL statement in the corresponding query type. function ret($timestamp = true) { // Set the login user if ($timestamp) { if (is_null($this->login)) { $this->login = get_login_sn(); } } switch ($this->_optype) { case ADDCOL_INSERT: $names = array(); $vals = array(); for ($i = 0; $i < count($this->_cols); $i++) { // Skip columns that are not modified if (!$this->_cols[$i]["mod"]) { continue; } $names[] = $this->_cols[$i]["name"]; $vals[] = $this->_valout_sql($this->_cols[$i]); } // Add the timestamp if ($timestamp) { if (in_array("created", $this->_allcols)) { $names[] = "created"; $vals[] = "now()"; } if (in_array("createdby", $this->_allcols)) { $names[] = "createdby"; $vals[] = $this->login; } if (in_array("updated", $this->_allcols)) { $names[] = "updated"; $vals[] = "now()"; } if (in_array("updatedby", $this->_allcols)) { $names[] = "updatedby"; $vals[] = $this->login; } } return "(" . implode(", ", $names) .")" . " VALUES (" . implode(", ", $vals) . ")"; case ADDCOL_UPDATE: default: $phrases = array(); for ($i = 0; $i < count($this->_cols); $i++) { // Skip columns that are not modified if (!$this->_cols[$i]["mod"]) { continue; } $phrases[] = $this->_cols[$i]["name"] . "=" . $this->_valout_sql($this->_cols[$i]); } // Add the timestamp if ($timestamp) { if (in_array("updated", $this->_allcols)) { $phrases[] = "updated=now()"; } if (in_array("updatedby", $this->_allcols)) { $phrases[] = "updatedby=" . $this->login; } } return "SET " . implode(", ", $phrases); } } // _valout_sql: Output a value in a proper SQL format. function _valout_sql($col) { switch ($col["type"]) { case _ADDCOL_TYPE_NULL: return "NULL"; case _ADDCOL_TYPE_NUM: return $col["value"]; case _ADDCOL_TYPE_STR: return "'" . sql_esctext($col["value"]) . "'"; case _ADDCOL_TYPE_DATE: return "'" . $col["value"] . "'"; case _ADDCOL_TYPE_FILE: return "'" . sql_escblob($col["value"]) . "'"; case _ADDCOL_TYPE_IPADDR: return "'" . $col["value"] . "'"; case _ADDCOL_TYPE_BOOL: return $col["value"]? sql_true(): sql_false(); case _ADDCOL_TYPE_EXPR: return $col["value"]; } } // retcsv: Retrieve the columns deposit in a CSV row. // Input: None. // Output: The CSV row function retcsv() { // CSV has no engine. Output the whole record anyway, // no matter updated or not. $vals = array(); for ($i = 0; $i < count($this->_cols); $i++) { $vals[] = $this->_valout_csv($this->_cols[$i]); } return implode(",", $vals) . "\n"; } // _valout_csv: Output a value in a proper CSV format. function _valout_csv($col) { switch ($col["type"]) { case _ADDCOL_TYPE_NULL: return "NULL"; case _ADDCOL_TYPE_NUM: return $col["value"]; case _ADDCOL_TYPE_STR: $val = addslashes($col["value"]); $val = str_replace("\n", "\\n", $val); $val = str_replace("\r", "\\r", $val); $val = str_replace("\0", "\\0", $val); return "\"" . $val . "\""; case _ADDCOL_TYPE_DATE: return "\"" . $col["value"] . "\""; case _ADDCOL_TYPE_BOOL: return $col["value"]? "TRUE": "FALSE"; case _ADDCOL_TYPE_IPADDR: return "\"" . $col["value"] . "\""; // CSV has no engine. The following is emulated. case _ADDCOL_TYPE_EXPR: switch ($col["value"]) { case "now()": return "\"" . date("Y-m-d H:i:s") . "\""; } } } } ?>