1. Import

This commit is contained in:
2026-03-29 10:34:57 +02:00
parent b0e00c1259
commit a1129565af
4899 changed files with 3007593 additions and 0 deletions

View File

@@ -0,0 +1,874 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Stig Bakken <ssb@fast.no> |
// | Tomas V.V.Cox <cox@idecnet.com> |
// +----------------------------------------------------------------------+
//
// $Id: DB.php,v 1.86.2.2 2002/04/09 19:04:02 ssb Exp $
//
// Database independent query interface.
//
require_once "PEAR.php";
/*
* The method mapErrorCode in each DB_dbtype implementation maps
* native error codes to one of these.
*
* If you add an error code here, make sure you also add a textual
* version of it in DB::errorMessage().
*/
define("DB_OK", 1);
define("DB_ERROR", -1);
define("DB_ERROR_SYNTAX", -2);
define("DB_ERROR_CONSTRAINT", -3);
define("DB_ERROR_NOT_FOUND", -4);
define("DB_ERROR_ALREADY_EXISTS", -5);
define("DB_ERROR_UNSUPPORTED", -6);
define("DB_ERROR_MISMATCH", -7);
define("DB_ERROR_INVALID", -8);
define("DB_ERROR_NOT_CAPABLE", -9);
define("DB_ERROR_TRUNCATED", -10);
define("DB_ERROR_INVALID_NUMBER", -11);
define("DB_ERROR_INVALID_DATE", -12);
define("DB_ERROR_DIVZERO", -13);
define("DB_ERROR_NODBSELECTED", -14);
define("DB_ERROR_CANNOT_CREATE", -15);
define("DB_ERROR_CANNOT_DELETE", -16);
define("DB_ERROR_CANNOT_DROP", -17);
define("DB_ERROR_NOSUCHTABLE", -18);
define("DB_ERROR_NOSUCHFIELD", -19);
define("DB_ERROR_NEED_MORE_DATA", -20);
define("DB_ERROR_NOT_LOCKED", -21);
define("DB_ERROR_VALUE_COUNT_ON_ROW", -22);
define("DB_ERROR_INVALID_DSN", -23);
define("DB_ERROR_CONNECT_FAILED", -24);
define("DB_ERROR_EXTENSION_NOT_FOUND",-25);
define("DB_ERROR_NOSUCHDB", -25);
define("DB_ERROR_ACCESS_VIOLATION", -26);
/*
* Warnings are not detected as errors by DB::isError(), and are not
* fatal. You can detect whether an error is in fact a warning with
* DB::isWarning().
*/
define('DB_WARNING', -1000);
define('DB_WARNING_READ_ONLY', -1001);
/*
* These constants are used when storing information about prepared
* statements (using the "prepare" method in DB_dbtype).
*
* The prepare/execute model in DB is mostly borrowed from the ODBC
* extension, in a query the "?" character means a scalar parameter.
* There are two extensions though, a "&" character means an opaque
* parameter. An opaque parameter is simply a file name, the real
* data are in that file (useful for putting uploaded files into your
* database and such). The "!" char means a parameter that must be
* left as it is.
* They modify the quote behavoir:
* DB_PARAM_SCALAR (?) => 'original string quoted'
* DB_PARAM_OPAQUE (&) => 'string from file quoted'
* DB_PARAM_MISC (!) => original string
*/
define('DB_PARAM_SCALAR', 1);
define('DB_PARAM_OPAQUE', 2);
define('DB_PARAM_MISC', 3);
/*
* These constants define different ways of returning binary data
* from queries. Again, this model has been borrowed from the ODBC
* extension.
*
* DB_BINMODE_PASSTHRU sends the data directly through to the browser
* when data is fetched from the database.
* DB_BINMODE_RETURN lets you return data as usual.
* DB_BINMODE_CONVERT returns data as well, only it is converted to
* hex format, for example the string "123" would become "313233".
*/
define('DB_BINMODE_PASSTHRU', 1);
define('DB_BINMODE_RETURN', 2);
define('DB_BINMODE_CONVERT', 3);
/**
* This is a special constant that tells DB the user hasn't specified
* any particular get mode, so the default should be used.
*/
define('DB_FETCHMODE_DEFAULT', 0);
/**
* Column data indexed by numbers, ordered from 0 and up
*/
define('DB_FETCHMODE_ORDERED', 1);
/**
* Column data indexed by column names
*/
define('DB_FETCHMODE_ASSOC', 2);
/**
* Column data as object properties
*/
define('DB_FETCHMODE_OBJECT', 3);
/**
* For multi-dimensional results: normally the first level of arrays
* is the row number, and the second level indexed by column number or name.
* DB_FETCHMODE_FLIPPED switches this order, so the first level of arrays
* is the column name, and the second level the row number.
*/
define('DB_FETCHMODE_FLIPPED', 4);
/* for compatibility */
define('DB_GETMODE_ORDERED', DB_FETCHMODE_ORDERED);
define('DB_GETMODE_ASSOC', DB_FETCHMODE_ASSOC);
define('DB_GETMODE_FLIPPED', DB_FETCHMODE_FLIPPED);
/**
* these are constants for the tableInfo-function
* they are bitwised or'ed. so if there are more constants to be defined
* in the future, adjust DB_TABLEINFO_FULL accordingly
*/
define('DB_TABLEINFO_ORDER', 1);
define('DB_TABLEINFO_ORDERTABLE', 2);
define('DB_TABLEINFO_FULL', 3);
/**
* The main "DB" class is simply a container class with some static
* methods for creating DB objects as well as some utility functions
* common to all parts of DB.
*
* The object model of DB is as follows (indentation means inheritance):
*
* DB The main DB class. This is simply a utility class
* with some "static" methods for creating DB objects as
* well as common utility functions for other DB classes.
*
* DB_common The base for each DB implementation. Provides default
* | implementations (in OO lingo virtual methods) for
* | the actual DB implementations as well as a bunch of
* | query utility functions.
* |
* +-DB_mysql The DB implementation for MySQL. Inherits DB_common.
* When calling DB::factory or DB::connect for MySQL
* connections, the object returned is an instance of this
* class.
*
* @package DB
* @author Stig Bakken <ssb@fast.no>
* @since PHP 4.0
*/
class DB
{
/**
* Create a new DB connection object for the specified database
* type
*
* @param string $type database type, for example "mysql"
*
* @return mixed a newly created DB object, or a DB error code on
* error
*
* access public
*/
function &factory($type)
{
@include_once("DB/${type}.php");
$classname = "DB_${type}";
if (!class_exists($classname)) {
return PEAR::raiseError(null, DB_ERROR_NOT_FOUND,
null, null, null, 'DB_Error', true);
}
@$obj =& new $classname;
return $obj;
}
/**
* Create a new DB connection object and connect to the specified
* database
*
* @param mixed $dsn "data source name", see the DB::parseDSN
* method for a description of the dsn format. Can also be
* specified as an array of the format returned by DB::parseDSN.
*
* @param mixed $options An associative array of option names and
* their values. For backwards compatibility, this parameter may
* also be a boolean that tells whether the connection should be
* persistent. See DB_common::setOption for more information on
* connection options.
*
* @return mixed a newly created DB connection object, or a DB
* error object on error
*
* @see DB::parseDSN
* @see DB::isError
* @see DB_common::setOption
*/
function &connect($dsn, $options = false)
{
if (is_array($dsn)) {
$dsninfo = $dsn;
} else {
$dsninfo = DB::parseDSN($dsn);
}
$type = $dsninfo["phptype"];
if (is_array($options) && isset($options["debug"]) &&
$options["debug"] >= 2) {
// expose php errors with sufficient debug level
include_once "DB/${type}.php";
} else {
@include_once "DB/${type}.php";
}
$classname = "DB_${type}";
if (!class_exists($classname)) {
return PEAR::raiseError(null, DB_ERROR_NOT_FOUND,
null, null, null, 'DB_Error', true);
}
@$obj =& new $classname;
if (is_array($options)) {
foreach ($options as $option => $value) {
$test = $obj->setOption($option, $value);
if (DB::isError($test)) {
return $test;
}
}
} else {
$obj->setOption('persistent', $options);
}
$err = $obj->connect($dsninfo, $obj->getOption('persistent'));
if (DB::isError($err)) {
$err->addUserInfo($dsn);
return $err;
}
return $obj;
}
/**
* Return the DB API version
*
* @return int the DB API version number
*
* @access public
*/
function apiVersion()
{
return 2;
}
/**
* Tell whether a result code from a DB method is an error
*
* @param $value int result code
*
* @return bool whether $value is an error
*
* @access public
*/
function isError($value)
{
return (is_object($value) &&
(get_class($value) == 'db_error' ||
is_subclass_of($value, 'db_error')));
}
/**
* Tell whether a query is a data manipulation query (insert,
* update or delete) or a data definition query (create, drop,
* alter, grant, revoke).
*
* @access public
*
* @param string $query the query
*
* @return boolean whether $query is a data manipulation query
*/
function isManip($query)
{
$manips = 'INSERT|UPDATE|DELETE|'.'REPLACE|CREATE|DROP|'.
'ALTER|GRANT|REVOKE|'.'LOCK|UNLOCK';
if (preg_match('/^\s*"?('.$manips.')\s+/i', $query)) {
return true;
}
return false;
}
/**
* Tell whether a result code from a DB method is a warning.
* Warnings differ from errors in that they are generated by DB,
* and are not fatal.
*
* @param mixed $value result value
*
* @return boolean whether $value is a warning
*
* @access public
*/
function isWarning($value)
{
return (is_object($value) &&
(get_class($value) == "db_warning" ||
is_subclass_of($value, "db_warning")));
}
/**
* Return a textual error message for a DB error code
*
* @param integer $value error code
*
* @return string error message, or false if the error code was
* not recognized
*/
function errorMessage($value)
{
static $errorMessages;
if (!isset($errorMessages)) {
$errorMessages = array(
DB_ERROR => 'unknown error',
DB_ERROR_ALREADY_EXISTS => 'already exists',
DB_ERROR_CANNOT_CREATE => 'can not create',
DB_ERROR_CANNOT_DELETE => 'can not delete',
DB_ERROR_CANNOT_DROP => 'can not drop',
DB_ERROR_CONSTRAINT => 'constraint violation',
DB_ERROR_DIVZERO => 'division by zero',
DB_ERROR_INVALID => 'invalid',
DB_ERROR_INVALID_DATE => 'invalid date or time',
DB_ERROR_INVALID_NUMBER => 'invalid number',
DB_ERROR_MISMATCH => 'mismatch',
DB_ERROR_NODBSELECTED => 'no database selected',
DB_ERROR_NOSUCHFIELD => 'no such field',
DB_ERROR_NOSUCHTABLE => 'no such table',
DB_ERROR_NOT_CAPABLE => 'DB backend not capable',
DB_ERROR_NOT_FOUND => 'not found',
DB_ERROR_NOT_LOCKED => 'not locked',
DB_ERROR_SYNTAX => 'syntax error',
DB_ERROR_UNSUPPORTED => 'not supported',
DB_ERROR_VALUE_COUNT_ON_ROW => 'value count on row',
DB_ERROR_INVALID_DSN => 'invalid DSN',
DB_ERROR_CONNECT_FAILED => 'connect failed',
DB_OK => 'no error',
DB_WARNING => 'unknown warning',
DB_WARNING_READ_ONLY => 'read only',
DB_ERROR_NEED_MORE_DATA => 'insufficient data supplied',
DB_ERROR_EXTENSION_NOT_FOUND=> 'extension not found',
DB_ERROR_NOSUCHDB => 'no such database',
DB_ERROR_ACCESS_VIOLATION => 'insufficient permissions'
);
}
if (DB::isError($value)) {
$value = $value->getCode();
}
return isset($errorMessages[$value]) ? $errorMessages[$value] : $errorMessages[DB_ERROR];
}
/**
* Parse a data source name
*
* A array with the following keys will be returned:
* phptype: Database backend used in PHP (mysql, odbc etc.)
* dbsyntax: Database used with regards to SQL syntax etc.
* protocol: Communication protocol to use (tcp, unix etc.)
* hostspec: Host specification (hostname[:port])
* database: Database to use on the DBMS server
* username: User name for login
* password: Password for login
*
* The format of the supplied DSN is in its fullest form:
*
* phptype(dbsyntax)://username:password@protocol+hostspec/database
*
* Most variations are allowed:
*
* phptype://username:password@protocol+hostspec:110//usr/db_file.db
* phptype://username:password@hostspec/database_name
* phptype://username:password@hostspec
* phptype://username@hostspec
* phptype://hostspec/database
* phptype://hostspec
* phptype(dbsyntax)
* phptype
*
* @param string $dsn Data Source Name to be parsed
*
* @return array an associative array
*
* @author Tomas V.V.Cox <cox@idecnet.com>
*/
function parseDSN($dsn)
{
if (is_array($dsn)) {
return $dsn;
}
$parsed = array(
'phptype' => false,
'dbsyntax' => false,
'username' => false,
'password' => false,
'protocol' => false,
'hostspec' => false,
'port' => false,
'socket' => false,
'database' => false
);
// Find phptype and dbsyntax
if (($pos = strpos($dsn, '://')) !== false) {
$str = substr($dsn, 0, $pos);
$dsn = substr($dsn, $pos + 3);
} else {
$str = $dsn;
$dsn = NULL;
}
// Get phptype and dbsyntax
// $str => phptype(dbsyntax)
if (preg_match('|^(.+?)\((.*?)\)$|', $str, $arr)) {
$parsed['phptype'] = $arr[1];
$parsed['dbsyntax'] = (empty($arr[2])) ? $arr[1] : $arr[2];
} else {
$parsed['phptype'] = $str;
$parsed['dbsyntax'] = $str;
}
if (empty($dsn)) {
return $parsed;
}
// Get (if found): username and password
// $dsn => username:password@protocol+hostspec/database
if (($at = strrpos($dsn,'@')) !== false) {
$str = substr($dsn, 0, $at);
$dsn = substr($dsn, $at + 1);
if (($pos = strpos($str, ':')) !== false) {
$parsed['username'] = urldecode(substr($str, 0, $pos));
$parsed['password'] = urldecode(substr($str, $pos + 1));
} else {
$parsed['username'] = urldecode($str);
}
}
// Find protocol and hostspec
// $dsn => proto(proto_opts)/database
if (preg_match('|^(.+?)\((.*?)\)/?(.*?)$|', $dsn, $match)) {
$proto = $match[1];
$proto_opts = (!empty($match[2])) ? $match[2] : false;
$dsn = $match[3];
// $dsn => protocol+hostspec/database (old format)
} else {
if (strpos($dsn, '+') !== false) {
list($proto, $dsn) = explode('+', $dsn, 2);
}
if (strpos($dsn, '/') !== false) {
list($proto_opts, $dsn) = explode('/', $dsn, 2);
} else {
$proto_opts = $dsn;
$dsn = null;
}
}
// process the different protocol options
$parsed['protocol'] = (!empty($proto)) ? $proto : 'tcp';
$proto_opts = urldecode($proto_opts);
if ($parsed['protocol'] == 'tcp') {
if (strpos($proto_opts, ':') !== false) {
list($parsed['hostspec'], $parsed['port']) = explode(':', $proto_opts);
} else {
$parsed['hostspec'] = $proto_opts;
}
} elseif ($parsed['protocol'] == 'unix') {
$parsed['socket'] = $proto_opts;
}
// Get dabase if any
// $dsn => database
if (!empty($dsn)) {
// /database
if (($pos = strpos($dsn, '?')) === false) {
$parsed['database'] = $dsn;
// /database?param1=value1&param2=value2
} else {
$parsed['database'] = substr($dsn, 0, $pos);
$dsn = substr($dsn, $pos + 1);
if (strpos($dsn, '&') !== false) {
$opts = explode('&', $dsn);
} else { // database?param1=value1
$opts = array($dsn);
}
foreach ($opts as $opt) {
list($key, $value) = explode('=', $opt);
if (!isset($parsed[$key])) { // don't allow params overwrite
$parsed[$key] = urldecode($value);
}
}
}
}
return $parsed;
}
/**
* Load a PHP database extension if it is not loaded already.
*
* @access public
*
* @param string $name the base name of the extension (without the .so or
* .dll suffix)
*
* @return boolean true if the extension was already or successfully
* loaded, false if it could not be loaded
*/
function assertExtension($name)
{
if (!extension_loaded($name)) {
$dlext = OS_WINDOWS ? '.dll' : '.so';
@dl($name . $dlext);
}
return extension_loaded($name);
}
}
/**
* DB_Error implements a class for reporting portable database error
* messages.
*
* @package DB
* @author Stig Bakken <ssb@fast.no>
*/
class DB_Error extends PEAR_Error
{
/**
* DB_Error constructor.
*
* @param mixed $code DB error code, or string with error message.
* @param integer $mode what "error mode" to operate in
* @param integer $level what error level to use for $mode & PEAR_ERROR_TRIGGER
* @param smixed $debuginfo additional debug info, such as the last query
*
* @access public
*
* @see PEAR_Error
*/
function DB_Error($code = DB_ERROR, $mode = PEAR_ERROR_RETURN,
$level = E_USER_NOTICE, $debuginfo = null)
{
if (is_int($code)) {
$this->PEAR_Error('DB Error: ' . DB::errorMessage($code), $code, $mode, $level, $debuginfo);
} else {
$this->PEAR_Error("DB Error: $code", DB_ERROR, $mode, $level, $debuginfo);
}
}
}
/**
* DB_Warning implements a class for reporting portable database
* warning messages.
*
* @package DB
* @author Stig Bakken <ssb@fast.no>
*/
class DB_Warning extends PEAR_Error
{
/**
* DB_Warning constructor.
*
* @param mixed $code DB error code, or string with error message.
* @param integer $mode what "error mode" to operate in
* @param integer $level what error level to use for $mode == PEAR_ERROR_TRIGGER
* @param mmixed $debuginfo additional debug info, such as the last query
*
* @access public
*
* @see PEAR_Error
*/
function DB_Warning($code = DB_WARNING, $mode = PEAR_ERROR_RETURN,
$level = E_USER_NOTICE, $debuginfo = null)
{
if (is_int($code)) {
$this->PEAR_Error('DB Warning: ' . DB::errorMessage($code), $code, $mode, $level, $debuginfo);
} else {
$this->PEAR_Error("DB Warning: $code", 0, $mode, $level, $debuginfo);
}
}
}
/**
* This class implements a wrapper for a DB result set.
* A new instance of this class will be returned by the DB implementation
* after processing a query that returns data.
*
* @package DB
* @author Stig Bakken <ssb@fast.no>
*/
class DB_result
{
var $dbh;
var $result;
var $row_counter = null;
/**
* for limit queries, the row to start fetching
* @var integer
*/
var $limit_from = null;
/**
* for limit queries, the number of rows to fetch
* @var integer
*/
var $limit_count = null;
/**
* DB_result constructor.
* @param resource $dbh DB object reference
* @param resource $result result resource id
*/
function DB_result(&$dbh, $result)
{
$this->dbh = &$dbh;
$this->result = $result;
}
/**
* Fetch and return a row of data (it uses driver->fetchInto for that)
* @param int $fetchmode format of fetched row
* @param int $rownum the row number to fetch
*
* @return array a row of data, NULL on no more rows or PEAR_Error on error
*
* @access public
*/
function fetch_assoc($fetchmode = DB_FETCHMODE_DEFAULT, $rownum=null)
{
if ($fetchmode === DB_FETCHMODE_DEFAULT) {
$fetchmode = $this->dbh->fetchmode;
}
if ($fetchmode === DB_FETCHMODE_OBJECT) {
$fetchmode = DB_FETCHMODE_ASSOC;
$object_class = $this->dbh->fetchmode_object_class;
}
if ($this->limit_from !== null) {
if ($this->row_counter === null) {
$this->row_counter = $this->limit_from;
// For Interbase
if ($this->dbh->features['limit'] == false) {
$i = 0;
while ($i++ < $this->limit_from) {
$this->dbh->fetchInto($this->result, $arr, $fetchmode);
}
}
}
if ($this->row_counter >= (
$this->limit_from + $this->limit_count))
{
return null;
}
if ($this->dbh->features['limit'] == 'emulate') {
$rownum = $this->row_counter;
}
$this->row_counter++;
}
$res = $this->dbh->fetchInto($this->result, $arr, $fetchmode, $rownum);
if ($res !== DB_OK) {
return $res;
}
if (isset($object_class)) {
// default mode specified in DB_common::fetchmode_object_class property
if ($object_class == 'stdClass') {
$ret = (object) $arr;
} else {
$ret =& new $object_class($arr);
}
return $ret;
}
return $arr;
}
/**
* Fetch a row of data into an existing variable.
*
* @param mixed $arr reference to data containing the row
* @param integer $fetchmode format of fetched row
* @param integer $rownum the row number to fetch
*
* @return mixed DB_OK on success, NULL on no more rows or
* a DB_Error object on error
*
* @access public
*/
function fetchInto(&$arr, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum=null)
{
if ($fetchmode === DB_FETCHMODE_DEFAULT) {
$fetchmode = $this->dbh->fetchmode;
}
if ($fetchmode === DB_FETCHMODE_OBJECT) {
$fetchmode = DB_FETCHMODE_ASSOC;
$object_class = $this->dbh->fetchmode_object_class;
}
if ($this->limit_from !== null) {
if ($this->row_counter === null) {
$this->row_counter = $this->limit_from;
// For Interbase
if ($this->dbh->features['limit'] == false) {
$i = 0;
while ($i++ < $this->limit_from) {
$this->dbh->fetchInto($this->result, $arr, $fetchmode);
}
}
}
if ($this->row_counter >= (
$this->limit_from + $this->limit_count))
{
return null;
}
if ($this->dbh->features['limit'] == 'emulate') {
$rownum = $this->row_counter;
}
$this->row_counter++;
}
$res = $this->dbh->fetchInto($this->result, $arr, $fetchmode, $rownum);
if (($res === DB_OK) && isset($object_class)) {
// default mode specified in DB_common::fetchmode_object_class property
if ($object_class == 'stdClass') {
$arr = (object) $arr;
} else {
$arr = new $object_class($arr);
}
}
return $res;
}
/**
* Get the the number of columns in a result set.
*
* @return int the number of columns, or a DB error
*
* @access public
*/
function numCols()
{
return $this->dbh->numCols($this->result);
}
/**
* Get the number of rows in a result set.
*
* @return int the number of rows, or a DB error
*
* @access public
*/
function numRows()
{
return $this->dbh->numRows($this->result);
}
/**
* Get the next result if a batch of queries was executed.
*
* @return bool true if a new result is available or false if not.
*
* @access public
*/
function nextResult()
{
return $this->dbh->nextResult($this->result);
}
/**
* Frees the resources allocated for this result set.
* @return int error code
*
* @access public
*/
function free()
{
$err = $this->dbh->freeResult($this->result);
if(DB::isError($err)) {
return $err;
}
$this->result = false;
return true;
}
/**
* @deprecated
*/
function tableInfo($mode = null)
{
return $this->dbh->tableInfo($this->result, $mode);
}
/**
* returns the actual rows number
* @return integer
*/
function getRowCounter()
{
return $this->row_counter;
}
}
/**
* Pear DB Row Object
* @see DB_common::setFetchMode()
*/
class DB_row
{
/**
* constructor
*
* @param resource row data as array
*/
function DB_row(&$arr)
{
for (reset($arr); $key = key($arr); next($arr)) {
$this->$key = &$arr[$key];
}
}
}
?>

View File

@@ -0,0 +1,90 @@
Abstracted Types (Stig)
-----------------------
DB needs a set of types representing the most commonly used types in
all backends. This type set could also be geared towards integration
with things like XML-RPC/SOAP implementations, HTML form classes, etc.
Real Query Parser (Stig)
------------------------
With a real query parser, DB can implement more of its portability
based on the query, instead of having support functions for
everything. One example would be LIMIT, another "INSERT
... RETURNING".
Portable transactions (Stig)
----------------------------
If DB can parse queries enough to determine what tables are affected
by queries, it should be possible to make a replayable transaction
log. GNOME uses an XML format for configuration data that lets you
checkpoint state once in a while, and revert to that state later.
With a similar approach for transactions in DB we can implement
portable transactions and checkpointing even for the databases that
don't support them.
Error reporting clean-up/debug (Tomas)
-------------------------------------
Now each driver has its own raiseError method, common has a raiseError and
DB has a DB_error class and its own isError() method. This error stuff
overhead could be simplified with only one raiseError, droping the DB Error
class and also the DB::isError() (use the PEAR.php ones instead).
Other idea could be to add a system for allowing people access to all the
queries sended by PEAR DB to the backend. Also a new PEAR_ERROR_DEBUG
flag that automatically (show|triggers) debug info, perhaps
with a new PEAR_(Warning|Debug) object.
Quote clean-up (Stig)
---------------------
1. Keep quote and quoteString, but move quoting of strings back into
quoteString and make quote call it for strings.
2. Add an optional "operator" parameter to quote that is one of "=",
"<", ">" or "<>" that will be inserted in front of the quoted value
unless it is NULL, in which case it will be converted to "IS" (for
"=") or "IS NOT" (for the others).
Auto free statements (Tomas)
----------------------------
By setting a param in query() or for the hole DB instance, PEAR DB
could auto-free results in DB_result->fetch(Into|Row) when the driver
returns false.
Datatypes in prepare syntax (Tomas)
-----------------------------------
Extend the actual prepare/execute placeholders to support data types, both
to check the data introduced to the query and to "cast" the result
to native php data types. Ex:
$sql = "INSERT INTO table VALUES ({{int(4)}}, {{bool}}, {{date('Y-m-d')}})";
$row = $db->query($sql, array(8, 't', '2001-04-1'));
Format: {{<data_type>(<param1>,<param2>)}}
"param" could be the max lenght of the data, date formats, not_null
checks or default values.
Other ideas could be:
1)
$sql = "INSERT INTO table VALUES (?, ?, ?)";
$sth = $db->prepare($sql, array('int(4)', 'bool', 'date');
$res = $db->execute($sth, array($a, $b, $c);
2)
$sql = "INSERT INTO table VALUES (?, ?, ?)";
$params = array(
0 => array($a, 'int(4)'),
1 => array($b, 'bool')
);
$res = $db->query($sql, $params);
Auto connect feature (Tomas)
----------------------------
Add the ability to create for example a light and dump DB object which
will only set up the connection when needed. With that people could
create the DB object in a common prepend or default file without the
need to waste system resources if the use of the database is finally
not needed.

View File

@@ -0,0 +1,15 @@
Maintainers for DB database backends/drivers:
ibase : Ludovico Magnocavallo <ludo@sumatrasolutions.com>
msql :
mssql : Frank M. Kromann <frank@frontbase.com>
mysql : Stig Bakken <ssb@fast.no>
oci8 : Tomas V.V.Cox <cox@idecnet.com>
odbc : Tomas V.V.Cox <cox@idecnet.com>
pgsql : Rui Hirokawa <rui_hirokawa@ybb.ne.jp>
Stig Bakken <ssb@fast.no>
sybase :
ifx : Tomas V.V.Cox <cox@idecnet.com>
fbsql : Frank M. Kromann <frank@frontbase.com>
dbase : Tomas V.V.Cox <cox@idecnet.com>
ldap : Ludovico Magnocavallo <ludo@sumatrasolutions.com>

View File

@@ -0,0 +1,38 @@
DB driver feature matrix:
Symbols:
"x" - implemented, but without tests
"t" - implemented, but one or more tests fail
"T" - implemented, passing all tests
"e" - emulated, without tests
"E" - emulated, passing all tests
"n" - returns "not capable"
"-" - no implementation of this feature
fbsql ifx mssql oci8 pgsql
FEATURE | ibase | msql | mysql | odbc | sybase
simpleQuery x T x x x T T x T x
numCols x T x x x T T x T x
numRows x n n x x T E x T n
errorNative x n x n n T x x T n
prepare/execute e x e e e E T e E e
sequences e T n n n E T n T n
affectedRows x n x x n T T x T x
fetch modes x T x x x T T x T x
fetch row by number x n x x x x n x x x
transactions x x n n x x x x x n
auto-commit x x n n n n x x x n
error mapping x x e - - T T x E -
tableInfo x n n n x T n n x n
Info returned by getListOf
fbsql ifx mssql oci8 pgsql
TYPE | ibase | msql | mysql | odbc | sybase
tables x - - - x x x - x x
views - - - - x n - - x x
users - - - - - x - - x -
databases - - - - - x - - x -
functions - - - - - - - - x -

View File

@@ -0,0 +1,45 @@
How to run tests
----------------
1) First you need the "run-tests.php" script located at the root
directory of the PHP 4 source tar ball.
2) Download the lastest PEAR DB from CVS:
Where you want to place Pear files
# cd /usr/local/lib
Log to the repository (use "phpfi" as password):
# cvs -d :pserver:cvsread@cvs.php.net:/repository login
# cvs -d :pserver:cox@cvs.php.net:/repository co php4/run-tests.php
# cvs -d :pserver:cvsread@cvs.php.net:/repository co php4/pear
# cd php4
# php -f run-tests.php -- <test file or directory>
<test file or directory> can be:
pear/DB/tests: Common PEAR DB tests
pear/DB/tests/<backend>: Specific backend tests
pear/DB/tests/driver: Common tests for all the drivers
DB tester matrix
----------------
B - A - C - K - E - N - D - S
TESTER ibase ifx msql mssql mysql oci8 odbc pgsql sybase fbsql
John Horton - X - - - - - - - -
Tim Zickus - - - - - X - - - -
Tim Parkin - - - - - X - - - -
Paul Gardiner - X - - - - - - - -
Daniel, Adam - - - - - X - - - -
szii@sziisoft.com - - - - - - X¹ - - -
jmh3@linuxfreak.com - - - - - - - X - -
Kevin Henrikson - - - - - X - - - -
Stig Bakken - - - - X - - X - -
Chuck Hagenbuch - - - X - - - - - -
Ludovico Magnocavallo X - - - - - - - - -
MISSING TESTERS - - X - - - - - X X
Comments:
[1]: ODBC using IBM DB2

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,123 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Author: Tomas V.V.Cox <cox@idecnet.com> |
// +----------------------------------------------------------------------+
//
// $Id: dbase.php,v 1.2 2002/02/28 08:27:08 sebastian Exp $
//
// Database independent query interface definition for PHP's dbase
// extension.
//
// XXX legend:
// You have to compile your PHP with the --enable-dbase option
//
require_once "DB/common.php";
class DB_dbase extends DB_common
{
// {{{ properties
var $connection;
var $phptype, $dbsyntax;
var $prepare_tokens = array();
var $prepare_types = array();
var $transaction_opcount = 0;
var $res_row = array();
var $result = 0;
// }}}
// {{{ constructor
/**
* DB_mysql constructor.
*
* @access public
*/
function DB_dbase()
{
$this->DB_common();
$this->phptype = 'dbase';
$this->dbsyntax = 'dbase';
$this->features = array(
'prepare' => false,
'pconnect' => false,
'transactions' => false,
'limit' => false
);
$this->errorcode_map = array();
}
function connect($dsninfo, $persistent = false)
{
if (!DB::assertExtension('dbase')) {
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
}
$this->dsn = $dsninfo;
ob_start();
$conn = dbase_open($dsninfo['database'], 0);
$error = ob_get_contents();
ob_end_clean();
if (!$conn) {
return $this->raiseError(DB_ERROR_CONNECT_FAILED, null,
null, null, strip_tags($error));
}
$this->connection = $conn;
return DB_OK;
}
function disconnect()
{
$ret = dbase_close($this->connection);
$this->connection = null;
return $ret;
}
function &query($query = null)
{
// emulate result resources
$this->res_row[$this->result] = 0;
return new DB_result($this, $this->result++);
}
function fetchInto($res, &$row, $fetchmode, $rownum = null)
{
if ($rownum === null) {
$rownum = $this->res_row[$res]++;
}
if ($fetchmode & DB_FETCHMODE_ASSOC) {
$row = @dbase_get_record_with_names($this->connection, $rownum);
} else {
$row = @dbase_get_record($this->connection, $rownum);
}
if (!$row) {
return null;
}
return DB_OK;
}
function numCols($foo)
{
return dbase_numfields($this->connection);
}
function numRows($foo)
{
return dbase_numrecords($this->connection);
}
}
?>

View File

@@ -0,0 +1,618 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Author: Frank M. Kromann <frank@frontbase.com> |
// +----------------------------------------------------------------------+
//
// $Id: fbsql.php,v 1.14 2002/02/28 08:27:08 sebastian Exp $
//
// Database independent query interface definition for PHP's FrontBase
// extension.
//
//
// XXX legend:
//
// XXX ERRORMSG: The error message from the fbsql function should
// be registered here.
//
require_once "DB/common.php";
class DB_fbsql extends DB_common
{
// {{{ properties
var $connection;
var $phptype, $dbsyntax;
var $prepare_tokens = array();
var $prepare_types = array();
var $num_rows = array();
var $fetchmode = DB_FETCHMODE_ORDERED; /* Default fetch mode */
// }}}
// {{{ constructor
/**
* DB_fbsql constructor.
*
* @access public
*/
function DB_fbsql()
{
$this->DB_common();
$this->phptype = 'fbsql';
$this->dbsyntax = 'fbsql';
$this->features = array(
'prepare' => false,
'pconnect' => true,
'transactions' => true,
'limit' => 'emulate'
);
$this->errorcode_map = array(
1004 => DB_ERROR_CANNOT_CREATE,
1005 => DB_ERROR_CANNOT_CREATE,
1006 => DB_ERROR_CANNOT_CREATE,
1007 => DB_ERROR_ALREADY_EXISTS,
1008 => DB_ERROR_CANNOT_DROP,
1046 => DB_ERROR_NODBSELECTED,
1050 => DB_ERROR_ALREADY_EXISTS,
1051 => DB_ERROR_NOSUCHTABLE,
1054 => DB_ERROR_NOSUCHFIELD,
1062 => DB_ERROR_ALREADY_EXISTS,
1064 => DB_ERROR_SYNTAX,
1100 => DB_ERROR_NOT_LOCKED,
1136 => DB_ERROR_VALUE_COUNT_ON_ROW,
1146 => DB_ERROR_NOSUCHTABLE,
);
}
// }}}
// {{{ connect()
/**
* Connect to a database and log in as the specified user.
*
* @param $dsn the data source name (see DB::parseDSN for syntax)
* @param $persistent (optional) whether the connection should
* be persistent
* @access public
* @return int DB_OK on success, a DB error on failure
*/
function connect($dsninfo, $persistent = false)
{
if (!DB::assertExtension('fbsql'))
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
$this->dsn = $dsninfo;
$dbhost = $dsninfo['hostspec'] ? $dsninfo['hostspec'] : 'localhost';
$user = $dsninfo['username'];
$pw = $dsninfo['password'];
$connect_function = $persistent ? 'fbsql_pconnect' : 'fbsql_connect';
ini_set('track_errors', true);
if ($dbhost && $user && $pw) {
$conn = @$connect_function($dbhost, $user, $pw);
} elseif ($dbhost && $user) {
$conn = @$connect_function($dbhost, $user);
} elseif ($dbhost) {
$conn = @$connect_function($dbhost);
} else {
$conn = false;
}
ini_restore("track_errors");
if (empty($conn)) {
if (empty($php_errormsg)) {
return $this->raiseError(DB_ERROR_CONNECT_FAILED);
} else {
return $this->raiseError(DB_ERROR_CONNECT_FAILED, null, null,
null, $php_errormsg);
}
}
if ($dsninfo['database']) {
if (!fbsql_select_db($dsninfo['database'], $conn)) {
return $this->fbsqlRaiseError();
}
}
$this->connection = $conn;
return DB_OK;
}
// }}}
// {{{ disconnect()
/**
* Log out and disconnect from the database.
*
* @access public
*
* @return bool TRUE on success, FALSE if not connected.
*/
function disconnect()
{
$ret = fbsql_close($this->connection);
$this->connection = null;
return $ret;
}
// }}}
// {{{ simpleQuery()
/**
* Send a query to fbsql and return the results as a fbsql resource
* identifier.
*
* @param the SQL query
*
* @access public
*
* @return mixed returns a valid fbsql result for successful SELECT
* queries, DB_OK for other successful queries. A DB error is
* returned on failure.
*/
function simpleQuery($query)
{
$this->last_query = $query;
$query = $this->modifyQuery($query);
$result = @fbsql_query("$query;", $this->connection);
if (!$result) {
return $this->fbsqlRaiseError();
}
// Determine which queries that should return data, and which
// should return an error code only.
if (DB::isManip($query)) {
return DB_OK;
}
$numrows = $this->numrows($result);
if (is_object($numrows)) {
return $numrows;
}
$this->num_rows[$result] = $numrows;
return $result;
}
// }}}
// {{{ nextResult()
/**
* Move the internal fbsql result pointer to the next available result
*
* @param a valid fbsql result resource
*
* @access public
*
* @return true if a result is available otherwise return false
*/
function nextResult($result)
{
return @fbsql_next_result($result);
}
// }}}
// {{{ fetch_assoc()
/**
* Fetch and return a row of data (it uses fetchInto for that)
* @param $result fbsql result identifier
* @param $fetchmode format of fetched row array
* @param $rownum the absolute row number to fetch
*
* @return array a row of data, or false on error
*/
function fetch_assoc($result, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum=null)
{
if ($fetchmode == DB_FETCHMODE_DEFAULT) {
$fetchmode = $this->fetchmode;
}
$res = $this->fetchInto ($result, $arr, $fetchmode, $rownum);
if ($res !== DB_OK) {
return $res;
}
return $arr;
}
// }}}
// {{{ fetchInto()
/**
* Fetch a row and insert the data into an existing array.
*
* @param $result fbsql result identifier
* @param $arr (reference) array where data from the row is stored
* @param $fetchmode how the array data should be indexed
* @param $rownum the row number to fetch
* @access public
*
* @return int DB_OK on success, a DB error on failure
*/
function fetchInto($result, &$arr, $fetchmode, $rownum=null)
{
if ($rownum !== null) {
if (!@fbsql_data_seek($result, $rownum)) {
return null;
}
}
if ($fetchmode & DB_FETCHMODE_ASSOC) {
$arr = @fbsql_fetch_array($result, FBSQL_ASSOC);
} else {
$arr = @fbsql_fetch_row($result);
}
if (!$arr) {
$errno = @fbsql_errno($this->connection);
if (!$errno) {
return NULL;
}
return $this->fbsqlRaiseError($errno);
}
return DB_OK;
}
// }}}
// {{{ freeResult()
/**
* Free the internal resources associated with $result.
*
* @param $result fbsql result identifier or DB statement identifier
*
* @access public
*
* @return bool TRUE on success, FALSE if $result is invalid
*/
function freeResult($result)
{
if (is_resource($result)) {
return fbsql_free_result($result);
}
if (!isset($this->prepare_tokens[(int)$result])) {
return false;
}
unset($this->prepare_tokens[(int)$result]);
unset($this->prepare_types[(int)$result]);
return true;
}
// }}}
// {{{ autoCommit()
function autoCommit($onoff=false)
{
if ($onoff) {
$this->query("SET COMMIT TRUE");
} else {
$this->query("SET COMMIT FALSE");
}
}
// }}}
// {{{ commit()
function commit()
{
fbsql_commit();
}
// }}}
// {{{ rollback()
function rollback()
{
fbsql_rollback();
}
// }}}
// {{{ numCols()
/**
* Get the number of columns in a result set.
*
* @param $result fbsql result identifier
*
* @access public
*
* @return int the number of columns per row in $result
*/
function numCols($result)
{
$cols = @fbsql_num_fields($result);
if (!$cols) {
return $this->fbsqlRaiseError();
}
return $cols;
}
// }}}
// {{{ numRows()
/**
* Get the number of rows in a result set.
*
* @param $result fbsql result identifier
*
* @access public
*
* @return int the number of rows in $result
*/
function numRows($result)
{
$rows = @fbsql_num_rows($result);
if ($rows === null) {
return $this->fbsqlRaiseError();
}
return $rows;
}
// }}}
// {{{ affectedRows()
/**
* Gets the number of rows affected by the data manipulation
* query. For other queries, this function returns 0.
*
* @return number of rows affected by the last query
*/
function affectedRows()
{
if (DB::isManip($this->last_query)) {
$result = @fbsql_affected_rows($this->connection);
} else {
$result = 0;
}
return $result;
}
// }}}
// {{{ errorNative()
/**
* Get the native error code of the last error (if any) that
* occured on the current connection.
*
* @access public
*
* @return int native fbsql error code
*/
function errorNative()
{
return fbsql_errno($this->connection);
}
// }}}
// {{{ nextId()
/**
* Get the next value in a sequence. We emulate sequences
* for fbsql. Will create the sequence if it does not exist.
*
* @access public
*
* @param $seq_name the name of the sequence
*
* @param $ondemand whether to create the sequence table on demand
* (default is true)
*
* @return a sequence integer, or a DB error
*/
function nextId($seq_name, $ondemand = true)
{
$sqn = preg_replace('/[^a-z0-9_]/i', '_', $seq_name);
$repeat = 0;
do {
$seqname = sprintf($this->getOption("seqname_format"), $sqn);
$result = $this->query("INSERT INTO ${seqname} VALUES(NULL)");
if ($ondemand && DB::isError($result) &&
$result->getCode() == DB_ERROR_NOSUCHTABLE) {
$repeat = 1;
$result = $this->createSequence($seq_name);
if (DB::isError($result)) {
return $result;
}
} else {
$repeat = 0;
}
} while ($repeat);
if (DB::isError($result)) {
return $result;
}
return fbsql_insert_id($this->connection);
}
// }}}
// {{{ createSequence()
function createSequence($seq_name)
{
$sqn = preg_replace('/[^a-z0-9_]/i', '_', $seq_name);
$seqname = sprintf($this->getOption("seqname_format"), $sqn);
return $this->query("CREATE TABLE ${seqname} ".
'(id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL,'.
' PRIMARY KEY(id))');
}
// }}}
// {{{ dropSequence()
function dropSequence($seq_name)
{
$sqn = preg_replace('/[^a-z0-9_]/i', '_', $seq_name);
$seqname = sprintf($this->getOption("seqname_format"), $sqn);
return $this->query("DROP TABLE ${seqname} RESTRICT");
}
// }}}
// {{{ modifyQuery()
function modifyQuery($query)
{
if ($this->options['optimize'] == 'portability') {
// "DELETE FROM table" gives 0 affected rows in fbsql.
// This little hack lets you know how many rows were deleted.
if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $query)) {
$query = preg_replace('/^\s*DELETE\s+FROM\s+(\S+)\s*$/',
'DELETE FROM \1 WHERE 1=1', $query);
}
}
return $query;
}
// }}}
// {{{ fbsqlRaiseError()
function fbsqlRaiseError($errno = null)
{
if ($errno === null) {
$errno = $this->errorCode(fbsql_errno($this->connection));
}
return $this->raiseError($errno, null, null, null,
fbsql_error($this->connection));
}
// }}}
// {{{ tableInfo()
function tableInfo($result, $mode = null) {
$count = 0;
$id = 0;
$res = array();
/*
* depending on $mode, metadata returns the following values:
*
* - mode is false (default):
* $result[]:
* [0]["table"] table name
* [0]["name"] field name
* [0]["type"] field type
* [0]["len"] field length
* [0]["flags"] field flags
*
* - mode is DB_TABLEINFO_ORDER
* $result[]:
* ["num_fields"] number of metadata records
* [0]["table"] table name
* [0]["name"] field name
* [0]["type"] field type
* [0]["len"] field length
* [0]["flags"] field flags
* ["order"][field name] index of field named "field name"
* The last one is used, if you have a field name, but no index.
* Test: if (isset($result['meta']['myfield'])) { ...
*
* - mode is DB_TABLEINFO_ORDERTABLE
* the same as above. but additionally
* ["ordertable"][table name][field name] index of field
* named "field name"
*
* this is, because if you have fields from different
* tables with the same field name * they override each
* other with DB_TABLEINFO_ORDER
*
* you can combine DB_TABLEINFO_ORDER and
* DB_TABLEINFO_ORDERTABLE with DB_TABLEINFO_ORDER |
* DB_TABLEINFO_ORDERTABLE * or with DB_TABLEINFO_FULL
*/
// if $result is a string, then we want information about a
// table without a resultset
if (is_string($result)) {
$id = @fbsql_list_fields($this->dsn['database'],
$result, $this->connection);
if (empty($id)) {
return $this->fbsqlRaiseError();
}
} else { // else we want information about a resultset
$id = $result;
if (empty($id)) {
return $this->fbsqlRaiseError();
}
}
$count = @fbsql_num_fields($id);
// made this IF due to performance (one if is faster than $count if's)
if (empty($mode)) {
for ($i=0; $i<$count; $i++) {
$res[$i]['table'] = @fbsql_field_table ($id, $i);
$res[$i]['name'] = @fbsql_field_name ($id, $i);
$res[$i]['type'] = @fbsql_field_type ($id, $i);
$res[$i]['len'] = @fbsql_field_len ($id, $i);
$res[$i]['flags'] = @fbsql_field_flags ($id, $i);
}
} else { // full
$res["num_fields"]= $count;
for ($i=0; $i<$count; $i++) {
$res[$i]['table'] = @fbsql_field_table ($id, $i);
$res[$i]['name'] = @fbsql_field_name ($id, $i);
$res[$i]['type'] = @fbsql_field_type ($id, $i);
$res[$i]['len'] = @fbsql_field_len ($id, $i);
$res[$i]['flags'] = @fbsql_field_flags ($id, $i);
if ($mode & DB_TABLEINFO_ORDER) {
$res['order'][$res[$i]['name']] = $i;
}
if ($mode & DB_TABLEINFO_ORDERTABLE) {
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
}
}
}
// free the result only if we were called on a table
if (is_string($result)) {
@fbsql_free_result($id);
}
return $res;
}
// }}}
// {{{ getSpecialQuery()
/**
* Returns the query needed to get some backend info
* @param string $type What kind of info you want to retrieve
* @return string The SQL query string
*/
function getSpecialQuery($type)
{
switch ($type) {
case 'tables':
$sql = 'select "table_name" from information_schema.tables';
break;
default:
return null;
}
return $sql;
}
// }}}
}
// TODO/wishlist:
// longReadlen
// binmode
?>

View File

@@ -0,0 +1,592 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Author: Sterling Hughes <sterling@php.net> |
// +----------------------------------------------------------------------+
//
// $Id: ibase.php,v 1.36.2.2 2002/04/09 19:04:13 ssb Exp $
//
// Database independent query interface definition for PHP's Interbase
// extension.
//
require_once 'DB/common.php';
class DB_ibase extends DB_common
{
var $connection;
var $phptype, $dbsyntax;
var $autocommit = 1;
var $manip_query = array();
function DB_ibase()
{
$this->DB_common();
$this->phptype = 'ibase';
$this->dbsyntax = 'ibase';
$this->features = array(
'prepare' => true,
'pconnect' => true,
'transactions' => true,
'limit' => false
);
// just a few of the tons of Interbase error codes listed in the
// Language Reference section of the Interbase manual
$this->errorcode_map = array(
-104 => DB_ERROR_SYNTAX,
-150 => DB_ERROR_ACCESS_VIOLATION,
-151 => DB_ERROR_ACCESS_VIOLATION,
-155 => DB_ERROR_NOSUCHTABLE,
-157 => DB_ERROR_NOSUCHFIELD,
-158 => DB_ERROR_VALUE_COUNT_ON_ROW,
-170 => DB_ERROR_MISMATCH,
-171 => DB_ERROR_MISMATCH,
-172 => DB_ERROR_INVALID,
-204 => DB_ERROR_INVALID,
-205 => DB_ERROR_NOSUCHFIELD,
-206 => DB_ERROR_NOSUCHFIELD,
-208 => DB_ERROR_INVALID,
-219 => DB_ERROR_NOSUCHTABLE,
-297 => DB_ERROR_CONSTRAINT,
-530 => DB_ERROR_CONSTRAINT,
-803 => DB_ERROR_CONSTRAINT,
-551 => DB_ERROR_ACCESS_VIOLATION,
-552 => DB_ERROR_ACCESS_VIOLATION,
-922 => DB_ERROR_NOSUCHDB,
-923 => DB_ERROR_CONNECT_FAILED,
-924 => DB_ERROR_CONNECT_FAILED
);
}
function connect($dsninfo, $persistent = false)
{
if (!DB::assertExtension('interbase')) {
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
}
$this->dsn = $dsninfo;
$user = $dsninfo['username'];
$pw = $dsninfo['password'];
$dbhost = $dsninfo['hostspec'] ?
($dsninfo['hostspec'] . ':/' . $dsninfo['database']) :
$dsninfo['database'];
$connect_function = $persistent ? 'ibase_pconnect' : 'ibase_connect';
$params = array();
$params[] = $dbhost;
$params[] = !empty($user) ? $user : null;
$params[] = !empty($pw) ? $pw : null;
$params[] = isset($dsninfo['charset']) ? $dsninfo['charset'] : null;
$params[] = isset($dsninfo['buffers']) ? $dsninfo['buffers'] : null;
$params[] = isset($dsninfo['dialect']) ? $dsninfo['dialect'] : null;
$params[] = isset($dsninfo['role']) ? $dsninfo['role'] : null;
/*
if ($dbhost && $user && $pw) {
$conn = $connect_function($dbhost, $user, $pw);
} elseif ($dbhost && $user) {
$conn = $connect_function($dbhost, $user);
} elseif ($dbhost) {
$conn = $connect_function($dbhost);
} else {
return $this->raiseError("no host, user or password");
}
*/
$conn = @call_user_func_array($connect_function, $params);
if (!$conn) {
return $this->ibaseRaiseError(DB_ERROR_CONNECT_FAILED);
}
$this->connection = $conn;
return DB_OK;
}
function disconnect()
{
$ret = @ibase_close($this->connection);
$this->connection = null;
return $ret;
}
function simpleQuery($query)
{
$ismanip = DB::isManip($query);
$this->last_query = $query;
$query = $this->modifyQuery($query);
$result = @ibase_query($this->connection, $query);
if (!$result) {
return $this->ibaseRaiseError();
}
if ($this->autocommit && $ismanip) {
ibase_commit($this->connection);
}
// Determine which queries that should return data, and which
// should return an error code only.
return DB::isManip($query) ? DB_OK : $result;
}
// {{{ modifyLimitQuery()
/**
* This method is used by backends to alter limited queries
* Uses the new FIRST n SKIP n Firebird 1.0 syntax, so it is
* only compatible with Firebird 1.x
*
* @param string $query query to modify
* @param integer $from the row to start to fetching
* @param integer $count the numbers of rows to fetch
*
* @return the new (modified) query
* @author Ludovico Magnocavallo <ludo@sumatrasolutions.com>
* @access private
*/
function modifyLimitQuery($query, $from, $count)
{
if ($this->dsn['dbsyntax'] == 'firebird') {
$from++; // SKIP starts from 1, ie SKIP 1 starts from the first record
$query = preg_replace('/^\s*select\s(.*)$/is',
"SELECT FIRST $count SKIP $from $1", $query);
}
return $query;
}
// }}}
// {{{ nextResult()
/**
* Move the internal ibase result pointer to the next available result
*
* @param a valid fbsql result resource
*
* @access public
*
* @return true if a result is available otherwise return false
*/
function nextResult($result)
{
return false;
}
// }}}
function fetchInto($result, &$ar, $fetchmode, $rownum = null)
{
if ($rownum !== NULL) {
return $this->ibaseRaiseError(DB_ERROR_NOT_CAPABLE);
}
if ($fetchmode & DB_FETCHMODE_ASSOC) {
$ar = get_object_vars(ibase_fetch_object($result));
if ($ar && $this->options['optimize'] == 'portability') {
$ar = array_change_key_case($ar, CASE_LOWER);
}
} else {
$ar = ibase_fetch_row($result);
}
if (!$ar) {
if ($errmsg = ibase_errmsg()) {
return $this->ibaseRaiseError(null, $errmsg);
} else {
return null;
}
}
return DB_OK;
}
function freeResult()
{
if (is_resource($result)) {
return ibase_free_result($result);
}
if (!isset($this->prepare_tokens[(int)$result])) {
return false;
}
unset($this->prepare_tokens[(int)$result]);
unset($this->prepare_types[(int)$result]);
return true;
}
function freeQuery($query)
{
ibase_free_query($query);
return true;
}
function numCols($result)
{
$cols = ibase_num_fields($result);
if (!$cols) {
return $this->ibaseRaiseError();
}
return $cols;
}
function prepare($query)
{
$this->last_query = $query;
$query = $this->modifyQuery($query);
$stmt = ibase_prepare($query);
$this->manip_query[(int)$stmt] = DB::isManip($query);
return $stmt;
}
function execute($stmt, $data = false)
{
$result = ibase_execute($stmt, $data);
if (!$result) {
return $this->ibaseRaiseError();
}
if ($this->autocommit) {
ibase_commit($this->connection);
}
return DB::isManip($this->manip_query[(int)$stmt]) ? DB_OK : new DB_result($this, $result);
}
function autoCommit($onoff = false)
{
$this->autocommit = $onoff ? 1 : 0;
return DB_OK;
}
function commit()
{
return ibase_commit($this->connection);
}
function rollback($trans_number)
{
return ibase_rollback($this->connection, $trans_number);
}
function transactionInit($trans_args = 0)
{
return $trans_args ? ibase_trans($trans_args, $this->connection) : ibase_trans();
}
// {{{ nextId()
/**
* Get the next value in a sequence.
*
* If the sequence does not exist, it will be created,
* unless $ondemand is false.
*
* @access public
* @param string $seq_name the name of the sequence
* @param bool $ondemand whether to create the sequence on demand
* @return a sequence integer, or a DB error
*/
function nextId($seq_name, $ondemand = true)
{
$sqn = strtoupper(preg_replace('/[^a-z0-9_]/i', '_', $seq_name));
$repeat = 0;
do {
$this->pushErrorHandling(PEAR_ERROR_RETURN);
$result = $this->query("SELECT GEN_ID(${sqn}_SEQ, 1) FROM RDB\$GENERATORS"
." WHERE RDB\$GENERATOR_NAME='${sqn}_SEQ'");
$this->popErrorHandling();
if ($ondemand && DB::isError($result)) {
$repeat = 1;
$result = $this->createSequence($seq_name);
if (DB::isError($result)) {
return $result;
}
} else {
$repeat = 0;
}
} while ($repeat);
if (DB::isError($result)) {
return $result;
}
$arr = $result->fetch_assoc(DB_FETCHMODE_ORDERED);
$result->free();
return $arr[0];
}
// }}}
// {{{ createSequence()
/**
* Create the sequence
*
* @param string $seq_name the name of the sequence
* @return mixed DB_OK on success or DB error on error
* @access public
*/
function createSequence($seq_name)
{
$sqn = strtoupper(preg_replace('/[^a-z0-9_]/i', '_', $seq_name));
$this->pushErrorHandling(PEAR_ERROR_RETURN);
$result = $this->query("CREATE GENERATOR ${sqn}_SEQ");
$this->popErrorHandling();
return $result;
}
// }}}
// {{{ dropSequence()
/**
* Drop a sequence
*
* @param string $seq_name the name of the sequence
* @return mixed DB_OK on success or DB error on error
* @access public
*/
function dropSequence($seq_name)
{
$sqn = strtoupper(preg_replace('/[^a-z0-9_]/i', '_', $seq_name));
return $this->query("DELETE FROM RDB\$GENERATORS WHERE RDB\$GENERATOR_NAME='${sqn}_SEQ'");
}
// }}}
// {{{ _ibaseFieldFlags()
/**
* get the Flags of a Field
*
* @param string $field_name the name of the field
* @param string $table_name the name of the table
*
* @return string The flags of the field ("primary_key", "unique_key", "not_null"
* "default", "computed" and "blob" are supported)
* @access private
*/
function _ibaseFieldFlags($field_name, $table_name)
{
$sql = 'SELECT R.RDB$CONSTRAINT_TYPE CTYPE'
.' FROM RDB$INDEX_SEGMENTS I'
.' JOIN RDB$RELATION_CONSTRAINTS R ON I.RDB$INDEX_NAME=R.RDB$INDEX_NAME'
.' WHERE I.RDB$FIELD_NAME=\''.$field_name.'\''
.' AND R.RDB$RELATION_NAME=\''.$table_name.'\'';
$result = ibase_query($this->connection, $sql);
if (empty($result)) {
return $this->ibaseRaiseError();
}
if ($obj = @ibase_fetch_object($result)) {
ibase_free_result($result);
if (isset($obj->CTYPE) && trim($obj->CTYPE) == 'PRIMARY KEY') {
$flags = 'primary_key ';
}
if (isset($obj->CTYPE) && trim($obj->CTYPE) == 'UNIQUE') {
$flags .= 'unique_key ';
}
}
$sql = 'SELECT R.RDB$NULL_FLAG AS NFLAG,'
.' R.RDB$DEFAULT_SOURCE AS DSOURCE,'
.' F.RDB$FIELD_TYPE AS FTYPE,'
.' F.RDB$COMPUTED_SOURCE AS CSOURCE'
.' FROM RDB$RELATION_FIELDS R '
.' JOIN RDB$FIELDS F ON R.RDB$FIELD_SOURCE=F.RDB$FIELD_NAME'
.' WHERE R.RDB$RELATION_NAME=\''.$table_name.'\''
.' AND R.RDB$FIELD_NAME=\''.$field_name.'\'';
$result = ibase_query($this->connection, $sql);
if (empty($result)) {
return $this->ibaseRaiseError();
}
if ($obj = @ibase_fetch_object($result)) {
ibase_free_result($result);
if (isset($obj->NFLAG)) {
$flags .= 'not_null ';
}
if (isset($obj->DSOURCE)) {
$flags .= 'default ';
}
if (isset($obj->CSOURCE)) {
$flags .= 'computed ';
}
if (isset($obj->FTYPE) && $obj->FTYPE == 261) {
$flags .= 'blob ';
}
}
return trim($flags);
}
// }}}
// {{{ tableInfo()
/**
* Returns information about a table or a result set
*
* NOTE: doesn't support 'flags'and 'table' if called from a db_result
*
* @param mixed $resource Interbase result identifier or table name
* @param int $mode A valid tableInfo mode (DB_TABLEINFO_ORDERTABLE or
* DB_TABLEINFO_ORDER)
*
* @return array An array with all the information
*/
function tableInfo($result, $mode = null)
{
$count = 0;
$id = 0;
$res = array();
/*
* depending on $mode, metadata returns the following values:
*
* - mode is false (default):
* $result[]:
* [0]["table"] table name
* [0]["name"] field name
* [0]["type"] field type
* [0]["len"] field length
* [0]["flags"] field flags
*
* - mode is DB_TABLEINFO_ORDER
* $result[]:
* ["num_fields"] number of metadata records
* [0]["table"] table name
* [0]["name"] field name
* [0]["type"] field type
* [0]["len"] field length
* [0]["flags"] field flags
* ["order"][field name] index of field named "field name"
* The last one is used, if you have a field name, but no index.
* Test: if (isset($result['meta']['myfield'])) { ...
*
* - mode is DB_TABLEINFO_ORDERTABLE
* the same as above. but additionally
* ["ordertable"][table name][field name] index of field
* named "field name"
*
* this is, because if you have fields from different
* tables with the same field name * they override each
* other with DB_TABLEINFO_ORDER
*
* you can combine DB_TABLEINFO_ORDER and
* DB_TABLEINFO_ORDERTABLE with DB_TABLEINFO_ORDER |
* DB_TABLEINFO_ORDERTABLE * or with DB_TABLEINFO_FULL
*/
// if $result is a string, then we want information about a
// table without a resultset
if (is_string($result)) {
$id = ibase_query($this->connection,"SELECT * FROM $result");
if (empty($id)) {
return $this->ibaseRaiseError();
}
} else { // else we want information about a resultset
$id = $result;
if (empty($id)) {
return $this->ibaseRaiseError();
}
}
$count = @ibase_num_fields($id);
// made this IF due to performance (one if is faster than $count if's)
if (empty($mode)) {
for ($i=0; $i<$count; $i++) {
$info = @ibase_field_info($id, $i);
$res[$i]['table'] = (is_string($result)) ? $result : '';
$res[$i]['name'] = $info['name'];
$res[$i]['type'] = $info['type'];
$res[$i]['len'] = $info['length'];
$res[$i]['flags'] = (is_string($result)) ? $this->_ibaseFieldFlags($info['name'], $result) : '';
}
} else { // full
$res["num_fields"]= $count;
for ($i=0; $i<$count; $i++) {
$info = @ibase_field_info($id, $i);
$res[$i]['table'] = (is_string($result)) ? $result : '';
$res[$i]['name'] = $info['name'];
$res[$i]['type'] = $info['type'];
$res[$i]['len'] = $info['length'];
$res[$i]['flags'] = (is_string($result)) ? $this->_ibaseFieldFlags($info['name'], $result) : '';
if ($mode & DB_TABLEINFO_ORDER) {
$res['order'][$res[$i]['name']] = $i;
}
if ($mode & DB_TABLEINFO_ORDERTABLE) {
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
}
}
}
// free the result only if we were called on a table
if (is_resource($id)) {
ibase_free_result($id);
}
return $res;
}
// }}}
// {{{ getSpecialQuery()
/**
* Returns the query needed to get some backend info
* @param string $type What kind of info you want to retrieve
* @return string The SQL query string
*/
function getSpecialQuery($type)
{
switch ($type) {
case 'tables':
default:
return null;
}
return $sql;
}
// }}}
// {{{ ibaseRaiseError()
function ibaseRaiseError($errno = null, $errmsg = null)
{
if ($errmsg === null)
$errmsg = ibase_errmsg();
// memo for the interbase php module hackers: we need something similar
// to mysql_errno() to retrieve error codes instead of this ugly hack
if (preg_match('/^([^0-9\-]+)([0-9\-]+)\s+(.*)$/', $errmsg, $m)) {
if ($errno === null) {
$ibase_errno = (int)$m[2];
// try to interpret Interbase error code (that's why we need ibase_errno()
// in the interbase module to return the real error code)
switch ($ibase_errno) {
case -204:
if (is_int(strpos($m[3], 'Table unknown'))) {
$errno = DB_ERROR_NOSUCHTABLE;
}
break;
default:
$errno = $this->errorCode($ibase_errno);
}
}
$errmsg = $m[2] . ' ' . $m[3];
}
return $this->raiseError($errno, null, null, $errmsg,
$this->last_query);
}
// }}}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
*/
?>

View File

@@ -0,0 +1,323 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Author: Tomas V.V.Cox <cox@idecnet.com> |
// +----------------------------------------------------------------------+
//
// $Id: ifx.php,v 1.18 2002/02/28 08:27:09 sebastian Exp $
//
// Database independent query interface definition for PHP's Informix
// extension.
//
// Legend:
// For more info on Informix errors see:
// http://www.informix.com/answers/english/ierrors.htm
//
// TODO:
// - set needed env Informix vars on connect
// - implement native prepare/execute
require_once 'DB/common.php';
class DB_ifx extends DB_common
{
var $connection;
var $affected = 0;
var $dsn = array();
var $fetchmode = DB_FETCHMODE_ORDERED; /* Default fetch mode */
function DB_ifx()
{
$this->phptype = 'ifx';
$this->dbsyntax = 'ifx';
$this->features = array(
'prepare' => false,
'pconnect' => true,
'transactions' => false,
'limit' => 'emulate'
);
$this->errorcode_map = array(
'-201' => DB_ERROR_SYNTAX,
'-206' => DB_ERROR_NOSUCHTABLE,
'-217' => DB_ERROR_NOSUCHFIELD,
'-329' => DB_ERROR_NODBSELECTED,
'-1204' => DB_ERROR_INVALID_DATE,
'-1205' => DB_ERROR_INVALID_DATE,
'-1206' => DB_ERROR_INVALID_DATE,
'-1209' => DB_ERROR_INVALID_DATE,
'-1210' => DB_ERROR_INVALID_DATE,
'-1212' => DB_ERROR_INVALID_DATE
);
}
/**
* Connect to a database and log in as the specified user.
*
* @param $dsn the data source name (see DB::parseDSN for syntax)
* @param $persistent (optional) whether the connection should
* be persistent
*
* @return int DB_OK on success, a DB error code on failure
*/
function connect(&$dsninfo, $persistent = false)
{
if (!DB::assertExtension('informix'))
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
$this->dsn = $dsninfo;
$dbhost = $dsninfo['hostspec'] ? '@' . $dsninfo['hostspec'] : '';
$dbname = $dsninfo['database'] ? $dsninfo['database'] . $dbhost : '';
$user = $dsninfo['username'] ? $dsninfo['username'] : '';
$pw = $dsninfo['password'] ? $dsninfo['password'] : '';
$connect_function = $persistent ? 'ifx_pconnect' : 'ifx_connect';
$this->connection = @$connect_function($dbname, $user, $pw);
if (!is_resource($this->connection)) {
return $this->ifxraiseError(DB_ERROR_CONNECT_FAILED);
}
return DB_OK;
}
/**
* Log out and disconnect from the database.
*
* @return bool TRUE on success, FALSE if not connected.
*/
function disconnect()
{
$ret = @ifx_close($this->connection);
$this->connection = null;
return $ret;
}
/**
* Send a query to Informix and return the results as a
* Informix resource identifier.
*
* @param $query the SQL query
*
* @return int returns a valid Informix result for successful SELECT
* queries, DB_OK for other successful queries. A DB error code
* is returned on failure.
*/
function simpleQuery($query)
{
$this->last_query = $query;
if (preg_match('/(SELECT)/i', $query)) { //TESTME: Use !DB::isManip()?
// the scroll is needed for fetching absolute row numbers
// in a select query result
$result = @ifx_query($query, $this->connection, IFX_SCROLL);
} else {
$result = @ifx_query($query, $this->connection);
}
if (!$result) {
return $this->ifxraiseError();
}
$this->affected = ifx_affected_rows ($result);
// Determine which queries that should return data, and which
// should return an error code only.
if (preg_match('/(SELECT)/i', $query)) {
return $result;
}
return DB_OK;
}
// {{{ nextResult()
/**
* Move the internal ifx result pointer to the next available result
*
* @param a valid fbsql result resource
*
* @access public
*
* @return true if a result is available otherwise return false
*/
function nextResult($result)
{
return false;
}
// }}}
/**
* Gets the number of rows affected by the last query.
* if the last query was a select, returns an _estimate_ value.
*
* @return number of rows affected by the last query
*/
function affectedRows()
{
return $this->affected;
}
/**
* Fetch and return a row of data (it uses fetchInto for that)
* @param $result Informix result identifier
* @param $fetchmode format of fetched row array
* @param $rownum the absolute row number to fetch
*
* @return array a row of data, or false on error
*/
function fetch_assoc($result, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum=null)
{
if ($fetchmode == DB_FETCHMODE_DEFAULT) {
$fetchmode = $this->fetchmode;
}
$res = $this->fetchInto ($result, $arr, $fetchmode, $rownum);
if ($res !== DB_OK) {
return $res;
}
return $arr;
}
/**
* Fetch a row and return as array.
*
* @param $result Informix result identifier
* @param $row (reference) array where data from the row is stored
* @param $fetchmode how the resulting array should be indexed
* @param $rownum the row number to fetch
*
* @return int an array on success, a DB error code on failure, NULL
* if there is no more data
*/
function fetchInto($result, &$row, $fetchmode, $rownum=null)
{
if (($rownum !== null) && ($rownum < 0)) {
return null;
}
// if $rownum is null, fetch row will return the next row
if (!$row = @ifx_fetch_row($result, $rownum)) {
return null;
}
if ($fetchmode !== DB_FETCHMODE_ASSOC) {
$i=0;
$order = array();
foreach ($row as $key => $val) {
$order[$i++] = $val;
}
$row = $order;
}
return DB_OK;
}
function numRows($result)
{
return $this->raiseError(DB_ERROR_NOT_CAPABLE);
}
/**
* Get the number of columns in a result set.
*
* @param $result Informix result identifier
*
* @return int the number of columns per row in $result
*/
function numCols($result)
{
if (!$cols = @ifx_num_fields($result)) {
return $this->ifxraiseError();
}
return $cols;
}
/**
* Free the internal resources associated with $result.
*
* @param $result Informix result identifier
*
* @return bool TRUE on success, DB_error on error
*/
function freeResult($result)
{
if (is_resource($result)) {
if (!@ifx_free_result($result)) {
return $this->ifxraiseError();
}
return true;
}
if (!isset($this->prepare_tokens[(int)$result])) {
return false;
}
unset($this->prepare_tokens[(int)$result]);
unset($this->prepare_types[(int)$result]);
return true;
}
function ifxraiseError($errno = null)
{
if ($errno === null) {
$errno = $this->errorCode(ifx_error());
}
return $this->raiseError($errno, null, null, null,
$this->errorNative());
}
/**
* Map native error codes to DB's portable ones. Requires that
* the DB implementation's constructor fills in the $errorcode_map
* property.
*
* @return int a portable DB error code, or DB_ERROR if this DB
* implementation has no mapping for the given error code.
*/
function errorCode($nativecode)
{
if (ereg('SQLCODE=(.*)]', $nativecode, $match)) {
$code = $match[1];
if (isset($this->errorcode_map[$code])) {
return $this->errorcode_map[$code];
}
}
return DB_ERROR;
}
/**
* Get the native error message of the last error (if any) that
* occured on the current connection.
*
* @return int native Informix error code
*/
function errorNative()
{
return ifx_error() . ' ' . ifx_errormsg();
}
// {{{ getSpecialQuery()
/**
* Returns the query needed to get some backend info
* @param string $type What kind of info you want to retrieve
* @return string The SQL query string
*/
function getSpecialQuery($type)
{
switch ($type) {
case 'tables':
default:
return null;
}
return $sql;
}
// }}}
}
?>

View File

@@ -0,0 +1,210 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Author: Sterling Hughes <sterling@php.net> |
// +----------------------------------------------------------------------+
//
// $Id: msql.php,v 1.25 2002/02/28 08:27:10 sebastian Exp $
//
// Database independent query interface definition for PHP's Mini-SQL
// extension.
//
require_once 'DB/common.php';
class DB_msql extends DB_common
{
var $connection;
var $phptype, $dbsyntax;
var $prepare_tokens = array();
var $prepare_types = array();
function DB_msql()
{
$this->DB_common();
$this->phptype = 'msql';
$this->dbsyntax = 'msql';
$this->features = array(
'prepare' => false,
'pconnect' => true,
'transactions' => false,
'limit' => 'emulate'
);
}
function connect($dsninfo, $persistent = false)
{
if (!DB::assertExtension('msql'))
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
$this->dsn = $dsninfo;
$user = $dsninfo['username'];
$pw = $dsninfo['password'];
$dbhost = $dsninfo['hostspec'] ? $dsninfo['hostspec'] : 'localhost';
$connect_function = $persistent ? 'msql_pconnect' : 'msql_connect';
if ($dbhost && $user && $pw) {
$conn = $connect_function($dbhost, $user, $pw);
} elseif ($dbhost && $user) {
$conn = $connect_function($dbhost,$user);
} else {
$conn = $connect_function($dbhost);
}
if (!$conn) {
$this->raiseError(DB_ERROR_CONNECT_FAILED);
}
if (!@msql_select_db($dsninfo['database'], $conn)){
return $this->raiseError(DB_ERROR_NODBSELECTED);
}
$this->connection = $conn;
return DB_OK;
}
function disconnect()
{
$ret = @msql_close($this->connection);
$this->connection = null;
return $ret;
}
function simpleQuery($query)
{
$this->last_query = $query;
$query = $this->modifyQuery($query);
$result = @msql_query($query, $this->connection);
if (!$result) {
return $this->raiseError();
}
// Determine which queries that should return data, and which
// should return an error code only.
return DB::isManip($query) ? DB_OK : $result;
}
// {{{ nextResult()
/**
* Move the internal msql result pointer to the next available result
*
* @param a valid fbsql result resource
*
* @access public
*
* @return true if a result is available otherwise return false
*/
function nextResult($result)
{
return false;
}
// }}}
function fetch_assoc($result, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum=null)
{
if ($fetchmode == DB_FETCHMODE_DEFAULT) {
$fetchmode = $this->fetchmode;
}
$res = $this->fetchInto ($result, $arr, $fetchmode, $rownum);
if ($res !== DB_OK) {
return $res;
}
return $arr;
}
function fetchInto($result, &$ar, $fetchmode, $rownum=null)
{
if ($rownum !== null) {
if (!@msql_data_seek($result, $rownum)) {
return null;
}
}
if ($fetchmode & DB_FETCHMODE_ASSOC) {
$ar = @msql_fetch_array($result, MSQL_ASSOC);
} else {
$ar = @msql_fetch_row($result);
}
if (!$ar) {
if ($error = msql_error()) {
return $this->raiseError($error);
} else {
return null;
}
}
return DB_OK;
}
function freeResult($result)
{
if (is_resource($result)) {
return @msql_free_result($result);
}
if (!isset($this->prepare_tokens[$result])) {
return false;
}
unset($this->prepare_tokens[$result]);
unset($this->prepare_types[$result]);
return true;
}
function numCols($result)
{
$cols = @msql_num_fields($result);
if (!$cols) {
return $this->raiseError();
}
return $cols;
}
function numRows($result)
{
$rows = @msql_num_rows($result);
if (!$rows) {
return $this->raiseError();
}
return $rows;
}
/**
* Gets the number of rows affected by a query.
*
* @return number of rows affected by the last query
*/
function affectedRows()
{
return @msql_affected_rows($this->connection);
}
// {{{ getSpecialQuery()
/**
* Returns the query needed to get some backend info
* @param string $type What kind of info you want to retrieve
* @return string The SQL query string
*/
function getSpecialQuery($type)
{
switch ($type) {
case 'tables':
default:
return null;
}
return $sql;
}
// }}}
}
?>

View File

@@ -0,0 +1,500 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Author: Sterling Hughes <sterling@php.net> |
// +----------------------------------------------------------------------+
//
// $Id: mssql.php,v 1.40 2002/02/28 08:27:10 sebastian Exp $
//
// Database independent query interface definition for PHP's Microsoft SQL Server
// extension.
//
require_once 'DB/common.php';
class DB_mssql extends DB_common
{
var $connection;
var $phptype, $dbsyntax;
var $prepare_tokens = array();
var $prepare_types = array();
var $transaction_opcount = 0;
var $autocommit = true;
function DB_mssql()
{
$this->DB_common();
$this->phptype = 'mssql';
$this->dbsyntax = 'mssql';
$this->features = array(
'prepare' => false,
'pconnect' => true,
'transactions' => true,
'limit' => 'emulate'
);
// XXX Add here error codes ie: 'S100E' => DB_ERROR_SYNTAX
$this->errorcode_map = array(
);
}
function connect($dsninfo, $persistent = false)
{
if (!DB::assertExtension('mssql') && !DB::assertExtension('sybase')
&& !DB::assertExtension('sybase_ct'))
{
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
}
$this->dsn = $dsninfo;
$user = $dsninfo['username'];
$pw = $dsninfo['password'];
$dbhost = $dsninfo['hostspec'] ? $dsninfo['hostspec'] : 'localhost';
$connect_function = $persistent ? 'mssql_pconnect' : 'mssql_connect';
if ($dbhost && $user && $pw) {
$conn = @$connect_function($dbhost, $user, $pw);
} elseif ($dbhost && $user) {
$conn = @$connect_function($dbhost, $user);
} else {
$conn = @$connect_function($dbhost);
}
if (!$conn) {
return $this->raiseError(DB_ERROR_CONNECT_FAILED, null, null,
null, mssql_get_last_message());
}
if ($dsninfo['database']) {
if (!@mssql_select_db($dsninfo['database'], $conn)) {
return $this->raiseError(DB_ERROR_NODBSELECTED, null, null,
null, mssql_get_last_message());
}
}
$this->connection = $conn;
return DB_OK;
}
function disconnect()
{
$ret = @mssql_close($this->connection);
$this->connection = null;
return $ret;
}
function simpleQuery($query)
{
$ismanip = DB::isManip($query);
$this->last_query = $query;
$query = $this->modifyQuery($query);
if (!$this->autocommit && $ismanip) {
if ($this->transaction_opcount == 0) {
$result = @mssql_query('BEGIN TRAN', $this->connection);
if (!$result) {
return $this->mssqlRaiseError();
}
}
$this->transaction_opcount++;
}
$result = @mssql_query($query, $this->connection);
if (!$result) {
return $this->mssqlRaiseError();
}
// Determine which queries that should return data, and which
// should return an error code only.
return $ismanip ? DB_OK : $result;
}
// {{{ nextResult()
/**
* Move the internal mssql result pointer to the next available result
*
* @param a valid fbsql result resource
*
* @access public
*
* @return true if a result is available otherwise return false
*/
function nextResult($result)
{
return mssql_next_result($result);
}
// }}}
function &fetch_assoc($result, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum=null)
{
if ($fetchmode == DB_FETCHMODE_DEFAULT) {
$fetchmode = $this->fetchmode;
}
$res = $this->fetchInto ($result, $arr, $fetchmode, $rownum);
if ($res !== DB_OK) {
return $res;
}
return $arr;
}
function fetchInto($result, &$ar, $fetchmode, $rownum=null)
{
if ($rownum !== null) {
if (!@mssql_data_seek($result, $rownum)) {
return null;
}
}
if ($fetchmode & DB_FETCHMODE_ASSOC) {
$ar = @mssql_fetch_array($result);
} else {
$ar = @mssql_fetch_row($result);
}
if (!$ar) {
/* This throws informative error messages,
don't use it for now
if ($msg = mssql_get_last_message()) {
return $this->raiseError($msg);
}
*/
return null;
}
return DB_OK;
}
function freeResult($result)
{
if (is_resource($result)) {
return @mssql_free_result($result);
}
if (!isset($this->prepare_tokens[$result])) {
return false;
}
unset($this->prepare_tokens[$result]);
unset($this->prepare_types[$result]);
return true;
}
function numCols($result)
{
$cols = @mssql_num_fields($result);
if (!$cols) {
return $this->mssqlRaiseError();
}
return $cols;
}
function numRows($result)
{
$rows = @mssql_num_rows($result);
if ($rows === false) {
return $this->mssqlRaiseError();
}
return $rows;
}
/**
* Enable/disable automatic commits
*/
function autoCommit($onoff = false)
{
// XXX if $this->transaction_opcount > 0, we should probably
// issue a warning here.
$this->autocommit = $onoff ? true : false;
return DB_OK;
}
// }}}
// {{{ commit()
/**
* Commit the current transaction.
*/
function commit()
{
if ($this->transaction_opcount > 0) {
$result = @mssql_query('COMMIT TRAN', $this->connection);
$this->transaction_opcount = 0;
if (!$result) {
return $this->mssqlRaiseError();
}
}
return DB_OK;
}
// }}}
// {{{ rollback()
/**
* Roll back (undo) the current transaction.
*/
function rollback()
{
if ($this->transaction_opcount > 0) {
$result = @mssql_query('ROLLBACK TRAN', $this->connection);
$this->transaction_opcount = 0;
if (!$result) {
return $this->mssqlRaiseError();
}
}
return DB_OK;
}
// }}}
// {{{ affectedRows()
/**
* Gets the number of rows affected by the last query.
* if the last query was a select, returns 0.
*
* @return number of rows affected by the last query or DB_ERROR
*/
function affectedRows()
{
if (DB::isManip($this->last_query)) {
$res = @mssql_query('select @@rowcount', $this->connection);
if (!$res) {
return $this->mssqlRaiseError();
}
$ar = @mssql_fetch_row($res);
if (!$ar) {
$result = 0;
} else {
@mssql_free_result($res);
$result = $ar[0];
}
} else {
$result = 0;
}
return $result;
}
// {{{ nextId()
/**
* Get the next value in a sequence. We emulate sequences
* for MSSQL. Will create the sequence if it does not exist.
*
* @access public
*
* @param $seq_name the name of the sequence
*
* @param $ondemand whether to create the sequence table on demand
* (default is true)
*
* @return a sequence integer, or a DB error
*/
function nextId($seq_name, $ondemand = true)
{
$seqname = $this->getSequenceName($seq_name);
$repeat = 0;
do {
$this->pushErrorHandling(PEAR_ERROR_RETURN);
$result = $this->query("INSERT INTO $seqname (vapor) VALUES (0)");
$this->popErrorHandling();
if ($ondemand && DB::isError($result) &&
($result->getCode() == DB_ERROR || $result->getCode() == DB_ERROR_NOSUCHTABLE))
{
$repeat = 1;
$result = $this->createSequence($seq_name);
if (DB::isError($result)) {
return $result;
}
} else {
$result = $this->query("SELECT @@IDENTITY FROM $seqname");
$repeat = 0;
}
} while ($repeat);
if (DB::isError($result)) {
return $this->raiseError($result);
}
$result = $result->fetch_assoc(DB_FETCHMODE_ORDERED);
return $result[0];
}
// }}}
// {{{ createSequence()
function createSequence($seq_name)
{
$seqname = $this->getSequenceName($seq_name);
return $this->query("CREATE TABLE $seqname ".
'([id] [int] IDENTITY (1, 1) NOT NULL ,' .
'[vapor] [int] NULL)');
}
// }}}
// {{{ dropSequence()
function dropSequence($seq_name)
{
$seqname = $this->getSequenceName($seq_name);
return $this->query("DROP TABLE $seqname");
}
// }}}
function errorCode()
{
$this->pushErrorHandling(PEAR_ERROR_RETURN);
$error_code = $this->getOne('select @@ERROR as ErrorCode');
$this->popErrorHandling();
// XXX Debug
if (!isset($this->errorcode_map[$error_code])) {
return DB_ERROR;
}
return $error_code;
}
function mssqlRaiseError($code = null)
{
if ($code !== null) {
$code = $this->errorCode();
if (DB::isError($code)) {
return $this->raiseError($code);
}
}
return $this->raiseError($code, null, null, null,
mssql_get_last_message());
}
/**
* Returns information about a table or a result set
*
* NOTE: doesn't support table name and flags if called from a db_result
*
* @param mixed $resource SQL Server result identifier or table name
* @param int $mode A valid tableInfo mode (DB_TABLEINFO_ORDERTABLE or
* DB_TABLEINFO_ORDER)
*
* @return array An array with all the information
*/
function tableInfo($result, $mode = null)
{
$count = 0;
$id = 0;
$res = array();
/*
* depending on $mode, metadata returns the following values:
*
* - mode is false (default):
* $result[]:
* [0]["table"] table name
* [0]["name"] field name
* [0]["type"] field type
* [0]["len"] field length
* [0]["flags"] field flags
*
* - mode is DB_TABLEINFO_ORDER
* $result[]:
* ["num_fields"] number of metadata records
* [0]["table"] table name
* [0]["name"] field name
* [0]["type"] field type
* [0]["len"] field length
* [0]["flags"] field flags
* ["order"][field name] index of field named "field name"
* The last one is used, if you have a field name, but no index.
* Test: if (isset($result['meta']['myfield'])) { ...
*
* - mode is DB_TABLEINFO_ORDERTABLE
* the same as above. but additionally
* ["ordertable"][table name][field name] index of field
* named "field name"
*
* this is, because if you have fields from different
* tables with the same field name * they override each
* other with DB_TABLEINFO_ORDER
*
* you can combine DB_TABLEINFO_ORDER and
* DB_TABLEINFO_ORDERTABLE with DB_TABLEINFO_ORDER |
* DB_TABLEINFO_ORDERTABLE * or with DB_TABLEINFO_FULL
*/
// if $result is a string, then we want information about a
// table without a resultset
if (is_string($result)) {
$id = mssql_query("SELECT * FROM $result", $this->connection);
if (empty($id)) {
return $this->mssqlRaiseError();
}
} else { // else we want information about a resultset
$id = $result;
if (empty($id)) {
return $this->mssqlRaiseError();
}
}
$count = @mssql_num_fields($id);
// made this IF due to performance (one if is faster than $count if's)
if (empty($mode)) {
for ($i=0; $i<$count; $i++) {
$res[$i]['table'] = (is_string($result)) ? $result : '';
$res[$i]['name'] = @mssql_field_name($id, $i);
$res[$i]['type'] = @mssql_field_type($id, $i);
$res[$i]['len'] = @mssql_field_length($id, $i);
$res[$i]['flags'] = '';
}
} else { // full
$res['num_fields']= $count;
for ($i=0; $i<$count; $i++) {
$res[$i]['table'] = (is_string($result)) ? $result : '';
$res[$i]['name'] = @mssql_field_name($id, $i);
$res[$i]['type'] = @mssql_field_type($id, $i);
$res[$i]['len'] = @mssql_field_length($id, $i);
$res[$i]['flags'] = '';
if ($mode & DB_TABLEINFO_ORDER) {
$res['order'][$res[$i]['name']] = $i;
}
if ($mode & DB_TABLEINFO_ORDERTABLE) {
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
}
}
}
// free the result only if we were called on a table
if (is_string($result)) {
@mssql_free_result($id);
}
return $res;
}
// {{{ getSpecialQuery()
/**
* Returns the query needed to get some backend info
* @param string $type What kind of info you want to retrieve
* @return string The SQL query string
*/
function getSpecialQuery($type)
{
switch ($type) {
case 'tables':
$sql = "select name from sysobjects where type = 'U' order by name";
break;
case 'views':
$sql = "select name from sysobjects where type = 'V'";
break;
default:
return null;
}
return $sql;
}
// }}}
}
?>

View File

@@ -0,0 +1,847 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Author: Stig Bakken <ssb@fast.no> |
// +----------------------------------------------------------------------+
//
// $Id: mysql.php,v 1.89.2.1 2002/04/09 19:04:14 ssb Exp $
//
// Database independent query interface definition for PHP's MySQL
// extension.
//
//
// XXX legend:
//
// XXX ERRORMSG: The error message from the mysql function should
// be registered here.
//
require_once "DB/common.php";
class DB_mysql extends DB_common
{
// {{{ properties
var $connection;
var $phptype, $dbsyntax;
var $prepare_tokens = array();
var $prepare_types = array();
var $num_rows = array();
var $transaction_opcount = 0;
var $autocommit = true;
var $fetchmode = DB_FETCHMODE_ORDERED; /* Default fetch mode */
var $_db = false;
// }}}
// {{{ constructor
/**
* DB_mysql constructor.
*
* @access public
*/
function DB_mysql()
{
$this->DB_common();
$this->phptype = 'mysql';
$this->dbsyntax = 'mysql';
$this->features = array(
'prepare' => false,
'pconnect' => true,
'transactions' => true,
'limit' => 'alter'
);
$this->errorcode_map = array(
1004 => DB_ERROR_CANNOT_CREATE,
1005 => DB_ERROR_CANNOT_CREATE,
1006 => DB_ERROR_CANNOT_CREATE,
1007 => DB_ERROR_ALREADY_EXISTS,
1008 => DB_ERROR_CANNOT_DROP,
1046 => DB_ERROR_NODBSELECTED,
1050 => DB_ERROR_ALREADY_EXISTS,
1051 => DB_ERROR_NOSUCHTABLE,
1054 => DB_ERROR_NOSUCHFIELD,
1062 => DB_ERROR_ALREADY_EXISTS,
1064 => DB_ERROR_SYNTAX,
1100 => DB_ERROR_NOT_LOCKED,
1136 => DB_ERROR_VALUE_COUNT_ON_ROW,
1146 => DB_ERROR_NOSUCHTABLE,
1048 => DB_ERROR_CONSTRAINT,
);
}
// }}}
// {{{ connect()
/**
* Connect to a database and log in as the specified user.
*
* @param $dsn the data source name (see DB::parseDSN for syntax)
* @param $persistent (optional) whether the connection should
* be persistent
* @access public
* @return int DB_OK on success, a DB error on failure
*/
function connect($dsninfo, $persistent = false)
{
if (!DB::assertExtension('mysql'))
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
$this->dsn = $dsninfo;
if (isset($dsninfo['protocol']) && $dsninfo['protocol'] == 'unix') {
$dbhost = ':' . $dsninfo['socket'];
} else {
$dbhost = $dsninfo['hostspec'] ? $dsninfo['hostspec'] : 'localhost';
if (!empty($dsninfo['port'])) {
$dbhost .= ':' . $dsninfo['port'];
}
}
$user = $dsninfo['username'];
$pw = $dsninfo['password'];
$connect_function = $persistent ? 'mysql_pconnect' : 'mysql_connect';
@ini_set('track_errors', true);
if ($dbhost && $user && $pw) {
$conn = @$connect_function($dbhost, $user, $pw);
} elseif ($dbhost && $user) {
$conn = @$connect_function($dbhost, $user);
} elseif ($dbhost) {
$conn = @$connect_function($dbhost);
} else {
$conn = false;
}
@ini_restore('track_errors');
if (empty($conn)) {
if (($err = @mysql_error()) != '') {
return $this->raiseError(DB_ERROR_CONNECT_FAILED, null, null,
null, $err);
} elseif (empty($php_errormsg)) {
return $this->raiseError(DB_ERROR_CONNECT_FAILED);
} else {
return $this->raiseError(DB_ERROR_CONNECT_FAILED, null, null,
null, $php_errormsg);
}
}
if ($dsninfo['database']) {
if (!@mysql_select_db($dsninfo['database'], $conn)) {
switch(mysql_errno($conn)) {
case 1049:
return $this->raiseError(DB_ERROR_NOSUCHDB, null, null,
null, mysql_error($conn));
break;
case 1044:
return $this->raiseError(DB_ERROR_ACCESS_VIOLATION, null, null,
null, mysql_error($conn));
break;
default:
return $this->raiseError(DB_ERROR, null, null,
null, mysql_error($conn));
break;
}
}
// fix to allow calls to different databases in the same script
$this->_db = $dsninfo['database'];
}
$this->connection = $conn;
return DB_OK;
}
// }}}
// {{{ disconnect()
/**
* Log out and disconnect from the database.
*
* @access public
*
* @return bool TRUE on success, FALSE if not connected.
*/
function disconnect()
{
$ret = mysql_close($this->connection);
$this->connection = null;
return $ret;
}
// }}}
// {{{ simpleQuery()
/**
* Send a query to MySQL and return the results as a MySQL resource
* identifier.
*
* @param the SQL query
*
* @access public
*
* @return mixed returns a valid MySQL result for successful SELECT
* queries, DB_OK for other successful queries. A DB error is
* returned on failure.
*/
function simpleQuery($query)
{
$ismanip = DB::isManip($query);
$this->last_query = $query;
$query = $this->modifyQuery($query);
if (!@mysql_select_db($this->_db, $this->connection)) {
return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED);
}
if (!$this->autocommit && $ismanip) {
if ($this->transaction_opcount == 0) {
$result = @mysql_query('SET AUTOCOMMIT=0', $this->connection);
$result = @mysql_query('BEGIN', $this->connection);
if (!$result) {
return $this->mysqlRaiseError();
}
}
$this->transaction_opcount++;
}
$result = @mysql_query($query, $this->connection);
if (!$result) {
return $this->mysqlRaiseError();
}
if (is_resource($result)) {
$numrows = $this->numrows($result);
if (is_object($numrows)) {
return $numrows;
}
$this->num_rows[$result] = $numrows;
return $result;
}
return DB_OK;
}
// }}}
// {{{ nextResult()
/**
* Move the internal mysql result pointer to the next available result
*
* @param a valid fbsql result resource
*
* @access public
*
* @return true if a result is available otherwise return false
*/
function nextResult($result)
{
return false;
}
// }}}
// {{{ fetch_assoc()
/**
* Fetch and return a row of data (it uses fetchInto for that)
* @param $result MySQL result identifier
* @param $fetchmode format of fetched row array
* @param $rownum the absolute row number to fetch
*
* @return array a row of data, or false on error
*/
function fetch_assoc($result, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum=null)
{
if ($fetchmode == DB_FETCHMODE_DEFAULT) {
$fetchmode = $this->fetchmode;
}
$res = $this->fetchInto ($result, $arr, $fetchmode, $rownum);
if ($res !== DB_OK) {
return $res;
}
return $arr;
}
// }}}
// {{{ fetchInto()
/**
* Fetch a row and insert the data into an existing array.
*
* @param $result MySQL result identifier
* @param $arr (reference) array where data from the row is stored
* @param $fetchmode how the array data should be indexed
* @param $rownum the row number to fetch
* @access public
*
* @return int DB_OK on success, a DB error on failure
*/
function fetchInto($result, &$arr, $fetchmode, $rownum=null)
{
if ($rownum !== null) {
if (!@mysql_data_seek($result, $rownum)) {
return null;
}
}
if ($fetchmode & DB_FETCHMODE_ASSOC) {
$arr = @mysql_fetch_array($result, MYSQL_ASSOC);
} else {
$arr = @mysql_fetch_row($result);
}
if (!$arr) {
$errno = @mysql_errno($this->connection);
if (!$errno) {
return NULL;
}
return $this->mysqlRaiseError($errno);
}
return DB_OK;
}
// }}}
// {{{ freeResult()
/**
* Free the internal resources associated with $result.
*
* @param $result MySQL result identifier or DB statement identifier
*
* @access public
*
* @return bool TRUE on success, FALSE if $result is invalid
*/
function freeResult($result)
{
if (is_resource($result)) {
return mysql_free_result($result);
}
$result = (int)$result; // $result is a prepared query handle
if (!isset($this->prepare_tokens[$result])) {
return false;
}
// [ssb]: WTF? unset($this->prepare_types[$result]) makes PHP
// crash on my laptop (4.1.2 as well as 4.3.0-dev)
$copy = $this->prepare_types;
unset($copy[$result]);
$this->prepare_types = $copy;
// unset($this->prepare_types[$result]);
$copy = $this->prepare_tokens;
unset($copy[$result]);
$this->prepare_tokens = $copy;
// unset($this->prepare_tokens[$result]);
return true;
}
// }}}
// {{{ numCols()
/**
* Get the number of columns in a result set.
*
* @param $result MySQL result identifier
*
* @access public
*
* @return int the number of columns per row in $result
*/
function numCols($result)
{
$cols = @mysql_num_fields($result);
if (!$cols) {
return $this->mysqlRaiseError();
}
return $cols;
}
// }}}
// {{{ numRows()
/**
* Get the number of rows in a result set.
*
* @param $result MySQL result identifier
*
* @access public
*
* @return int the number of rows in $result
*/
function numRows($result)
{
$rows = @mysql_num_rows($result);
if ($rows === null) {
return $this->mysqlRaiseError();
}
return $rows;
}
// }}}
// {{{ autoCommit()
/**
* Enable/disable automatic commits
*/
function autoCommit($onoff = false)
{
// XXX if $this->transaction_opcount > 0, we should probably
// issue a warning here.
$this->autocommit = $onoff ? true : false;
return DB_OK;
}
// }}}
// {{{ commit()
/**
* Commit the current transaction.
*/
function commit()
{
if ($this->transaction_opcount > 0) {
if (!@mysql_select_db($this->_db, $this->connection)) {
return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED);
}
$result = @mysql_query('COMMIT', $this->connection);
$result = @mysql_query('SET AUTOCOMMIT=1', $this->connection);
$this->transaction_opcount = 0;
if (!$result) {
return $this->mysqlRaiseError();
}
}
return DB_OK;
}
// }}}
// {{{ rollback()
/**
* Roll back (undo) the current transaction.
*/
function rollback()
{
if ($this->transaction_opcount > 0) {
if (!@mysql_select_db($this->_db, $this->connection)) {
return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED);
}
$result = @mysql_query('ROLLBACK', $this->connection);
$result = @mysql_query('SET AUTOCOMMIT=1', $this->connection);
$this->transaction_opcount = 0;
if (!$result) {
return $this->mysqlRaiseError();
}
}
return DB_OK;
}
// }}}
// {{{ affectedRows()
/**
* Gets the number of rows affected by the data manipulation
* query. For other queries, this function returns 0.
*
* @return number of rows affected by the last query
*/
function affectedRows()
{
if (DB::isManip($this->last_query)) {
$result = @mysql_affected_rows($this->connection);
} else {
$result = 0;
}
return $result;
}
// }}}
// {{{ errorNative()
/**
* Get the native error code of the last error (if any) that
* occured on the current connection.
*
* @access public
*
* @return int native MySQL error code
*/
function errorNative()
{
return mysql_errno($this->connection);
}
// }}}
// {{{ nextId()
/**
* Get the next value in a sequence. We emulate sequences
* for MySQL. Will create the sequence if it does not exist.
*
* @access public
*
* @param string $seq_name the name of the sequence
*
* @param bool $ondemand whether to create the sequence table on demand
* (default is true)
*
* @return mixed a sequence integer, or a DB error
*/
function nextId($seq_name, $ondemand = true)
{
$seqname = $this->getSequenceName($seq_name);
do {
$repeat = 0;
$this->pushErrorHandling(PEAR_ERROR_RETURN);
$result = $this->query("UPDATE ${seqname} ".
'SET id=LAST_INSERT_ID(id+1)');
$this->popErrorHandling();
if ($result == DB_OK) {
/** COMMON CASE **/
$id = mysql_insert_id($this->connection);
if ($id != 0) {
return $id;
}
/** EMPTY SEQ TABLE **/
// Sequence table must be empty for some reason, so fill it and return 1
// Obtain a user-level lock
$result = $this->getOne("SELECT GET_LOCK('${seqname}_lock',10)");
if (DB::isError($result)) {
return $this->raiseError($result);
}
if ($result == 0) {
// Failed to get the lock, bail with a DB_ERROR_NOT_LOCKED error
return $this->mysqlRaiseError(DB_ERROR_NOT_LOCKED);
}
// add the default value
$result = $this->query("REPLACE INTO ${seqname} VALUES (0)");
if (DB::isError($result)) {
return $this->raiseError($result);
}
// Release the lock
$result = $this->getOne("SELECT RELEASE_LOCK('${seqname}_lock')");
if (DB::isError($result)) {
return $this->raiseError($result);
}
// We know what the result will be, so no need to try again
return 1;
/** ONDEMAND TABLE CREATION **/
} elseif ($ondemand && DB::isError($result) &&
$result->getCode() == DB_ERROR_NOSUCHTABLE)
{
$result = $this->createSequence($seq_name);
// Since createSequence initializes the ID to be 1,
// we do not need to retrieve the ID again (or we will get 2)
if (DB::isError($result)) {
return $this->raiseError($result);
} else {
// First ID of a newly created sequence is 1
return 1;
}
/** BACKWARDS COMPAT **/
} elseif (DB::isError($result) &&
$result->getCode() == DB_ERROR_ALREADY_EXISTS)
{
// see _BCsequence() comment
$result = $this->_BCsequence($seqname);
if (DB::isError($result)) {
return $this->raiseError($result);
}
$repeat = 1;
}
} while ($repeat);
return $this->raiseError($result);
}
// }}}
// {{{ createSequence()
function createSequence($seq_name)
{
$seqname = $this->getSequenceName($seq_name);
$res = $this->query("CREATE TABLE ${seqname} ".
'(id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL,'.
' PRIMARY KEY(id))');
if (DB::isError($res)) {
return $res;
}
// insert yields value 1, nextId call will generate ID 2
return $this->query("INSERT INTO ${seqname} VALUES(0)");
}
// }}}
// {{{ dropSequence()
function dropSequence($seq_name)
{
$seqname = $this->getSequenceName($seq_name);
return $this->query("DROP TABLE ${seqname}");
}
// }}}
/**
* Bacwards Compatibility with old sequence emulation implementation
* (clean up the dupes)
* @param string $seqname The sequence name to clean up
* @return mixed DB_Error or true
*/
function _BCsequence($seqname)
{
// Obtain a user-level lock... this will release any previous
// application locks, but unlike LOCK TABLES, it does not abort
// the current transaction and is much less frequently used.
$result = $this->getOne("SELECT GET_LOCK('${seqname}_lock',10)");
if (DB::isError($result)) {
return $result;
}
if ($result == 0) {
// Failed to get the lock, can't do the conversion, bail
// with a DB_ERROR_NOT_LOCKED error
return $this->mysqlRaiseError(DB_ERROR_NOT_LOCKED);
}
$highest_id = $this->getOne("SELECT MAX(id) FROM ${seqname}");
if (DB::isError($highest_id)) {
return $highest_id;
}
// This should kill all rows except the highest
// We should probably do something if $highest_id isn't
// numeric, but I'm at a loss as how to handle that...
$result = $this->query("DELETE FROM ${seqname} WHERE id <> $highest_id");
if (DB::isError($result)) {
return $result;
}
// If another thread has been waiting for this lock,
// it will go thru the above procedure, but will have no
// real effect
$result = $this->getOne("SELECT RELEASE_LOCK('${seqname}_lock')");
if (DB::isError($result)) {
return $result;
}
return true;
}
// {{{ quote()
/**
* Quote the given string so it can be safely used within string delimiters
* in a query.
* @param $string mixed Data to be quoted
* @return mixed "NULL" string, quoted string or original data
*/
function quote($str = null)
{
switch (strtolower(gettype($str))) {
case 'null':
return 'NULL';
case 'integer':
return $str;
case 'string':
default:
return "'".mysql_escape_string($str)."'";
}
}
// }}}
// {{{ modifyQuery()
function modifyQuery($query, $subject = null)
{
if ($this->options['optimize'] == 'portability') {
// "DELETE FROM table" gives 0 affected rows in MySQL.
// This little hack lets you know how many rows were deleted.
if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $query)) {
$query = preg_replace('/^\s*DELETE\s+FROM\s+(\S+)\s*$/',
'DELETE FROM \1 WHERE 1=1', $query);
}
}
return $query;
}
// }}}
// {{{ modifyLimitQuery()
function modifyLimitQuery($query, $from, $count)
{
$query = $query . " LIMIT $from, $count";
return $query;
}
// }}}
// {{{ mysqlRaiseError()
function mysqlRaiseError($errno = null)
{
if ($errno === null) {
$errno = $this->errorCode(mysql_errno($this->connection));
}
return $this->raiseError($errno, null, null, null,
@mysql_errno($this->connection) . " ** " .
@mysql_error($this->connection));
}
// }}}
// {{{ tableInfo()
function tableInfo($result, $mode = null) {
$count = 0;
$id = 0;
$res = array();
/*
* depending on $mode, metadata returns the following values:
*
* - mode is false (default):
* $result[]:
* [0]["table"] table name
* [0]["name"] field name
* [0]["type"] field type
* [0]["len"] field length
* [0]["flags"] field flags
*
* - mode is DB_TABLEINFO_ORDER
* $result[]:
* ["num_fields"] number of metadata records
* [0]["table"] table name
* [0]["name"] field name
* [0]["type"] field type
* [0]["len"] field length
* [0]["flags"] field flags
* ["order"][field name] index of field named "field name"
* The last one is used, if you have a field name, but no index.
* Test: if (isset($result['meta']['myfield'])) { ...
*
* - mode is DB_TABLEINFO_ORDERTABLE
* the same as above. but additionally
* ["ordertable"][table name][field name] index of field
* named "field name"
*
* this is, because if you have fields from different
* tables with the same field name * they override each
* other with DB_TABLEINFO_ORDER
*
* you can combine DB_TABLEINFO_ORDER and
* DB_TABLEINFO_ORDERTABLE with DB_TABLEINFO_ORDER |
* DB_TABLEINFO_ORDERTABLE * or with DB_TABLEINFO_FULL
*/
// if $result is a string, then we want information about a
// table without a resultset
if (is_string($result)) {
$id = @mysql_list_fields($this->dsn['database'],
$result, $this->connection);
if (empty($id)) {
return $this->mysqlRaiseError();
}
} else { // else we want information about a resultset
$id = $result;
if (empty($id)) {
return $this->mysqlRaiseError();
}
}
$count = @mysql_num_fields($id);
// made this IF due to performance (one if is faster than $count if's)
if (empty($mode)) {
for ($i=0; $i<$count; $i++) {
$res[$i]['table'] = @mysql_field_table ($id, $i);
$res[$i]['name'] = @mysql_field_name ($id, $i);
$res[$i]['type'] = @mysql_field_type ($id, $i);
$res[$i]['len'] = @mysql_field_len ($id, $i);
$res[$i]['flags'] = @mysql_field_flags ($id, $i);
}
} else { // full
$res['num_fields']= $count;
for ($i=0; $i<$count; $i++) {
$res[$i]['table'] = @mysql_field_table ($id, $i);
$res[$i]['name'] = @mysql_field_name ($id, $i);
$res[$i]['type'] = @mysql_field_type ($id, $i);
$res[$i]['len'] = @mysql_field_len ($id, $i);
$res[$i]['flags'] = @mysql_field_flags ($id, $i);
if ($mode & DB_TABLEINFO_ORDER) {
$res['order'][$res[$i]['name']] = $i;
}
if ($mode & DB_TABLEINFO_ORDERTABLE) {
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
}
}
}
// free the result only if we were called on a table
if (is_string($result)) {
@mysql_free_result($id);
}
return $res;
}
// }}}
// {{{ getTablesQuery()
/**
* Returns the query needed to get some backend info
* @param string $type What kind of info you want to retrieve
* @return string The SQL query string
*/
function getSpecialQuery($type)
{
switch ($type) {
case 'tables':
$sql = "SHOW TABLES";
break;
case 'views':
return DB_ERROR_NOT_CAPABLE;
case 'users':
$sql = "select distinct User from user";
if($this->dsn['database'] != 'mysql') {
$dsn = $this->dsn;
$dsn['database'] = 'mysql';
if (DB::isError($db = DB::connect($dsn))) {
return $db;
}
$sql = $db->getCol($sql);
$db->disconnect();
// XXX Fixme the mysql driver should take care of this
if (!@mysql_select_db($this->dsn['database'], $this->connection)) {
return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED);
}
}
return $sql;
break;
case 'databases':
$sql = "SHOW DATABASES";
break;
default:
return null;
}
return $sql;
}
// }}}
// TODO/wishlist:
// longReadlen
// binmode
}
?>

View File

@@ -0,0 +1,664 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Author: James L. Pine <jlp@valinux.com> |
// +----------------------------------------------------------------------+
//
// $Id: oci8.php,v 1.47.2.1 2002/04/09 19:04:15 ssb Exp $
//
// Database independent query interface definition for PHP's Oracle 8
// call-interface extension.
//
//
// be aware... OCIError() only appears to return anything when given a
// statement, so functions return the generic DB_ERROR instead of more
// useful errors that have to do with feedback from the database.
//
require_once 'DB/common.php';
class DB_oci8 extends DB_common
{
// {{{ properties
var $connection;
var $phptype, $dbsyntax;
var $manip_query = array();
var $prepare_types = array();
var $autoCommit = 1;
var $last_stmt = false;
// }}}
// {{{ constructor
function DB_oci8()
{
$this->DB_common();
$this->phptype = 'oci8';
$this->dbsyntax = 'oci8';
$this->features = array(
'prepare' => false,
'pconnect' => true,
'transactions' => true,
'limit' => 'alter'
);
$this->errorcode_map = array(
900 => DB_ERROR_SYNTAX,
904 => DB_ERROR_NOSUCHFIELD,
923 => DB_ERROR_SYNTAX,
942 => DB_ERROR_NOSUCHTABLE,
955 => DB_ERROR_ALREADY_EXISTS,
1476 => DB_ERROR_DIVZERO,
1722 => DB_ERROR_INVALID_NUMBER,
2289 => DB_ERROR_NOSUCHTABLE,
2291 => DB_ERROR_CONSTRAINT,
2449 => DB_ERROR_CONSTRAINT,
);
}
// }}}
// {{{ connect()
/**
* Connect to a database and log in as the specified user.
*
* @param $dsn the data source name (see DB::parseDSN for syntax)
* @param $persistent (optional) whether the connection should
* be persistent
*
* @return int DB_OK on success, a DB error code on failure
*/
function connect($dsninfo, $persistent = false)
{
if (!DB::assertExtension('oci8')) {
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
}
$this->dsn = $dsninfo;
$user = $dsninfo['username'];
$pw = $dsninfo['password'];
$hostspec = $dsninfo['hostspec'];
$connect_function = $persistent ? 'OCIPLogon' : 'OCILogon';
if ($hostspec) {
$conn = @$connect_function($user,$pw,$hostspec);
} elseif ($user || $pw) {
$conn = @$connect_function($user,$pw);
} else {
$conn = false;
}
if ($conn == false) {
$error = OCIError();
$error = (is_array($error)) ? $error['message'] : null;
return $this->raiseError(DB_ERROR_CONNECT_FAILED, null, null,
null, $error);
}
$this->connection = $conn;
return DB_OK;
}
// }}}
// {{{ disconnect()
/**
* Log out and disconnect from the database.
*
* @return bool TRUE on success, FALSE if not connected.
*/
function disconnect()
{
$ret = @OCILogOff($this->connection);
$this->connection = null;
return $ret;
}
// }}}
// {{{ simpleQuery()
/**
* Send a query to oracle and return the results as an oci8 resource
* identifier.
*
* @param $query the SQL query
*
* @return int returns a valid oci8 result for successful SELECT
* queries, DB_OK for other successful queries. A DB error code
* is returned on failure.
*/
function simpleQuery($query)
{
$this->last_query = $query;
$query = $this->modifyQuery($query);
$result = @OCIParse($this->connection, $query);
if (!$result) {
return $this->oci8RaiseError();
}
if ($this->autoCommit) {
$success = @OCIExecute($result,OCI_COMMIT_ON_SUCCESS);
} else {
$success = @OCIExecute($result,OCI_DEFAULT);
}
if (!$success) {
return $this->oci8RaiseError($result);
}
$this->last_stmt=$result;
// Determine which queries that should return data, and which
// should return an error code only.
return DB::isManip($query) ? DB_OK : $result;
}
// }}}
// {{{ nextResult()
/**
* Move the internal oracle result pointer to the next available result
*
* @param a valid oci8 result resource
*
* @access public
*
* @return true if a result is available otherwise return false
*/
function nextResult($result)
{
return false;
}
// }}}
// {{{ fetch_assoc()
/**
* Fetch a row and return as array.
*
* @param $result oci8 result identifier
* @param $fetchmode how the resulting array should be indexed
*
* @return int an array on success, a DB error code on failure, NULL
* if there is no more data
*/
function &fetch_assoc($result, $fetchmode = DB_FETCHMODE_DEFAULT)
{
if ($fetchmode == DB_FETCHMODE_DEFAULT) {
$fetchmode = $this->fetchmode;
}
if ($fetchmode & DB_FETCHMODE_ASSOC) {
$moredata = @OCIFetchInto($result, $row, OCI_ASSOC + OCI_RETURN_NULLS + OCI_RETURN_LOBS);
} else {
$moredata = @OCIFetchInto($result, $row, OCI_RETURN_NULLS + OCI_RETURN_LOBS);
}
if (!$moredata) {
return NULL;
}
return $row;
}
// }}}
// {{{ fetchInto()
/**
* Fetch a row and insert the data into an existing array.
*
* @param $result oci8 result identifier
* @param $arr (reference) array where data from the row is stored
* @param $fetchmode how the array data should be indexed
* @param $rownum the row number to fetch (not yet supported)
*
* @return int DB_OK on success, a DB error code on failure
*/
function fetchInto($result, &$arr, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum=NULL)
{
if ($rownum !== NULL) {
return $this->raiseError(DB_ERROR_NOT_CAPABLE);
}
if ($fetchmode & DB_FETCHMODE_ASSOC) {
$moredata = @OCIFetchInto($result,$arr,OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS);
if ($moredata && $this->options['optimize'] == 'portability') {
$arr = array_change_key_case($arr, CASE_LOWER);
}
} else {
$moredata = @OCIFetchInto($result,$arr,OCI_RETURN_NULLS+OCI_RETURN_LOBS);
}
if (!$moredata) {
return NULL;
}
return DB_OK;
}
// }}}
// {{{ freeResult()
/**
* Free the internal resources associated with $result.
*
* @param $result oci8 result identifier or DB statement identifier
*
* @return bool TRUE on success, FALSE if $result is invalid
*/
function freeResult($result)
{
if (is_resource($result)) {
return @OCIFreeStatement($result);
}
if (!isset($this->prepare_tokens[(int)$result])) {
return false;
}
unset($this->prepare_tokens[(int)$result]);
unset($this->prepare_types[(int)$result]);
unset($this->manip_query[(int)$result]);
return true;
}
// }}}
// {{{ numRows()
function numRows($result)
{
// emulate numRows for Oracle. yuck.
if ($this->options['optimize'] == 'portability' &&
$result === $this->last_stmt) {
$countquery = preg_replace('/^\s*SELECT\s+(.*?)\s+FROM\s+/is',
'SELECT COUNT(*) FROM ',
$this->last_query);
$save_query = $this->last_query;
$save_stmt = $this->last_stmt;
$count = $this->query($countquery);
if (DB::isError($count) ||
DB::isError($row = $count->fetch_assoc(DB_FETCHMODE_ORDERED)))
{
$this->last_query = $save_query;
$this->last_stmt = $save_stmt;
return $this->raiseError(DB_ERROR_NOT_CAPABLE);
}
return $row[0];
}
return $this->raiseError(DB_ERROR_NOT_CAPABLE);
}
// }}}
// {{{ numCols()
/**
* Get the number of columns in a result set.
*
* @param $result oci8 result identifier
*
* @return int the number of columns per row in $result
*/
function numCols($result)
{
$cols = @OCINumCols($result);
if (!$cols) {
return $this->oci8RaiseError($result);
}
return $cols;
}
// }}}
// {{{ errorNative()
/**
* Get the native error code of the last error (if any) that occured
* on the current connection. This does not work, as OCIError does
* not work unless given a statement. If OCIError does return
* something, so will this.
*
* @return int native oci8 error code
*/
function errorNative()
{
if (is_resource($this->last_stmt)) {
$error = @OCIError($this->last_stmt);
} else {
$error = @OCIError($this->connection);
}
if (is_array($error)) {
return $error['code'];
}
return false;
}
// }}}
// {{{ prepare()
/**
* Prepares a query for multiple execution with execute(). With
* oci8, this is emulated.
* @param $query query to be prepared
*
* @return DB statement resource
*/
function prepare($query)
{
$tokens = split('[\&\?]', $query);
$token = 0;
$types = array();
for ($i = 0; $i < strlen($query); $i++) {
switch ($query[$i]) {
case '?':
$types[$token++] = DB_PARAM_SCALAR;
break;
case '&':
$types[$token++] = DB_PARAM_OPAQUE;
break;
}
}
$binds = sizeof($tokens) - 1;
$newquery = '';
for ($i = 0; $i < $binds; $i++) {
$newquery .= $tokens[$i] . ":bind" . $i;
}
$newquery .= $tokens[$i];
$this->last_query = $query;
$newquery = $this->modifyQuery($newquery);
$stmt = @OCIParse($this->connection, $newquery);
$this->prepare_types[$stmt] = $types;
$this->manip_query[(int)$stmt] = DB::isManip($query);
return $stmt;
}
// }}}
// {{{ execute()
/**
* Executes a DB statement prepared with prepare().
*
* @param $stmt a DB statement resource (returned from prepare())
* @param $data data to be used in execution of the statement
*
* @return int returns an oci8 result resource for successful
* SELECT queries, DB_OK for other successful queries. A DB error
* code is returned on failure.
*/
function execute($stmt, $data = false)
{
$types=&$this->prepare_types[$stmt];
if (($size = sizeof($types)) != sizeof($data)) {
return $this->raiseError(DB_ERROR_MISMATCH);
}
for ($i = 0; $i < $size; $i++) {
if (is_array($data)) {
$pdata[$i] = &$data[$i];
}
else {
$pdata[$i] = &$data;
}
if ($types[$i] == DB_PARAM_OPAQUE) {
$fp = fopen($pdata[$i], "r");
$pdata[$i] = '';
if ($fp) {
while (($buf = fread($fp, 4096)) != false) {
$pdata[$i] .= $buf;
}
}
}
if (!@OCIBindByName($stmt, ":bind" . $i, $pdata[$i], -1)) {
return $this->oci8RaiseError($stmt);
}
}
if ($this->autoCommit) {
$success = @OCIExecute($stmt, OCI_COMMIT_ON_SUCCESS);
}
else {
$success = @OCIExecute($stmt, OCI_DEFAULT);
}
if (!$success) {
return $this->oci8RaiseError($stmt);
}
$this->last_stmt = $stmt;
if ($this->manip_query[(int)$stmt]) {
return DB_OK;
} else {
return new DB_result($this, $stmt);
}
}
// }}}
// {{{ autoCommit()
/**
* Enable/disable automatic commits
*
* @param $onoff true/false whether to autocommit
*/
function autoCommit($onoff = false)
{
$this->autoCommit = (bool)$onoff;;
return DB_OK;
}
// }}}
// {{{ commit()
/**
* Commit transactions on the current connection
*
* @return DB_ERROR or DB_OK
*/
function commit()
{
$result = @OCICommit($this->connection);
if (!$result) {
return $this->oci8RaiseError();
}
return DB_OK;
}
// }}}
// {{{ rollback()
/**
* Roll back all uncommitted transactions on the current connection.
*
* @return DB_ERROR or DB_OK
*/
function rollback()
{
$result = @OCIRollback($this->connection);
if (!$result) {
return $this->oci8RaiseError();
}
return DB_OK;
}
// }}}
// {{{ affectedRows()
/**
* Gets the number of rows affected by the last query.
* if the last query was a select, returns 0.
*
* @return number of rows affected by the last query or DB_ERROR
*/
function affectedRows()
{
if ($this->last_stmt === false) {
return $this->oci8RaiseError();
}
$result = @OCIRowCount($this->last_stmt);
if ($result === false) {
return $this->oci8RaiseError($this->last_stmt);
}
return $result;
}
// }}}
// {{{ modifyQuery()
function modifyQuery($query)
{
// "SELECT 2+2" must be "SELECT 2+2 FROM dual" in Oracle
if (preg_match('/^\s*SELECT/i', $query) &&
!preg_match('/\sFROM\s/i', $query)) {
$query .= " FROM dual";
}
return $query;
}
// }}}
// {{{ modifyLimitQuery()
/**
* Emulate the row limit support altering the query
*
* @param string $query The query to treat
* @param int $from The row to start to fetch from
* @param int $count The offset
* @return string The modified query
*
* @author Tomas V.V.Cox <cox@idecnet.com>
*/
function modifyLimitQuery($query, $from, $count)
{
// Let Oracle return the name of the columns instead of
// coding a "home" SQL parser
$q_fields = "SELECT * FROM ($query) WHERE NULL = NULL";
if (!$result = OCIParse($this->connection, $q_fields)) {
return $this->oci8RaiseError();
}
if (!OCIExecute($result, OCI_DEFAULT)) {
return $this->oci8RaiseError($result);
}
$ncols = OCINumCols($result);
$cols = array();
for ( $i = 1; $i <= $ncols; $i++ ) {
$cols[] = OCIColumnName($result, $i);
}
$fields = implode(', ', $cols);
// XXX Test that (tip by John Lim)
//if(preg_match('/^\s*SELECT\s+/is', $query, $match)) {
// // Introduce the FIRST_ROWS Oracle query optimizer
// $query = substr($query, strlen($match[0]), strlen($query));
// $query = "SELECT /* +FIRST_ROWS */ " . $query;
//}
// Construct the query
// more at: http://marc.theaimsgroup.com/?l=php-db&m=99831958101212&w=2
// Perhaps this could be optimized with the use of Unions
$from += 1; // in Oracle rownum starts at 1
$query = "SELECT $fields FROM".
" (SELECT rownum as linenum, $fields FROM".
" ($query)".
" WHERE rownum <= ". ($from + $count) .
") WHERE linenum >= $from";
return $query;
}
// }}}
// {{{ nextId()
/**
* Get the next value in a sequence. We emulate sequences
* for MySQL. Will create the sequence if it does not exist.
*
* @access public
*
* @param $seq_name the name of the sequence
*
* @param $ondemand whether to create the sequence table on demand
* (default is true)
*
* @return a sequence integer, or a DB error
*/
function nextId($seq_name, $ondemand = true)
{
$seqname = $this->getSequenceName($seq_name);
$repeat = 0;
do {
$this->expectError(DB_ERROR_NOSUCHTABLE);
$result = $this->query("SELECT ${seqname}.nextval FROM dual");
$this->popExpect();
if ($ondemand && DB::isError($result) &&
$result->getCode() == DB_ERROR_NOSUCHTABLE) {
$repeat = 1;
$result = $this->createSequence($seq_name);
if (DB::isError($result)) {
return $this->raiseError($result);
}
} else {
$repeat = 0;
}
} while ($repeat);
if (DB::isError($result)) {
return $this->raiseError($result);
}
$arr = $result->fetch_assoc(DB_FETCHMODE_ORDERED);
return $arr[0];
}
// }}}
// {{{ createSequence()
function createSequence($seq_name)
{
$seqname = $this->getSequenceName($seq_name);
return $this->query("CREATE SEQUENCE ${seqname}");
}
// }}}
// {{{ dropSequence()
function dropSequence($seq_name)
{
$seqname = $this->getSequenceName($seq_name);
return $this->query("DROP SEQUENCE ${seqname}");
}
// }}}
// {{{ oci8RaiseError()
function oci8RaiseError($errno = null)
{
if ($errno === null) {
$error = @OCIError($this->connection);
return $this->raiseError($this->errorCode($error['code']),
null, null, null, $error['message']);
} elseif (is_resource($errno)) {
$error = @OCIError($errno);
return $this->raiseError($this->errorCode($error['code']),
null, null, null, $error['message']);
}
return $this->raiseError($this->errorCode($errno));
}
// }}}
// {{{ getSpecialQuery()
/**
* Returns the query needed to get some backend info
* @param string $type What kind of info you want to retrieve
* @return string The SQL query string
*/
function getSpecialQuery($type)
{
switch ($type) {
case 'tables':
$sql = "SELECT table_name FROM user_tables";
break;
default:
return null;
}
return $sql;
}
// }}}
}
// Local variables:
// tab-width: 4
// c-basic-offset: 4
// End:
?>

View File

@@ -0,0 +1,484 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Author: Stig Bakken <ssb@fast.no> |
// +----------------------------------------------------------------------+
//
// $Id: odbc.php,v 1.54 2002/02/28 08:27:11 sebastian Exp $
//
// Database independent query interface definition for PHP's ODBC
// extension.
//
//
// XXX legend:
// More info on ODBC errors could be found here:
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/trblsql/tr_err_odbc_5stz.asp
//
// XXX ERRORMSG: The error message from the odbc function should
// be registered here.
//
require_once 'DB/common.php';
class DB_odbc extends DB_common
{
// {{{ properties
var $connection;
var $phptype, $dbsyntax;
var $row = array();
// }}}
// {{{ constructor
function DB_odbc()
{
$this->DB_common();
$this->phptype = 'odbc';
$this->dbsyntax = 'sql92';
$this->features = array(
'prepare' => true,
'pconnect' => true,
'transactions' => false,
'limit' => 'emulate'
);
$this->errorcode_map = array(
'01004' => DB_ERROR_TRUNCATED,
'07001' => DB_ERROR_MISMATCH,
'21S01' => DB_ERROR_MISMATCH,
'21S02' => DB_ERROR_MISMATCH,
'22003' => DB_ERROR_INVALID_NUMBER,
'22008' => DB_ERROR_INVALID_DATE,
'22012' => DB_ERROR_DIVZERO,
'23000' => DB_ERROR_CONSTRAINT,
'24000' => DB_ERROR_INVALID,
'34000' => DB_ERROR_INVALID,
'37000' => DB_ERROR_SYNTAX,
'42000' => DB_ERROR_SYNTAX,
'IM001' => DB_ERROR_UNSUPPORTED,
'S0000' => DB_ERROR_NOSUCHTABLE,
'S0001' => DB_ERROR_NOT_FOUND,
'S0002' => DB_ERROR_NOT_FOUND,
'S0011' => DB_ERROR_ALREADY_EXISTS,
'S0012' => DB_ERROR_NOT_FOUND,
'S0021' => DB_ERROR_ALREADY_EXISTS,
'S0022' => DB_ERROR_NOT_FOUND,
'S1009' => DB_ERROR_INVALID,
'S1090' => DB_ERROR_INVALID,
'S1C00' => DB_ERROR_NOT_CAPABLE
);
}
// }}}
// {{{ connect()
/**
* Connect to a database and log in as the specified user.
*
* @param $dsn the data source name (see DB::parseDSN for syntax)
* @param $persistent (optional) whether the connection should
* be persistent
*
* @return int DB_OK on success, a DB error code on failure
*/
function connect($dsninfo, $persistent = false)
{
if (!DB::assertExtension('odbc'))
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
$this->dsn = $dsninfo;
if (!empty($dsninfo['dbsyntax'])) {
$this->dbsyntax = $dsninfo['dbsyntax'];
}
switch ($this->dbsyntax) {
case 'solid':
$this->features = array(
'prepare' => true,
'pconnect' => true,
'transactions' => true
);
$default_dsn = 'localhost';
break;
case 'navision':
// the Navision driver doesn't support fetch row by number
$this->features['limit'] = false;
break;
default:
break;
}
$dbhost = $dsninfo['hostspec'] ? $dsninfo['hostspec'] : 'localhost';
$user = $dsninfo['username'];
$pw = $dsninfo['password'];
if ($this->provides('pconnect')) {
$connect_function = $persistent ? 'odbc_pconnect' : 'odbc_connect';
} else {
$connect_function = 'odbc_connect';
}
$conn = @$connect_function($dbhost, $user, $pw);
if (!is_resource($conn)) {
return $this->raiseError(DB_ERROR_CONNECT_FAILED, null, null,
null, $this->errorNative());
}
$this->connection = $conn;
return DB_OK;
}
// }}}
// {{{ disconnect()
function disconnect()
{
$err = @odbc_close($this->connection);
$this->connection = null;
return $err;
}
// }}}
// {{{ simpleQuery()
/**
* Send a query to ODBC and return the results as a ODBC resource
* identifier.
*
* @param $query the SQL query
*
* @return int returns a valid ODBC result for successful SELECT
* queries, DB_OK for other successful queries. A DB error code
* is returned on failure.
*/
function simpleQuery($query)
{
$this->last_query = $query;
$query = $this->modifyQuery($query);
$result = @odbc_exec($this->connection, $query);
if (!$result) {
return $this->odbcRaiseError(); // XXX ERRORMSG
}
// Determine which queries that should return data, and which
// should return an error code only.
if (DB::isManip($query)) {
$this->manip_result = $result; // For affectedRows()
return DB_OK;
}
$this->row[$result] = 0;
$this->manip_result = 0;
return $result;
}
// }}}
// {{{ nextResult()
/**
* Move the internal odbc result pointer to the next available result
*
* @param a valid fbsql result resource
*
* @access public
*
* @return true if a result is available otherwise return false
*/
function nextResult($result)
{
return odbc_next_result($result);
}
// }}}
// {{{ fetch_assoc()
function fetch_assoc($result, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum=null)
{
if ($fetchmode == DB_FETCHMODE_DEFAULT) {
$fetchmode = $this->fetchmode;
}
$res = $this->fetchInto ($result, $arr, $fetchmode, $rownum);
if ($res !== DB_OK) {
return $res;
}
return $arr;
}
// }}}
// {{{ fetchInto()
function fetchInto($result, &$row, $fetchmode, $rownum=null)
{
$row = array();
if ($rownum !== null) {
$rownum++; // ODBC first row is 1
if (!function_exists('version_compare') || version_compare(phpversion(), "4.0.5", "lt")) {
$cols = odbc_fetch_into($result, $rownum, &$row);
} else {
$cols = odbc_fetch_into($result, $rownum, $row);
}
} else {
if (!function_exists('version_compare') || version_compare(phpversion(), "4.0.5", "lt")) {
$cols = odbc_fetch_into($result, &$row);
} else {
$cols = odbc_fetch_into($result, $row);
}
}
if (!$cols) {
/* XXX FIXME: doesn't work with unixODBC and easysoft
(get corrupted $errno values)
if ($errno = odbc_error($this->connection)) {
return $this->RaiseError($errno);
}*/
return null;
}
if ($fetchmode !== DB_FETCHMODE_ORDERED) {
for ($i = 0; $i < count($row); $i++) {
$colName = odbc_field_name($result, $i+1);
$a[$colName] = $row[$i];
}
$row = $a;
}
return DB_OK;
}
// }}}
// {{{ freeResult()
function freeResult($result)
{
if (is_resource($result)) {
// Always return true
return odbc_free_result($result);
}
if (!isset($this->prepare_tokens[(int)$result])) {
return false;
}
unset($this->prepare_tokens[(int)$result]);
unset($this->prepare_types[(int)$result]);
return true;
}
// }}}
// {{{ numCols()
function numCols($result)
{
$cols = @odbc_num_fields($result);
if (!$cols) {
return $this->odbcRaiseError();
}
return $cols;
}
// }}}
// {{{ affectedRows()
/**
* Returns the number of rows affected by a manipulative query
* (INSERT, DELETE, UPDATE)
* @return mixed int affected rows, 0 when non manip queries or
* DB error on error
*/
function affectedRows()
{
if (empty($this->manip_result)) { // In case of SELECT stms
return 0;
}
$nrows = odbc_num_rows($this->manip_result);
if ($nrows == -1) {
return $this->odbcRaiseError();
}
return $nrows;
}
// }}}
// {{{ numRows()
/**
* ODBC may or may not support counting rows in the result set of
* SELECTs.
*
* @param $result the odbc result resource
* @return the number of rows, or 0
*/
function numRows($result)
{
$nrows = odbc_num_rows($result);
if ($nrows == -1) {
return $this->odbcRaiseError(DB_ERROR_UNSUPPORTED);
}
return $nrows;
}
// }}}
// {{{ errorNative()
/**
* Get the native error code of the last error (if any) that
* occured on the current connection.
*
* @access public
*
* @return int ODBC error code
*/
function errorNative()
{
if (!isset($this->connection) || !is_resource($this->connection)) {
return odbc_error() . ' ' . odbc_errormsg();
}
return odbc_error($this->connection) . ' ' . odbc_errormsg($this->connection);
}
// }}}
// {{{ nextId()
/**
* Get the next value in a sequence. We emulate sequences
* for odbc. Will create the sequence if it does not exist.
*
* @access public
*
* @param $seq_name the name of the sequence
*
* @param $ondemand whether to create the sequence table on demand
* (default is true)
*
* @return a sequence integer, or a DB error
*/
function nextId($seq_name, $ondemand = true)
{
$seqname = $this->getSequenceName($seq_name);
$repeat = 0;
do {
$result = $this->query("update ${seqname} set id = id + 1");
if ($ondemand && DB::isError($result) &&
$result->getCode() == DB_ERROR_NOT_FOUND) {
$repeat = 1;
$result = $this->createSequence($seq_name);
if (DB::isError($result)) {
return $result;
}
$result = $this->query("insert into ${seqname} (id) values(0)");
} else {
$repeat = 0;
}
} while ($repeat);
if (DB::isError($result)) {
return $result;
}
$result = $this->query("select id from ${seqname}");
if (DB::isError($result)) {
return $result;
}
$row = $result->fetch_assoc(DB_FETCHMODE_ASSOC);
if (DB::isError($row || !$row)) {
return $row;
}
return $row['id'];
}
// }}}
// {{{ createSequence()
function createSequence($seq_name)
{
$seqname = $this->getSequenceName($seq_name);
return $this->query("CREATE TABLE ${seqname} ".
'(id bigint NOT NULL,'.
' PRIMARY KEY(id))');
}
// }}}
// {{{ dropSequence()
function dropSequence($seq_name)
{
$seqname = $this->getSequenceName($seq_name);
return $this->query("DROP TABLE ${seqname}");
}
// }}}
// {{{ autoCommit()
function autoCommit($onoff = false)
{
if (!@odbc_autocommit($this->connection, $onoff)) {
return $this->odbcRaiseError();
}
return DB_OK;
}
// }}}
// {{{ commit()
function commit()
{
if (!@odbc_commit($this->connection)) {
return $this->odbcRaiseError();
}
return DB_OK;
}
// }}}
// {{{ rollback()
function rollback()
{
if (!@odbc_rollback($this->connection)) {
return $this->odbcRaiseError();
}
return DB_OK;
}
// }}}
// {{{ odbcRaiseError()
function odbcRaiseError($errno = null)
{
if ($errno === null) {
$errno = $this->errorCode(odbc_error($this->connection));
}
return $this->raiseError($errno, null, null, null,
$this->errorNative());
}
// }}}
// {{{ getSpecialQuery()
/**
* Returns the query needed to get some backend info
* @param string $type What kind of info you want to retrieve
* @return string The SQL query string
*/
function getSpecialQuery($type)
{
switch ($type) {
case 'tables':
default:
return null;
}
return $sql;
}
// }}}
}
// Local variables:
// tab-width: 4
// c-basic-offset: 4
// End:
?>

View File

@@ -0,0 +1,810 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Rui Hirokawa <rui_hirokawa@ybb.ne.jp> |
// | Stig Bakken <ssb@fast.no> |
// +----------------------------------------------------------------------+
//
// $Id: pgsql.php,v 1.65.2.3 2002/04/10 08:38:42 edink Exp $
//
// Database independent query interface definition for PHP's PostgreSQL
// extension.
//
//
// XXX legend:
//
// XXX ERRORMSG: The error message from the pgsql function should
// be registered here.
//
require_once 'DB/common.php';
class DB_pgsql extends DB_common
{
// {{{ properties
var $connection;
var $phptype, $dbsyntax;
var $prepare_tokens = array();
var $prepare_types = array();
var $transaction_opcount = 0;
var $dsn = array();
var $row = array();
var $num_rows = array();
var $affected = 0;
var $autocommit = true;
var $fetchmode = DB_FETCHMODE_ORDERED;
// }}}
// {{{ constructor
function DB_pgsql()
{
$this->DB_common();
$this->phptype = 'pgsql';
$this->dbsyntax = 'pgsql';
$this->features = array(
'prepare' => false,
'pconnect' => true,
'transactions' => true,
'limit' => 'alter'
);
$this->errorcode_map = array(
);
}
// }}}
// {{{ connect()
/**
* Connect to a database and log in as the specified user.
*
* @param $dsn the data source name (see DB::parseDSN for syntax)
* @param $persistent (optional) whether the connection should
* be persistent
*
* @return int DB_OK on success, a DB error code on failure
*/
function connect($dsninfo, $persistent = false)
{
if (!DB::assertExtension('pgsql'))
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
$this->dsn = $dsninfo;
$protocol = (isset($dsninfo['protocol'])) ? $dsninfo['protocol'] : 'tcp';
$connstr = '';
if ($protocol == 'tcp') {
if ($dsninfo['hostspec']) {
$connstr = 'host=' . $dsninfo['hostspec'];
}
if ($dsninfo['port']) {
$connstr .= ' port=' . $dsninfo['port'];
}
}
if (isset($dsninfo['database'])) {
$connstr .= ' dbname=' . $dsninfo['database'];
}
if (!empty($dsninfo['username'])) {
$connstr .= ' user=' . $dsninfo['username'];
}
if (!empty($dsninfo['password'])) {
$connstr .= ' password=' . $dsninfo['password'];
}
if (!empty($dsninfo['options'])) {
$connstr .= ' options=' . $dsninfo['options'];
}
if (!empty($dsninfo['tty'])) {
$connstr .= ' tty=' . $dsninfo['tty'];
}
$connect_function = $persistent ? 'pg_pconnect' : 'pg_connect';
// catch error
ob_start();
$conn = $connect_function($connstr);
$error = ob_get_contents();
ob_end_clean();
if ($conn == false) {
return $this->raiseError(DB_ERROR_CONNECT_FAILED, null,
null, null, strip_tags($error));
}
$this->connection = $conn;
return DB_OK;
}
// }}}
// {{{ disconnect()
/**
* Log out and disconnect from the database.
*
* @return bool TRUE on success, FALSE if not connected.
*/
function disconnect()
{
$ret = @pg_close($this->connection); // XXX ERRORMSG
$this->connection = null;
return $ret;
}
// }}}
// {{{ simpleQuery()
/**
* Send a query to PostgreSQL and return the results as a
* PostgreSQL resource identifier.
*
* @param $query the SQL query
*
* @return int returns a valid PostgreSQL result for successful SELECT
* queries, DB_OK for other successful queries. A DB error code
* is returned on failure.
*/
function simpleQuery($query)
{
$ismanip = DB::isManip($query);
$this->last_query = $query;
$query = $this->modifyQuery($query);
if (!$this->autocommit && $ismanip) {
if ($this->transaction_opcount == 0) {
$result = @pg_exec($this->connection, "begin;");
if (!$result) {
return $this->pgsqlRaiseError();
}
}
$this->transaction_opcount++;
}
$result = @pg_exec($this->connection, $query);
if (!$result) {
return $this->pgsqlRaiseError();
}
// Determine which queries that should return data, and which
// should return an error code only.
if ($ismanip) {
$this->affected = @pg_cmdtuples($result);
return DB_OK;
} elseif (preg_match('/^\s*\(?\s*SELECT\s+/si', $query) &&
!preg_match('/^\s*\(?\s*SELECT\s+INTO\s/si', $query)) {
/* PostgreSQL commands:
ABORT, ALTER, BEGIN, CLOSE, CLUSTER, COMMIT, COPY,
CREATE, DECLARE, DELETE, DROP TABLE, EXPLAIN, FETCH,
GRANT, INSERT, LISTEN, LOAD, LOCK, MOVE, NOTIFY, RESET,
REVOKE, ROLLBACK, SELECT, SELECT INTO, SET, SHOW,
UNLISTEN, UPDATE, VACUUM
*/
$this->row[$result] = 0; // reset the row counter.
$numrows = $this->numrows($result);
if (is_object($numrows)) {
return $numrows;
}
$this->num_rows[$result] = $numrows;
$this->affected = 0;
return $result;
} else {
$this->affected = 0;
return DB_OK;
}
}
// }}}
// {{{ nextResult()
/**
* Move the internal pgsql result pointer to the next available result
*
* @param a valid fbsql result resource
*
* @access public
*
* @return true if a result is available otherwise return false
*/
function nextResult($result)
{
return false;
}
// }}}
// {{{ errorCode()
/**
* Map native error codes to DB's portable ones. Requires that
* the DB implementation's constructor fills in the $errorcode_map
* property.
*
* @param $nativecode the native error code, as returned by the backend
* database extension (string or integer)
*
* @return int a portable DB error code, or FALSE if this DB
* implementation has no mapping for the given error code.
*/
function errorCode($errormsg)
{
static $error_regexps;
if (empty($error_regexps)) {
$error_regexps = array(
'/(Table does not exist\.|Relation [\"\'].*[\"\'] does not exist|sequence does not exist|class ".+" not found)$/' => DB_ERROR_NOSUCHTABLE,
'/Relation [\"\'].*[\"\'] already exists|Cannot insert a duplicate key into (a )?unique index.*/' => DB_ERROR_ALREADY_EXISTS,
'/divide by zero$/' => DB_ERROR_DIVZERO,
'/pg_atoi: error in .*: can\'t parse /' => DB_ERROR_INVALID_NUMBER,
'/ttribute [\"\'].*[\"\'] not found$|Relation [\"\'].*[\"\'] does not have attribute [\"\'].*[\"\']/' => DB_ERROR_NOSUCHFIELD,
'/parser: parse error at or near \"/' => DB_ERROR_SYNTAX,
'/referential integrity violation/' => DB_ERROR_CONSTRAINT
);
}
foreach ($error_regexps as $regexp => $code) {
if (preg_match($regexp, $errormsg)) {
return $code;
}
}
// Fall back to DB_ERROR if there was no mapping.
return DB_ERROR;
}
// }}}
/**
* Fetch and return a row of data (it uses fetchInto for that)
* @param $result PostgreSQL result identifier
* @param $fetchmode format of fetched row array
* @param $rownum the absolute row number to fetch
*
* @return array a row of data, or false on error
*/
function fetch_assoc($result, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum=null)
{
if ($fetchmode == DB_FETCHMODE_DEFAULT) {
$fetchmode = $this->fetchmode;
}
$res = $this->fetchInto ($result, $arr, $fetchmode, $rownum);
if ($res !== DB_OK) {
return $res;
}
return $arr;
}
// {{{ fetchInto()
/**
* Fetch a row and insert the data into an existing array.
*
* @param $result PostgreSQL result identifier
* @param $row (reference) array where data from the row is stored
* @param $fetchmode how the array data should be indexed
* @param $rownum the row number to fetch
*
* @return int DB_OK on success, a DB error code on failure
*/
function fetchInto($result, &$row, $fetchmode, $rownum=null)
{
$rownum = ($rownum !== null) ? $rownum : $this->row[$result];
if ($rownum >= $this->num_rows[$result]) {
return null;
}
if ($fetchmode & DB_FETCHMODE_ASSOC) {
$row = @pg_fetch_array($result, $rownum, PGSQL_ASSOC);
} else {
$row = @pg_fetch_row($result, $rownum);
}
if (!$row) {
$err = pg_errormessage($this->connection);
if (!$err) {
return null;
}
return $this->pgsqlRaiseError();
}
$this->row[$result] = ++$rownum;
return DB_OK;
}
// }}}
// {{{ freeResult()
/**
* Free the internal resources associated with $result.
*
* @param $result int PostgreSQL result identifier or DB statement identifier
*
* @return bool TRUE on success, FALSE if $result is invalid
*/
function freeResult($result)
{
if (is_resource($result)) {
return @pg_freeresult($result);
}
if (!isset($this->prepare_tokens[(int)$result])) {
return false;
}
unset($this->prepare_tokens[(int)$result]);
unset($this->prepare_types[(int)$result]);
unset($this->row[(int)$result]);
unset($this->num_rows[(int)$result]);
$this->affected = 0;
return true;
}
// }}}
// {{{ quote()
/**
* Quote the given string so it can be safely used within string delimiters
* in a query.
* @param $string mixed Data to be quoted
* @return mixed "NULL" string, quoted string or original data
*/
function quote($str = null)
{
switch (strtolower(gettype($str))) {
case 'null':
return 'NULL';
case 'integer':
case 'double' :
return $str;
case 'string':
default:
$str = str_replace("'", "''", $str);
//PostgreSQL treats a backslash as an escape character.
$str = str_replace('\\', '\\\\', $str);
return "'$str'";
}
}
// }}}
// {{{ numCols()
/**
* Get the number of columns in a result set.
*
* @param $result resource PostgreSQL result identifier
*
* @return int the number of columns per row in $result
*/
function numCols($result)
{
$cols = @pg_numfields($result);
if (!$cols) {
return $this->pgsqlRaiseError();
}
return $cols;
}
// }}}
// {{{ numRows()
/**
* Get the number of rows in a result set.
*
* @param $result resource PostgreSQL result identifier
*
* @return int the number of rows in $result
*/
function numRows($result)
{
$rows = @pg_numrows($result);
if ($rows === null) {
return $this->pgsqlRaiseError();
}
return $rows;
}
// }}}
// {{{ errorNative()
/**
* Get the native error code of the last error (if any) that
* occured on the current connection.
*
* @return int native PostgreSQL error code
*/
function errorNative()
{
return pg_errormessage($this->connection);
}
// }}}
// {{{ autoCommit()
/**
* Enable/disable automatic commits
*/
function autoCommit($onoff = false)
{
// XXX if $this->transaction_opcount > 0, we should probably
// issue a warning here.
$this->autocommit = $onoff ? true : false;
return DB_OK;
}
// }}}
// {{{ commit()
/**
* Commit the current transaction.
*/
function commit()
{
if ($this->transaction_opcount > 0) {
// (disabled) hack to shut up error messages from libpq.a
//@fclose(@fopen("php://stderr", "w"));
$result = @pg_exec($this->connection, "end;");
$this->transaction_opcount = 0;
if (!$result) {
return $this->pgsqlRaiseError();
}
}
return DB_OK;
}
// }}}
// {{{ rollback()
/**
* Roll back (undo) the current transaction.
*/
function rollback()
{
if ($this->transaction_opcount > 0) {
$result = @pg_exec($this->connection, "abort;");
$this->transaction_opcount = 0;
if (!$result) {
return $this->pgsqlRaiseError();
}
}
return DB_OK;
}
// }}}
// {{{ affectedRows()
/**
* Gets the number of rows affected by the last query.
* if the last query was a select, returns 0.
*
* @return int number of rows affected by the last query or DB_ERROR
*/
function affectedRows()
{
return $this->affected;
}
// }}}
// {{{ nextId()
/**
* Get the next value in a sequence.
*
* We are using native PostgreSQL sequences. If a sequence does
* not exist, it will be created, unless $ondemand is false.
*
* @access public
* @param string $seq_name the name of the sequence
* @param bool $ondemand whether to create the sequence on demand
* @return a sequence integer, or a DB error
*/
function nextId($seq_name, $ondemand = true)
{
$seqname = $this->getSequenceName($seq_name);
$repeat = 0;
do {
$this->pushErrorHandling(PEAR_ERROR_RETURN);
$result = $this->query("SELECT NEXTVAL('${seqname}')");
$this->popErrorHandling();
if ($ondemand && DB::isError($result) &&
$result->getCode() == DB_ERROR_NOSUCHTABLE) {
$repeat = 1;
$result = $this->createSequence($seq_name);
if (DB::isError($result)) {
return $this->raiseError($result);
}
} else {
$repeat = 0;
}
} while ($repeat);
if (DB::isError($result)) {
return $this->raiseError($result);
}
$arr = $result->fetch_assoc(DB_FETCHMODE_ORDERED);
$result->free();
return $arr[0];
}
// }}}
// {{{ createSequence()
/**
* Create the sequence
*
* @param string $seq_name the name of the sequence
* @return mixed DB_OK on success or DB error on error
* @access public
*/
function createSequence($seq_name)
{
$seqname = $this->getSequenceName($seq_name);
$this->pushErrorHandling(PEAR_ERROR_RETURN);
$result = $this->query("CREATE SEQUENCE ${seqname}");
$this->popErrorHandling();
return $result;
}
// }}}
// {{{ dropSequence()
/**
* Drop a sequence
*
* @param string $seq_name the name of the sequence
* @return mixed DB_OK on success or DB error on error
* @access public
*/
function dropSequence($seq_name)
{
$seqname = $this->getSequenceName($seq_name);
return $this->query("DROP SEQUENCE ${seqname}");
}
// }}}
// {{{ modifyLimitQuery()
function modifyLimitQuery($query, $from, $count)
{
$query = $query . " LIMIT $count, $from";
return $query;
}
// }}}
// {{{ pgsqlRaiseError()
function pgsqlRaiseError($errno = null)
{
$native = $this->errorNative();
if ($errno === null) {
$err = $this->errorCode($native);
} else {
$err = $errno;
}
return $this->raiseError($err, null, null, null, $native);
}
// }}}
// {{{ _pgFieldFlags()
/**
* Flags of a Field
*
* @param int $resource PostgreSQL result identifier
* @param int $num_field the field number
*
* @return string The flags of the field ("not_null", "default_xx", "primary_key",
* "unique" and "multiple_key" are supported)
* @access private
*/
function _pgFieldFlags($resource, $num_field, $table_name)
{
$field_name = @pg_fieldname($resource, $num_field);
$result = pg_exec($this->connection, "SELECT f.attnotnull, f.atthasdef
FROM pg_attribute f, pg_class tab, pg_type typ
WHERE tab.relname = typ.typname
AND typ.typrelid = f.attrelid
AND f.attname = '$field_name'
AND tab.relname = '$table_name'");
if (pg_numrows($result) > 0) {
$row = pg_fetch_row($result, 0);
$flags = ($row[0] == 't') ? 'not_null ' : '';
if ($row[1] == 't') {
$result = pg_exec($this->connection, "SELECT a.adsrc
FROM pg_attribute f, pg_class tab, pg_type typ, pg_attrdef a
WHERE tab.relname = typ.typname AND typ.typrelid = f.attrelid
AND f.attrelid = a.adrelid AND f.attname = '$field_name'
AND tab.relname = '$table_name'");
$row = pg_fetch_row($result, 0);
$num = str_replace('\'', '', $row[0]);
$flags .= "default_$num ";
}
}
$result = pg_exec($this->connection, "SELECT i.indisunique, i.indisprimary, i.indkey
FROM pg_attribute f, pg_class tab, pg_type typ, pg_index i
WHERE tab.relname = typ.typname
AND typ.typrelid = f.attrelid
AND f.attrelid = i.indrelid
AND f.attname = '$field_name'
AND tab.relname = '$table_name'");
$count = pg_numrows($result);
for ($i = 0; $i < $count ; $i++) {
$row = pg_fetch_row($result, $i);
$keys = explode(" ", $row[2]);
if (in_array($num_field + 1, $keys)) {
$flags .= ($row[0] == 't') ? 'unique ' : '';
$flags .= ($row[1] == 't') ? 'primary ' : '';
if (count($keys) > 1)
$flags .= 'multiple_key ';
}
}
return trim($flags);
}
// }}}
// {{{ tableInfo()
/**
* Returns information about a table or a result set
*
* NOTE: doesn't support table name and flags if called from a db_result
*
* @param mixed $resource PostgreSQL result identifier or table name
* @param int $mode A valid tableInfo mode (DB_TABLEINFO_ORDERTABLE or
* DB_TABLEINFO_ORDER)
*
* @return array An array with all the information
*/
function tableInfo($result, $mode = null)
{
$count = 0;
$id = 0;
$res = array();
/*
* depending on $mode, metadata returns the following values:
*
* - mode is false (default):
* $result[]:
* [0]["table"] table name
* [0]["name"] field name
* [0]["type"] field type
* [0]["len"] field length
* [0]["flags"] field flags
*
* - mode is DB_TABLEINFO_ORDER
* $result[]:
* ["num_fields"] number of metadata records
* [0]["table"] table name
* [0]["name"] field name
* [0]["type"] field type
* [0]["len"] field length
* [0]["flags"] field flags
* ["order"][field name] index of field named "field name"
* The last one is used, if you have a field name, but no index.
* Test: if (isset($result['meta']['myfield'])) { ...
*
* - mode is DB_TABLEINFO_ORDERTABLE
* the same as above. but additionally
* ["ordertable"][table name][field name] index of field
* named "field name"
*
* this is, because if you have fields from different
* tables with the same field name * they override each
* other with DB_TABLEINFO_ORDER
*
* you can combine DB_TABLEINFO_ORDER and
* DB_TABLEINFO_ORDERTABLE with DB_TABLEINFO_ORDER |
* DB_TABLEINFO_ORDERTABLE * or with DB_TABLEINFO_FULL
*/
// if $result is a string, then we want information about a
// table without a resultset
if (is_string($result)) {
$id = pg_exec($this->connection,"SELECT * FROM $result");
if (empty($id)) {
return $this->pgsqlRaiseError();
}
} else { // else we want information about a resultset
$id = $result;
if (empty($id)) {
return $this->pgsqlRaiseError();
}
}
$count = @pg_numfields($id);
// made this IF due to performance (one if is faster than $count if's)
if (empty($mode)) {
for ($i=0; $i<$count; $i++) {
$res[$i]['table'] = (is_string($result)) ? $result : '';
$res[$i]['name'] = @pg_fieldname ($id, $i);
$res[$i]['type'] = @pg_fieldtype ($id, $i);
$res[$i]['len'] = @pg_fieldsize ($id, $i);
$res[$i]['flags'] = (is_string($result)) ? $this->_pgFieldflags($id, $i, $result) : '';
}
} else { // full
$res["num_fields"]= $count;
for ($i=0; $i<$count; $i++) {
$res[$i]['table'] = (is_string($result)) ? $result : '';
$res[$i]['name'] = @pg_fieldname ($id, $i);
$res[$i]['type'] = @pg_fieldtype ($id, $i);
$res[$i]['len'] = @pg_fieldsize ($id, $i);
$res[$i]['flags'] = (is_string($result)) ? $this->_pgFieldFlags($id, $i, $result) : '';
if ($mode & DB_TABLEINFO_ORDER) {
$res['order'][$res[$i]['name']] = $i;
}
if ($mode & DB_TABLEINFO_ORDERTABLE) {
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
}
}
}
// free the result only if we were called on a table
if (is_resource($id)) {
@pg_freeresult($id);
}
return $res;
}
// }}}
// {{{ getTablesQuery()
/**
* Returns the query needed to get some backend info
* @param string $type What kind of info you want to retrieve
* @return string The SQL query string
*/
function getSpecialQuery($type)
{
switch ($type) {
case 'tables': {
$sql = "SELECT c.relname as \"Name\"
FROM pg_class c, pg_user u
WHERE c.relowner = u.usesysid AND c.relkind = 'r'
AND not exists (select 1 from pg_views where viewname = c.relname)
AND c.relname !~ '^pg_'
UNION
SELECT c.relname as \"Name\"
FROM pg_class c
WHERE c.relkind = 'r'
AND not exists (select 1 from pg_views where viewname = c.relname)
AND not exists (select 1 from pg_user where usesysid = c.relowner)
AND c.relname !~ '^pg_'";
break;
}
case 'views': {
// Table cols: viewname | viewowner | definition
$sql = "SELECT viewname FROM pg_views";
break;
}
case 'users': {
// cols: usename |usesysid|usecreatedb|usetrace|usesuper|usecatupd|passwd |valuntil
$sql = 'SELECT usename FROM pg_user';
break;
}
case 'databases': {
$sql = 'SELECT datname FROM pg_database';
break;
}
case 'functions': {
$sql = 'SELECT proname FROM pg_proc';
break;
}
default:
return null;
}
return $sql;
}
// }}}
}
// Local variables:
// tab-width: 4
// c-basic-offset: 4
// End:
?>

View File

@@ -0,0 +1,444 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Author: Stig Bakken <stig@php.net> |
// +----------------------------------------------------------------------+
//
// $Id: storage.php,v 1.28 2002/02/28 08:27:11 sebastian Exp $
//
// DB_storage: a class that lets you return SQL data as objects that
// can be manipulated and that updates the database accordingly.
//
require_once "PEAR.php";
require_once "DB.php";
/**
* DB_storage provides an object interface to a table row. It lets
* you add, delete and change rows without using SQL.
*
* @author Stig Bakken <stig@php.net>
*
* @package DB
*/
class DB_storage extends PEAR
{
/** the name of the table (or view, if the backend database supports
updates in views) we hold data from */
var $_table = null;
/** which column(s) in the table contains primary keys, can be a
string for single-column primary keys, or an array of strings
for multiple-column primary keys */
var $_keycolumn = null;
/** DB connection handle used for all transactions */
var $_dbh = null;
/** an assoc with the names of database fields stored as properties
in this object */
var $_properties = array();
/** an assoc with the names of the properties in this object that
have been changed since they were fetched from the database */
var $_changes = array();
/** flag that decides if data in this object can be changed.
objects that don't have their table's key column in their
property lists will be flagged as read-only. */
var $_readonly = false;
/** function or method that implements a validator for fields that
are set, this validator function returns true if the field is
valid, false if not */
var $_validator = null;
/**
* Constructor
*
* @param $table string the name of the database table
*
* @param $keycolumn mixed string with name of key column, or array of
* strings if the table has a primary key of more than one column
*
* @param $dbh object database connection object
*
* @param $validator mixed function or method used to validate
* each new value, called with three parameters: the name of the
* field/column that is changing, a reference to the new value and
* a reference to this object
*
*/
function DB_storage($table, $keycolumn, &$dbh, $validator = null)
{
$this->PEAR('DB_Error');
$this->_table = $table;
$this->_keycolumn = $keycolumn;
$this->_dbh = $dbh;
$this->_readonly = false;
$this->_validator = $validator;
}
/**
* Utility method to build a "WHERE" clause to locate ourselves in
* the table.
*
* XXX future improvement: use rowids?
*
* @access private
*/
function _makeWhere($keyval = null)
{
if (is_array($this->_keycolumn)) {
if ($keyval === null) {
for ($i = 0; $i < sizeof($this->_keycolumn); $i++) {
$keyval[] = $this->{$this->_keycolumn[$i]};
}
}
$whereclause = '';
for ($i = 0; $i < sizeof($this->_keycolumn); $i++) {
if ($i > 0) {
$whereclause .= ' AND ';
}
$whereclause .= $this->_keycolumn[$i];
if (is_null($keyval[$i])) {
// there's not much point in having a NULL key,
// but we support it anyway
$whereclause .= ' IS NULL';
} else {
$whereclause .= ' = ' . $this->_dbh->quote($keyval[$i]);
}
}
} else {
if ($keyval === null) {
$keyval = @$this->{$this->_keycolumn};
}
$whereclause = $this->_keycolumn;
if (is_null($keyval)) {
// there's not much point in having a NULL key,
// but we support it anyway
$whereclause .= ' IS NULL';
} else {
$whereclause .= ' = ' . $this->_dbh->quote($keyval);
}
}
return $whereclause;
}
/**
* Method used to initialize a DB_storage object from the
* configured table.
*
* @param $keyval mixed the key[s] of the row to fetch (string or array)
*
* @return int DB_OK on success, a DB error if not
*/
function setup($keyval)
{
$qval = $this->_dbh->quote($keyval);
$whereclause = $this->_makeWhere($keyval);
$query = 'SELECT * FROM ' . $this->_table . ' WHERE ' . $whereclause;
$sth = $this->_dbh->query($query);
if (DB::isError($sth)) {
return $sth;
}
$row = $sth->fetch_assoc(DB_FETCHMODE_ASSOC);
if (DB::isError($row)) {
return $row;
}
if (empty($row)) {
return $this->raiseError(null, DB_ERROR_NOT_FOUND, null, null,
$query, null, true);
}
foreach ($row as $key => $value) {
$this->_properties[$key] = true;
$this->$key = $value;
}
return DB_OK;
}
/**
* Create a new (empty) row in the configured table for this
* object.
*/
function insert($newpk)
{
if (is_array($this->_keycolumn)) {
$primarykey = $this->_keycolumn;
} else {
$primarykey = array($this->_keycolumn);
}
settype($newpk, "array");
for ($i = 0; $i < sizeof($primarykey); $i++) {
$pkvals[] = $this->_dbh->quote($newpk[$i]);
}
$sth = $this->_dbh->query("INSERT INTO $this->_table (" .
implode(",", $primarykey) . ") VALUES(" .
implode(",", $pkvals) . ")");
if (DB::isError($sth)) {
return $sth;
}
if (sizeof($newpk) == 1) {
$newpk = $newpk[0];
}
$this->setup($newpk);
}
/**
* Output a simple description of this DB_storage object.
* @return string object description
*/
function toString()
{
$info = get_class($this);
$info .= " (table=";
$info .= $this->_table;
$info .= ", keycolumn=";
if (is_array($this->_keycolumn)) {
$info .= "(" . implode(",", $this->_keycolumn) . ")";
} else {
$info .= $this->_keycolumn;
}
$info .= ", dbh=";
if (is_object($this->_dbh)) {
$info .= $this->_dbh->toString();
} else {
$info .= "null";
}
$info .= ")";
if (sizeof($this->_properties)) {
$info .= " [loaded, key=";
$keyname = $this->_keycolumn;
if (is_array($keyname)) {
$info .= "(";
for ($i = 0; $i < sizeof($keyname); $i++) {
if ($i > 0) {
$info .= ",";
}
$info .= $this->$keyname[$i];
}
$info .= ")";
} else {
$info .= $this->$keyname;
}
$info .= "]";
}
if (sizeof($this->_changes)) {
$info .= " [modified]";
}
return $info;
}
/**
* Dump the contents of this object to "standard output".
*/
function dump()
{
reset($this->_properties);
while (list($prop, $foo) = each($this->_properties)) {
print "$prop = ";
print htmlentities($this->$prop);
print "<BR>\n";
}
}
/**
* Static method used to create new DB storage objects.
* @param $data assoc. array where the keys are the names
* of properties/columns
* @return object a new instance of DB_storage or a subclass of it
*/
function &create($table, &$data)
{
$classname = get_class($this);
$obj = new $classname($table);
reset($data);
while (list($name, $value) = each($data)) {
$obj->_properties[$name] = true;
$obj->$name = &$value;
}
return $obj;
}
/**
* Loads data into this object from the given query. If this
* object already contains table data, changes will be saved and
* the object re-initialized first.
*
* @param $query SQL query
*
* @param $params parameter list in case you want to use
* prepare/execute mode
*
* @return int DB_OK on success, DB_WARNING_READ_ONLY if the
* returned object is read-only (because the object's specified
* key column was not found among the columns returned by $query),
* or another DB error code in case of errors.
*/
// XXX commented out for now
/*
function loadFromQuery($query, $params = null)
{
if (sizeof($this->_properties)) {
if (sizeof($this->_changes)) {
$this->store();
$this->_changes = array();
}
$this->_properties = array();
}
$rowdata = $this->_dbh->getRow($query, DB_FETCHMODE_ASSOC, $params);
if (DB::isError($rowdata)) {
return $rowdata;
}
reset($rowdata);
$found_keycolumn = false;
while (list($key, $value) = each($rowdata)) {
if ($key == $this->_keycolumn) {
$found_keycolumn = true;
}
$this->_properties[$key] = true;
$this->$key = &$value;
unset($value); // have to unset, or all properties will
// refer to the same value
}
if (!$found_keycolumn) {
$this->_readonly = true;
return DB_WARNING_READ_ONLY;
}
return DB_OK;
}
*/
/**
* Modify an attriute value.
*/
function set($property, $newvalue)
{
// only change if $property is known and object is not
// read-only
if ($this->_readonly) {
return $this->raiseError(null, DB_WARNING_READ_ONLY, null,
null, null, null, true);
}
if (@isset($this->_properties[$property])) {
if (empty($this->_validator)) {
$valid = true;
} else {
$valid = @call_user_func($this->_validator,
$this->_table,
$property,
$newvalue,
$this->$property,
$this);
}
if ($valid) {
$this->$property = $newvalue;
@$this->_changes[$property]++;
} else {
return $this->raiseError(null, DB_ERROR_INVALID, null,
null, "invalid field: $property",
null, true);
}
return true;
}
return $this->raiseError(null, DB_ERROR_NOSUCHFIELD, null,
null, "unknown field: $property",
null, true);
}
/**
* Fetch an attribute value.
*
* @param string attribute name
*
* @return attribute contents, or null if the attribute name is
* unknown
*/
function &get($property)
{
// only return if $property is known
if (isset($this->_properties[$property])) {
return $this->$property;
}
return null;
}
/**
* Destructor, calls DB_storage::store() if there are changes
* that are to be kept.
*/
function _DB_storage()
{
if (empty($this->_discard) && sizeof($this->_changes)) {
$this->store();
}
$this->_properties = array();
$this->_changes = array();
$this->_table = null;
}
/**
* Stores changes to this object in the database.
*
* @return DB_OK or a DB error
*/
function store()
{
while (list($name, $changed) = each($this->_changes)) {
$params[] = &$this->$name;
$vars[] = $name . ' = ?';
}
if ($vars) {
$query = 'UPDATE ' . $this->_table . ' SET ' .
implode(', ', $vars) . ' WHERE ' .
$this->_makeWhere();
$stmt = $this->_dbh->prepare($query);
$res = $this->_dbh->execute($stmt, $params);
if (DB::isError($res)) {
return $res;
}
$this->_changes = array();
}
return DB_OK;
}
/**
* Remove the row represented by this object from the database.
*
* @return mixed DB_OK or a DB error
*/
function remove()
{
if ($this->_readonly) {
return $this->raiseError(null, DB_WARNING_READ_ONLY, null,
null, null, null, true);
}
$query = 'DELETE FROM ' . $this->_table .' WHERE '.
$this->_makeWhere();
$res = $this->_dbh->query($query);
if (DB::isError($res)) {
return $res;
}
foreach ($this->_properties as $prop => $foo) {
unset($this->$prop);
}
$this->_properties = array();
$this->_changes = array();
return DB_OK;
}
}
?>

View File

@@ -0,0 +1,251 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Author: Sterling Hughes <sterling@php.net> |
// +----------------------------------------------------------------------+
//
// $Id: sybase.php,v 1.30 2002/02/28 08:27:11 sebastian Exp $
//
// Database independent query interface definition for PHP's Sybase
// extension.
//
require_once 'DB/common.php';
class DB_sybase extends DB_common
{
// {{{ properties
var $connection;
var $phptype, $dbsyntax;
var $prepare_tokens = array();
var $prepare_types = array();
// }}}
// {{{ constructor
function DB_sybase()
{
$this->DB_common();
$this->phptype = 'sybase';
$this->dbsyntax = 'sybase';
$this->features = array(
'prepare' => false,
'pconnect' => true,
'transactions' => false,
'limit' => 'emulate'
);
}
// }}}
// {{{ connect()
function connect($dsninfo, $persistent = false)
{
if (!DB::assertExtension('sybase') && !DB::assertExtension('sybase_ct'))
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
$this->dsn = $dsninfo;
$user = $dsninfo['username'];
$pw = $dsninfo['password'];
$dbhost = $dsninfo['hostspec'] ? $dsninfo['hostspec'] : 'localhost';
$connect_function = $persistent ? 'sybase_pconnect' : 'sybase_connect';
if ($dbhost && $user && $pw) {
$conn = $connect_function($dbhost, $user, $pw);
} elseif ($dbhost && $user) {
$conn = $connect_function($dbhost, $user);
} elseif ($dbhost) {
$conn = $connect_function($dbhost);
} else {
$conn = $connect_function();
}
if (!$conn) {
return $this->raiseError(DB_ERROR_CONNECT_FAILED);
}
if ($dsninfo['database']) {
if (!@sybase_select_db($dsninfo['database'], $conn)) {
return $this->raiseError(DB_ERROR_NODBSELECTED);
}
}
$this->connection = $conn;
return DB_OK;
}
// }}}
// {{{ disconnect()
function disconnect()
{
$ret = @sybase_close($this->connection);
$this->connection = null;
return $ret;
}
// }}}
// {{{ simpleQuery()
function simpleQuery($query)
{
$this->last_query = $query;
$query = $this->modifyQuery($query);
$result = @sybase_query($query, $this->connection);
if (!$result) {
return $this->raiseError();
}
// Determine which queries that should return data, and which
// should return an error code only.
return DB::isManip($query) ? DB_OK : $result;
}
// }}}
// {{{ nextResult()
/**
* Move the internal sybase result pointer to the next available result
*
* @param a valid fbsql result resource
*
* @access public
*
* @return true if a result is available otherwise return false
*/
function nextResult($result)
{
return false;
}
// }}}
// {{{ fetch_assoc()
function &fetch_assoc($result, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum=null)
{
if ($fetchmode == DB_FETCHMODE_DEFAULT) {
$fetchmode = $this->fetchmode;
}
$res = $this->fetchInto ($result, $arr, $fetchmode, $rownum);
if ($res !== DB_OK) {
return $res;
}
return $arr;
}
// }}}
// {{{ fetchInto()
function fetchInto($result, &$ar, $fetchmode, $rownum=null)
{
if ($rownum !== null) {
if (!sybase_data_seek($result, $rownum)) {
return $this->raiseError();
}
}
$ar = ($fetchmode & DB_FETCHMODE_ASSOC) ? @sybase_fetch_array($result) : @sybase_fetch_row($result);
if (!$ar) {
// reported not work as seems that sybase_get_last_message()
// always return a message here
//if ($errmsg = sybase_get_last_message()) {
// return $this->raiseError($errmsg);
//} else {
return null;
//}
}
return DB_OK;
}
// }}}
// {{{ freeResult()
function freeResult($result)
{
if (is_resource($result)) {
return @sybase_free_result($result);
}
if (!isset($this->prepare_tokens[(int)$result])) {
return false;
}
unset($this->prepare_tokens[(int)$result]);
unset($this->prepare_types[(int)$result]);
return true;
}
// }}}
// {{{ numCols()
function numCols($result)
{
$cols = @sybase_num_fields($result);
if (!$cols) {
return $this->raiseError();
}
return $cols;
}
// }}}
// {{{ affectedRows()
/**
* Gets the number of rows affected by the data manipulation
* query. For other queries, this function returns 0.
*
* @return number of rows affected by the last query
*/
function affectedRows()
{
if (DB::isManip($this->last_query)) {
$result = @sybase_affected_rows($this->connection);
} else {
$result = 0;
}
return $result;
}
// }}}
// {{{ getSpecialQuery()
/**
* Returns the query needed to get some backend info
* @param string $type What kind of info you want to retrieve
* @return string The SQL query string
*/
function getSpecialQuery($type)
{
switch ($type) {
case 'tables':
$sql = "select name from sysobjects where type = 'U' order by name";
break;
case 'views':
$sql = "select name from sysobjects where type = 'V'";
break;
default:
return null;
}
return $sql;
}
// }}}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
*/
?>

View File

@@ -0,0 +1,793 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Sterling Hughes <sterling@php.net> |
// | Stig Bakken <ssb@fast.no> |
// | Tomas V.V.Cox <cox@idecnet.com> |
// +----------------------------------------------------------------------+
//
// $Id: PEAR.php,v 1.32.2.2 2002/04/09 19:04:07 ssb Exp $
//
define('PEAR_ERROR_RETURN', 1);
define('PEAR_ERROR_PRINT', 2);
define('PEAR_ERROR_TRIGGER', 4);
define('PEAR_ERROR_DIE', 8);
define('PEAR_ERROR_CALLBACK', 16);
if (substr(PHP_OS, 0, 3) == 'WIN') {
define('OS_WINDOWS', true);
define('OS_UNIX', false);
define('PEAR_OS', 'Windows');
} else {
define('OS_WINDOWS', false);
define('OS_UNIX', true);
define('PEAR_OS', 'Unix'); // blatant assumption
}
$GLOBALS['_PEAR_default_error_mode'] = PEAR_ERROR_RETURN;
$GLOBALS['_PEAR_default_error_options'] = E_USER_NOTICE;
$GLOBALS['_PEAR_default_error_callback'] = '';
$GLOBALS['_PEAR_destructor_object_list'] = array();
//
// Tests needed: - PEAR inheritance
//
/**
* Base class for other PEAR classes. Provides rudimentary
* emulation of destructors.
*
* If you want a destructor in your class, inherit PEAR and make a
* destructor method called _yourclassname (same name as the
* constructor, but with a "_" prefix). Also, in your constructor you
* have to call the PEAR constructor: $this->PEAR();.
* The destructor method will be called without parameters. Note that
* at in some SAPI implementations (such as Apache), any output during
* the request shutdown (in which destructors are called) seems to be
* discarded. If you need to get any debug information from your
* destructor, use error_log(), syslog() or something similar.
*
* @since PHP 4.0.2
* @author Stig Bakken <ssb@fast.no>
*/
class PEAR
{
// {{{ properties
/**
* Whether to enable internal debug messages.
*
* @var bool
* @access private
*/
var $_debug = false;
/**
* Default error mode for this object.
*
* @var int
* @access private
*/
var $_default_error_mode = null;
/**
* Default error options used for this object when error mode
* is PEAR_ERROR_TRIGGER.
*
* @var int
* @access private
*/
var $_default_error_options = null;
/**
* Default error handler (callback) for this object, if error mode is
* PEAR_ERROR_CALLBACK.
*
* @var string
* @access private
*/
var $_default_error_handler = '';
/**
* Which class to use for error objects.
*
* @var string
* @access private
*/
var $_error_class = 'PEAR_Error';
/**
* An array of expected errors.
*
* @var array
* @access private
*/
var $_expected_errors = array();
// }}}
// {{{ constructor
/**
* Constructor. Registers this object in
* $_PEAR_destructor_object_list for destructor emulation if a
* destructor object exists.
*
* @param string (optional) which class to use for error objects,
* defaults to PEAR_Error.
* @access public
* @return void
*/
function PEAR($error_class = null)
{
$classname = get_class($this);
if ($this->_debug) {
print "PEAR constructor called, class=$classname\n";
}
if ($error_class !== null) {
$this->_error_class = $error_class;
}
while ($classname) {
$destructor = "_$classname";
if (method_exists($this, $destructor)) {
global $_PEAR_destructor_object_list;
$_PEAR_destructor_object_list[] = &$this;
break;
} else {
$classname = get_parent_class($classname);
}
}
}
// }}}
// {{{ destructor
/**
* Destructor (the emulated type of...). Does nothing right now,
* but is included for forward compatibility, so subclass
* destructors should always call it.
*
* See the note in the class desciption about output from
* destructors.
*
* @access public
* @return void
*/
function _PEAR() {
if ($this->_debug) {
printf("PEAR destructor called, class=%s\n", get_class($this));
}
}
// }}}
// {{{ isError()
/**
* Tell whether a value is a PEAR error.
*
* @param mixed the value to test
* @access public
* @return bool true if parameter is an error
*/
function isError($data) {
return (bool)(is_object($data) &&
(get_class($data) == 'pear_error' ||
is_subclass_of($data, 'pear_error')));
}
// }}}
// {{{ setErrorHandling()
/**
* Sets how errors generated by this DB object should be handled.
* Can be invoked both in objects and statically. If called
* statically, setErrorHandling sets the default behaviour for all
* PEAR objects. If called in an object, setErrorHandling sets
* the default behaviour for that object.
*
* @param int $mode
* One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
* PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE or
* PEAR_ERROR_CALLBACK.
*
* @param mixed $options
* When $mode is PEAR_ERROR_TRIGGER, this is the error level (one
* of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
*
* When $mode is PEAR_ERROR_CALLBACK, this parameter is expected
* to be the callback function or method. A callback
* function is a string with the name of the function, a
* callback method is an array of two elements: the element
* at index 0 is the object, and the element at index 1 is
* the name of the method to call in the object.
*
* When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is
* a printf format string used when printing the error
* message.
*
* @access public
* @return void
* @see PEAR_ERROR_RETURN
* @see PEAR_ERROR_PRINT
* @see PEAR_ERROR_TRIGGER
* @see PEAR_ERROR_DIE
* @see PEAR_ERROR_CALLBACK
*
* @since PHP 4.0.5
*/
function setErrorHandling($mode = null, $options = null)
{
if (isset($this)) {
$setmode = &$this->_default_error_mode;
$setoptions = &$this->_default_error_options;
//$setcallback = &$this->_default_error_callback;
} else {
$setmode = &$GLOBALS['_PEAR_default_error_mode'];
$setoptions = &$GLOBALS['_PEAR_default_error_options'];
//$setcallback = &$GLOBALS['_PEAR_default_error_callback'];
}
switch ($mode) {
case PEAR_ERROR_RETURN:
case PEAR_ERROR_PRINT:
case PEAR_ERROR_TRIGGER:
case PEAR_ERROR_DIE:
case null:
$setmode = $mode;
$setoptions = $options;
break;
case PEAR_ERROR_CALLBACK:
$setmode = $mode;
if ((is_string($options) && function_exists($options)) ||
(is_array($options) && method_exists(@$options[0], @$options[1])))
{
$setoptions = $options;
} else {
trigger_error("invalid error callback", E_USER_WARNING);
}
break;
default:
trigger_error("invalid error mode", E_USER_WARNING);
break;
}
}
// }}}
// {{{ expectError()
/**
* This method is used to tell which errors you expect to get.
* Expected errors are always returned with error mode
* PEAR_ERROR_RETURN. Expected error codes are stored in a stack,
* and this method pushes a new element onto it. The list of
* expected errors are in effect until they are popped off the
* stack with the popExpect() method.
*
* @param mixed a single error code or an array of error codes
* to expect
*
* @return int the new depth of the "expected errors" stack
*/
function expectError($code = "*")
{
if (is_array($code)) {
array_push($this->_expected_errors, $code);
} else {
array_push($this->_expected_errors, array($code));
}
return sizeof($this->_expected_errors);
}
// }}}
// {{{ popExpect()
/**
* This method pops one element off the expected error codes
* stack.
*
* @return array the list of error codes that were popped
*/
function popExpect()
{
return array_pop($this->_expected_errors);
}
// }}}
// {{{ raiseError()
/**
* This method is a wrapper that returns an instance of the
* configured error class with this object's default error
* handling applied. If the $mode and $options parameters are not
* specified, the object's defaults are used.
*
* @param $message a text error message or a PEAR error object
*
* @param $code a numeric error code (it is up to your class
* to define these if you want to use codes)
*
* @param $mode One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
* PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE or
* PEAR_ERROR_CALLBACK.
*
* @param $options If $mode is PEAR_ERROR_TRIGGER, this parameter
* specifies the PHP-internal error level (one of
* E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
* If $mode is PEAR_ERROR_CALLBACK, this
* parameter specifies the callback function or
* method. In other error modes this parameter
* is ignored.
*
* @param $userinfo If you need to pass along for example debug
* information, this parameter is meant for that.
*
* @param $error_class The returned error object will be instantiated
* from this class, if specified.
*
* @param $skipmsg If true, raiseError will only pass error codes,
* the error message parameter will be dropped.
*
* @access public
* @return object a PEAR error object
* @see PEAR::setErrorHandling
* @since PHP 4.0.5
*/
function &raiseError($message = null,
$code = null,
$mode = null,
$options = null,
$userinfo = null,
$error_class = null,
$skipmsg = false)
{
// The error is yet a PEAR error object
if (is_object($message)) {
$code = $message->getCode();
$userinfo = $message->getUserInfo();
$error_class = $message->getType();
$message = $message->getMessage();
}
if (isset($this) && isset($this->_expected_errors) && sizeof($this->_expected_errors) > 0 && sizeof($exp = end($this->_expected_errors))) {
if ($exp[0] == "*" ||
(is_int(reset($exp)) && in_array($code, $exp)) ||
(is_string(reset($exp)) && in_array($message, $exp))) {
$mode = PEAR_ERROR_RETURN;
}
}
if ($mode === null) {
if (isset($this) && isset($this->_default_error_mode)) {
$mode = $this->_default_error_mode;
} else {
$mode = $GLOBALS['_PEAR_default_error_mode'];
}
}
if ($mode == PEAR_ERROR_TRIGGER && $options === null) {
if (isset($this)) {
if (isset($this->_default_error_options)) {
$options = $this->_default_error_options;
}
} else {
$options = $GLOBALS['_PEAR_default_error_options'];
}
}
if ($mode == PEAR_ERROR_CALLBACK) {
if (!is_string($options) &&
!(is_array($options) && sizeof($options) == 2 &&
is_object($options[0]) && is_string($options[1])))
{
if (isset($this) && isset($this->_default_error_options)) {
$options = $this->_default_error_options;
} else {
$options = $GLOBALS['_PEAR_default_error_options'];
}
}
} else {
if ($options === null) {
if (isset($this)) {
if (isset($this->_default_error_options)) {
$options = $this->_default_error_options;
}
} else {
$options = $GLOBALS['_PEAR_default_error_options'];
}
}
}
if ($error_class !== null) {
$ec = $error_class;
} elseif (isset($this) && isset($this->_error_class)) {
$ec = $this->_error_class;
} else {
$ec = 'PEAR_Error';
}
if ($skipmsg) {
return new $ec($code, $mode, $options, $userinfo);
} else {
return new $ec($message, $code, $mode, $options, $userinfo);
}
}
// }}}
// {{{ pushErrorHandling()
/**
* Push a new error handler on top of the error handler options stack. With this
* you can easily override the actual error handler for some code and restore
* it later with popErrorHandling.
*
* @param $mode mixed (same as setErrorHandling)
* @param $options mixed (same as setErrorHandling)
*
* @return bool Always true
*
* @see PEAR::setErrorHandling
*/
function pushErrorHandling($mode, $options = null)
{
$stack = &$GLOBALS['_PEAR_error_handler_stack'];
if (!is_array($stack)) {
if (isset($this)) {
$def_mode = &$this->_default_error_mode;
$def_options = &$this->_default_error_options;
// XXX Used anywhere?
//$def_callback = &$this->_default_error_callback;
} else {
$def_mode = &$GLOBALS['_PEAR_default_error_mode'];
$def_options = &$GLOBALS['_PEAR_default_error_options'];
// XXX Used anywhere?
//$def_callback = &$GLOBALS['_PEAR_default_error_callback'];
}
$stack = array();
$stack[] = array($def_mode, $def_options);
}
if (isset($this)) {
$this->setErrorHandling($mode, $options);
} else {
PEAR::setErrorHandling($mode, $options);
}
$stack[] = array($mode, $options);
return true;
}
// }}}
// {{{ popErrorHandling()
/**
* Pop the last error handler used
*
* @return bool Always true
*
* @see PEAR::pushErrorHandling
*/
function popErrorHandling()
{
$stack = &$GLOBALS['_PEAR_error_handler_stack'];
array_pop($stack);
list($mode, $options) = $stack[sizeof($stack) - 1];
if (isset($this)) {
$this->setErrorHandling($mode, $options);
} else {
PEAR::setErrorHandling($mode, $options);
}
return true;
}
// }}}
}
// {{{ _PEAR_call_destructors()
function _PEAR_call_destructors()
{
global $_PEAR_destructor_object_list;
if (is_array($_PEAR_destructor_object_list) &&
sizeof($_PEAR_destructor_object_list))
{
reset($_PEAR_destructor_object_list);
while (list($k, $objref) = each($_PEAR_destructor_object_list)) {
$classname = get_class($objref);
while ($classname) {
$destructor = "_$classname";
if (method_exists($objref, $destructor)) {
$objref->$destructor();
break;
} else {
$classname = get_parent_class($classname);
}
}
}
// Empty the object list to ensure that destructors are
// not called more than once.
$_PEAR_destructor_object_list = array();
}
}
// }}}
class PEAR_Error
{
// {{{ properties
var $error_message_prefix = '';
var $mode = PEAR_ERROR_RETURN;
var $level = E_USER_NOTICE;
var $code = -1;
var $message = '';
var $userinfo = '';
// Wait until we have a stack-groping function in PHP.
//var $file = '';
//var $line = 0;
// }}}
// {{{ constructor
/**
* PEAR_Error constructor
*
* @param $message error message
*
* @param $code (optional) error code
*
* @param $mode (optional) error mode, one of: PEAR_ERROR_RETURN,
* PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER or
* PEAR_ERROR_CALLBACK
*
* @param $level (optional) error level, _OR_ in the case of
* PEAR_ERROR_CALLBACK, the callback function or object/method
* tuple.
*
* @access public
*
*/
function PEAR_Error($message = 'unknown error', $code = null,
$mode = null, $options = null, $userinfo = null)
{
if ($mode === null) {
$mode = PEAR_ERROR_RETURN;
}
$this->message = $message;
$this->code = $code;
$this->mode = $mode;
$this->userinfo = $userinfo;
if ($mode & PEAR_ERROR_CALLBACK) {
$this->level = E_USER_NOTICE;
$this->callback = $options;
} else {
if ($options === null) {
$options = E_USER_NOTICE;
}
$this->level = $options;
$this->callback = null;
}
if ($this->mode & PEAR_ERROR_PRINT) {
if (is_null($options) || is_int($options)) {
$format = "%s";
} else {
$format = $options;
}
printf($format, $this->getMessage());
}
if ($this->mode & PEAR_ERROR_TRIGGER) {
trigger_error($this->getMessage(), $this->level);
}
if ($this->mode & PEAR_ERROR_DIE) {
$msg = $this->getMessage();
if (is_null($options) || is_int($options)) {
$format = "%s";
if (substr($msg, -1) != "\n") {
$msg .= "\n";
}
} else {
$format = $options;
}
die(sprintf($format, $msg));
}
if ($this->mode & PEAR_ERROR_CALLBACK) {
if (is_string($this->callback) && strlen($this->callback)) {
call_user_func($this->callback, $this);
} elseif (is_array($this->callback) &&
sizeof($this->callback) == 2 &&
is_object($this->callback[0]) &&
is_string($this->callback[1]) &&
strlen($this->callback[1])) {
@call_user_method($this->callback[1], $this->callback[0],
$this);
}
}
}
// }}}
// {{{ getMode()
/**
* Get the error mode from an error object.
*
* @return int error mode
* @access public
*/
function getMode() {
return $this->mode;
}
// }}}
// {{{ getCallback()
/**
* Get the callback function/method from an error object.
*
* @return mixed callback function or object/method array
* @access public
*/
function getCallback() {
return $this->callback;
}
// }}}
// {{{ getMessage()
/**
* Get the error message from an error object.
*
* @return string full error message
* @access public
*/
function getMessage ()
{
return ($this->error_message_prefix . $this->message);
}
// }}}
// {{{ getCode()
/**
* Get error code from an error object
*
* @return int error code
* @access public
*/
function getCode()
{
return $this->code;
}
// }}}
// {{{ getType()
/**
* Get the name of this error/exception.
*
* @return string error/exception name (type)
* @access public
*/
function getType ()
{
return get_class($this);
}
// }}}
// {{{ getUserInfo()
/**
* Get additional user-supplied information.
*
* @return string user-supplied information
* @access public
*/
function getUserInfo ()
{
return $this->userinfo;
}
// }}}
// {{{ getDebugInfo()
/**
* Get additional debug information supplied by the application.
*
* @return string debug information
* @access public
*/
function getDebugInfo ()
{
return $this->getUserInfo();
}
// }}}
// {{{ addUserInfo()
function addUserInfo($info)
{
if (empty($this->userinfo)) {
$this->userinfo = $info;
} else {
$this->userinfo .= " ** $info";
}
}
// }}}
// {{{ toString()
/**
* Make a string representation of this object.
*
* @return string a string with an object summary
* @access public
*/
function toString() {
$modes = array();
$levels = array(E_USER_NOTICE => 'notice',
E_USER_WARNING => 'warning',
E_USER_ERROR => 'error');
if ($this->mode & PEAR_ERROR_CALLBACK) {
if (is_array($this->callback)) {
$callback = get_class($this->callback[0]) . '::' .
$this->callback[1];
} else {
$callback = $this->callback;
}
return sprintf('[%s: message="%s" code=%d mode=callback '.
'callback=%s prefix="%s" info="%s"]',
get_class($this), $this->message, $this->code,
$callback, $this->error_message_prefix,
$this->userinfo);
}
if ($this->mode & PEAR_ERROR_CALLBACK) {
$modes[] = 'callback';
}
if ($this->mode & PEAR_ERROR_PRINT) {
$modes[] = 'print';
}
if ($this->mode & PEAR_ERROR_TRIGGER) {
$modes[] = 'trigger';
}
if ($this->mode & PEAR_ERROR_DIE) {
$modes[] = 'die';
}
if ($this->mode & PEAR_ERROR_RETURN) {
$modes[] = 'return';
}
return sprintf('[%s: message="%s" code=%d mode=%s level=%s '.
'prefix="%s" info="%s"]',
get_class($this), $this->message, $this->code,
implode("|", $modes), $levels[$this->level],
$this->error_message_prefix,
$this->userinfo);
}
// }}}
}
register_shutdown_function("_PEAR_call_destructors");
/*
* Local Variables:
* mode: php
* tab-width: 4
* c-basic-offset: 4
* End:
*/
?>

View File

@@ -0,0 +1,872 @@
<?php
/**
* RFC 822 Email address list validation Utility
*
* What is it?
*
* This class will take an address string, and parse it into it's consituent
* parts, be that either addresses, groups, or combinations. Nested groups
* are not supported. The structure it returns is pretty straight forward,
* and is similar to that provided by the imap_rfc822_parse_adrlist(). Use
* print_r() to view the structure.
*
* How do I use it?
*
* $address_string = 'My Group: "Richard Heyes" <richard@localhost> (A comment), ted@example.com (Ted Bloggs), Barney;';
* $structure = Mail_RFC822::parseAddressList($address_string, 'example.com', TRUE)
* print_r($structure);
*
* @author Richard Heyes <richard@phpguru.org>
* @author Chuck Hagenbuch <chuck@horde.org>
* @version $Revision: 1.1 $
* @package Mail
*/
class Mail_RFC822
{
/**
* The address being parsed by the RFC822 object.
* @var string $address
*/
var $address = '';
/**
* The default domain to use for unqualified addresses.
* @var string $default_domain
*/
var $default_domain = 'localhost';
/**
* Should we return a nested array showing groups, or flatten everything?
* @var boolean $nestGroups
*/
var $nestGroups = true;
/**
* Whether or not to validate atoms for non-ascii characters.
* @var boolean $validate
*/
var $validate = true;
/**
* The array of raw addresses built up as we parse.
* @var array $addresses
*/
var $addresses = array();
/**
* The final array of parsed address information that we build up.
* @var array $structure
*/
var $structure = array();
/**
* The current error message, if any.
* @var string $error
*/
var $error = null;
/**
* An internal counter/pointer.
* @var integer $index
*/
var $index = null;
/**
* The number of groups that have been found in the address list.
* @var integer $num_groups
* @access public
*/
var $num_groups = 0;
/**
* A variable so that we can tell whether or not we're inside a
* Mail_RFC822 object.
* @var boolean $mailRFC822
*/
var $mailRFC822 = true;
/**
* A limit after which processing stops
* @var int $limit
*/
var $limit = null;
/**
* Sets up the object. The address must either be set here or when
* calling parseAddressList(). One or the other.
*
* @access public
* @param string $address The address(es) to validate.
* @param string $default_domain Default domain/host etc. If not supplied, will be set to localhost.
* @param boolean $nest_groups Whether to return the structure with groups nested for easier viewing.
* @param boolean $validate Whether to validate atoms. Turn this off if you need to run addresses through before encoding the personal names, for instance.
*
* @return object Mail_RFC822 A new Mail_RFC822 object.
*/
function Mail_RFC822($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null)
{
if (isset($address)) $this->address = $address;
if (isset($default_domain)) $this->default_domain = $default_domain;
if (isset($nest_groups)) $this->nestGroups = $nest_groups;
if (isset($validate)) $this->validate = $validate;
if (isset($limit)) $this->limit = $limit;
}
/**
* Starts the whole process. The address must either be set here
* or when creating the object. One or the other.
*
* @access public
* @param string $address The address(es) to validate.
* @param string $default_domain Default domain/host etc.
* @param boolean $nest_groups Whether to return the structure with groups nested for easier viewing.
* @param boolean $validate Whether to validate atoms. Turn this off if you need to run addresses through before encoding the personal names, for instance.
*
* @return array A structured array of addresses.
*/
function parseAddressList($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null)
{
if (!isset($this->mailRFC822)) {
$obj = new Mail_RFC822($address, $default_domain, $nest_groups, $validate, $limit);
return $obj->parseAddressList();
}
if (isset($address)) $this->address = $address;
if (isset($default_domain)) $this->default_domain = $default_domain;
if (isset($nest_groups)) $this->nestGroups = $nest_groups;
if (isset($validate)) $this->validate = $validate;
if (isset($limit)) $this->limit = $limit;
$this->structure = array();
$this->addresses = array();
$this->error = null;
$this->index = null;
while ($this->address = $this->_splitAddresses($this->address)) {
continue;
}
if ($this->address === false || isset($this->error)) {
return false;
}
// Reset timer since large amounts of addresses can take a long time to
// get here
set_time_limit(30);
// Loop through all the addresses
for ($i = 0; $i < count($this->addresses); $i++){
if (($return = $this->_validateAddress($this->addresses[$i])) === false
|| isset($this->error)) {
return false;
}
if (!$this->nestGroups) {
$this->structure = array_merge($this->structure, $return);
} else {
$this->structure[] = $return;
}
}
return $this->structure;
}
/**
* Splits an address into seperate addresses.
*
* @access private
* @param string $address The addresses to split.
* @return boolean Success or failure.
*/
function _splitAddresses($address)
{
if (!empty($this->limit) AND count($this->addresses) == $this->limit) {
return '';
}
if ($this->_isGroup($address) && !isset($this->error)) {
$split_char = ';';
$is_group = true;
} elseif (!isset($this->error)) {
$split_char = ',';
$is_group = false;
} elseif (isset($this->error)) {
return false;
}
// Split the string based on the above ten or so lines.
$parts = explode($split_char, $address);
$string = $this->_splitCheck($parts, $split_char);
// If a group...
if ($is_group) {
// If $string does not contain a colon outside of
// brackets/quotes etc then something's fubar.
// First check there's a colon at all:
if (strpos($string, ':') === false) {
$this->error = 'Invalid address: ' . $string;
return false;
}
// Now check it's outside of brackets/quotes:
if (!$this->_splitCheck(explode(':', $string), ':'))
return false;
// We must have a group at this point, so increase the counter:
$this->num_groups++;
}
// $string now contains the first full address/group.
// Add to the addresses array.
$this->addresses[] = array(
'address' => trim($string),
'group' => $is_group
);
// Remove the now stored address from the initial line, the +1
// is to account for the explode character.
$address = trim(substr($address, strlen($string) + 1));
// If the next char is a comma and this was a group, then
// there are more addresses, otherwise, if there are any more
// chars, then there is another address.
if ($is_group && substr($address, 0, 1) == ','){
$address = trim(substr($address, 1));
return $address;
} elseif (strlen($address) > 0) {
return $address;
} else {
return '';
}
// If you got here then something's off
return false;
}
/**
* Checks for a group at the start of the string.
*
* @access private
* @param string $address The address to check.
* @return boolean Whether or not there is a group at the start of the string.
*/
function _isGroup($address)
{
// First comma not in quotes, angles or escaped:
$parts = explode(',', $address);
$string = $this->_splitCheck($parts, ',');
// Now we have the first address, we can reliably check for a
// group by searching for a colon that's not escaped or in
// quotes or angle brackets.
if (count($parts = explode(':', $string)) > 1) {
$string2 = $this->_splitCheck($parts, ':');
return ($string2 !== $string);
} else {
return false;
}
}
/**
* A common function that will check an exploded string.
*
* @access private
* @param array $parts The exloded string.
* @param string $char The char that was exploded on.
* @return mixed False if the string contains unclosed quotes/brackets, or the string on success.
*/
function _splitCheck($parts, $char)
{
$string = $parts[0];
for ($i = 0; $i < count($parts); $i++) {
if ($this->_hasUnclosedQuotes($string)
|| $this->_hasUnclosedBrackets($string, '<>')
|| $this->_hasUnclosedBrackets($string, '[]')
|| $this->_hasUnclosedBrackets($string, '()')
|| substr($string, -1) == '\\') {
if (isset($parts[$i + 1])) {
$string = $string . $char . $parts[$i + 1];
} else {
$this->error = 'Invalid address spec. Unclosed bracket or quotes';
return false;
}
} else {
$this->index = $i;
break;
}
}
return $string;
}
/**
* Checks if a string has an unclosed quotes or not.
*
* @access private
* @param string $string The string to check.
* @return boolean True if there are unclosed quotes inside the string, false otherwise.
*/
function _hasUnclosedQuotes($string)
{
$string = explode('"', $string);
$string_cnt = count($string);
for ($i = 0; $i < (count($string) - 1); $i++)
if (substr($string[$i], -1) == '\\')
$string_cnt--;
return ($string_cnt % 2 === 0);
}
/**
* Checks if a string has an unclosed brackets or not. IMPORTANT:
* This function handles both angle brackets and square brackets;
*
* @access private
* @param string $string The string to check.
* @param string $chars The characters to check for.
* @return boolean True if there are unclosed brackets inside the string, false otherwise.
*/
function _hasUnclosedBrackets($string, $chars)
{
$num_angle_start = substr_count($string, $chars[0]);
$num_angle_end = substr_count($string, $chars[1]);
$this->_hasUnclosedBracketsSub($string, $num_angle_start, $chars[0]);
$this->_hasUnclosedBracketsSub($string, $num_angle_end, $chars[1]);
if ($num_angle_start < $num_angle_end) {
$this->error = 'Invalid address spec. Unmatched quote or bracket (' . $chars . ')';
return false;
} else {
return ($num_angle_start > $num_angle_end);
}
}
/**
* Sub function that is used only by hasUnclosedBrackets().
*
* @access private
* @param string $string The string to check.
* @param integer &$num The number of occurences.
* @param string $char The character to count.
* @return integer The number of occurences of $char in $string, adjusted for backslashes.
*/
function _hasUnclosedBracketsSub($string, &$num, $char)
{
$parts = explode($char, $string);
for ($i = 0; $i < count($parts); $i++){
if (substr($parts[$i], -1) == '\\' || $this->_hasUnclosedQuotes($parts[$i]))
$num--;
if (isset($parts[$i + 1]))
$parts[$i + 1] = $parts[$i] . $char . $parts[$i + 1];
}
return $num;
}
/**
* Function to begin checking the address.
*
* @access private
* @param string $address The address to validate.
* @return mixed False on failure, or a structured array of address information on success.
*/
function _validateAddress($address)
{
$is_group = false;
if ($address['group']) {
$is_group = true;
// Get the group part of the name
$parts = explode(':', $address['address']);
$groupname = $this->_splitCheck($parts, ':');
$structure = array();
// And validate the group part of the name.
if (!$this->_validatePhrase($groupname)){
$this->error = 'Group name did not validate.';
return false;
} else {
// Don't include groups if we are not nesting
// them. This avoids returning invalid addresses.
if ($this->nestGroups) {
$structure = new stdClass;
$structure->groupname = $groupname;
}
}
$address['address'] = ltrim(substr($address['address'], strlen($groupname . ':')));
}
// If a group then split on comma and put into an array.
// Otherwise, Just put the whole address in an array.
if ($is_group) {
while (strlen($address['address']) > 0) {
$parts = explode(',', $address['address']);
$addresses[] = $this->_splitCheck($parts, ',');
$address['address'] = trim(substr($address['address'], strlen(end($addresses) . ',')));
}
} else {
$addresses[] = $address['address'];
}
// Check that $addresses is set, if address like this:
// Groupname:;
// Then errors were appearing.
if (!isset($addresses)){
$this->error = 'Empty group.';
return false;
}
for ($i = 0; $i < count($addresses); $i++) {
$addresses[$i] = trim($addresses[$i]);
}
// Validate each mailbox.
// Format could be one of: name <geezer@domain.com>
// geezer@domain.com
// geezer
// ... or any other format valid by RFC 822.
array_walk($addresses, array($this, 'validateMailbox'));
// Nested format
if ($this->nestGroups) {
if ($is_group) {
$structure->addresses = $addresses;
} else {
$structure = $addresses[0];
}
// Flat format
} else {
if ($is_group) {
$structure = array_merge($structure, $addresses);
} else {
$structure = $addresses;
}
}
return $structure;
}
/**
* Function to validate a phrase.
*
* @access private
* @param string $phrase The phrase to check.
* @return boolean Success or failure.
*/
function _validatePhrase($phrase)
{
// Splits on one or more Tab or space.
$parts = preg_split('/[ \\x09]+/', $phrase, -1, PREG_SPLIT_NO_EMPTY);
$phrase_parts = array();
while (count($parts) > 0){
$phrase_parts[] = $this->_splitCheck($parts, ' ');
for ($i = 0; $i < $this->index + 1; $i++)
array_shift($parts);
}
for ($i = 0; $i < count($phrase_parts); $i++) {
// If quoted string:
if (substr($phrase_parts[$i], 0, 1) == '"') {
if (!$this->_validateQuotedString($phrase_parts[$i]))
return false;
continue;
}
// Otherwise it's an atom:
if (!$this->_validateAtom($phrase_parts[$i])) return false;
}
return true;
}
/**
* Function to validate an atom which from rfc822 is:
* atom = 1*<any CHAR except specials, SPACE and CTLs>
*
* If validation ($this->validate) has been turned off, then
* validateAtom() doesn't actually check anything. This is so that you
* can split a list of addresses up before encoding personal names
* (umlauts, etc.), for example.
*
* @access private
* @param string $atom The string to check.
* @return boolean Success or failure.
*/
function _validateAtom($atom)
{
if (!$this->validate) {
// Validation has been turned off; assume the atom is okay.
return true;
}
// Check for any char from ASCII 0 - ASCII 127
if (!preg_match('/^[\\x00-\\x7E]+$/i', $atom, $matches)) {
return false;
}
// Check for specials:
if (preg_match('/[][()<>@,;\\:". ]/', $atom)) {
return false;
}
// Check for control characters (ASCII 0-31):
if (preg_match('/[\\x00-\\x1F]+/', $atom)) {
return false;
}
return true;
}
/**
* Function to validate quoted string, which is:
* quoted-string = <"> *(qtext/quoted-pair) <">
*
* @access private
* @param string $qstring The string to check
* @return boolean Success or failure.
*/
function _validateQuotedString($qstring)
{
// Leading and trailing "
$qstring = substr($qstring, 1, -1);
// Perform check.
return !(preg_match('/(.)[\x0D\\\\"]/', $qstring, $matches) && $matches[1] != '\\');
}
/**
* Function to validate a mailbox, which is:
* mailbox = addr-spec ; simple address
* / phrase route-addr ; name and route-addr
*
* @access public
* @param string &$mailbox The string to check.
* @return boolean Success or failure.
*/
function validateMailbox(&$mailbox)
{
// A couple of defaults.
$phrase = '';
$comment = '';
// Catch any RFC822 comments and store them separately
$_mailbox = $mailbox;
while (strlen(trim($_mailbox)) > 0) {
$parts = explode('(', $_mailbox);
$before_comment = $this->_splitCheck($parts, '(');
if ($before_comment != $_mailbox) {
// First char should be a (
$comment = substr(str_replace($before_comment, '', $_mailbox), 1);
$parts = explode(')', $comment);
$comment = $this->_splitCheck($parts, ')');
$comments[] = $comment;
// +1 is for the trailing )
$_mailbox = substr($_mailbox, strpos($_mailbox, $comment)+strlen($comment)+1);
} else {
break;
}
}
for($i=0; $i<count(@$comments); $i++){
$mailbox = str_replace('('.$comments[$i].')', '', $mailbox);
}
$mailbox = trim($mailbox);
// Check for name + route-addr
if (substr($mailbox, -1) == '>' && substr($mailbox, 0, 1) != '<') {
$parts = explode('<', $mailbox);
$name = $this->_splitCheck($parts, '<');
$phrase = trim($name);
$route_addr = trim(substr($mailbox, strlen($name.'<'), -1));
if ($this->_validatePhrase($phrase) === false || ($route_addr = $this->_validateRouteAddr($route_addr)) === false)
return false;
// Only got addr-spec
} else {
// First snip angle brackets if present.
if (substr($mailbox,0,1) == '<' && substr($mailbox,-1) == '>')
$addr_spec = substr($mailbox,1,-1);
else
$addr_spec = $mailbox;
if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false)
return false;
}
// Construct the object that will be returned.
$mbox = new stdClass();
// Add the phrase (even if empty) and comments
$mbox->personal = $phrase;
$mbox->comment = isset($comments) ? $comments : array();
if (isset($route_addr)) {
$mbox->mailbox = $route_addr['local_part'];
$mbox->host = $route_addr['domain'];
$route_addr['adl'] !== '' ? $mbox->adl = $route_addr['adl'] : '';
} else {
$mbox->mailbox = $addr_spec['local_part'];
$mbox->host = $addr_spec['domain'];
}
$mailbox = $mbox;
return true;
}
/**
* This function validates a route-addr which is:
* route-addr = "<" [route] addr-spec ">"
*
* Angle brackets have already been removed at the point of
* getting to this function.
*
* @access private
* @param string $route_addr The string to check.
* @return mixed False on failure, or an array containing validated address/route information on success.
*/
function _validateRouteAddr($route_addr)
{
// Check for colon.
if (strpos($route_addr, ':') !== false) {
$parts = explode(':', $route_addr);
$route = $this->_splitCheck($parts, ':');
} else {
$route = $route_addr;
}
// If $route is same as $route_addr then the colon was in
// quotes or brackets or, of course, non existent.
if ($route === $route_addr){
unset($route);
$addr_spec = $route_addr;
if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) {
return false;
}
} else {
// Validate route part.
if (($route = $this->_validateRoute($route)) === false) {
return false;
}
$addr_spec = substr($route_addr, strlen($route . ':'));
// Validate addr-spec part.
if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) {
return false;
}
}
if (isset($route)) {
$return['adl'] = $route;
} else {
$return['adl'] = '';
}
$return = array_merge($return, $addr_spec);
return $return;
}
/**
* Function to validate a route, which is:
* route = 1#("@" domain) ":"
*
* @access private
* @param string $route The string to check.
* @return mixed False on failure, or the validated $route on success.
*/
function _validateRoute($route)
{
// Split on comma.
$domains = explode(',', trim($route));
for ($i = 0; $i < count($domains); $i++) {
$domains[$i] = str_replace('@', '', trim($domains[$i]));
if (!$this->_validateDomain($domains[$i])) return false;
}
return $route;
}
/**
* Function to validate a domain, though this is not quite what
* you expect of a strict internet domain.
*
* domain = sub-domain *("." sub-domain)
*
* @access private
* @param string $domain The string to check.
* @return mixed False on failure, or the validated domain on success.
*/
function _validateDomain($domain)
{
// Note the different use of $subdomains and $sub_domains
$subdomains = explode('.', $domain);
while (count($subdomains) > 0) {
$sub_domains[] = $this->_splitCheck($subdomains, '.');
for ($i = 0; $i < $this->index + 1; $i++)
array_shift($subdomains);
}
for ($i = 0; $i < count($sub_domains); $i++) {
if (!$this->_validateSubdomain(trim($sub_domains[$i])))
return false;
}
// Managed to get here, so return input.
return $domain;
}
/**
* Function to validate a subdomain:
* subdomain = domain-ref / domain-literal
*
* @access private
* @param string $subdomain The string to check.
* @return boolean Success or failure.
*/
function _validateSubdomain($subdomain)
{
if (preg_match('|^\[(.*)]$|', $subdomain, $arr)){
if (!$this->_validateDliteral($arr[1])) return false;
} else {
if (!$this->_validateAtom($subdomain)) return false;
}
// Got here, so return successful.
return true;
}
/**
* Function to validate a domain literal:
* domain-literal = "[" *(dtext / quoted-pair) "]"
*
* @access private
* @param string $dliteral The string to check.
* @return boolean Success or failure.
*/
function _validateDliteral($dliteral)
{
return !preg_match('/(.)[][\x0D\\\\]/', $dliteral, $matches) && $matches[1] != '\\';
}
/**
* Function to validate an addr-spec.
*
* addr-spec = local-part "@" domain
*
* @access private
* @param string $addr_spec The string to check.
* @return mixed False on failure, or the validated addr-spec on success.
*/
function _validateAddrSpec($addr_spec)
{
$addr_spec = trim($addr_spec);
// Split on @ sign if there is one.
if (strpos($addr_spec, '@') !== false) {
$parts = explode('@', $addr_spec);
$local_part = $this->_splitCheck($parts, '@');
$domain = substr($addr_spec, strlen($local_part . '@'));
// No @ sign so assume the default domain.
} else {
$local_part = $addr_spec;
$domain = $this->default_domain;
}
if (($local_part = $this->_validateLocalPart($local_part)) === false) return false;
if (($domain = $this->_validateDomain($domain)) === false) return false;
// Got here so return successful.
return array('local_part' => $local_part, 'domain' => $domain);
}
/**
* Function to validate the local part of an address:
* local-part = word *("." word)
*
* @access private
* @param string $local_part
* @return mixed False on failure, or the validated local part on success.
*/
function _validateLocalPart($local_part)
{
$parts = explode('.', $local_part);
// Split the local_part into words.
while (count($parts) > 0){
$words[] = $this->_splitCheck($parts, '.');
for ($i = 0; $i < $this->index + 1; $i++) {
array_shift($parts);
}
}
// Validate each word.
for ($i = 0; $i < count($words); $i++) {
if ($this->_validatePhrase(trim($words[$i])) === false) return false;
}
// Managed to get here, so return the input.
return $local_part;
}
/**
* Returns an approximate count of how many addresses are
* in the given string. This is APPROXIMATE as it only splits
* based on a comma which has no preceding backslash. Could be
* useful as large amounts of addresses will end up producing
* *large* structures when used with parseAddressList().
*
* @param string $data Addresses to count
* @return int Approximate count
*/
function approximateCount($data)
{
return count(preg_split('/(?<!\\\\),/', $data));
}
/**
* This is a email validating function seperate to the rest
* of the class. It simply validates whether an email is of
* the common internet form: <user>@<domain>. This can be
* sufficient for most people. Optional stricter mode can
* be utilised which restricts mailbox characters allowed
* to alphanumeric, full stop, hyphen and underscore.
*
* @param string $data Address to check
* @param boolean $strict Optional stricter mode
* @return mixed False if it fails, an indexed array
* username/domain if it matches
*/
function isValidInetAddress($data, $strict = false)
{
$regex = $strict ? '/^([.0-9a-z_-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,4})$/i' : '/^([*+!.&#$|\'\\%\/0-9a-z^_`{}=?~:-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,4})$/i';
if (preg_match($regex, trim($data), $matches)) {
return array($matches[1], $matches[2]);
} else {
return false;
}
}
}
?>

View File

@@ -0,0 +1,43 @@
<?php
/*=======================================================================
*
* automailer_internal.php
*
* Autor: Marc Vollmann
*
=======================================================================*/
include_once ("mc_gen_include.inc.php");
include_once ("htmlMimeMail.php");
$auth = trim($argv[1]);
$errMsg = trim($argv[2]);
// Execution-Time for script
set_time_limit(60);
if ($auth == "comegetsome97531" && $errMsg != "") :
$dirName = dirname(__FILE__);
$dirName = str_replace("\\", "/", $dirName);
$lastSlashPos = strrpos($dirName,"/");
$path = substr($dirName, 0, $lastSlashPos);
// Send mail to admin@assecutor.de
$mailObj = new htmlMimeMail();
$mailObj->setFrom("support@assecutor.de");
$mailObj->setSubject("VOTIAN - INTERNE MELDUNG!");
// PLAIN-TEXT
$mailtext = "<" . $errMsg . ">";
if ($errMsg == "metaobject_db_fail") :
$mailtext .= " - " . "METAOBJECT-DATENBANK VERMUTLICH NICHT ERREICHBAR!";
endif;
$mailObj->setText($mailtext);
$mailResult = $mailObj->send(array("admin@assecutor.de"), 'smtp');
$mailObj = NULL;
endif;
?>

View File

@@ -0,0 +1,782 @@
<?php
/**
* Filename.......: class.html.mime.mail.inc
* Project........: HTML Mime mail class
* Last Modified..: $Date: 2002/07/24 13:14:10 $
* CVS Revision...: $Revision: 1.4 $
* Copyright......: 2001, 2002 Richard Heyes
*/
require_once(dirname(__FILE__) . '/mimePart.php');
class htmlMimeMail
{
/**
* The html part of the message
* @var string
*/
var $html;
/**
* The text part of the message(only used in TEXT only messages)
* @var string
*/
var $text;
/**
* The main body of the message after building
* @var string
*/
var $output;
/**
* The alternative text to the HTML part (only used in HTML messages)
* @var string
*/
var $html_text;
/**
* An array of embedded images/objects
* @var array
*/
var $html_images;
/**
* An array of recognised image types for the findHtmlImages() method
* @var array
*/
var $image_types;
/**
* Parameters that affect the build process
* @var array
*/
var $build_params;
/**
* Array of attachments
* @var array
*/
var $attachments;
/**
* The main message headers
* @var array
*/
var $headers;
/**
* Whether the message has been built or not
* @var boolean
*/
var $is_built;
/**
* The return path address. If not set the From:
* address is used instead
* @var string
*/
var $return_path;
/**
* Array of information needed for smtp sending
* @var array
*/
var $smtp_params;
/**
* Constructor function. Sets the headers
* if supplied.
*/
function htmlMimeMail()
{
/**
* Initialise some variables.
*/
$this->html_images = array();
$this->headers = array();
$this->is_built = false;
/**
* If you want the auto load functionality
* to find other image/file types, add the
* extension and content type here.
*/
$this->image_types = array(
'gif' => 'image/gif',
'jpg' => 'image/jpeg',
'jpeg' => 'image/jpeg',
'jpe' => 'image/jpeg',
'bmp' => 'image/bmp',
'png' => 'image/png',
'tif' => 'image/tiff',
'tiff' => 'image/tiff',
'swf' => 'application/x-shockwave-flash'
);
/**
* Set these up
*/
$this->build_params['html_encoding'] = 'quoted-printable';
$this->build_params['text_encoding'] = '7bit';
$this->build_params['html_charset'] = 'ISO-8859-1';
$this->build_params['text_charset'] = 'ISO-8859-1';
$this->build_params['head_charset'] = 'ISO-8859-1';
$this->build_params['text_wrap'] = 998;
/**
* Defaults for smtp sending
*/
if (!empty($GLOBALS['HTTP_SERVER_VARS']['HTTP_HOST'])) {
$helo = $GLOBALS['HTTP_SERVER_VARS']['HTTP_HOST'];
} elseif (!empty($GLOBALS['HTTP_SERVER_VARS']['SERVER_NAME'])) {
$helo = $GLOBALS['HTTP_SERVER_VARS']['SERVER_NAME'];
} else {
$helo = 'localhost';
}
/*
$this->smtp_params['host'] = 'smtp.1und1.com';
$this->smtp_params['port'] = 25;
$this->smtp_params['helo'] = $helo;
$this->smtp_params['auth'] = true;
$this->smtp_params['user'] = 'm34847762-7';
$this->smtp_params['pass'] = '%CdGm%';
*/
$this->smtp_params['host'] = 'smtp.pop-i.de';
$this->smtp_params['port'] = 25;
$this->smtp_params['helo'] = $helo;
$this->smtp_params['auth'] = false;
$this->smtp_params['user'] = '';
$this->smtp_params['pass'] = '';
/**
* Make sure the MIME version header is first.
*/
$this->headers['MIME-Version'] = '1.0';
}
/**
* This function will read a file in
* from a supplied filename and return
* it. This can then be given as the first
* argument of the the functions
* add_html_image() or add_attachment().
*/
function getFile($filename)
{
$return = '';
if ($fp = fopen($filename, 'rb')) {
while (!feof($fp)) {
$return .= fread($fp, 1024);
}
fclose($fp);
return $return;
} else {
return false;
}
}
/**
* Accessor to set the CRLF style
*/
function setCrlf($crlf = "\n")
{
if (!defined('CRLF')) {
define('CRLF', $crlf, true);
}
if (!defined('MAIL_MIMEPART_CRLF')) {
define('MAIL_MIMEPART_CRLF', $crlf, true);
}
}
/**
* Accessor to set the SMTP parameters
*/
function setSMTPParams($host = null, $port = null, $helo = null, $auth = null, $user = null, $pass = null)
{
if (!is_null($host)) $this->smtp_params['host'] = $host;
if (!is_null($port)) $this->smtp_params['port'] = $port;
if (!is_null($helo)) $this->smtp_params['helo'] = $helo;
if (!is_null($auth)) $this->smtp_params['auth'] = $auth;
if (!is_null($user)) $this->smtp_params['user'] = $user;
if (!is_null($pass)) $this->smtp_params['pass'] = $pass;
}
/**
* Accessor function to set the text encoding
*/
function setTextEncoding($encoding = '7bit')
{
$this->build_params['text_encoding'] = $encoding;
}
/**
* Accessor function to set the HTML encoding
*/
function setHtmlEncoding($encoding = 'quoted-printable')
{
$this->build_params['html_encoding'] = $encoding;
}
/**
* Accessor function to set the text charset
*/
function setTextCharset($charset = 'ISO-8859-1')
{
$this->build_params['text_charset'] = $charset;
}
/**
* Accessor function to set the HTML charset
*/
function setHtmlCharset($charset = 'ISO-8859-1')
{
$this->build_params['html_charset'] = $charset;
}
/**
* Accessor function to set the header encoding charset
*/
function setHeadCharset($charset = 'ISO-8859-1')
{
$this->build_params['head_charset'] = $charset;
}
/**
* Accessor function to set the text wrap count
*/
function setTextWrap($count = 998)
{
$this->build_params['text_wrap'] = $count;
}
/**
* Accessor to set a header
*/
function setHeader($name, $value)
{
$this->headers[$name] = $value;
}
/**
* Accessor to add a Subject: header
*/
function setSubject($subject)
{
$this->headers['Subject'] = $subject;
}
/**
* Accessor to add a From: header
*/
function setFrom($from)
{
$this->headers['From'] = $from;
}
/**
* Accessor to set the return path
*/
function setReturnPath($return_path)
{
$this->return_path = $return_path;
}
/**
* Accessor to add a Cc: header
*/
function setCc($cc)
{
$this->headers['Cc'] = $cc;
}
/**
* Accessor to add a Bcc: header
*/
function setBcc($bcc)
{
$this->headers['Bcc'] = $bcc;
}
/**
* Adds plain text. Use this function
* when NOT sending html email
*/
function setText($text = '')
{
$this->text = $text;
}
/**
* Adds a html part to the mail.
* Also replaces image names with
* content-id's.
*/
function setHtml($html, $text = null, $images_dir = null)
{
$this->html = $html;
$this->html_text = $text;
if (isset($images_dir)) {
$this->_findHtmlImages($images_dir);
}
}
/**
* Function for extracting images from
* html source. This function will look
* through the html code supplied by add_html()
* and find any file that ends in one of the
* extensions defined in $obj->image_types.
* If the file exists it will read it in and
* embed it, (not an attachment).
*
* @author Dan Allen
*/
function _findHtmlImages($images_dir)
{
// Build the list of image extensions
while (list($key,) = each($this->image_types)) {
$extensions[] = $key;
}
preg_match_all('/(?:"|\')([^"\']+\.('.implode('|', $extensions).'))(?:"|\')/Ui', $this->html, $images);
for ($i=0; $i<count($images[1]); $i++) {
if (file_exists($images_dir . $images[1][$i])) {
$html_images[] = $images[1][$i];
$this->html = str_replace($images[1][$i], basename($images[1][$i]), $this->html);
}
}
if (!empty($html_images)) {
// If duplicate images are embedded, they may show up as attachments, so remove them.
$html_images = array_unique($html_images);
sort($html_images);
for ($i=0; $i<count($html_images); $i++) {
if ($image = $this->getFile($images_dir.$html_images[$i])) {
$ext = substr($html_images[$i], strrpos($html_images[$i], '.') + 1);
$content_type = $this->image_types[strtolower($ext)];
$this->addHtmlImage($image, basename($html_images[$i]), $content_type);
}
}
}
}
/**
* Adds an image to the list of embedded
* images.
*/
function addHtmlImage($file, $name = '', $c_type='application/octet-stream')
{
$this->html_images[] = array(
'body' => $file,
'name' => $name,
'c_type' => $c_type,
'cid' => md5(uniqid(time()))
);
}
/**
* Adds a file to the list of attachments.
*/
function addAttachment($file, $name = '', $c_type='application/octet-stream', $encoding = 'base64')
{
$this->attachments[] = array(
'body' => $file,
'name' => $name,
'c_type' => $c_type,
'encoding' => $encoding
);
}
/**
* Adds a text subpart to a mime_part object
*/
function &_addTextPart(&$obj, $text)
{
$params['content_type'] = 'text/plain';
$params['encoding'] = $this->build_params['text_encoding'];
$params['charset'] = $this->build_params['text_charset'];
if (is_object($obj)) {
return $obj->addSubpart($text, $params);
} else {
return new Mail_mimePart($text, $params);
}
}
/**
* Adds a html subpart to a mime_part object
*/
function &_addHtmlPart(&$obj)
{
$params['content_type'] = 'text/html';
$params['encoding'] = $this->build_params['html_encoding'];
$params['charset'] = $this->build_params['html_charset'];
if (is_object($obj)) {
return $obj->addSubpart($this->html, $params);
} else {
return new Mail_mimePart($this->html, $params);
}
}
/**
* Starts a message with a mixed part
*/
function &_addMixedPart()
{
$params['content_type'] = 'multipart/mixed';
return new Mail_mimePart('', $params);
}
/**
* Adds an alternative part to a mime_part object
*/
function &_addAlternativePart(&$obj)
{
$params['content_type'] = 'multipart/alternative';
if (is_object($obj)) {
return $obj->addSubpart('', $params);
} else {
return new Mail_mimePart('', $params);
}
}
/**
* Adds a html subpart to a mime_part object
*/
function &_addRelatedPart(&$obj)
{
$params['content_type'] = 'multipart/related';
if (is_object($obj)) {
return $obj->addSubpart('', $params);
} else {
return new Mail_mimePart('', $params);
}
}
/**
* Adds an html image subpart to a mime_part object
*/
function &_addHtmlImagePart(&$obj, $value)
{
$params['content_type'] = $value['c_type'];
$params['encoding'] = 'base64';
$params['disposition'] = 'inline';
$params['dfilename'] = $value['name'];
$params['cid'] = $value['cid'];
$obj->addSubpart($value['body'], $params);
}
/**
* Adds an attachment subpart to a mime_part object
*/
function &_addAttachmentPart(&$obj, $value)
{
$params['content_type'] = $value['c_type'];
$params['encoding'] = $value['encoding'];
$params['disposition'] = 'attachment';
$params['dfilename'] = $value['name'];
$obj->addSubpart($value['body'], $params);
}
/**
* Builds the multipart message from the
* list ($this->_parts). $params is an
* array of parameters that shape the building
* of the message. Currently supported are:
*
* $params['html_encoding'] - The type of encoding to use on html. Valid options are
* "7bit", "quoted-printable" or "base64" (all without quotes).
* 7bit is EXPRESSLY NOT RECOMMENDED. Default is quoted-printable
* $params['text_encoding'] - The type of encoding to use on plain text Valid options are
* "7bit", "quoted-printable" or "base64" (all without quotes).
* Default is 7bit
* $params['text_wrap'] - The character count at which to wrap 7bit encoded data.
* Default this is 998.
* $params['html_charset'] - The character set to use for a html section.
* Default is ISO-8859-1
* $params['text_charset'] - The character set to use for a text section.
* - Default is ISO-8859-1
* $params['head_charset'] - The character set to use for header encoding should it be needed.
* - Default is ISO-8859-1
*/
function buildMessage($params = array())
{
if (!empty($params)) {
while (list($key, $value) = each($params)) {
$this->build_params[$key] = $value;
}
}
if (!empty($this->html_images)) {
foreach ($this->html_images as $value) {
$this->html = str_replace($value['name'], 'cid:'.$value['cid'], $this->html);
}
}
$null = null;
$attachments = !empty($this->attachments) ? true : false;
$html_images = !empty($this->html_images) ? true : false;
$html = !empty($this->html) ? true : false;
$text = isset($this->text) ? true : false;
switch (true) {
case $text AND !$attachments:
$message = &$this->_addTextPart($null, $this->text);
break;
case !$text AND $attachments AND !$html:
$message = &$this->_addMixedPart();
for ($i=0; $i<count($this->attachments); $i++) {
$this->_addAttachmentPart($message, $this->attachments[$i]);
}
break;
case $text AND $attachments:
$message = &$this->_addMixedPart();
$this->_addTextPart($message, $this->text);
for ($i=0; $i<count($this->attachments); $i++) {
$this->_addAttachmentPart($message, $this->attachments[$i]);
}
break;
case $html AND !$attachments AND !$html_images:
if (!is_null($this->html_text)) {
$message = &$this->_addAlternativePart($null);
$this->_addTextPart($message, $this->html_text);
$this->_addHtmlPart($message);
} else {
$message = &$this->_addHtmlPart($null);
}
break;
case $html AND !$attachments AND $html_images:
if (!is_null($this->html_text)) {
$message = &$this->_addAlternativePart($null);
$this->_addTextPart($message, $this->html_text);
$related = &$this->_addRelatedPart($message);
} else {
$message = &$this->_addRelatedPart($null);
$related = &$message;
}
$this->_addHtmlPart($related);
for ($i=0; $i<count($this->html_images); $i++) {
$this->_addHtmlImagePart($related, $this->html_images[$i]);
}
break;
case $html AND $attachments AND !$html_images:
$message = &$this->_addMixedPart();
if (!is_null($this->html_text)) {
$alt = &$this->_addAlternativePart($message);
$this->_addTextPart($alt, $this->html_text);
$this->_addHtmlPart($alt);
} else {
$this->_addHtmlPart($message);
}
for ($i=0; $i<count($this->attachments); $i++) {
$this->_addAttachmentPart($message, $this->attachments[$i]);
}
break;
case $html AND $attachments AND $html_images:
$message = &$this->_addMixedPart();
if (!is_null($this->html_text)) {
$alt = &$this->_addAlternativePart($message);
$this->_addTextPart($alt, $this->html_text);
$rel = &$this->_addRelatedPart($alt);
} else {
$rel = &$this->_addRelatedPart($message);
}
$this->_addHtmlPart($rel);
for ($i=0; $i<count($this->html_images); $i++) {
$this->_addHtmlImagePart($rel, $this->html_images[$i]);
}
for ($i=0; $i<count($this->attachments); $i++) {
$this->_addAttachmentPart($message, $this->attachments[$i]);
}
break;
}
if (isset($message)) {
$output = $message->encode();
$this->output = $output['body'];
$this->headers = array_merge($this->headers, $output['headers']);
// Add message ID header
srand((double)microtime()*10000000);
$message_id = sprintf('<%s.%s@%s>', base_convert(time(), 10, 36), base_convert(rand(), 10, 36), !empty($GLOBALS['HTTP_SERVER_VARS']['HTTP_HOST']) ? $GLOBALS['HTTP_SERVER_VARS']['HTTP_HOST'] : $GLOBALS['HTTP_SERVER_VARS']['SERVER_NAME']);
$this->headers['Message-ID'] = $message_id;
$this->is_built = true;
return true;
} else {
return false;
}
}
/**
* Function to encode a header if necessary
* according to RFC2047
*/
function _encodeHeader($input, $charset = 'ISO-8859-1')
{
preg_match_all('/(\w*[\x80-\xFF]+\w*)/', $input, $matches);
foreach ($matches[1] as $value) {
$replacement = preg_replace('/([\x80-\xFF])/e', '"=" . strtoupper(dechex(ord("\1")))', $value);
$input = str_replace($value, '=?' . $charset . '?Q?' . $replacement . '?=', $input);
}
return $input;
}
/**
* Sends the mail.
*
* @param array $recipients
* @param string $type OPTIONAL
* @return mixed
*/
function send($recipients, $type = 'mail')
{
if (!defined('CRLF')) {
$this->setCrlf($type == 'mail' ? "\n" : "\r\n");
}
if (!$this->is_built) {
$this->buildMessage();
}
switch ($type) {
case 'mail':
$subject = '';
if (!empty($this->headers['Subject'])) {
$subject = $this->_encodeHeader($this->headers['Subject'], $this->build_params['head_charset']);
unset($this->headers['Subject']);
}
// Get flat representation of headers
foreach ($this->headers as $name => $value) {
$headers[] = $name . ': ' . $this->_encodeHeader($value, $this->build_params['head_charset']);
}
$to = $this->_encodeHeader(implode(', ', $recipients), $this->build_params['head_charset']);
if (!empty($this->return_path)) {
$result = mail($to, $subject, $this->output, implode(CRLF, $headers), '-f' . $this->return_path);
} else {
$result = mail($to, $subject, $this->output, implode(CRLF, $headers));
}
// Reset the subject in case mail is resent
if ($subject !== '') {
$this->headers['Subject'] = $subject;
}
// Return
return $result;
break;
case 'smtp':
require_once(dirname(__FILE__) . '/smtp.php');
require_once(dirname(__FILE__) . '/RFC822.php');
$smtp = &smtp::connect($this->smtp_params);
// Parse recipients argument for internet addresses
foreach ($recipients as $recipient) {
$addresses = Mail_RFC822::parseAddressList($recipient, $this->smtp_params['helo'], null, false);
foreach ($addresses as $address) {
$smtp_recipients[] = sprintf('%s@%s', $address->mailbox, $address->host);
}
}
unset($addresses); // These are reused
unset($address); // These are reused
// Get flat representation of headers, parsing
// Cc and Bcc as we go
foreach ($this->headers as $name => $value) {
if ($name == 'Cc' OR $name == 'Bcc') {
$addresses = Mail_RFC822::parseAddressList($value, $this->smtp_params['helo'], null, false);
foreach ($addresses as $address) {
$smtp_recipients[] = sprintf('%s@%s', $address->mailbox, $address->host);
}
}
if ($name == 'Bcc') {
continue;
}
$headers[] = $name . ': ' . $this->_encodeHeader($value, $this->build_params['head_charset']);
}
// Add To header based on $recipients argument
$headers[] = 'To: ' . $this->_encodeHeader(implode(', ', $recipients), $this->build_params['head_charset']);
// Add headers to send_params
$send_params['headers'] = $headers;
$send_params['recipients'] = array_values(array_unique($smtp_recipients));
$send_params['body'] = $this->output;
// Setup return path
if (isset($this->return_path)) {
$send_params['from'] = $this->return_path;
} elseif (!empty($this->headers['From'])) {
$from = Mail_RFC822::parseAddressList($this->headers['From']);
$send_params['from'] = sprintf('%s@%s', $from[0]->mailbox, $from[0]->host);
} else {
$send_params['from'] = 'postmaster@' . $this->smtp_params['helo'];
}
// Send it
if (!$smtp->send($send_params)) {
$this->errors = $smtp->errors;
return false;
}
return true;
break;
}
}
/**
* Use this method to return the email
* in message/rfc822 format. Useful for
* adding an email to another email as
* an attachment. there's a commented
* out example in example.php.
*/
function getRFC822($recipients)
{
// Make up the date header as according to RFC822
$this->setHeader('Date', date('D, d M y H:i:s O'));
if (!defined('CRLF')) {
$this->setCrlf($type == 'mail' ? "\n" : "\r\n");
}
if (!$this->is_built) {
$this->buildMessage();
}
// Return path ?
if (isset($this->return_path)) {
$headers[] = 'Return-Path: ' . $this->return_path;
}
// Get flat representation of headers
foreach ($this->headers as $name => $value) {
$headers[] = $name . ': ' . $value;
}
$headers[] = 'To: ' . implode(', ', $recipients);
return implode(CRLF, $headers) . CRLF . CRLF . $this->output;
}
} // End of class.
?>

View File

@@ -0,0 +1,4 @@
<?php
require_once 'System.php';
var_dump(class_exists('System', false));
?>

View File

@@ -0,0 +1,375 @@
<?php
$HTTP_POST_VARS = !empty($HTTP_POST_VARS) ? $HTTP_POST_VARS : $_POST;
$HTTP_GET_VARS = !empty($HTTP_GET_VARS) ? $HTTP_GET_VARS : $_GET;
$HTTP_COOKIE_VARS = !empty($HTTP_COOKIE_VARS) ? $HTTP_COOKIE_VARS : $_COOKIE;
$HTTP_SERVER_VARS = !empty($HTTP_SERVER_VARS) ? $HTTP_SERVER_VARS : $_SERVER;
$HTTP_ENV_VARS = !empty($HTTP_ENV_VARS) ? $HTTP_ENV_VARS : $_ENV;
$HTTP_POST_FILES = !empty($HTTP_POST_FILES) ? $HTTP_POST_FILES : $_FILES;
if (!isset($PHP_SELF))
$PHP_SELF = $_SERVER["PHP_SELF"];
if (substr(phpversion(), 0, 3) >= "5.1") :
date_default_timezone_set('Europe/Berlin');
endif;
// ini_set('memory_limit','256M');
// *****************************************************************************
// Decryption
// Takes the parameter "$value" and returns the decrypted, original value
// See also corresponding function "ec" for encryption of the original value
function dc($value) {
global $eca, $randomCryptionNumber;
$len = strlen(HTTP_VARS_SEC_SEQ);
if ((HTTP_VARS_SEC_STATE == "1") && (substr($value, 0, $len) == HTTP_VARS_SEC_SEQ) && (substr($value, -$len) == HTTP_VARS_SEC_SEQ)) :
// Extract value from identificator-box
$value = substr($value, strlen(HTTP_VARS_SEC_SEQ), -strlen(HTTP_VARS_SEC_SEQ));
// Decrypt the encrypted value
if (is_numeric($value)) :
$value = (((((((($value - $eca[4]) / 2) - $eca[3]) / 2) - $eca[2]) / 2) - $eca[1]) / 2) - $eca[0] - $randomCryptionNumber;
else :
$value = urldecode($value);
endif;
endif;
return $value;
}
function getHttpVars($httpVars)
{
global $HTTP_GET_VARS, $HTTP_POST_VARS;
$retArr = array();
foreach($httpVars as $hVar)
$retArr[] = (isset($HTTP_GET_VARS[$hVar])) ? $HTTP_GET_VARS[$hVar] :
((isset($HTTP_POST_VARS[$hVar])) ? $HTTP_POST_VARS[$hVar] : "");
return $retArr;
}
// Gets all script-parameters (HTTP_GET_VARS and HTTP_POST_VARS).
// If "$mode == 1" then all id-parameters (only these!) will be decoded
function getSecHttpVars($getSecHttpVarsMode = "0", $httpVars)
{
global $HTTP_GET_VARS, $HTTP_POST_VARS;
$retArr = getHttpVars($httpVars);
$i = 0;
foreach ($httpVars as $par) {
global $$par;
$$par = $retArr[$i];
$i++;
}
// Decryption of the fields if encrypted
if ($getSecHttpVarsMode == "1") :
foreach ($httpVars as $par) {
$$par = dc($$par);
}
endif;
return $retArr;
}
// Writes a string to a file optional with or without linefeed
function writeToFile($fileName, $stringToOperate, $mode = 'a', $noLf = "") {
$fileHandle = fopen($fileName, $mode);
if ($noLf == "") : $stringToOperate .= "\n"; endif;
$opCode = fwrite($fileHandle, $stringToOperate);
fclose($fileHandle);
return $opCode;
}
function getFieldValueFromId($table,$pKeyName,$pKeyVal,$field,$dbConnection = "") {
global $db, $PHP_SELF;
if (!is_object($dbConnection) || $dbConnection == "") : $dbConnection = $db; endif;
$retValue = "";
$sqlStmt = "SELECT $field FROM $table WHERE $pKeyName = '$pKeyVal'";
$result = $dbConnection->query($sqlStmt);
if (DB::isError($result)) die ("$PHP_SELF: <br>$sqlStmt<br>" . $result->getMessage());
while ($row = $result->fetch_assoc()):
$retValue = $row[$field];
endwhile;
$result->free();
return $retValue;
}
function getFieldValueFromClause($table,$field,$whereClause = "",$dbConnection = "") {
global $db, $PHP_SELF;
if (!is_object($dbConnection) || $dbConnection == "") : $dbConnection = $db; endif;
$retValue = "";
$sqlStmt = "SELECT $field FROM $table WHERE $whereClause";
// writeToFile("xxxxxxxx.log", $sqlStmt);
$result = $dbConnection->query($sqlStmt);
if (DB::isError($result)) die ("$PHP_SELF: <br>$sqlStmt<br>" . $result->getMessage());
while ($row = $result->fetch_assoc()):
$retValue = $row[$field];
endwhile;
$result->free();
return $retValue;
}
function getColVectorFromDB2ArrayByClause($table, $pValName, $pWhereClause, $pKeyName = "", $pSortName = "", $pDistinct = "", $dbConnection = "") {
global $db, $PHP_SELF;
if (!is_object($dbConnection) || $dbConnection == "") : $dbConnection = $db; endif;
$retArray = array();
$sqlStmt = "SELECT " . ($pDistinct != "" ? "DISTINCT " : "") . ($pKeyName != "" ? $pKeyName . ", " : "") . "$pValName FROM $table " . ($pWhereClause != "" ? "WHERE " . $pWhereClause : "");
if ($pSortName != "") : $sqlStmt .= " ORDER BY $pSortName"; endif;
$result = $dbConnection->query($sqlStmt);
if (DB::isError($result)) die ("$PHP_SELF: <br>$sqlStmt<br>" . $result->getMessage());
$pValName = (strpos($pValName, " AS ")) ? (substr(stristr($pValName, " AS "), 4)) : $pValName;
$pValName = (strpos($pValName, ".")) ? (substr(stristr($pValName, "."), 1)) : $pValName;
$pKeyName = (strpos($pKeyName, ".")) ? (substr(stristr($pKeyName, "."), 1)) : $pKeyName;
while ($row = $result->fetch_assoc()):
if ($pKeyName != "") :
$retArray[$row[$pKeyName]]= $row[$pValName];
else :
array_push($retArray, $row[$pValName]);
endif;
endwhile;
$result->free();
return $retArray;
}
function getDbConnectionSpecial ($dbhost, $dbname, $dblogin, $dbpassword) {
global $PHP_SELF;
$db_conn = "";
$dsn = "mysql://$dblogin:$dbpassword@$dbhost/$dbname";
$db_conn = DB::connect($dsn, false);
if (DB::isError($db_conn)) return "ERR_DB";
$db_conn->setFetchMode(DB_FETCHMODE_ASSOC);
return $db_conn;
}
function existsEntry ($table,$fields,$dbConnection = "") {
global $db, $PHP_SELF;
if (!is_object($dbConnection) || $dbConnection == "") : $dbConnection = $db; endif;
$fs = "";
$whereClause = "";
$fieldsLength = count($fields);
for ($i = 0; $i < $fieldsLength; $i += 2) :
$fs .= $fields[$i];
$whereClause .= $fields[$i] . " = '" . $fields[$i + 1] . "'";
if ($i < $fieldsLength - 2) :
$fs .= ",";
$whereClause .= " AND ";
endif;
endfor;
if ($whereClause != "") :
$whereClause = " WHERE " . $whereClause;
endif;
$retValue = FALSE;
$sqlStmt = "SELECT $fs FROM $table $whereClause";
$result = $dbConnection->query($sqlStmt);
if (DB::isError($result)) die ("$PHP_SELF: <br>$sqlStmt<br>" . $result->getMessage());
while ($row = $result->fetch_assoc()):
$retValue = TRUE;
endwhile;
$result->free();
return $retValue;
}
function insertStmt($table,$fields,$dbConnection = "") {
global $db, $PHP_SELF;
if (!is_object($dbConnection) || $dbConnection == "") : $dbConnection = $db; endif;
$fs = "";
$vs = "";
$fieldsLength = count($fields);
for ($i = 0; $i < $fieldsLength; $i += 2) :
$fs .= $fields[$i];
$vs .= "'" . $fields[$i + 1] . "'";
if ($i < $fieldsLength - 2) :
$fs .= ",";
$vs .= ",";
endif;
endfor;
$sqlStmt = "INSERT INTO $table ($fs) VALUES ($vs)";
$res = $dbConnection->query($sqlStmt);
if (DB::isError($res)) die ("$PHP_SELF:<br>$sqlStmt<br>" . $res->getMessage());
return $res;
}
function dbInsert($table, $keyValueArray, $dbConnection = "") {
global $db, $PHP_SELF;
if (!is_object($dbConnection) || $dbConnection == "") : $dbConnection = $db; endif;
$retVal = "";
if ($table != "" && is_array($keyValueArray) && count($keyValueArray) > 0) :
insertStmt($table, $keyValueArray,$dbConnection);
$retVal = getLastInsertId();
endif;
return $retVal;
}
function updateStmt($table,$pKeyName,$pKeyVal,$fields,$whereClause = "",$dbConnection = "") {
global $db, $PHP_SELF;
if (!is_object($dbConnection) || $dbConnection == "") : $dbConnection = $db; endif;
$fs = "";
$fieldsLength = count($fields);
for ($i = 0; $i < $fieldsLength; $i += 2) :
$fs .= $fields[$i] . "='" . $fields[$i + 1] . "'";
if ($i < $fieldsLength - 2) :
$fs .= ", ";
endif;
endfor;
if ($pKeyName != ""):
$sqlStmt = "UPDATE $table SET $fs WHERE $pKeyName = '$pKeyVal'";
if ($whereClause != "") : $sqlStmt .= " AND " . $whereClause ; endif;
else:
$sqlStmt = "UPDATE $table SET $fs WHERE " . $whereClause;
endif;
$res = $dbConnection->query($sqlStmt);
if (DB::isError($res)) die ("$PHP_SELF: <br>$sqlStmt<br>" . $res->getMessage());
return $res;
}
function deleteStmt($table,$whereClause, $dbConnection = "") {
global $db;
if (!is_object($dbConnection) || $dbConnection == "") : $dbConnection = $db; endif;
if ($whereClause != "") :
$sqlStmt = "DELETE FROM $table WHERE $whereClause";
$res = $db->query($sqlStmt);
return $res;
endif;
return FALSE;
}
// Returns last autoincrement-value of previous INSERT/UPDATE
function getLastInsertID($dbConnection = "") {
global $db;
if (!is_object($dbConnection) || $dbConnection == "") : $dbConnection = $db; endif;
$lastInsertId = $dbConnection->getOne("SELECT LAST_INSERT_ID()");
return $lastInsertId;
}
// Gets the connection to the central meta objects table
function getConnectionToMetaDB ($dbName = "meta_object", $tableName = "metaobject") {
global $dbhost, $dblogin, $dbpassword;
// $constExtDbInst = getParameterValue("0", "EXTERNAL_DB_METAOBJECT", "0", "0");
$constExtDbInst = $dbhost;
$db_conn = getDbConnectionSpecial($constExtDbInst, $dbName, $dblogin, $dbpassword);
if ($db_conn == "ERR_DB") :
// Check cascade of replicants
$constExtDbInst = "172.16.0.111:3711";
$db_conn = getDbConnectionSpecial($constExtDbInst, $dbName, $dblogin, $dbpassword);
if ($db_conn == "ERR_DB") :
$constExtDbInst = "172.16.0.109:3711";
$db_conn = getDbConnectionSpecial($constExtDbInst, $dbName, $dblogin, $dbpassword);
if ($db_conn == "ERR_DB") :
$constExtDbInst = "172.16.0.103:3711";
$db_conn = getDbConnectionSpecial($constExtDbInst, $dbName, $dblogin, $dbpassword);
endif;
endif;
// Send info mail
// sendInternalMail("metaobject_db_fail");
endif;
return $db_conn;
}
// Gets all databases and its IPs and ports listed in the central meta objects table
function getGlobalDbEnvironments ($dbName = "meta_object", $tableName = "metaobject") {
$dbhostArray = array();
$db_conn = getConnectionToMetaDB($dbName, $tableName);
if ($db_conn != "ERR_DB") :
$sqlquery = "SELECT mo_mnemonic, mo_value FROM " . $dbName . "." . $tableName . " AS mo WHERE mo_obj_type = 'db' AND mo_mnemonic != ''";
$result = $db_conn->query($sqlquery);
if (DB::isError($result)) die ("$PHP_SELF: " . $result->getMessage());
while ($row = $result->fetch_assoc()):
$dbhostArray[$row["mo_mnemonic"]] = $row["mo_value"];
endwhile;
$result->free();
endif;
return $dbhostArray;
}
// Gets the operational database via connection data of metaobject
function getOperationalDatabase ($moId) {
global $db, $PHP_SELF;
global $dbhost, $dbname, $dblogin, $dbpassword;
$retVal = "";
if ($moId != "" && is_numeric($moId)) :
// $constExtDbInst = getExternalMetaDbInst();
$constExtDbInst = $dbhost;
if ($constExtDbInst != "") :
$db_conn = getDbConnectionSpecial($constExtDbInst, $dbname, $dblogin, $dbpassword);
$tmpSqlQuery = "SELECT mo_value FROM meta_object.metaobject WHERE mo_id = '" . $moId . "' AND mo_obj_type = 'db'";
$result = $db_conn->query($tmpSqlQuery);
while ($row = $result->fetch_assoc()):
$retVal = $row["mo_value"];
endwhile;
$result->free();
endif;
endif;
return $retVal;
}
// Gets XML tag
function getSingleTagContent ($strToParse, $tagBegin, $tagEnd) {
$tagContent = "";
$repeat = TRUE;
while ($repeat && !(strpos($strToParse, $tagBegin) === FALSE) && !(strpos($strToParse, $tagEnd) === FALSE)) :
$pos0 = strpos($strToParse, $tagBegin); // begin of tagBegin (first occurrence)
$pos1 = strpos($strToParse, $tagBegin) + strlen($tagBegin); // end of tagBegin (first occurrence)
$pos2 = strpos($strToParse, $tagEnd); // begin of tagEnd (first occurrence)
$pos3 = strpos($strToParse, $tagEnd) + strlen($tagEnd); // end of tagEnd (first occurrence)
$repeat = FALSE;
if ($pos2 - $pos1 > 0) :
// Get the content of the tag
$tagContent = substr($strToParse, $pos1, $pos2 - $pos1);
endif;
endwhile;
return $tagContent;
};
// Get the actual DATETIME (e.g. according to the scheme needed in MySql)
function getDateTime($mode = "0", $dateTimeArray = "", $formatStr = "") {
$retVal = "";
if ($mode == "0") : $retVal = date("Y-m-d H:i:s"); endif; // 2003-03-10 17:16:17
if ($mode == "1") : $retVal = date("Ymd"); endif; // 20030310
if ($mode == "2") : $retVal = date("m.d.y"); endif; // 03.10.01
if ($mode == "3") : $retVal = date("Y-m-d"); endif; // 2003-03-10
if ($mode == "4") : $retVal = date("H:i:s"); endif; // 17:16:17
if ($mode == "5") : $retVal = date("d.m.Y"); endif; // 10.03.2003
if ($mode == "6") : $retVal = date("YmdHis"); endif; // 20030310171617
if ($mode == "7") : $retVal = date("dmY"); endif; // 31122003
if ($mode == "day") : $retVal = date("d"); endif; // 01 .. 31
if ($mode == "month") : $retVal = date("m"); endif; // 01 .. 12
if ($mode == "year") : $retVal = date("Y"); endif; // 2003, ...
if ($mode == "hour") : $retVal = date("H"); endif; // 00 .. 11
if ($mode == "minute") : $retVal = date("i"); endif; // 00 .. 59
if ($mode == "second") : $retVal = date("s"); endif; // 00 .. 59
if ($mode == "now") : $retVal = date("YmdHis", mktime(date("H"),date("i"),date("s"),date("m"),date("d"),date("y"))); endif; // 20090807105959
if ($mode == "day_tomorrow") : $retVal = date("d",mktime(0,0,0,date("m"),date("d")+1,date("Y"))); endif; // 01 .. 31
if ($mode == "month_tomorrow") : $retVal = date("m",mktime(0,0,0,date("m"),date("d")+1,date("Y"))); endif; // 01 .. 12
if ($mode == "year_tomorrow") : $retVal = date("Y",mktime(0,0,0,date("m"),date("d")+1,date("Y"))); endif; // 2003, ...
if ($mode == "day_yesterday") : $retVal = date("d",mktime(0,0,0,date("m"),date("d")-1,date("Y"))); endif; // 01 .. 31
if ($mode == "month_yesterday") : $retVal = date("m",mktime(0,0,0,date("m"),date("d")-1,date("Y"))); endif; // 01 .. 12
if ($mode == "year_yesterday") : $retVal = date("Y",mktime(0,0,0,date("m"),date("d")-1,date("Y"))); endif; // 2003, ...
if ($mode == "date_plus_offset") :
$retVal = date($formatStr, mktime(0,0,0,date("m")+$dateTimeArray[0],date("d")+$dateTimeArray[1],date("Y")+$dateTimeArray[2]));
endif;
if ($mode == "datetime_plus_offset") :
$retVal = date($formatStr, mktime(date("H")+$dateTimeArray[0],date("i")+$dateTimeArray[1],date("s")+$dateTimeArray[2],date("m")+$dateTimeArray[3],date("d")+$dateTimeArray[4],date("Y")+$dateTimeArray[5]));
endif;
if ($mode == "format" && $dateTimeArray != "" && $formatStr != "") :
// int mktime ( [int Stunde [, int Minute [, int Sekunde [, int Monat [, int Tag [, int Jahr [, int is_dst]]]]]]])
$retVal = date($formatStr, mktime($dateTimeArray[0],$dateTimeArray[1],$dateTimeArray[2],$dateTimeArray[3],$dateTimeArray[4],$dateTimeArray[5]));
endif;
return $retVal;
}
?>

View File

@@ -0,0 +1,375 @@
<?php
$HTTP_POST_VARS = !empty($HTTP_POST_VARS) ? $HTTP_POST_VARS : $_POST;
$HTTP_GET_VARS = !empty($HTTP_GET_VARS) ? $HTTP_GET_VARS : $_GET;
$HTTP_COOKIE_VARS = !empty($HTTP_COOKIE_VARS) ? $HTTP_COOKIE_VARS : $_COOKIE;
$HTTP_SERVER_VARS = !empty($HTTP_SERVER_VARS) ? $HTTP_SERVER_VARS : $_SERVER;
$HTTP_ENV_VARS = !empty($HTTP_ENV_VARS) ? $HTTP_ENV_VARS : $_ENV;
$HTTP_POST_FILES = !empty($HTTP_POST_FILES) ? $HTTP_POST_FILES : $_FILES;
if (!isset($PHP_SELF))
$PHP_SELF = $_SERVER["PHP_SELF"];
if (substr(phpversion(), 0, 3) >= "5.1") :
date_default_timezone_set('Europe/Berlin');
endif;
// ini_set('memory_limit','256M');
// *****************************************************************************
// Decryption
// Takes the parameter "$value" and returns the decrypted, original value
// See also corresponding function "ec" for encryption of the original value
function dc($value) {
global $eca, $randomCryptionNumber;
$len = strlen(HTTP_VARS_SEC_SEQ);
if ((HTTP_VARS_SEC_STATE == "1") && (substr($value, 0, $len) == HTTP_VARS_SEC_SEQ) && (substr($value, -$len) == HTTP_VARS_SEC_SEQ)) :
// Extract value from identificator-box
$value = substr($value, strlen(HTTP_VARS_SEC_SEQ), -strlen(HTTP_VARS_SEC_SEQ));
// Decrypt the encrypted value
if (is_numeric($value)) :
$value = (((((((($value - $eca[4]) / 2) - $eca[3]) / 2) - $eca[2]) / 2) - $eca[1]) / 2) - $eca[0] - $randomCryptionNumber;
else :
$value = urldecode($value);
endif;
endif;
return $value;
}
function getHttpVars($httpVars)
{
global $HTTP_GET_VARS, $HTTP_POST_VARS;
$retArr = array();
foreach($httpVars as $hVar)
$retArr[] = (isset($HTTP_GET_VARS[$hVar])) ? $HTTP_GET_VARS[$hVar] :
((isset($HTTP_POST_VARS[$hVar])) ? $HTTP_POST_VARS[$hVar] : "");
return $retArr;
}
// Gets all script-parameters (HTTP_GET_VARS and HTTP_POST_VARS).
// If "$mode == 1" then all id-parameters (only these!) will be decoded
function getSecHttpVars($getSecHttpVarsMode = "0", $httpVars)
{
global $HTTP_GET_VARS, $HTTP_POST_VARS;
$retArr = getHttpVars($httpVars);
$i = 0;
foreach ($httpVars as $par) {
global $$par;
$$par = $retArr[$i];
$i++;
}
// Decryption of the fields if encrypted
if ($getSecHttpVarsMode == "1") :
foreach ($httpVars as $par) {
$$par = dc($$par);
}
endif;
return $retArr;
}
// Writes a string to a file optional with or without linefeed
function writeToFile($fileName, $stringToOperate, $mode = 'a', $noLf = "") {
$fileHandle = fopen($fileName, $mode);
if ($noLf == "") : $stringToOperate .= "\n"; endif;
$opCode = fwrite($fileHandle, $stringToOperate);
fclose($fileHandle);
return $opCode;
}
function getFieldValueFromId($table,$pKeyName,$pKeyVal,$field,$dbConnection = "") {
global $db, $PHP_SELF;
if (!is_object($dbConnection) || $dbConnection == "") : $dbConnection = $db; endif;
$retValue = "";
$sqlStmt = "SELECT $field FROM $table WHERE $pKeyName = '$pKeyVal'";
$result = $dbConnection->query($sqlStmt);
if (DB::isError($result)) die ("$PHP_SELF: <br>$sqlStmt<br>" . $result->getMessage());
while ($row = $result->fetch_assoc()):
$retValue = $row[$field];
endwhile;
$result->free();
return $retValue;
}
function getFieldValueFromClause($table,$field,$whereClause = "",$dbConnection = "") {
global $db, $PHP_SELF;
if (!is_object($dbConnection) || $dbConnection == "") : $dbConnection = $db; endif;
$retValue = "";
$sqlStmt = "SELECT $field FROM $table WHERE $whereClause";
// writeToFile("xxxxxxxx.log", $sqlStmt);
$result = $dbConnection->query($sqlStmt);
if (DB::isError($result)) die ("$PHP_SELF: <br>$sqlStmt<br>" . $result->getMessage());
while ($row = $result->fetch_assoc()):
$retValue = $row[$field];
endwhile;
$result->free();
return $retValue;
}
function getColVectorFromDB2ArrayByClause($table, $pValName, $pWhereClause, $pKeyName = "", $pSortName = "", $pDistinct = "", $dbConnection = "") {
global $db, $PHP_SELF;
if (!is_object($dbConnection) || $dbConnection == "") : $dbConnection = $db; endif;
$retArray = array();
$sqlStmt = "SELECT " . ($pDistinct != "" ? "DISTINCT " : "") . ($pKeyName != "" ? $pKeyName . ", " : "") . "$pValName FROM $table " . ($pWhereClause != "" ? "WHERE " . $pWhereClause : "");
if ($pSortName != "") : $sqlStmt .= " ORDER BY $pSortName"; endif;
$result = $dbConnection->query($sqlStmt);
if (DB::isError($result)) die ("$PHP_SELF: <br>$sqlStmt<br>" . $result->getMessage());
$pValName = (strpos($pValName, " AS ")) ? (substr(stristr($pValName, " AS "), 4)) : $pValName;
$pValName = (strpos($pValName, ".")) ? (substr(stristr($pValName, "."), 1)) : $pValName;
$pKeyName = (strpos($pKeyName, ".")) ? (substr(stristr($pKeyName, "."), 1)) : $pKeyName;
while ($row = $result->fetch_assoc()):
if ($pKeyName != "") :
$retArray[$row[$pKeyName]]= $row[$pValName];
else :
array_push($retArray, $row[$pValName]);
endif;
endwhile;
$result->free();
return $retArray;
}
function getDbConnectionSpecial ($dbhost, $dbname, $dblogin, $dbpassword) {
global $PHP_SELF;
$db_conn = "";
$dsn = "mysql://$dblogin:$dbpassword@$dbhost/$dbname";
$db_conn = DB::connect($dsn, false);
if (DB::isError($db_conn)) return "ERR_DB";
$db_conn->setFetchMode(DB_FETCHMODE_ASSOC);
return $db_conn;
}
function existsEntry ($table,$fields,$dbConnection = "") {
global $db, $PHP_SELF;
if (!is_object($dbConnection) || $dbConnection == "") : $dbConnection = $db; endif;
$fs = "";
$whereClause = "";
$fieldsLength = count($fields);
for ($i = 0; $i < $fieldsLength; $i += 2) :
$fs .= $fields[$i];
$whereClause .= $fields[$i] . " = '" . $fields[$i + 1] . "'";
if ($i < $fieldsLength - 2) :
$fs .= ",";
$whereClause .= " AND ";
endif;
endfor;
if ($whereClause != "") :
$whereClause = " WHERE " . $whereClause;
endif;
$retValue = FALSE;
$sqlStmt = "SELECT $fs FROM $table $whereClause";
$result = $dbConnection->query($sqlStmt);
if (DB::isError($result)) die ("$PHP_SELF: <br>$sqlStmt<br>" . $result->getMessage());
while ($row = $result->fetch_assoc()):
$retValue = TRUE;
endwhile;
$result->free();
return $retValue;
}
function insertStmt($table,$fields,$dbConnection = "") {
global $db, $PHP_SELF;
if (!is_object($dbConnection) || $dbConnection == "") : $dbConnection = $db; endif;
$fs = "";
$vs = "";
$fieldsLength = count($fields);
for ($i = 0; $i < $fieldsLength; $i += 2) :
$fs .= $fields[$i];
$vs .= "'" . $fields[$i + 1] . "'";
if ($i < $fieldsLength - 2) :
$fs .= ",";
$vs .= ",";
endif;
endfor;
$sqlStmt = "INSERT INTO $table ($fs) VALUES ($vs)";
$res = $dbConnection->query($sqlStmt);
if (DB::isError($res)) die ("$PHP_SELF:<br>$sqlStmt<br>" . $res->getMessage());
return $res;
}
function dbInsert($table, $keyValueArray, $dbConnection = "") {
global $db, $PHP_SELF;
if (!is_object($dbConnection) || $dbConnection == "") : $dbConnection = $db; endif;
$retVal = "";
if ($table != "" && is_array($keyValueArray) && count($keyValueArray) > 0) :
insertStmt($table, $keyValueArray,$dbConnection);
$retVal = getLastInsertId();
endif;
return $retVal;
}
function updateStmt($table,$pKeyName,$pKeyVal,$fields,$whereClause = "",$dbConnection = "") {
global $db, $PHP_SELF;
if (!is_object($dbConnection) || $dbConnection == "") : $dbConnection = $db; endif;
$fs = "";
$fieldsLength = count($fields);
for ($i = 0; $i < $fieldsLength; $i += 2) :
$fs .= $fields[$i] . "='" . $fields[$i + 1] . "'";
if ($i < $fieldsLength - 2) :
$fs .= ", ";
endif;
endfor;
if ($pKeyName != ""):
$sqlStmt = "UPDATE $table SET $fs WHERE $pKeyName = '$pKeyVal'";
if ($whereClause != "") : $sqlStmt .= " AND " . $whereClause ; endif;
else:
$sqlStmt = "UPDATE $table SET $fs WHERE " . $whereClause;
endif;
$res = $dbConnection->query($sqlStmt);
if (DB::isError($res)) die ("$PHP_SELF: <br>$sqlStmt<br>" . $res->getMessage());
return $res;
}
function deleteStmt($table,$whereClause, $dbConnection = "") {
global $db;
if (!is_object($dbConnection) || $dbConnection == "") : $dbConnection = $db; endif;
if ($whereClause != "") :
$sqlStmt = "DELETE FROM $table WHERE $whereClause";
$res = $db->query($sqlStmt);
return $res;
endif;
return FALSE;
}
// Returns last autoincrement-value of previous INSERT/UPDATE
function getLastInsertID($dbConnection = "") {
global $db;
if (!is_object($dbConnection) || $dbConnection == "") : $dbConnection = $db; endif;
$lastInsertId = $dbConnection->getOne("SELECT LAST_INSERT_ID()");
return $lastInsertId;
}
// Gets the connection to the central meta objects table
function getConnectionToMetaDB ($dbName = "meta_object", $tableName = "metaobject") {
global $dbhost, $dblogin, $dbpassword;
// $constExtDbInst = getParameterValue("0", "EXTERNAL_DB_METAOBJECT", "0", "0");
$constExtDbInst = $dbhost;
$db_conn = getDbConnectionSpecial($constExtDbInst, $dbName, $dblogin, $dbpassword);
if ($db_conn == "ERR_DB") :
// Check cascade of replicants
$constExtDbInst = "172.16.0.111:3711";
$db_conn = getDbConnectionSpecial($constExtDbInst, $dbName, $dblogin, $dbpassword);
if ($db_conn == "ERR_DB") :
$constExtDbInst = "172.16.0.109:3711";
$db_conn = getDbConnectionSpecial($constExtDbInst, $dbName, $dblogin, $dbpassword);
if ($db_conn == "ERR_DB") :
$constExtDbInst = "172.16.0.103:3711";
$db_conn = getDbConnectionSpecial($constExtDbInst, $dbName, $dblogin, $dbpassword);
endif;
endif;
// Send info mail
// sendInternalMail("metaobject_db_fail");
endif;
return $db_conn;
}
// Gets all databases and its IPs and ports listed in the central meta objects table
function getGlobalDbEnvironments ($dbName = "meta_object", $tableName = "metaobject") {
$dbhostArray = array();
$db_conn = getConnectionToMetaDB($dbName, $tableName);
if ($db_conn != "ERR_DB") :
$sqlquery = "SELECT mo_mnemonic, mo_value FROM " . $dbName . "." . $tableName . " AS mo WHERE mo_obj_type = 'db' AND mo_mnemonic != ''";
$result = $db_conn->query($sqlquery);
if (DB::isError($result)) die ("$PHP_SELF: " . $result->getMessage());
while ($row = $result->fetch_assoc()):
$dbhostArray[$row["mo_mnemonic"]] = $row["mo_value"];
endwhile;
$result->free();
endif;
return $dbhostArray;
}
// Gets the operational database via connection data of metaobject
function getOperationalDatabase ($moId) {
global $db, $PHP_SELF;
global $dbhost, $dbname, $dblogin, $dbpassword;
$retVal = "";
if ($moId != "" && is_numeric($moId)) :
// $constExtDbInst = getExternalMetaDbInst();
$constExtDbInst = $dbhost;
if ($constExtDbInst != "") :
$db_conn = getDbConnectionSpecial($constExtDbInst, $dbname, $dblogin, $dbpassword);
$tmpSqlQuery = "SELECT mo_value FROM meta_object.metaobject WHERE mo_id = '" . $moId . "' AND mo_obj_type = 'db'";
$result = $db_conn->query($tmpSqlQuery);
while ($row = $result->fetch_assoc()):
$retVal = $row["mo_value"];
endwhile;
$result->free();
endif;
endif;
return $retVal;
}
// Gets XML tag
function getSingleTagContent ($strToParse, $tagBegin, $tagEnd) {
$tagContent = "";
$repeat = TRUE;
while ($repeat && !(strpos($strToParse, $tagBegin) === FALSE) && !(strpos($strToParse, $tagEnd) === FALSE)) :
$pos0 = strpos($strToParse, $tagBegin); // begin of tagBegin (first occurrence)
$pos1 = strpos($strToParse, $tagBegin) + strlen($tagBegin); // end of tagBegin (first occurrence)
$pos2 = strpos($strToParse, $tagEnd); // begin of tagEnd (first occurrence)
$pos3 = strpos($strToParse, $tagEnd) + strlen($tagEnd); // end of tagEnd (first occurrence)
$repeat = FALSE;
if ($pos2 - $pos1 > 0) :
// Get the content of the tag
$tagContent = substr($strToParse, $pos1, $pos2 - $pos1);
endif;
endwhile;
return $tagContent;
};
// Get the actual DATETIME (e.g. according to the scheme needed in MySql)
function getDateTime($mode = "0", $dateTimeArray = "", $formatStr = "") {
$retVal = "";
if ($mode == "0") : $retVal = date("Y-m-d H:i:s"); endif; // 2003-03-10 17:16:17
if ($mode == "1") : $retVal = date("Ymd"); endif; // 20030310
if ($mode == "2") : $retVal = date("m.d.y"); endif; // 03.10.01
if ($mode == "3") : $retVal = date("Y-m-d"); endif; // 2003-03-10
if ($mode == "4") : $retVal = date("H:i:s"); endif; // 17:16:17
if ($mode == "5") : $retVal = date("d.m.Y"); endif; // 10.03.2003
if ($mode == "6") : $retVal = date("YmdHis"); endif; // 20030310171617
if ($mode == "7") : $retVal = date("dmY"); endif; // 31122003
if ($mode == "day") : $retVal = date("d"); endif; // 01 .. 31
if ($mode == "month") : $retVal = date("m"); endif; // 01 .. 12
if ($mode == "year") : $retVal = date("Y"); endif; // 2003, ...
if ($mode == "hour") : $retVal = date("H"); endif; // 00 .. 11
if ($mode == "minute") : $retVal = date("i"); endif; // 00 .. 59
if ($mode == "second") : $retVal = date("s"); endif; // 00 .. 59
if ($mode == "now") : $retVal = date("YmdHis", mktime(date("H"),date("i"),date("s"),date("m"),date("d"),date("y"))); endif; // 20090807105959
if ($mode == "day_tomorrow") : $retVal = date("d",mktime(0,0,0,date("m"),date("d")+1,date("Y"))); endif; // 01 .. 31
if ($mode == "month_tomorrow") : $retVal = date("m",mktime(0,0,0,date("m"),date("d")+1,date("Y"))); endif; // 01 .. 12
if ($mode == "year_tomorrow") : $retVal = date("Y",mktime(0,0,0,date("m"),date("d")+1,date("Y"))); endif; // 2003, ...
if ($mode == "day_yesterday") : $retVal = date("d",mktime(0,0,0,date("m"),date("d")-1,date("Y"))); endif; // 01 .. 31
if ($mode == "month_yesterday") : $retVal = date("m",mktime(0,0,0,date("m"),date("d")-1,date("Y"))); endif; // 01 .. 12
if ($mode == "year_yesterday") : $retVal = date("Y",mktime(0,0,0,date("m"),date("d")-1,date("Y"))); endif; // 2003, ...
if ($mode == "date_plus_offset") :
$retVal = date($formatStr, mktime(0,0,0,date("m")+$dateTimeArray[0],date("d")+$dateTimeArray[1],date("Y")+$dateTimeArray[2]));
endif;
if ($mode == "datetime_plus_offset") :
$retVal = date($formatStr, mktime(date("H")+$dateTimeArray[0],date("i")+$dateTimeArray[1],date("s")+$dateTimeArray[2],date("m")+$dateTimeArray[3],date("d")+$dateTimeArray[4],date("Y")+$dateTimeArray[5]));
endif;
if ($mode == "format" && $dateTimeArray != "" && $formatStr != "") :
// int mktime ( [int Stunde [, int Minute [, int Sekunde [, int Monat [, int Tag [, int Jahr [, int is_dst]]]]]]])
$retVal = date($formatStr, mktime($dateTimeArray[0],$dateTimeArray[1],$dateTimeArray[2],$dateTimeArray[3],$dateTimeArray[4],$dateTimeArray[5]));
endif;
return $retVal;
}
?>

View File

@@ -0,0 +1,333 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Richard Heyes <richard@phpguru.org> |
// +----------------------------------------------------------------------+
/**
*
* Raw mime encoding class
*
* What is it?
* This class enables you to manipulate and build
* a mime email from the ground up.
*
* Why use this instead of mime.php?
* mime.php is a userfriendly api to this class for
* people who aren't interested in the internals of
* mime mail. This class however allows full control
* over the email.
*
* Eg.
*
* // Since multipart/mixed has no real body, (the body is
* // the subpart), we set the body argument to blank.
*
* $params['content_type'] = 'multipart/mixed';
* $email = new Mail_mimePart('', $params);
*
* // Here we add a text part to the multipart we have
* // already. Assume $body contains plain text.
*
* $params['content_type'] = 'text/plain';
* $params['encoding'] = '7bit';
* $text = $email->addSubPart($body, $params);
*
* // Now add an attachment. Assume $attach is
* the contents of the attachment
*
* $params['content_type'] = 'application/zip';
* $params['encoding'] = 'base64';
* $params['disposition'] = 'attachment';
* $params['dfilename'] = 'example.zip';
* $attach =& $email->addSubPart($body, $params);
*
* // Now build the email. Note that the encode
* // function returns an associative array containing two
* // elements, body and headers. You will need to add extra
* // headers, (eg. Mime-Version) before sending.
*
* $email = $message->encode();
* $email['headers'][] = 'Mime-Version: 1.0';
*
*
* Further examples are available at http://www.phpguru.org
*
* TODO:
* - Set encode() to return the $obj->encoded if encode()
* has already been run. Unless a flag is passed to specifically
* re-build the message.
*
* @author Richard Heyes <richard@phpguru.org>
* @version $Revision: 1.3 $
* @package Mail
*/
class Mail_mimePart {
/**
* The encoding type of this part
* @var string
*/
var $_encoding;
/**
* An array of subparts
* @var array
*/
var $_subparts;
/**
* The output of this part after being built
* @var string
*/
var $_encoded;
/**
* Headers for this part
* @var array
*/
var $_headers;
/**
* The body of this part (not encoded)
* @var string
*/
var $_body;
/**
* Constructor.
*
* Sets up the object.
*
* @param $body - The body of the mime part if any.
* @param $params - An associative array of parameters:
* content_type - The content type for this part eg multipart/mixed
* encoding - The encoding to use, 7bit, 8bit, base64, or quoted-printable
* cid - Content ID to apply
* disposition - Content disposition, inline or attachment
* dfilename - Optional filename parameter for content disposition
* description - Content description
* charset - Character set to use
* @access public
*/
function Mail_mimePart($body = '', $params = array())
{
if (!defined('MAIL_MIMEPART_CRLF')) {
define('MAIL_MIMEPART_CRLF', defined('MAIL_MIME_CRLF') ? MAIL_MIME_CRLF : "\r\n", TRUE);
}
foreach ($params as $key => $value) {
switch ($key) {
case 'content_type':
$headers['Content-Type'] = $value . (isset($charset) ? '; charset="' . $charset . '"' : '');
break;
case 'encoding':
$this->_encoding = $value;
$headers['Content-Transfer-Encoding'] = $value;
break;
case 'cid':
$headers['Content-ID'] = '<' . $value . '>';
break;
case 'disposition':
$headers['Content-Disposition'] = $value . (isset($dfilename) ? '; filename="' . $dfilename . '"' : '');
break;
case 'dfilename':
if (isset($headers['Content-Disposition'])) {
$headers['Content-Disposition'] .= '; filename="' . $value . '"';
} else {
$dfilename = $value;
}
break;
case 'description':
$headers['Content-Description'] = $value;
break;
case 'charset':
if (isset($headers['Content-Type'])) {
$headers['Content-Type'] .= '; charset="' . $value . '"';
} else {
$charset = $value;
}
break;
}
}
// Default content-type
if (!isset($headers['Content-Type'])) {
$headers['Content-Type'] = 'text/plain';
}
//Default encoding
if (!isset($this->_encoding)) {
$this->_encoding = '7bit';
}
// Assign stuff to member variables
$this->_encoded = array();
$this->_headers = $headers;
$this->_body = $body;
}
/**
* encode()
*
* Encodes and returns the email. Also stores
* it in the encoded member variable
*
* @return An associative array containing two elements,
* body and headers. The headers element is itself
* an indexed array.
* @access public
*/
function encode()
{
$encoded =& $this->_encoded;
if (!empty($this->_subparts)) {
srand((double)microtime()*1000000);
$boundary = '=_' . md5(uniqid(rand()) . microtime());
$this->_headers['Content-Type'] .= ';' . MAIL_MIMEPART_CRLF . "\t" . 'boundary="' . $boundary . '"';
// Add body parts to $subparts
for ($i = 0; $i < count($this->_subparts); $i++) {
$headers = array();
$tmp = $this->_subparts[$i]->encode();
foreach ($tmp['headers'] as $key => $value) {
$headers[] = $key . ': ' . $value;
}
$subparts[] = implode(MAIL_MIMEPART_CRLF, $headers) . MAIL_MIMEPART_CRLF . MAIL_MIMEPART_CRLF . $tmp['body'];
}
$encoded['body'] = '--' . $boundary . MAIL_MIMEPART_CRLF .
implode('--' . $boundary . MAIL_MIMEPART_CRLF, $subparts) .
'--' . $boundary.'--' . MAIL_MIMEPART_CRLF;
} else {
$encoded['body'] = $this->_getEncodedData($this->_body, $this->_encoding) . MAIL_MIMEPART_CRLF;
}
// Add headers to $encoded
$encoded['headers'] =& $this->_headers;
return $encoded;
}
/**
* &addSubPart()
*
* Adds a subpart to current mime part and returns
* a reference to it
*
* @param $body The body of the subpart, if any.
* @param $params The parameters for the subpart, same
* as the $params argument for constructor.
* @return A reference to the part you just added. It is
* crucial if using multipart/* in your subparts that
* you use =& in your script when calling this function,
* otherwise you will not be able to add further subparts.
* @access public
*/
function &addSubPart($body, $params)
{
$this->_subparts[] = new Mail_mimePart($body, $params);
return $this->_subparts[count($this->_subparts) - 1];
}
/**
* _getEncodedData()
*
* Returns encoded data based upon encoding passed to it
*
* @param $data The data to encode.
* @param $encoding The encoding type to use, 7bit, base64,
* or quoted-printable.
* @access private
*/
function _getEncodedData($data, $encoding)
{
switch ($encoding) {
case '8bit':
case '7bit':
return $data;
break;
case 'quoted-printable':
return $this->_quotedPrintableEncode($data);
break;
case 'base64':
return rtrim(chunk_split(base64_encode($data), 76, MAIL_MIMEPART_CRLF));
break;
default:
return $data;
}
}
/**
* quoteadPrintableEncode()
*
* Encodes data to quoted-printable standard.
*
* @param $input The data to encode
* @param $line_max Optional max line length. Should
* not be more than 76 chars
*
* @access private
*/
function _quotedPrintableEncode($input , $line_max = 76)
{
$lines = preg_split("/\r?\n/", $input);
$eol = MAIL_MIMEPART_CRLF;
$escape = '=';
$output = '';
while(list(, $line) = each($lines)){
$linlen = strlen($line);
$newline = '';
for ($i = 0; $i < $linlen; $i++) {
$char = substr($line, $i, 1);
$dec = ord($char);
if (($dec == 32) AND ($i == ($linlen - 1))){ // convert space at eol only
$char = '=20';
} elseif($dec == 9) {
; // Do nothing if a tab.
} elseif(($dec == 61) OR ($dec < 32 ) OR ($dec > 126)) {
$char = $escape . strtoupper(sprintf('%02s', dechex($dec)));
}
if ((strlen($newline) + strlen($char)) >= $line_max) { // MAIL_MIMEPART_CRLF is not counted
$output .= $newline . $escape . $eol; // soft line break; " =\r\n" is okay
$newline = '';
}
$newline .= $char;
} // end of for
$output .= $newline . $eol;
}
$output = substr($output, 0, -1 * strlen($eol)); // Don't want last crlf
return $output;
}
} // End of class
?>

View File

@@ -0,0 +1,31 @@
<?php
$req = "";
$req .= "<xml></xml>";
$req = urlencode($req);
?>
<html>
<head>
</head>
<body>
<form name="UPLOADER_test" action="https://app.assecutor.de/upload/uploader_LD.php" method="post">
<input type="hidden" name="filedata" value="<?php echo "TESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTEST" ?>">
<input type="hidden" name="filename" value="<?php echo "1481358302357.jpg" ?>">
<input type="hidden" name="metadata" value="<?php echo "<metadata><context>lda</context><acc>test_ht:irens01</acc><sess_key>40867564c5cc8ed66f0d7ea35b0c914663b6ee9af6ebc6aeb8d632bbc41216fb</sess_key><comm>470011</comm></metadata>" ?>">
<input type="submit" value="Senden POST">
</form>
</body>
</html>

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,359 @@
<?php
/**
* Filename.......: class.smtp.inc
* Project........: SMTP Class
* Version........: 1.0.5
* Last Modified..: 21 December 2001
*/
define('SMTP_STATUS_NOT_CONNECTED', 1, TRUE);
define('SMTP_STATUS_CONNECTED', 2, TRUE);
class smtp{
var $authenticated;
var $connection;
var $recipients;
var $headers;
var $timeout;
var $errors;
var $status;
var $body;
var $from;
var $host;
var $port;
var $helo;
var $auth;
var $user;
var $pass;
/**
* Constructor function. Arguments:
* $params - An assoc array of parameters:
*
* host - The hostname of the smtp server Default: localhost
* port - The port the smtp server runs on Default: 25
* helo - What to send as the HELO command Default: localhost
* (typically the hostname of the
* machine this script runs on)
* auth - Whether to use basic authentication Default: FALSE
* user - Username for authentication Default: <blank>
* pass - Password for authentication Default: <blank>
* timeout - The timeout in seconds for the call Default: 5
* to fsockopen()
*/
function smtp($params = array()){
if(!defined('CRLF'))
define('CRLF', "\r\n", TRUE);
$this->authenticated = FALSE;
$this->timeout = 5;
$this->status = SMTP_STATUS_NOT_CONNECTED;
$this->host = 'localhost';
$this->port = 25;
$this->helo = 'localhost';
$this->auth = FALSE;
$this->user = '';
$this->pass = '';
$this->errors = array();
foreach($params as $key => $value){
$this->$key = $value;
}
}
/**
* Connect function. This will, when called
* statically, create a new smtp object,
* call the connect function (ie this function)
* and return it. When not called statically,
* it will connect to the server and send
* the HELO command.
*/
function &connect($params = array()){
if(!isset($this->status)){
$obj = new smtp($params);
if($obj->connect()){
$obj->status = SMTP_STATUS_CONNECTED;
}
return $obj;
}else{
$this->connection = fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout);
if(function_exists('socket_set_timeout')){
@socket_set_timeout($this->connection, 5, 0);
}
$greeting = $this->get_data();
if(is_resource($this->connection)){
return $this->auth ? $this->ehlo() : $this->helo();
}else{
$this->errors[] = 'Failed to connect to server: '.$errstr;
return FALSE;
}
}
}
/**
* Function which handles sending the mail.
* Arguments:
* $params - Optional assoc array of parameters.
* Can contain:
* recipients - Indexed array of recipients
* from - The from address. (used in MAIL FROM:),
* this will be the return path
* headers - Indexed array of headers, one header per array entry
* body - The body of the email
* It can also contain any of the parameters from the connect()
* function
*/
function send($params = array()){
foreach($params as $key => $value){
$this->set($key, $value);
}
if($this->is_connected()){
// Do we auth or not? Note the distinction between the auth variable and auth() function
if($this->auth AND !$this->authenticated){
if(!$this->auth())
return FALSE;
}
$this->mail($this->from);
if(is_array($this->recipients))
foreach($this->recipients as $value)
$this->rcpt($value);
else
$this->rcpt($this->recipients);
if(!$this->data())
return FALSE;
// Transparency
$headers = str_replace(CRLF.'.', CRLF.'..', trim(implode(CRLF, $this->headers)));
$body = str_replace(CRLF.'.', CRLF.'..', $this->body);
$body = $body[0] == '.' ? '.'.$body : $body;
$this->send_data($headers);
$this->send_data('');
$this->send_data($body);
$this->send_data('.');
$result = (substr(trim($this->get_data()), 0, 3) === '250');
//$this->rset();
return $result;
}else{
$this->errors[] = 'Not connected!';
return FALSE;
}
}
/**
* Function to implement HELO cmd
*/
function helo(){
if(is_resource($this->connection)
AND $this->send_data('HELO '.$this->helo)
AND substr(trim($error = $this->get_data()), 0, 3) === '250' ){
return TRUE;
}else{
$this->errors[] = 'HELO command failed, output: ' . trim(substr(trim($error),3));
return FALSE;
}
}
/**
* Function to implement EHLO cmd
*/
function ehlo(){
if(is_resource($this->connection)
AND $this->send_data('EHLO '.$this->helo)
AND substr(trim($error = $this->get_data()), 0, 3) === '250' ){
return TRUE;
}else{
$this->errors[] = 'EHLO command failed, output: ' . trim(substr(trim($error),3));
return FALSE;
}
}
/**
* Function to implement RSET cmd
*/
function rset(){
if(is_resource($this->connection)
AND $this->send_data('RSET')
AND substr(trim($error = $this->get_data()), 0, 3) === '250' ){
return TRUE;
}else{
$this->errors[] = 'RSET command failed, output: ' . trim(substr(trim($error),3));
return FALSE;
}
}
/**
* Function to implement QUIT cmd
*/
function quit(){
if(is_resource($this->connection)
AND $this->send_data('QUIT')
AND substr(trim($error = $this->get_data()), 0, 3) === '221' ){
fclose($this->connection);
$this->status = SMTP_STATUS_NOT_CONNECTED;
return TRUE;
}else{
$this->errors[] = 'QUIT command failed, output: ' . trim(substr(trim($error),3));
return FALSE;
}
}
/**
* Function to implement AUTH cmd
*/
function auth(){
if(is_resource($this->connection)
AND $this->send_data('AUTH LOGIN')
AND substr(trim($error = $this->get_data()), 0, 3) === '334'
AND $this->send_data(base64_encode($this->user)) // Send username
AND substr(trim($error = $this->get_data()),0,3) === '334'
AND $this->send_data(base64_encode($this->pass)) // Send password
AND substr(trim($error = $this->get_data()),0,3) === '235' ){
$this->authenticated = TRUE;
return TRUE;
}else{
$this->errors[] = 'AUTH command failed: ' . trim(substr(trim($error),3));
return FALSE;
}
}
/**
* Function that handles the MAIL FROM: cmd
*/
function mail($from){
if($this->is_connected()
AND $this->send_data('MAIL FROM:<'.$from.'>')
AND substr(trim($this->get_data()), 0, 2) === '250' ){
return TRUE;
}else
return FALSE;
}
/**
* Function that handles the RCPT TO: cmd
*/
function rcpt($to){
if($this->is_connected()
AND $this->send_data('RCPT TO:<'.$to.'>')
AND substr(trim($error = $this->get_data()), 0, 2) === '25' ){
return TRUE;
}else{
$this->errors[] = trim(substr(trim($error), 3));
return FALSE;
}
}
/**
* Function that sends the DATA cmd
*/
function data(){
if($this->is_connected()
AND $this->send_data('DATA')
AND substr(trim($error = $this->get_data()), 0, 3) === '354' ){
return TRUE;
}else{
$this->errors[] = trim(substr(trim($error), 3));
return FALSE;
}
}
/**
* Function to determine if this object
* is connected to the server or not.
*/
function is_connected(){
return (is_resource($this->connection) AND ($this->status === SMTP_STATUS_CONNECTED));
}
/**
* Function to send a bit of data
*/
function send_data($data){
if(is_resource($this->connection)){
return fwrite($this->connection, $data.CRLF, strlen($data)+2);
}else
return FALSE;
}
/**
* Function to get data.
*/
function &get_data(){
$return = '';
$line = '';
$loops = 0;
if(is_resource($this->connection)){
while((strpos($return, CRLF) === FALSE OR substr($line,3,1) !== ' ') AND $loops < 100){
$line = fgets($this->connection, 512);
$return .= $line;
$loops++;
}
return $return;
}else
return FALSE;
}
/**
* Sets a variable
*/
function set($var, $value){
$this->$var = $value;
return TRUE;
}
} // End of class
?>

View File

@@ -0,0 +1,261 @@
<?php
include_once ("mc_gen_include.inc.php");
include_once ("htmlMimeMail.php");
require_once "DB.php";
// Get absolute system path (e.g. "/data0/srv/www/htsdocs/xxxx")
function getAbsoluteSystemPath () {
$dirName = dirname(__FILE__);
$dirName = str_replace("\\", "/", $dirName);
$lastSlashPos = strrpos($dirName,"/");
$path = substr($dirName, 0, $lastSlashPos);
return $path;
}
// Triggers the script for sending an internal mail
function sendInternalMail ($errMsg) {
if ($errMsg != "") :
$path = getAbsoluteSystemPath();
$result = "";
// $cmd = "php " . $path . "/include/automailer_internal.php comegetsome97531 " . $errMsg . " &";
$cmd = "php automailer_internal.php comegetsome97531 \"" . $errMsg . "\" &";
exec($cmd . " > /dev/null &");
endif;
}
// *****************************************************************************
// Current timestamp
$currentTime = date("Y-m-d H:i:s");
// Define start time for b2b_object only !!!!
$constAmStarttimeInDays = 30;
$startTime = getDateTime("datetime_plus_offset", array(0,0,0,0,-($constAmStarttimeInDays),0), "Y-m-d") . " 00:00:00";
$whereClauseStarttime = " bo_createtime >= '" . $startTime . "' AND ";
getSecHttpVars("0", array("filedata", "filename", "metadata"));
//writeToFile("uploader_post.log", "[" . $currentTime . " | " . trim($_SERVER['REMOTE_ADDR']) . "]\n" . var_export($HTTP_POST_VARS, true) . "\n");
//writeToFile("uploader_post_raw.log", "[" . $currentTime . " | " . trim($_SERVER['REMOTE_ADDR']) . "]\n" . file_get_contents("php://input") . "\n");
// DB-Config
$dbhost = "172.16.0.111:3711"; // EXTERNAL_DB_METAOBJECT
$dblogin = "phoenix";
$dbpassword = "AdAdgkS13";
$dbname = "phoenix";
$dsn = "mysql://$dblogin:$dbpassword@$dbhost/$dbname";
$db = DB::connect($dsn, false);
if (mysql_errno())
writeToFile("upload.log", "DB-Error:" . " | " . $currentTime . " | " . date("Y-m-d H:i:s") . " | " . trim($_SERVER['REMOTE_ADDR']) . " | " . $filename . mysql_error());
if (DB::isError($db))
die ("$PHP_SELF: " . $db->getMessage());
$db->setFetchMode(DB_FETCHMODE_ASSOC);
$db->query('SET NAMES latin1');
// calling client IP
$currentClientIP = trim($_SERVER['REMOTE_ADDR']);
$opState = "OK";
$filename = trim($filename);
// 30.08.2016 CA: "Filename empty" and "No file data" shall be ignored from now on because those data will never ever be sent correctly
if ($filename == "")
$filename = trim($_SERVER['REMOTE_ADDR']) . "_" . date("YmdHis") . ".jpg";
if ($filedata == "")
$filedata = "No file data";
if ($currentClientIP != "") :
if ($filename != "") :
if ($filedata != "") :
// Set and check upload counter for AMOK mail
if ($currentClientIP != "" && $filename != "") :
if (!existsEntry("temp.app_upload",array("appu_ip",$currentClientIP,"appu_file",$filename))) :
insertStmt("temp.app_upload", array("appu_ip", $currentClientIP, "appu_file", $filename, "appu_cnt", "1"));
else :
$cnt = getFieldValueFromClause("temp.app_upload","appu_cnt","appu_ip = '" . $currentClientIP . "' AND appu_file = '" . $filename . "'");
$cnt++;
updateStmt("temp.app_upload","appu_ip",$currentClientIP,array("appu_cnt",$cnt),"appu_file = '" . $filename . "'");
endif;
$cnt = getFieldValueFromClause("temp.app_upload","appu_cnt","appu_ip = '" . $currentClientIP . "' AND appu_file = '" . $filename . "'");
if ($cnt == "") : $cnt = "0"; endif;
if (($cnt % 10) == 0) :
sendInternalMail("AMOK-FILE " . $filename . " [" . $currentClientIP . "] UPLOAD-COUNTER: " . $cnt);
endif;
endif;
// **** Write data into DB ****
// Get external databases (e.g. APP properties, mobile data, etc.)
$dbhostArray = getGlobalDbEnvironments();
$dbhostArrayLen = count($dbhostArray);
$dbConnectionArray = array();
if ($dbhostArrayLen > 0) :
$dbConnectionArray["app_property"] = getDbConnectionSpecial($dbhostArray["as_intern"], "sysadmin", $dblogin, $dbpassword);
if ($dbConnectionArray["app_property"] != "") :
// Get cust_id, hq_id and usr_id from table conf_prop
$sqlquery = "SELECT cust_id, hq_id, usr_id FROM sysadmin.conf_prop WHERE prop_id = '1' AND cp_val = '" . $currentClientIP . "'";
$result = $dbConnectionArray["app_property"]->query($sqlquery);
if (DB::isError($result)) die ("$PHP_SELF: " . $result->getMessage());
$confPropRowMatched = false;
while ($row = $result->fetch_assoc()):
$custId = $row["cust_id"];
$hqId = $row["hq_id"];
$usrId = $row["usr_id"];
$confPropRowMatched = true;
endwhile;
$result->free();
if ($confPropRowMatched) :
// Get tr_id from "metadata"
// <metadata><context>pp</context><type>jpg</type><cust>moebel_live</cust><jb_id>380311</jb_id></metadata>
$xmlContext = getSingleTagContent($metadata, "<context>", "</context>");
$xmlType = getSingleTagContent($metadata, "<type>", "</type>");
$xmlCust = getSingleTagContent($metadata, "<cust>", "</cust>");
$xmlJbId = getSingleTagContent($metadata, "<jb_id>", "</jb_id>");
// Get special database from information in
$moMnemonicTargetDb = getOperationalDatabase($custId);
if ($moMnemonicTargetDb != "") :
$remDb = $db;
$db = getDbConnectionSpecial($moMnemonicTargetDb, $dbname, $dblogin, $dbpassword);
if ($custId == "3" || $custId == "103") :
// Decode BASE64 and uncompress
$filedata = base64_decode($filedata);
$filedata = gzinflate($filedata);
// Get cr_id from usr_id
$crId = getFieldValueFromId("phoenix.courier","usr_id", $usrId,"cr_id");
if ($crId != "" && $crId != "0") :
// Generate output file by writing $filedata
$path = "../upload/mbl_foto/";
// if (file_exists($path . $filename)) :
// unlink($path . $filename);
// endif;
writeToFile($path . $filename, $filedata);
// sleep(2);
// if (!file_exists($path . $filename)) :
// $opState = "ERR 113 : No bo_ext_id0 ID!";
// endif;
// Get b2b object
$boId = getFieldValueFromClause("phoenix_log.b2b_objects", "bo_id", $whereClauseStarttime . "bo_type = '101' AND bo_ext_id1=" . $crId . " AND bo_obj_data = '" . $filename . "'");
if ($boId != "" && $boId != "0") :
$res = updateStmt("phoenix_log.b2b_objects","bo_ext_id0",$boId,array("bo_state", "1"), "bo_type = '105'");
/*
if ($db->affected_rows = 0) :
$opState = "ERR 112 : No update by 105!";
endif;
*/
$boIdNew101 = $boId; // For error handling ONLY
else :
$sqlStmt = "INSERT INTO phoenix_log.b2b_objects (bo_ver,bo_type,bo_state,bo_ext_id0,bo_ext_id1,bo_ext_id2,bo_obj_data,bo_createtime)" .
" VALUES ('0','101','1','0','$crId','0','$filename','$currentTime')";
$res = $db->query($sqlStmt);
if (DB::isError($res)) : die ("$PHP_SELF: " . $res->getMessage()); endif;
$boIdNew101 = getLastInsertID();
// $opState = "ERR 111 : No bo_ext_id0 ID!";
endif;
else :
// $opState = "ERR 110 : No courier ID!";
endif;
elseif ($custId == "6" || $custId == "106" || $custId == "11") :
// Decode BASE64 and uncompress
$filedata = base64_decode($filedata);
$filedata = gzinflate($filedata);
$filedata = base64_encode($filedata);
// writeToFile("debug.log", $filedata);
$filedataArray = str_split($filedata, 32768); // 32K
$filedataArrayLen = count($filedataArray);
for ($i = 0; $i < $filedataArrayLen; $i++) :
$tmpChunk = $filedataArray[$i];
$filedataArray[$i] = "<![CDATA[" . $tmpChunk . "]]>";
endfor;
// writeToFile("debug2.log", $tmpOut);
// Write main file
// writeToFile($filename, $filedata);
// $bo_ext_id0 = "";
$bo_ext_id0 = $xmlJbId;
/*
if ($xmlCust == "moebel_live") :
if ($xmlJbId != "" && is_numeric($xmlJbId)) :
$bo_ext_id0 = getFieldValueFromClause("phoenix.tour","tr_id","jb_id = '" . $xmlJbId . "' AND tr_sort = '2'"); // equals tr_id
endif;
endif;
*/
// **** Insert data sets into b2b_objects ***
if (!existsEntry("phoenix_log.b2b_objects",array("bo_type","101","bo_ext_id0",$bo_ext_id0,"bo_obj_data",$filename))) :
// Insert "101"
$sqlStmt = "INSERT INTO phoenix_log.b2b_objects (bo_ver,bo_type,bo_state,bo_ext_id0,bo_ext_id1,bo_ext_id2,bo_obj_data,bo_createtime)" .
" VALUES ('0','101','0','$bo_ext_id0','$usrId','0','$filename','$currentTime')";
$res = $db->query($sqlStmt);
if (DB::isError($res)) : die ("$PHP_SELF: " . $res->getMessage()); endif;
$boIdNew101 = getLastInsertID();
// Insert "102"
for ($i = 0; $i < $filedataArrayLen; $i++) :
$sqlStmt = "INSERT INTO phoenix_log.b2b_objects (bo_ver,bo_type,bo_state,bo_ext_id0,bo_ext_id1,bo_ext_id2,bo_obj_data,bo_createtime)" .
" VALUES ('0','102','0','$boIdNew101','$usrId','$i','$filedataArray[$i]','$currentTime')";
$res = $db->query($sqlStmt);
if (DB::isError($res)) : die ("$PHP_SELF: " . $res->getMessage()); endif;
$boIdNew102 = getLastInsertID();
endfor;
endif;
endif;
$db = $remDb;
else :
$opState = "ERR 107 : No target database specified!";
endif;
else :
$opState = "ERR 106 : No row in table conf_prop matched!";
endif;
else :
$opState = "ERR 105 : metaobject not reachable!";
endif;
else :
$opState = "ERR 104 : No global environment definitions found!";
endif;
else :
$opState = "ERR 103 : No file data!";
endif;
else :
$opState = "ERR 102 : Filename empty!";
endif;
else :
$opState = "ERR 101 : Unknown client IP!";
endif;
// Write metadata to log
$logFilename = "upload.log";
if ($custId != "" && is_numeric($custId)) :
$logFilename = "upload_" . $custId . ".log";
endif;
writeToFile($logFilename, $custId . " | " . $currentTime . " | " . date("Y-m-d H:i:s") . " | OLD_VERSION | " . $currentClientIP . " | " . $filename . " | " . $metadata . " | " . $opState . " | " . $boIdNew101 . " | " . $boIdNew102);
// Write file data by error
if (($opState != "OK" || ($boIdNew101 == "" || !is_numeric($boIdNew101))) && $filename != "" && $filedata != "") :
$errPath = "../upload/photos_err/";
writeToFile($errPath . $filename, $filedata);
$opState = "OK";
endif;
// Response
//echo $opState;
// 01.09.2016 CA: always respond "OK" because the data will never be sent correctly if they are wrong
echo "OK";
?>

View File

@@ -0,0 +1,378 @@
<?php
include_once ("mc_gen_include.inc.php");
include_once ("htmlMimeMail.php");
require_once "DB.php";
// Get absolute system path (e.g. "/data0/srv/www/htsdocs/xxxx")
function getAbsoluteSystemPath () {
$dirName = dirname(__FILE__);
$dirName = str_replace("\\", "/", $dirName);
$lastSlashPos = strrpos($dirName,"/");
$path = substr($dirName, 0, $lastSlashPos);
return $path;
}
// Triggers the script for sending an internal mail
function sendInternalMail ($errMsg) {
if ($errMsg != "") :
$path = getAbsoluteSystemPath();
$result = "";
// $cmd = "php " . $path . "/include/automailer_internal.php comegetsome97531 " . $errMsg . " &";
$cmd = "php automailer_internal.php comegetsome97531 \"" . $errMsg . "\" &";
exec($cmd . " > /dev/null &");
endif;
}
// *****************************************************************************
// Current timestamp
$currentTime = date("Y-m-d H:i:s");
$currentDateYesterday = getDateTime("date_plus_offset", array(0,-1,0), $formatStr = "Y-m-d");
// Define start time for b2b_object only !!!!
$constAmStarttimeInDays = 30;
$startTime = getDateTime("datetime_plus_offset", array(0,0,0,0,-($constAmStarttimeInDays),0), "Y-m-d") . " 00:00:00";
$whereClauseStarttime = " bo_createtime >= '" . $startTime . "' AND ";
getSecHttpVars("0", array("filedata", "filename", "metadata"));
writeToFile("uploader_post.log", "[" . $currentTime . " | " . trim($_SERVER['REMOTE_ADDR']) . "]\n" . var_export($HTTP_POST_VARS, true) . "\n");
writeToFile("uploader_post_raw.log", "[" . $currentTime . " | " . trim($_SERVER['REMOTE_ADDR']) . "]\n" . file_get_contents("php://input") . "\n");
// DB-Config
$dbhost = "172.16.0.111:3711"; // EXTERNAL_DB_METAOBJECT
$dblogin = "phoenix";
$dbpassword = "AdAdgkS13";
$dbname = "phoenix";
$dsn = "mysql://$dblogin:$dbpassword@$dbhost/$dbname";
$db = DB::connect($dsn, false);
if (mysql_errno())
writeToFile("upload.log", "DB-Error:" . " | " . $currentTime . " | " . date("Y-m-d H:i:s") . " | " . trim($_SERVER['REMOTE_ADDR']) . " | " . $filename . mysql_error());
if (DB::isError($db))
die ("$PHP_SELF: " . $db->getMessage());
$db->setFetchMode(DB_FETCHMODE_ASSOC);
$db->query('SET NAMES latin1');
// calling client IP
$currentClientIP = trim($_SERVER['REMOTE_ADDR']);
$opState = "OK";
$filename = trim($filename);
$semaphorKey = "automailer";
$semaphorLiveTime = 120;
// 30.08.2016 CA: "Filename empty" and "No file data" shall be ignored from now on because those data will never ever be sent correctly
if ($filename == "")
$filename = trim($_SERVER['REMOTE_ADDR']) . "_" . date("YmdHis") . ".jpg";
if ($filedata == "")
$filedata = "No file data";
if ($currentClientIP != "") :
if ($filename != "") :
if ($filedata != "") :
// Set and check upload counter for AMOK mail
if ($currentClientIP != "" && $filename != "") :
if (!existsEntry("temp.app_upload",array("appu_ip",$currentClientIP,"appu_file",$filename))) :
insertStmt("temp.app_upload", array("appu_ip", $currentClientIP, "appu_file", $filename, "appu_cnt", "1"));
else :
$cnt = getFieldValueFromClause("temp.app_upload","appu_cnt","appu_ip = '" . $currentClientIP . "' AND appu_file = '" . $filename . "'");
$cnt++;
updateStmt("temp.app_upload","appu_ip",$currentClientIP,array("appu_cnt",$cnt),"appu_file = '" . $filename . "'");
endif;
$cnt = getFieldValueFromClause("temp.app_upload","appu_cnt","appu_ip = '" . $currentClientIP . "' AND appu_file = '" . $filename . "'");
if ($cnt == "") : $cnt = "0"; endif;
if (($cnt % 10) == 0) :
sendInternalMail("AMOK-FILE " . $filename . " [" . $currentClientIP . "] UPLOAD-COUNTER: " . $cnt);
endif;
endif;
// **** Write data into DB ****
// Get external databases (e.g. APP properties, mobile data, etc.)
$dbhostArray = getGlobalDbEnvironments();
$dbhostArrayLen = count($dbhostArray);
$dbConnectionArray = array();
if ($dbhostArrayLen > 0) :
$dbConnectionArray["app_property"] = getDbConnectionSpecial($dbhostArray["as_intern"], "sysadmin", $dblogin, $dbpassword);
if ($dbConnectionArray["app_property"] != "") :
$confPropRowMatched = false;
// Get tr_id from "metadata"
// <metadata><context>pp</context><type>jpg</type><cust>moebel_live</cust><jb_id>380311</jb_id></metadata>
// <metadata><context>ap</context><type>jpg</type><cust>htm</cust><jb_id>380311</jb_id></metadata>
// <metadata><context>lda</context><acc>HB105</acc><sess_key>77638762387464942387498723</sess_key><comm>77747888</comm></metadata>
// <metadata><context>tour</context><jb_id>....</jb_id><tr_id>....</tr_id></metadata>
$xmlContext = getSingleTagContent($metadata, "<context>", "</context>");
$xmlType = getSingleTagContent($metadata, "<type>", "</type>");
// $xmlCust = getSingleTagContent($metadata, "<cust>", "</cust>");
$xmlJbId = getSingleTagContent($metadata, "<jb_id>", "</jb_id>");
$xmlTrId = getSingleTagContent($metadata, "<tr_id>", "</tr_id>");
// $debugMode = false;
// $xmlDebug = getSingleTagContent($metadata, "<debug>", "</debug>");
// if ($xmlDebug != "") :
$debugMode = true;
// endif;
if ($xmlContext == "lda") :
$xmlAcc = getSingleTagContent($metadata, "<acc>", "</acc>");
$xmlSessKey = getSingleTagContent($metadata, "<sess_key>", "</sess_key>");
$xmlComm = getSingleTagContent($metadata, "<comm>", "</comm>");
$xmlComm = trim($xmlComm); // !!!!
$custId = getFieldValueFromId("temp.user_session","us_key", $xmlSessKey,"cust_id",$dbConnectionArray["app_property"]);
$usrId = getFieldValueFromId("temp.user_session","us_key", $xmlSessKey,"usr_id",$dbConnectionArray["app_property"]);
$confPropRowMatched = true; // No entry in conf_prop, because of LDA mode, but ok to proceed!
else:
// Get cust_id, hq_id and usr_id from table conf_prop
$sqlquery = "SELECT cust_id, hq_id, usr_id FROM sysadmin.conf_prop WHERE prop_id = '1' AND cp_val = '" . $currentClientIP . "'";
$result = $dbConnectionArray["app_property"]->query($sqlquery);
if (DB::isError($result)) die ("$PHP_SELF: " . $result->getMessage());
while ($row = $result->fetch_assoc()):
$custId = $row["cust_id"];
$hqId = $row["hq_id"];
$usrId = $row["usr_id"];
$confPropRowMatched = true;
endwhile;
$result->free();
endif;
if ($confPropRowMatched) :
// Get special database from information in
$moMnemonicTargetDb = getOperationalDatabase($custId);
if ($moMnemonicTargetDb != "") :
$remDb = $db;
$db = getDbConnectionSpecial($moMnemonicTargetDb, $dbname, $dblogin, $dbpassword);
// In older VPA client versions <tr_id> contains "tr_sort" and has to be mapped to "tr_id"!
if ($xmlContext == "tour") :
if ($xmlJbId != "" && is_numeric($xmlJbId) && $xmlTrId != "" && is_numeric($xmlTrId) && $xmlTrId < 100) :
$xmlTrId = getFieldValueFromClause("phoenix.tour", "tr_id", "jb_id = '" . $xmlJbId . "' AND tr_sort = '" . $xmlTrId . "'");
endif;
endif;
// If job ID does exist AND automailer functionality is enabled then write semaphor into taget database
if ($xmlJbId != "" && is_numeric($xmlJbId)) :
// $constAutomailerEnabled = getParameterValue("0", "AUTOMAILER_ENABLED", "0"); // "Meta-Global" <=> hq_id = 0
$constAutomailerEnabled = "1";
if ($constAutomailerEnabled == '1') :
if (existsEntry("phoenix_log.semaphor",array("sp_obj_type","jb","sp_obj_id",$xmlJbId,"sp_fieldname",$semaphorKey))) :
updateStmt("phoenix_log.semaphor", "sp_obj_id", $xmlJbId, array("sp_createtime", $currentTime),"sp_obj_type = 'jb' AND sp_fieldname = '" . $semaphorKey . "'");
else :
insertStmt("phoenix_log.semaphor", array("sp_obj_type", "jb", "sp_obj_id", $xmlJbId, "sp_fieldname", $semaphorKey, "sp_content", "UPLOAD_IMG", "sp_context", "LOCKED", "sp_createtime", $currentTime));
endif;
endif;
endif;
if ($custId == "3" || $custId == "103") :
// if (false) :
// Decode BASE64 and uncompress
$filedata = base64_decode($filedata);
$filedata = gzinflate($filedata);
// Get cr_id from usr_id
$crId = getFieldValueFromId("phoenix.courier","usr_id", $usrId,"cr_id");
if ($crId != "" && $crId != "0") :
// Generate output file by writing $filedata
$path = "../upload/mbl_foto/";
// if (file_exists($path . $filename)) :
// unlink($path . $filename);
// endif;
writeToFile($path . $filename, $filedata);
// sleep(2);
// if (!file_exists($path . $filename)) :
// $opState = "ERR 113 : No bo_ext_id0 ID!";
// endif;
// Get b2b object
$boId = getFieldValueFromClause("phoenix_log.b2b_objects", "bo_id", $whereClauseStarttime . "bo_type = '101' AND bo_ext_id1=" . $crId . " AND bo_obj_data = '" . $filename . "'");
if ($boId != "" && $boId != "0") :
$res = updateStmt("phoenix_log.b2b_objects","bo_ext_id0",$boId,array("bo_state", "1"), "bo_type = '105'");
// if ($db->affected_rows = 0) :
// $opState = "ERR 112 : No update by 105!";
// endif;
$boIdNew101 = $boId; // For error handling ONLY
else :
$sqlStmt = "INSERT INTO phoenix_log.b2b_objects (bo_ver,bo_type,bo_state,bo_ext_id0,bo_ext_id1,bo_ext_id2,bo_obj_data,bo_createtime)" .
" VALUES ('0','101','1','0','$crId','0','$filename','$currentTime')";
$res = $db->query($sqlStmt);
if (DB::isError($res)) : die ("$PHP_SELF: " . $res->getMessage()); endif;
$boIdNew101 = getLastInsertID();
// $opState = "ERR 111 : No bo_ext_id0 ID!";
endif;
else :
// $opState = "ERR 110 : No courier ID!";
endif;
// elseif ($custId == "6" || $custId == "106" || $custId == "11" || $custId == "1" || $custId == "2" || $custId == "100" || $custId == "101" || $custId == "102") :
else :
if ($xmlContext == "lda" && $xmlTrId == "") :
if ($xmlComm != "" && ($custId == "1" || $custId == "2" || $custId == "100" || $custId == "101" || $custId == "102")) :
$xmlJbId = getFieldValueFromClause("phoenix.tour", "jb_id", "tr_commission_no = '" . $xmlComm . "' ORDER BY jb_id DESC LIMIT 0,1");
$xmlTrId = getFieldValueFromClause("phoenix.tour", "tr_id", "tr_commission_no = '" . $xmlComm . "' ORDER BY jb_id DESC LIMIT 0,1");
$hqId = getFieldValueFromId("phoenix.user","usr_id", $usrId,"hq_id");
endif;
endif;
// Decode BASE64 and uncompress
$filedata = base64_decode($filedata);
$filedata = gzinflate($filedata);
$filedata = base64_encode($filedata);
// writeToFile("debug.log", $filedata);
$filedataArray = str_split($filedata, 32768); // 32K
$filedataArrayLen = count($filedataArray);
for ($i = 0; $i < $filedataArrayLen; $i++) :
$tmpChunk = $filedataArray[$i];
$filedataArray[$i] = "<![CDATA[" . $tmpChunk . "]]>";
endfor;
// writeToFile("debug2.log", $tmpOut);
// Write main file
// writeToFile($filename, $filedata);
// $bo_ext_id0 = "";
// $bo_ext_id0 = $xmlJbId;
/*
if ($xmlCust == "moebel_live") :
if ($xmlJbId != "" && is_numeric($xmlJbId)) :
$bo_ext_id0 = getFieldValueFromClause("phoenix.tour","tr_id","jb_id = '" . $xmlJbId . "' AND tr_sort = '2'"); // equals tr_id
endif;
endif;
*/
if ($debugMode) :
echo "xmlJbId: " . $xmlJbId . "<br>";
echo "xmlTrId: " . $xmlTrId . "<br>";
echo "usrId: " . $usrId . "<br>";
echo "filename: " . $filename . "<br>";
echo "currentTime: " . $currentTime . "<br>";
echo "hqId: " . $hqId . "<br>";
endif;
// **** Insert data sets into b2b_objects ***
if (($xmlContext == "pp" || $xmlContext == "ap") && $xmlJbId != "") :
if (!existsEntry("phoenix_log.b2b_objects",array("bo_type","101","bo_ext_id0",$xmlJbId,"bo_obj_data",$filename))) :
// Insert "101"
$sqlStmt = "INSERT INTO phoenix_log.b2b_objects (bo_ver,bo_type,bo_state,bo_ext_id0,bo_ext_id1,bo_ext_id2,bo_obj_data,bo_createtime)" .
" VALUES ('0','101','0','$xmlJbId','$usrId','0','$filename','$currentTime')";
$res = $db->query($sqlStmt);
if (DB::isError($res)) : die ("$PHP_SELF: " . $res->getMessage()); endif;
$boIdNew101 = getLastInsertID();
if ($debugMode) :
echo "boIdNew101: " . $boIdNew101 . "<br>";
endif;
// Insert "102"
for ($i = 0; $i < $filedataArrayLen; $i++) :
$sqlStmt = "INSERT INTO phoenix_log.b2b_objects (bo_ver,bo_type,bo_state,bo_ext_id0,bo_ext_id1,bo_ext_id2,bo_obj_data,bo_createtime)" .
" VALUES ('0','102','0','$boIdNew101','$usrId','$i','$filedataArray[$i]','$currentTime')";
$res = $db->query($sqlStmt);
if (DB::isError($res)) : die ("$PHP_SELF: " . $res->getMessage()); endif;
$boIdNew102 = getLastInsertID();
endfor;
endif;
elseif (($xmlContext == "tour" && $xmlTrId != "") || ($xmlContext == "lda" && $xmlJbId != "")) :
// Existing "101"
$boIdNew101 = getFieldValueFromClause("phoenix_log.b2b_objects", "bo_id", "bo_type = '101' AND bo_createtime >= '" . $currentDateYesterday . "' AND bo_obj_data = '" . $filename . "'");
if ($xmlContext == "lda") :
// $xmlJbId = getFieldValueFromClause("phoenix_log.b2b_objects", "bo_ext_id1", "bo_type = '120' AND bo_state > '0' AND bo_createtime >= '" . $currentDateYesterday . "' AND bo_obj_data LIKE '%" . $filename . "%'");
$xmlTrId = getFieldValueFromClause("phoenix_log.b2b_objects", "bo_ext_id2", "bo_type = '120' AND bo_createtime >= '" . $currentDateYesterday . "' AND bo_obj_data LIKE '%" . $filename . "%'");
endif;
if ($debugMode) :
echo "xmlJbId: " . $xmlJbId . "<br>";
echo "xmlTrId: " . $xmlTrId . "<br>";
endif;
if ($boIdNew101 == "") :
// Insert "101"
$sqlStmt = "INSERT INTO phoenix_log.b2b_objects (bo_ver,bo_type,bo_state,bo_ext_id0,bo_ext_id1,bo_ext_id2,bo_obj_data,bo_createtime)" .
" VALUES ('0','101','0','$xmlTrId','$usrId','0','$filename','$currentTime')";
$res = $db->query($sqlStmt);
if (DB::isError($res)) : die ("$PHP_SELF: " . $res->getMessage()); endif;
$boIdNew101 = getLastInsertID();
else :
// Update "101"
$sqlStmt = "UPDATE phoenix_log.b2b_objects SET bo_ext_id0 = '$xmlTrId' WHERE bo_id = '$boIdNew101'";
$res = $db->query($sqlStmt);
if (DB::isError($res)) : die ("$PHP_SELF: " . $res->getMessage()); endif;
endif;
if ($debugMode) :
echo "boIdNew101: " . $boIdNew101 . "<br>";
endif;
// Insert "102"
if ($boIdNew101 != "") :
for ($i = 0; $i < $filedataArrayLen; $i++) :
$sqlStmt = "INSERT INTO phoenix_log.b2b_objects (bo_ver,bo_type,bo_state,bo_ext_id0,bo_ext_id1,bo_ext_id2,bo_obj_data,bo_createtime)" .
" VALUES ('0','102','0','$boIdNew101','$usrId','$i','$filedataArray[$i]','$currentTime')";
$res = $db->query($sqlStmt);
if (DB::isError($res)) : die ("$PHP_SELF: " . $res->getMessage()); endif;
$boIdNew102 = getLastInsertID();
endfor;
endif;
endif;
endif;
$db = $remDb;
else :
$opState = "ERR 107 : No target database specified!";
endif;
else :
$opState = "ERR 106 : No row in table conf_prop matched!";
endif;
else :
$opState = "ERR 105 : metaobject not reachable!";
endif;
else :
$opState = "ERR 104 : No global environment definitions found!";
endif;
else :
$opState = "ERR 103 : No file data!";
endif;
else :
$opState = "ERR 102 : Filename empty!";
endif;
else :
$opState = "ERR 101 : Unknown client IP!";
endif;
// Write metadata to log
$logFilename = "upload.log";
if ($custId != "" && is_numeric($custId)) :
$logFilename = "upload_" . $custId . ".log";
endif;
writeToFile($logFilename, $custId . " | " . $currentTime . " | " . date("Y-m-d H:i:s") . " | " . $currentClientIP . " | " . $filename . " | " . $metadata . " | " . $opState . " | boIdNew101: " . $boIdNew101 . " | boIdNew102: " . $boIdNew102 . " | xmlJbId: " . $xmlJbId . " | xmlTrId: " . $xmlTrId);
// Write file data by error
if (($opState != "OK" || ($boIdNew101 == "" || !is_numeric($boIdNew101))) && $filename != "" && $filedata != "") :
$errPath = "../upload/photos_err/";
writeToFile($errPath . $filename, $filedata);
$opState = "OK";
endif;
// Response
//echo $opState;
// 01.09.2016 CA: always respond "OK" because the data will never be sent correctly if they are wrong
echo "OK";
?>

View File

@@ -0,0 +1,412 @@
<?php
include_once ("mc_gen_include.inc.php");
include_once ("htmlMimeMail.php");
require_once "DB.php";
// Get absolute system path (e.g. "/data0/srv/www/htsdocs/xxxx")
function getAbsoluteSystemPath () {
$dirName = dirname(__FILE__);
$dirName = str_replace("\\", "/", $dirName);
$lastSlashPos = strrpos($dirName,"/");
$path = substr($dirName, 0, $lastSlashPos);
return $path;
}
// Triggers the script for sending an internal mail
function sendInternalMail ($errMsg) {
if ($errMsg != "") :
$path = getAbsoluteSystemPath();
$result = "";
// $cmd = "php " . $path . "/include/automailer_internal.php comegetsome97531 " . $errMsg . " &";
$cmd = "php automailer_internal.php comegetsome97531 \"" . $errMsg . "\" &";
exec($cmd . " > /dev/null &");
endif;
}
// *****************************************************************************
// Current timestamp
$currentTime = date("Y-m-d H:i:s");
$currentDateYesterday = getDateTime("date_plus_offset", array(0,-1,0), $formatStr = "Y-m-d");
// Define start time for b2b_object only !!!!
$constAmStarttimeInDays = 30;
$startTime = getDateTime("datetime_plus_offset", array(0,0,0,0,-($constAmStarttimeInDays),0), "Y-m-d") . " 00:00:00";
$whereClauseStarttime = " bo_createtime >= '" . $startTime . "' AND ";
getSecHttpVars("0", array("filedata", "filename", "metadata", "debug"));
$debugOut = "";
if ($debug != "" && ($debug == "1" || $debug == "YES")) :
$debug = true;
else :
$debug = false;
endif;
if ($debug) :
writeToFile("uploader_post.log", "[" . $currentTime . " | " . trim($_SERVER['REMOTE_ADDR']) . "]\n" . var_export($HTTP_POST_VARS, true) . "\n");
writeToFile("uploader_post.log", "---------------------------------------------------------------------------------------------------------\n");
writeToFile("uploader_post_raw.log", "[" . $currentTime . " | " . trim($_SERVER['REMOTE_ADDR']) . "]\n" . file_get_contents("php://input") . "\n");
writeToFile("uploader_post_raw.log", "---------------------------------------------------------------------------------------------------------\n");
endif;
// DB-Config
$dbhost = "172.16.0.111:3711"; // EXTERNAL_DB_METAOBJECT
$dblogin = "phoenix";
$dbpassword = "AdAdgkS13";
$dbname = "phoenix";
$dsn = "mysql://$dblogin:$dbpassword@$dbhost/$dbname";
$db = DB::connect($dsn, false);
if (mysql_errno())
writeToFile("upload.log", "DB-Error:" . " | " . $currentTime . " | " . date("Y-m-d H:i:s") . " | " . trim($_SERVER['REMOTE_ADDR']) . " | " . $filename . mysql_error());
if (DB::isError($db))
die ("$PHP_SELF: " . $db->getMessage());
$db->setFetchMode(DB_FETCHMODE_ASSOC);
$db->query('SET NAMES latin1');
// calling client IP
$currentClientIP = trim($_SERVER['REMOTE_ADDR']);
//if ($currentClientIP == "80.242.181.215")
// $currentClientIP = "10.243.0.8";
$opState = "OK";
$filename = trim($filename);
$semaphorKey = "uploader_photo";
$semaphorLiveTime = 120;
// 30.08.2016 CA: "Filename empty" and "No file data" shall be ignored from now on because those data will never ever be sent correctly
if ($filename == "")
$filename = trim($_SERVER['REMOTE_ADDR']) . "_" . date("YmdHis") . ".jpg";
if ($filedata == "")
$filedata = "No file data";
if ($currentClientIP != "") :
if ($filename != "") :
if ($filedata != "") :
// Set and check upload counter for AMOK mail
if ($currentClientIP != "" && $filename != "") :
if (!existsEntry("temp.app_upload",array("appu_ip",$currentClientIP,"appu_file",$filename))) :
insertStmt("temp.app_upload", array("appu_ip", $currentClientIP, "appu_file", $filename, "appu_cnt", "1"));
else :
$cnt = getFieldValueFromClause("temp.app_upload","appu_cnt","appu_ip = '" . $currentClientIP . "' AND appu_file = '" . $filename . "'");
$cnt++;
updateStmt("temp.app_upload","appu_ip",$currentClientIP,array("appu_cnt",$cnt),"appu_file = '" . $filename . "'");
endif;
$cnt = getFieldValueFromClause("temp.app_upload","appu_cnt","appu_ip = '" . $currentClientIP . "' AND appu_file = '" . $filename . "'");
if ($cnt == "") : $cnt = "0"; endif;
if (($cnt % 10) == 0) :
sendInternalMail("AMOK-FILE " . $filename . " [" . $currentClientIP . "] UPLOAD-COUNTER: " . $cnt);
endif;
endif;
// **** Write data into DB ****
// Get external databases (e.g. APP properties, mobile data, etc.)
$dbhostArray = getGlobalDbEnvironments();
$dbhostArrayLen = count($dbhostArray);
$dbConnectionArray = array();
if ($dbhostArrayLen > 0) :
$dbConnectionArray["app_property"] = getDbConnectionSpecial($dbhostArray["as_intern"], "sysadmin", $dblogin, $dbpassword);
if ($dbConnectionArray["app_property"] != "") :
$confPropRowMatched = false;
// Get tr_id from "metadata"
// <metadata><context>pp</context><type>jpg</type><cust>moebel_live</cust><jb_id>380311</jb_id></metadata>
// <metadata><context>ap</context><type>jpg</type><cust>htm</cust><jb_id>380311</jb_id></metadata>
// <metadata><context>lda</context><acc>HB105</acc><sess_key>77638762387464942387498723</sess_key><comm>77747888</comm></metadata>
// <metadata><context>tour</context><jb_id>....</jb_id><tr_id>....</tr_id></metadata>
$xmlContext = getSingleTagContent($metadata, "<context>", "</context>");
$xmlType = getSingleTagContent($metadata, "<type>", "</type>");
// $xmlCust = getSingleTagContent($metadata, "<cust>", "</cust>");
$xmlJbId = getSingleTagContent($metadata, "<jb_id>", "</jb_id>");
$xmlTrId = getSingleTagContent($metadata, "<tr_id>", "</tr_id>");
$debugMode = false;
$xmlDebug = getSingleTagContent($metadata, "<debug>", "</debug>");
if ($xmlDebug != "") :
$debugMode = true;
endif;
if ($xmlContext == "lda") :
$xmlAcc = getSingleTagContent($metadata, "<acc>", "</acc>");
$xmlSessKey = getSingleTagContent($metadata, "<sess_key>", "</sess_key>");
$xmlComm = getSingleTagContent($metadata, "<comm>", "</comm>");
$xmlComm = trim($xmlComm); // !!!!
$custId = getFieldValueFromId("temp.user_session","us_key", $xmlSessKey,"cust_id",$dbConnectionArray["app_property"]);
$usrId = getFieldValueFromId("temp.user_session","us_key", $xmlSessKey,"usr_id",$dbConnectionArray["app_property"]);
$confPropRowMatched = true; // No entry in conf_prop, because of LDA mode, but ok to proceed!
else:
// Get cust_id, hq_id and usr_id from table conf_prop
$sqlquery = "SELECT cust_id, hq_id, usr_id FROM sysadmin.conf_prop WHERE prop_id = '1' AND cp_val = '" . $currentClientIP . "'";
$result = $dbConnectionArray["app_property"]->query($sqlquery);
if (DB::isError($result)) die ("$PHP_SELF: " . $result->getMessage());
while ($row = $result->fetch_assoc()):
$custId = $row["cust_id"];
$hqId = $row["hq_id"];
$usrId = $row["usr_id"];
$confPropRowMatched = true;
endwhile;
$result->free();
endif;
if ($confPropRowMatched) :
// Get special database from information in
$moMnemonicTargetDb = getOperationalDatabase($custId);
if ($moMnemonicTargetDb != "") :
$remDb = $db;
$db = getDbConnectionSpecial($moMnemonicTargetDb, $dbname, $dblogin, $dbpassword);
// In older VPA client versions <tr_id> contains "tr_sort" and has to be mapped to "tr_id"!
if ($xmlContext == "tour") :
if ($xmlJbId != "" && is_numeric($xmlJbId) && $xmlTrId != "" && is_numeric($xmlTrId) && $xmlTrId < 100) :
$xmlTrId = getFieldValueFromClause("phoenix.tour", "tr_id", "jb_id = '" . $xmlJbId . "' AND tr_sort = '" . $xmlTrId . "'");
endif;
endif;
// If job ID does exist AND automailer functionality is enabled then write semaphor into taget database
if ($xmlJbId != "" && is_numeric($xmlJbId)) :
// $constAutomailerEnabled = getParameterValue("0", "AUTOMAILER_ENABLED", "0"); // "Meta-Global" <=> hq_id = 0
$constAutomailerEnabled = "1";
if ($constAutomailerEnabled == '1') :
if (existsEntry("phoenix_log.semaphor",array("sp_obj_type","jb","sp_obj_id",$xmlJbId,"sp_fieldname",$semaphorKey))) :
updateStmt("phoenix_log.semaphor", "sp_obj_id", $xmlJbId, array("sp_createtime", $currentTime),"sp_obj_type = 'jb' AND sp_fieldname = '" . $semaphorKey . "'");
else :
insertStmt("phoenix_log.semaphor", array("sp_obj_type", "jb", "sp_obj_id", $xmlJbId, "sp_fieldname", $semaphorKey, "sp_content", "UPLOAD_IMG", "sp_context", "LOCKED", "sp_createtime", $currentTime));
endif;
endif;
endif;
if ($custId == "3" || $custId == "103") :
// if (false) :
// Decode BASE64 and uncompress
$filedata = base64_decode($filedata);
$filedata = gzinflate($filedata);
// Get cr_id from usr_id
$crId = getFieldValueFromId("phoenix.courier","usr_id", $usrId,"cr_id");
if ($crId != "" && $crId != "0") :
// Generate output file by writing $filedata
$path = "../upload/mbl_foto/";
// if (file_exists($path . $filename)) :
// unlink($path . $filename);
// endif;
writeToFile($path . $filename, $filedata);
// sleep(2);
// if (!file_exists($path . $filename)) :
// $opState = "ERR 113 : No bo_ext_id0 ID!";
// endif;
// Get b2b object
$boId = getFieldValueFromClause("phoenix_log.b2b_objects", "bo_id", $whereClauseStarttime . "bo_type = '101' AND bo_ext_id1=" . $crId . " AND bo_obj_data = '" . $filename . "'");
if ($boId != "" && $boId != "0") :
$res = updateStmt("phoenix_log.b2b_objects","bo_ext_id0",$boId,array("bo_state", "1"), "bo_type = '105'");
// if ($db->affected_rows = 0) :
// $opState = "ERR 112 : No update by 105!";
// endif;
$boIdNew101 = $boId; // For error handling ONLY
else :
$sqlStmt = "INSERT INTO phoenix_log.b2b_objects (bo_ver,bo_type,bo_state,bo_ext_id0,bo_ext_id1,bo_ext_id2,bo_obj_data,bo_createtime)" .
" VALUES ('0','101','1','0','$crId','0','$filename','$currentTime')";
$res = $db->query($sqlStmt);
if (DB::isError($res)) : die ("$PHP_SELF: " . $res->getMessage()); endif;
$boIdNew101 = getLastInsertID();
// $opState = "ERR 111 : No bo_ext_id0 ID!";
endif;
else :
// $opState = "ERR 110 : No courier ID!";
endif;
// elseif ($custId == "6" || $custId == "106" || $custId == "11" || $custId == "1" || $custId == "2" || $custId == "100" || $custId == "101" || $custId == "102") :
else :
if ($xmlContext == "lda" && $xmlTrId == "") :
if ($xmlComm != "" && ($custId == "1" || $custId == "2" || $custId == "100" || $custId == "101" || $custId == "102")) :
$xmlJbId = getFieldValueFromClause("phoenix.tour", "jb_id", "tr_commission_no = '" . $xmlComm . "' ORDER BY jb_id DESC LIMIT 0,1");
$xmlTrId = getFieldValueFromClause("phoenix.tour", "tr_id", "tr_commission_no = '" . $xmlComm . "' ORDER BY jb_id DESC LIMIT 0,1");
$hqId = getFieldValueFromId("phoenix.user","usr_id", $usrId,"hq_id");
endif;
endif;
// Decode BASE64 and uncompress
$filedata = base64_decode($filedata);
$filedata = gzinflate($filedata);
$filedata = base64_encode($filedata);
// writeToFile("debug.log", $filedata);
$filedataArray = str_split($filedata, 32768); // 32K
$filedataArrayLen = count($filedataArray);
for ($i = 0; $i < $filedataArrayLen; $i++) :
$tmpChunk = $filedataArray[$i];
$filedataArray[$i] = "<![CDATA[" . $tmpChunk . "]]>";
endfor;
// writeToFile("debug2.log", $tmpOut);
// Write main file
// writeToFile($filename, $filedata);
// $bo_ext_id0 = "";
// $bo_ext_id0 = $xmlJbId;
/*
if ($xmlCust == "moebel_live") :
if ($xmlJbId != "" && is_numeric($xmlJbId)) :
$bo_ext_id0 = getFieldValueFromClause("phoenix.tour","tr_id","jb_id = '" . $xmlJbId . "' AND tr_sort = '2'"); // equals tr_id
endif;
endif;
*/
if ($debugMode) :
echo "xmlJbId: " . $xmlJbId . "<br>";
echo "xmlTrId: " . $xmlTrId . "<br>";
echo "usrId: " . $usrId . "<br>";
echo "filename: " . $filename . "<br>";
echo "currentTime: " . $currentTime . "<br>";
echo "hqId: " . $hqId . "<br>";
endif;
if ($debug) :
$debugOut = "xmlJbId: " . $xmlJbId . "\n";
$debugOut .= "xmlTrId: " . $xmlTrId . "\n";
$debugOut .= "usrId: " . $usrId . "\n";
$debugOut .= "filename: " . $filename . "\n";
$debugOut .= "currentTime: " . $currentTime . "\n";
$debugOut .= "hqId: " . $hqId . "\n";
writeToFile("uploader_post.log", $debugOut . "\n");
endif;
// **** Insert data sets into b2b_objects ***
if (($xmlContext == "pp" || $xmlContext == "ap") && $xmlJbId != "") :
if (!existsEntry("phoenix_log.b2b_objects",array("bo_type","101","bo_ext_id0",$xmlJbId,"bo_obj_data",$filename))) :
// Insert "101"
$sqlStmt = "INSERT INTO phoenix_log.b2b_objects (bo_ver,bo_type,bo_state,bo_ext_id0,bo_ext_id1,bo_ext_id2,bo_obj_data,bo_createtime)" .
" VALUES ('0','101','0','$xmlJbId','$usrId','0','$filename','$currentTime')";
$res = $db->query($sqlStmt);
if (DB::isError($res)) : die ("$PHP_SELF: " . $res->getMessage()); endif;
$boIdNew101 = getLastInsertID();
if ($debugMode) :
echo "boIdNew101: " . $boIdNew101 . "<br>";
endif;
if ($debug) :
$debugOut = "boIdNew101: " . $boIdNew101 . "\n";
writeToFile("uploader_post.log", $debugOut . "\n");
endif;
// Insert "102"
for ($i = 0; $i < $filedataArrayLen; $i++) :
$sqlStmt = "INSERT INTO phoenix_log.b2b_objects (bo_ver,bo_type,bo_state,bo_ext_id0,bo_ext_id1,bo_ext_id2,bo_obj_data,bo_createtime)" .
" VALUES ('0','102','0','$boIdNew101','$usrId','$i','$filedataArray[$i]','$currentTime')";
$res = $db->query($sqlStmt);
if (DB::isError($res)) : die ("$PHP_SELF: " . $res->getMessage()); endif;
$boIdNew102 = getLastInsertID();
endfor;
endif;
elseif (($xmlContext == "tour" && $xmlTrId != "") || ($xmlContext == "lda" && $xmlJbId != "")) :
// Existing "101"
$boIdNew101 = getFieldValueFromClause("phoenix_log.b2b_objects", "bo_id", "bo_type = '101' AND bo_createtime >= '" . $currentDateYesterday . "' AND bo_obj_data = '" . $filename . "'");
if ($xmlContext == "lda") :
// $xmlJbId = getFieldValueFromClause("phoenix_log.b2b_objects", "bo_ext_id1", "bo_type = '120' AND bo_state > '0' AND bo_createtime >= '" . $currentDateYesterday . "' AND bo_obj_data LIKE '%" . $filename . "%'");
$xmlTrId = getFieldValueFromClause("phoenix_log.b2b_objects", "bo_ext_id2", "bo_type = '120' AND bo_createtime >= '" . $currentDateYesterday . "' AND bo_obj_data LIKE '%" . $filename . "%'");
endif;
if ($debugMode) :
echo "xmlJbId: " . $xmlJbId . "<br>";
echo "xmlTrId: " . $xmlTrId . "<br>";
endif;
if ($debug) :
$debugOut = "xmlJbId: " . $xmlJbId . "\n";
$debugOut .= "xmlTrId: " . $xmlTrId . "\n";
writeToFile("uploader_post.log", $debugOut . "\n");
endif;
if ($boIdNew101 == "") :
// Insert "101"
$sqlStmt = "INSERT INTO phoenix_log.b2b_objects (bo_ver,bo_type,bo_state,bo_ext_id0,bo_ext_id1,bo_ext_id2,bo_obj_data,bo_createtime)" .
" VALUES ('0','101','0','$xmlTrId','$usrId','0','$filename','$currentTime')";
$res = $db->query($sqlStmt);
if (DB::isError($res)) : die ("$PHP_SELF: " . $res->getMessage()); endif;
$boIdNew101 = getLastInsertID();
else :
// Update "101"
$sqlStmt = "UPDATE phoenix_log.b2b_objects SET bo_ext_id0 = '$xmlTrId' WHERE bo_id = '$boIdNew101'";
$res = $db->query($sqlStmt);
if (DB::isError($res)) : die ("$PHP_SELF: " . $res->getMessage()); endif;
endif;
if ($debugMode) :
echo "boIdNew101: " . $boIdNew101 . "<br>";
endif;
if ($debug) :
$debugOut = "boIdNew101: " . $boIdNew101 . "\n";
writeToFile("uploader_post.log", $debugOut . "\n");
endif;
// Insert "102"
if ($boIdNew101 != "") :
for ($i = 0; $i < $filedataArrayLen; $i++) :
$sqlStmt = "INSERT INTO phoenix_log.b2b_objects (bo_ver,bo_type,bo_state,bo_ext_id0,bo_ext_id1,bo_ext_id2,bo_obj_data,bo_createtime)" .
" VALUES ('0','102','0','$boIdNew101','$usrId','$i','$filedataArray[$i]','$currentTime')";
$res = $db->query($sqlStmt);
if (DB::isError($res)) : die ("$PHP_SELF: " . $res->getMessage()); endif;
$boIdNew102 = getLastInsertID();
endfor;
endif;
endif;
endif;
$db = $remDb;
else :
$opState = "ERR 107 : No target database specified!";
endif;
else :
$opState = "ERR 106 : No row in table conf_prop matched!";
endif;
else :
$opState = "ERR 105 : metaobject not reachable!";
endif;
else :
$opState = "ERR 104 : No global environment definitions found!";
endif;
else :
$opState = "ERR 103 : No file data!";
endif;
else :
$opState = "ERR 102 : Filename empty!";
endif;
else :
$opState = "ERR 101 : Unknown client IP!";
endif;
// Write metadata to log
$logFilename = "upload.log";
if ($custId != "" && is_numeric($custId)) :
$logFilename = "upload_" . $custId . ".log";
endif;
writeToFile($logFilename, $custId . " | " . $currentTime . " | " . date("Y-m-d H:i:s") . " | " . $currentClientIP . " | " . $filename . " | " . $metadata . " | " . $opState . " | boIdNew101: " . $boIdNew101 . " | boIdNew102: " . $boIdNew102 . " | xmlJbId: " . $xmlJbId . " | xmlTrId: " . $xmlTrId);
// Write file data by error
if (($opState != "OK" || ($boIdNew101 == "" || !is_numeric($boIdNew101))) && $filename != "" && $filedata != "") :
$errPath = "../upload/photos_err/";
writeToFile($errPath . $filename, $filedata);
$opState = "OK";
endif;
// Response
//echo $opState;
// 01.09.2016 CA: always respond "OK" because the data will never be sent correctly if they are wrong
echo "OK";
?>

View File

@@ -0,0 +1,418 @@
<?php
include_once ("mc_gen_include.inc.php");
include_once ("htmlMimeMail.php");
require_once "DB.php";
// Get absolute system path (e.g. "/data0/srv/www/htsdocs/xxxx")
function getAbsoluteSystemPath () {
$dirName = dirname(__FILE__);
$dirName = str_replace("\\", "/", $dirName);
$lastSlashPos = strrpos($dirName,"/");
$path = substr($dirName, 0, $lastSlashPos);
return $path;
}
// Triggers the script for sending an internal mail
function sendInternalMail ($errMsg) {
if ($errMsg != "") :
$path = getAbsoluteSystemPath();
$result = "";
// $cmd = "php " . $path . "/include/automailer_internal.php comegetsome97531 " . $errMsg . " &";
$cmd = "php automailer_internal.php comegetsome97531 \"" . $errMsg . "\" &";
exec($cmd . " > /dev/null &");
endif;
}
// *****************************************************************************
// Current timestamp
$currentTime = date("Y-m-d H:i:s");
$currentDateYesterday = getDateTime("date_plus_offset", array(0,-1,0), $formatStr = "Y-m-d");
// Define start time for b2b_object only !!!!
$constAmStarttimeInDays = 30;
$startTime = getDateTime("datetime_plus_offset", array(0,0,0,0,-($constAmStarttimeInDays),0), "Y-m-d") . " 00:00:00";
$whereClauseStarttime = " bo_createtime >= '" . $startTime . "' AND ";
getSecHttpVars("0", array("filedata", "filename", "metadata", "debug", "clientIP"));
// calling client IP
// $currentClientIP = trim($_SERVER['REMOTE_ADDR']);
// $currentClientIP = trim($_SERVER['HTTP_X_FORWARDED_FOR']);
$currentClientIP = trim($clientIP);
//if ($currentClientIP == "80.242.181.215")
// $currentClientIP = "10.243.0.8";
$debugOut = "";
$debug = false;
if ($debug != "" && ($debug == "1" || $debug == "YES")) :
$debug = true;
endif;
if ($debug) :
writeToFile("uploader_post.log", "[" . $currentTime . " | " . $currentClientIP . "]\n" . var_export($HTTP_POST_VARS, true) . "\n");
writeToFile("uploader_post.log", "---------------------------------------------------------------------------------------------------------\n");
writeToFile("uploader_post_raw.log", "[" . $currentTime . " | " . $currentClientIP . "]\n" . file_get_contents("php://input") . "\n");
writeToFile("uploader_post_raw.log", "---------------------------------------------------------------------------------------------------------\n");
endif;
// DB-Config
$dbhost = "172.16.0.111:3711"; // EXTERNAL_DB_METAOBJECT
$dblogin = "phoenix";
$dbpassword = "AdAdgkS13";
$dbname = "phoenix";
$dsn = "mysql://$dblogin:$dbpassword@$dbhost/$dbname";
$db = DB::connect($dsn, false);
if (mysql_errno())
writeToFile("upload.log", "DB-Error:" . " | " . $currentTime . " | " . date("Y-m-d H:i:s") . " | " . $currentClientIP . " | " . $filename . mysql_error());
if (DB::isError($db))
die ("$PHP_SELF: " . $db->getMessage());
$db->setFetchMode(DB_FETCHMODE_ASSOC);
$db->query('SET NAMES latin1');
$opState = "OK";
$filename = trim($filename);
$semaphorKey = "uploader_photo";
$semaphorLiveTime = 120;
// 30.08.2016 CA: "Filename empty" and "No file data" shall be ignored from now on because those data will never ever be sent correctly
if ($filename == "")
$filename = $currentClientIP . "_" . date("YmdHis") . ".jpg";
if ($filedata == "")
$filedata = "No file data";
if ($currentClientIP != "") :
if ($filename != "") :
if ($filedata != "") :
// Set and check upload counter for AMOK mail
if ($currentClientIP != "" && $filename != "") :
if (!existsEntry("temp.app_upload",array("appu_ip",$currentClientIP,"appu_file",$filename))) :
insertStmt("temp.app_upload", array("appu_ip", $currentClientIP, "appu_file", $filename, "appu_cnt", "1"));
else :
$cnt = getFieldValueFromClause("temp.app_upload","appu_cnt","appu_ip = '" . $currentClientIP . "' AND appu_file = '" . $filename . "'");
$cnt++;
updateStmt("temp.app_upload","appu_ip",$currentClientIP,array("appu_cnt",$cnt),"appu_file = '" . $filename . "'");
endif;
$cnt = getFieldValueFromClause("temp.app_upload","appu_cnt","appu_ip = '" . $currentClientIP . "' AND appu_file = '" . $filename . "'");
if ($cnt == "") : $cnt = "0"; endif;
if (($cnt % 10) == 0) :
sendInternalMail("AMOK-FILE " . $filename . " [" . $currentClientIP . "] UPLOAD-COUNTER: " . $cnt);
endif;
endif;
// **** Write data into DB ****
// Get external databases (e.g. APP properties, mobile data, etc.)
$dbhostArray = getGlobalDbEnvironments();
$dbhostArrayLen = count($dbhostArray);
$dbConnectionArray = array();
if ($dbhostArrayLen > 0) :
$dbConnectionArray["app_property"] = getDbConnectionSpecial($dbhostArray["as_intern"], "sysadmin", $dblogin, $dbpassword);
if ($dbConnectionArray["app_property"] != "") :
$confPropRowMatched = false;
// Get tr_id from "metadata"
// <metadata><context>pp</context><type>jpg</type><cust>moebel_live</cust><jb_id>380311</jb_id></metadata>
// <metadata><context>ap</context><type>jpg</type><cust>htm</cust><jb_id>380311</jb_id></metadata>
// <metadata><context>lda</context><acc>HB105</acc><sess_key>77638762387464942387498723</sess_key><comm>77747888</comm></metadata>
// <metadata><context>tour</context><jb_id>....</jb_id><tr_id>....</tr_id></metadata>
$xmlContext = getSingleTagContent($metadata, "<context>", "</context>");
$xmlType = getSingleTagContent($metadata, "<type>", "</type>");
// $xmlCust = getSingleTagContent($metadata, "<cust>", "</cust>");
$xmlJbId = getSingleTagContent($metadata, "<jb_id>", "</jb_id>");
$xmlTrId = getSingleTagContent($metadata, "<tr_id>", "</tr_id>");
$debugMode = false;
$xmlDebug = getSingleTagContent($metadata, "<debug>", "</debug>");
if ($xmlDebug != "") :
$debugMode = true;
endif;
if ($xmlContext == "lda") :
$xmlAcc = getSingleTagContent($metadata, "<acc>", "</acc>");
$xmlSessKey = getSingleTagContent($metadata, "<sess_key>", "</sess_key>");
$xmlComm = getSingleTagContent($metadata, "<comm>", "</comm>");
$xmlComm = trim($xmlComm); // !!!!
$custId = getFieldValueFromId("temp.user_session","us_key", $xmlSessKey,"cust_id",$dbConnectionArray["app_property"]);
$usrId = getFieldValueFromId("temp.user_session","us_key", $xmlSessKey,"usr_id",$dbConnectionArray["app_property"]);
$confPropRowMatched = true; // No entry in conf_prop, because of LDA mode, but ok to proceed!
else:
// Get cust_id, hq_id and usr_id from table conf_prop
$sqlquery = "SELECT cust_id, hq_id, usr_id FROM sysadmin.conf_prop WHERE prop_id = '1' AND cp_val = '" . $currentClientIP . "'";
$result = $dbConnectionArray["app_property"]->query($sqlquery);
if (DB::isError($result)) die ("$PHP_SELF: " . $result->getMessage());
while ($row = $result->fetch_assoc()):
$custId = $row["cust_id"];
$hqId = $row["hq_id"];
$usrId = $row["usr_id"];
$confPropRowMatched = true;
endwhile;
$result->free();
endif;
if ($confPropRowMatched) :
// Get special database from information in
$moMnemonicTargetDb = getOperationalDatabase($custId);
if ($moMnemonicTargetDb != "") :
$remDb = $db;
$db = getDbConnectionSpecial($moMnemonicTargetDb, $dbname, $dblogin, $dbpassword);
// In older VPA client versions <tr_id> contains "tr_sort" and has to be mapped to "tr_id"!
if ($xmlContext == "tour") :
if ($xmlJbId != "" && is_numeric($xmlJbId) && $xmlTrId != "" && is_numeric($xmlTrId) && $xmlTrId < 100) :
$xmlTrId = getFieldValueFromClause("phoenix.tour", "tr_id", "jb_id = '" . $xmlJbId . "' AND tr_sort = '" . $xmlTrId . "'");
endif;
endif;
// If job ID does exist AND automailer functionality is enabled then write semaphor into taget database
if ($xmlJbId != "" && is_numeric($xmlJbId)) :
// $constAutomailerEnabled = getParameterValue("0", "AUTOMAILER_ENABLED", "0"); // "Meta-Global" <=> hq_id = 0
$constAutomailerEnabled = "1";
if ($constAutomailerEnabled == '1') :
if (existsEntry("phoenix_log.semaphor",array("sp_obj_type","jb","sp_obj_id",$xmlJbId,"sp_fieldname",$semaphorKey))) :
updateStmt("phoenix_log.semaphor", "sp_obj_id", $xmlJbId, array("sp_createtime", $currentTime),"sp_obj_type = 'jb' AND sp_fieldname = '" . $semaphorKey . "'");
else :
insertStmt("phoenix_log.semaphor", array("sp_obj_type", "jb", "sp_obj_id", $xmlJbId, "sp_fieldname", $semaphorKey, "sp_content", "UPLOAD_IMG", "sp_context", "LOCKED", "sp_createtime", $currentTime));
endif;
endif;
endif;
if ($custId == "3" || $custId == "103") :
// if (false) :
// Decode BASE64 and uncompress
$filedata = base64_decode($filedata);
$filedata = gzinflate($filedata);
// Get cr_id from usr_id
$crId = getFieldValueFromId("phoenix.courier","usr_id", $usrId,"cr_id");
if ($crId != "" && $crId != "0") :
// Generate output file by writing $filedata
$path = "../upload/mbl_foto/";
// if (file_exists($path . $filename)) :
// unlink($path . $filename);
// endif;
writeToFile($path . $filename, $filedata);
// sleep(2);
// if (!file_exists($path . $filename)) :
// $opState = "ERR 113 : No bo_ext_id0 ID!";
// endif;
// Get b2b object
$boId = getFieldValueFromClause("phoenix_log.b2b_objects", "bo_id", $whereClauseStarttime . "bo_type = '101' AND bo_ext_id1=" . $crId . " AND bo_obj_data = '" . $filename . "'");
if ($boId != "" && $boId != "0") :
$res = updateStmt("phoenix_log.b2b_objects","bo_ext_id0",$boId,array("bo_state", "1"), "bo_type = '105'");
// if ($db->affected_rows = 0) :
// $opState = "ERR 112 : No update by 105!";
// endif;
$boIdNew101 = $boId; // For error handling ONLY
else :
$sqlStmt = "INSERT INTO phoenix_log.b2b_objects (bo_ver,bo_type,bo_state,bo_ext_id0,bo_ext_id1,bo_ext_id2,bo_obj_data,bo_createtime)" .
" VALUES ('0','101','1','0','$crId','0','$filename','$currentTime')";
$res = $db->query($sqlStmt);
if (DB::isError($res)) : die ("$PHP_SELF: " . $res->getMessage()); endif;
$boIdNew101 = getLastInsertID();
// $opState = "ERR 111 : No bo_ext_id0 ID!";
endif;
else :
// $opState = "ERR 110 : No courier ID!";
endif;
// elseif ($custId == "6" || $custId == "106" || $custId == "11" || $custId == "1" || $custId == "2" || $custId == "100" || $custId == "101" || $custId == "102") :
else :
if ($xmlContext == "lda" && $xmlTrId == "") :
if ($xmlComm != "" && ($custId == "1" || $custId == "2" || $custId == "100" || $custId == "101" || $custId == "102")) :
$xmlJbId = getFieldValueFromClause("phoenix.tour", "jb_id", "tr_commission_no = '" . $xmlComm . "' ORDER BY jb_id DESC LIMIT 0,1");
$xmlTrId = getFieldValueFromClause("phoenix.tour", "tr_id", "tr_commission_no = '" . $xmlComm . "' ORDER BY jb_id DESC LIMIT 0,1");
$hqId = getFieldValueFromId("phoenix.user","usr_id", $usrId,"hq_id");
endif;
endif;
// Decode BASE64 and uncompress
$filedata = base64_decode($filedata);
$filedata = gzinflate($filedata);
$filedata = base64_encode($filedata);
// writeToFile("debug.log", $filedata);
$filedataArray = str_split($filedata, 32768); // 32K
$filedataArrayLen = count($filedataArray);
for ($i = 0; $i < $filedataArrayLen; $i++) :
$tmpChunk = $filedataArray[$i];
$filedataArray[$i] = "<![CDATA[" . $tmpChunk . "]]>";
endfor;
// writeToFile("debug2.log", $tmpOut);
// Write main file
// writeToFile($filename, $filedata);
// $bo_ext_id0 = "";
// $bo_ext_id0 = $xmlJbId;
/*
if ($xmlCust == "moebel_live") :
if ($xmlJbId != "" && is_numeric($xmlJbId)) :
$bo_ext_id0 = getFieldValueFromClause("phoenix.tour","tr_id","jb_id = '" . $xmlJbId . "' AND tr_sort = '2'"); // equals tr_id
endif;
endif;
*/
if ($debugMode) :
echo "xmlJbId: " . $xmlJbId . "<br>";
echo "xmlTrId: " . $xmlTrId . "<br>";
echo "usrId: " . $usrId . "<br>";
echo "filename: " . $filename . "<br>";
echo "currentTime: " . $currentTime . "<br>";
echo "hqId: " . $hqId . "<br>";
endif;
if ($debug) :
$debugOut = "xmlJbId: " . $xmlJbId . "\n";
$debugOut .= "xmlTrId: " . $xmlTrId . "\n";
$debugOut .= "usrId: " . $usrId . "\n";
$debugOut .= "filename: " . $filename . "\n";
$debugOut .= "currentTime: " . $currentTime . "\n";
$debugOut .= "hqId: " . $hqId . "\n";
writeToFile("uploader_post.log", $debugOut . "\n");
endif;
// **** Insert data sets into b2b_objects ***
if (($xmlContext == "pp" || $xmlContext == "ap") && $xmlJbId != "") :
if (!existsEntry("phoenix_log.b2b_objects",array("bo_type","101","bo_ext_id0",$xmlJbId,"bo_obj_data",$filename))) :
// Insert "101"
$sqlStmt = "INSERT INTO phoenix_log.b2b_objects (bo_ver,bo_type,bo_state,bo_ext_id0,bo_ext_id1,bo_ext_id2,bo_obj_data,bo_createtime)" .
" VALUES ('0','101','0','$xmlJbId','$usrId','0','$filename','$currentTime')";
$res = $db->query($sqlStmt);
if (DB::isError($res)) : die ("$PHP_SELF: " . $res->getMessage()); endif;
$boIdNew101 = getLastInsertID();
if ($debugMode) :
echo "boIdNew101: " . $boIdNew101 . "<br>";
endif;
if ($debug) :
$debugOut = "boIdNew101: " . $boIdNew101 . "\n";
writeToFile("uploader_post.log", $debugOut . "\n");
endif;
// Insert "102"
for ($i = 0; $i < $filedataArrayLen; $i++) :
$sqlStmt = "INSERT INTO phoenix_log.b2b_objects (bo_ver,bo_type,bo_state,bo_ext_id0,bo_ext_id1,bo_ext_id2,bo_obj_data,bo_createtime)" .
" VALUES ('0','102','0','$boIdNew101','$usrId','$i','$filedataArray[$i]','$currentTime')";
$res = $db->query($sqlStmt);
if (DB::isError($res)) : die ("$PHP_SELF: " . $res->getMessage()); endif;
$boIdNew102 = getLastInsertID();
endfor;
endif;
elseif (($xmlContext == "tour" && $xmlTrId != "") || ($xmlContext == "lda" && $xmlJbId != "")) :
// Existing "101"
$boIdNew101 = getFieldValueFromClause("phoenix_log.b2b_objects", "bo_id", "bo_type = '101' AND bo_createtime >= '" . $currentDateYesterday . "' AND bo_obj_data = '" . $filename . "'");
if ($xmlContext == "lda") :
// $xmlJbId = getFieldValueFromClause("phoenix_log.b2b_objects", "bo_ext_id1", "bo_type = '120' AND bo_state > '0' AND bo_createtime >= '" . $currentDateYesterday . "' AND bo_obj_data LIKE '%" . $filename . "%'");
$xmlTrId = getFieldValueFromClause("phoenix_log.b2b_objects", "bo_ext_id2", "bo_type = '120' AND bo_createtime >= '" . $currentDateYesterday . "' AND bo_obj_data LIKE '%" . $filename . "%'");
endif;
if ($debugMode) :
echo "xmlJbId: " . $xmlJbId . "<br>";
echo "xmlTrId: " . $xmlTrId . "<br>";
endif;
if ($debug) :
$debugOut = "xmlJbId: " . $xmlJbId . "\n";
$debugOut .= "xmlTrId: " . $xmlTrId . "\n";
writeToFile("uploader_post.log", $debugOut . "\n");
endif;
if ($boIdNew101 == "") :
// Insert "101"
$sqlStmt = "INSERT INTO phoenix_log.b2b_objects (bo_ver,bo_type,bo_state,bo_ext_id0,bo_ext_id1,bo_ext_id2,bo_obj_data,bo_createtime)" .
" VALUES ('0','101','0','$xmlTrId','$usrId','0','$filename','$currentTime')";
$res = $db->query($sqlStmt);
if (DB::isError($res)) : die ("$PHP_SELF: " . $res->getMessage()); endif;
$boIdNew101 = getLastInsertID();
else :
// Update "101"
$sqlStmt = "UPDATE phoenix_log.b2b_objects SET bo_ext_id0 = '$xmlTrId' WHERE bo_id = '$boIdNew101'";
$res = $db->query($sqlStmt);
if (DB::isError($res)) : die ("$PHP_SELF: " . $res->getMessage()); endif;
endif;
if ($debugMode) :
echo "boIdNew101: " . $boIdNew101 . "<br>";
endif;
if ($debug) :
$debugOut = "boIdNew101: " . $boIdNew101 . "\n";
writeToFile("uploader_post.log", $debugOut . "\n");
endif;
// Insert "102"
if ($boIdNew101 != "") :
for ($i = 0; $i < $filedataArrayLen; $i++) :
$sqlStmt = "INSERT INTO phoenix_log.b2b_objects (bo_ver,bo_type,bo_state,bo_ext_id0,bo_ext_id1,bo_ext_id2,bo_obj_data,bo_createtime)" .
" VALUES ('0','102','0','$boIdNew101','$usrId','$i','$filedataArray[$i]','$currentTime')";
$res = $db->query($sqlStmt);
if (DB::isError($res)) : die ("$PHP_SELF: " . $res->getMessage()); endif;
$boIdNew102 = getLastInsertID();
endfor;
endif;
endif;
endif;
$db = $remDb;
else :
$opState = "ERR 107 : No target database specified!";
endif;
else :
$opState = "ERR 106 : No row in table conf_prop matched!";
endif;
else :
$opState = "ERR 105 : metaobject not reachable!";
endif;
else :
$opState = "ERR 104 : No global environment definitions found!";
endif;
else :
$opState = "ERR 103 : No file data!";
endif;
else :
$opState = "ERR 102 : Filename empty!";
endif;
else :
$opState = "ERR 101 : Unknown client IP!";
endif;
// Write metadata to log
$logFilename = "upload.log";
if ($custId != "" && is_numeric($custId)) :
$logFilename = "upload_" . $custId . ".log";
endif;
writeToFile($logFilename, $custId . " | " . $currentTime . " | " . date("Y-m-d H:i:s") . " | " . $currentClientIP . " | " . $filename . " | " . $metadata . " | " . $opState . " | boIdNew101: " . $boIdNew101 . " | boIdNew102: " . $boIdNew102 . " | xmlJbId: " . $xmlJbId . " | xmlTrId: " . $xmlTrId);
// Write file data by error
if (($opState != "OK" || ($boIdNew101 == "" || !is_numeric($boIdNew101))) && $filename != "" && $filedata != "") :
// $errPath = "../upload/photos_err/";
$errPath = "photos_err/";
// writeToFile($errPath . $filename, $filedata);
writeToFile($errPath . "photo_err.log", "filename: " . $filename . "|" . "opState: " . $opState . "|" . "boIdNew101: " . $boIdNew101 . "|" . "filedata: " . substr($filedata,0,100));
$opState = "OK";
endif;
// Response
//echo $opState;
// 01.09.2016 CA: always respond "OK" because the data will never be sent correctly if they are wrong
// echo "OK";
?>

View File

@@ -0,0 +1,67 @@
<?php
// Writes a string to a file optional with or without linefeed
function writeToFile($fileName, $stringToOperate, $mode = 'a', $noLf = "") {
$fileHandle = fopen($fileName, $mode);
if ($noLf == "") : $stringToOperate .= "\n"; endif;
$opCode = fwrite($fileHandle, $stringToOperate);
fclose($fileHandle);
return $opCode;
}
function sendHttpPostRedirect ($url, $postArray = array(), $httpXFowardedFor = "") {
global $debug;
$retVal = "NO_DATA";
if ($debug) :
// print_r($_POST);
$currentTime = date("Y-m-d H:i:s");
writeToFile("uploader_post.log", "[" . $currentTime . " | " . trim($_SERVER['HTTP_X_FORWARDED_FOR']) . "]");
endif;
if ($url != "" && is_array($postArray) && count($postArray) > 0) :
$fields = $postArray;
if ($httpXFowardedFor == "1") :
$fields["clientIP"] = trim($_SERVER['HTTP_X_FORWARDED_FOR']);
endif;
if (!isset($fields_string))
$fields_string = "";
foreach($fields as $key=>$value) { $fields_string .= $key.'='.urlencode($value).'&'; }
rtrim($fields_string, '&');
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_POST, count($fields));
curl_setopt($ch,CURLOPT_POSTFIELDS, $fields_string);
if (isset($returnResponse) && $returnResponse != "") :
curl_setopt($ch,CURLOPT_RETURNTRANSFER, "1");
endif;
$result = curl_exec($ch);
curl_close($ch);
if (!($result === false)) :
if (isset($returnResponse) && $returnResponse == "") :
$retVal = "SENT_OK";
else :
$retVal = $result;
endif;
endif;
endif;
return $retVal;
}
$debug = true;
$url = 'https://mps2.assecutor.de/uploader/uploader_ALL_REDIRECT_RECEIVER.php';
$retVal = sendHttpPostRedirect($url, $_POST, "1");
// if ($retVal != "SENT_OK") {
echo "OK";
// };
?>

View File

@@ -0,0 +1,35 @@
<?php
// Writes a string to a file optional with or without linefeed
function writeToFile($fileName, $stringToOperate, $mode = 'a', $noLf = "") {
$fileHandle = fopen($fileName, $mode);
if ($noLf == "") : $stringToOperate .= "\n"; endif;
$opCode = fwrite($fileHandle, $stringToOperate);
fclose($fileHandle);
return $opCode;
}
?>
<html>
<!-- form id="uploader" action="https://172.16.0.147/test_php7_sb/sysadmin/uploader/uploader_ALL.php" method="post" -->
<form id="uploader" action="https://mps2.assecutor.de/uploader/uploader_ALL_REDIRECT_RECEIVER.php" method="post">
<?php
$debug = true;
if ($debug) :
// print_r($_POST);
$currentTime = date("Y-m-d H:i:s");
writeToFile("uploader_post.log", "[" . $currentTime . " | " . trim($_SERVER['HTTP_X_FORWARDED_FOR']) . "]");
endif;
echo '<input type="hidden" name="clientIP" value="'. trim($_SERVER['HTTP_X_FORWARDED_FOR']) .'">';
foreach ($_POST as $key => $val) {
// echo '<input type="hidden" name="'.htmlentities($key).'" value="'.htmlentities($val).'">';
echo '<input type="hidden" name="' . $key . '" value="'. $val .'">';
}
?>
</form>
<script type="text/javascript">
document.getElementById('uploader').submit();
</script>
</html>

View File

@@ -0,0 +1,352 @@
<?php
include_once ("mc_gen_include.inc.php");
include_once ("htmlMimeMail.php");
require_once "DB.php";
// Get absolute system path (e.g. "/data0/srv/www/htsdocs/xxxx")
function getAbsoluteSystemPath () {
$dirName = dirname(__FILE__);
$dirName = str_replace("\\", "/", $dirName);
$lastSlashPos = strrpos($dirName,"/");
$path = substr($dirName, 0, $lastSlashPos);
return $path;
}
// Triggers the script for sending an internal mail
function sendInternalMail ($errMsg) {
if ($errMsg != "") :
$path = getAbsoluteSystemPath();
$result = "";
// $cmd = "php " . $path . "/include/automailer_internal.php comegetsome97531 " . $errMsg . " &";
$cmd = "php automailer_internal.php comegetsome97531 \"" . $errMsg . "\" &";
exec($cmd . " > /dev/null &");
endif;
}
// *****************************************************************************
// Current timestamp
$currentTime = date("Y-m-d H:i:s");
$currentDateYesterday = getDateTime("date_plus_offset", array(0,-1,0), $formatStr = "Y-m-d");
// Define start time for b2b_object only !!!!
$constAmStarttimeInDays = 30;
$startTime = getDateTime("datetime_plus_offset", array(0,0,0,0,-($constAmStarttimeInDays),0), "Y-m-d") . " 00:00:00";
$whereClauseStarttime = " bo_createtime >= '" . $startTime . "' AND ";
getSecHttpVars("0", array("filedata", "filename", "metadata"));
//writeToFile("uploader_post.log", "[" . $currentTime . " | " . trim($_SERVER['REMOTE_ADDR']) . "]\n" . var_export($HTTP_POST_VARS, true) . "\n");
//writeToFile("uploader_post_raw.log", "[" . $currentTime . " | " . trim($_SERVER['REMOTE_ADDR']) . "]\n" . file_get_contents("php://input") . "\n");
// DB-Config
$dbhost = "172.16.0.111:3711"; // EXTERNAL_DB_METAOBJECT
$dblogin = "phoenix";
$dbpassword = "AdAdgkS13";
$dbname = "phoenix";
$dsn = "mysql://$dblogin:$dbpassword@$dbhost/$dbname";
$db = DB::connect($dsn, false);
if (mysql_errno())
writeToFile("upload.log", "DB-Error:" . " | " . $currentTime . " | " . date("Y-m-d H:i:s") . " | " . trim($_SERVER['REMOTE_ADDR']) . " | " . $filename . mysql_error());
if (DB::isError($db))
die ("$PHP_SELF: " . $db->getMessage());
$db->setFetchMode(DB_FETCHMODE_ASSOC);
$db->query('SET NAMES latin1');
// calling client IP
$currentClientIP = trim($_SERVER['REMOTE_ADDR']);
$opState = "OK";
$filename = trim($filename);
// 30.08.2016 CA: "Filename empty" and "No file data" shall be ignored from now on because those data will never ever be sent correctly
if ($filename == "")
$filename = trim($_SERVER['REMOTE_ADDR']) . "_" . date("YmdHis") . ".jpg";
if ($filedata == "")
$filedata = "No file data";
if ($currentClientIP != "") :
if ($filename != "") :
if ($filedata != "") :
// Set and check upload counter for AMOK mail
if ($currentClientIP != "" && $filename != "") :
if (!existsEntry("temp.app_upload",array("appu_ip",$currentClientIP,"appu_file",$filename))) :
insertStmt("temp.app_upload", array("appu_ip", $currentClientIP, "appu_file", $filename, "appu_cnt", "1"));
else :
$cnt = getFieldValueFromClause("temp.app_upload","appu_cnt","appu_ip = '" . $currentClientIP . "' AND appu_file = '" . $filename . "'");
$cnt++;
updateStmt("temp.app_upload","appu_ip",$currentClientIP,array("appu_cnt",$cnt),"appu_file = '" . $filename . "'");
endif;
$cnt = getFieldValueFromClause("temp.app_upload","appu_cnt","appu_ip = '" . $currentClientIP . "' AND appu_file = '" . $filename . "'");
if ($cnt == "") : $cnt = "0"; endif;
if (($cnt % 10) == 0) :
sendInternalMail("AMOK-FILE " . $filename . " [" . $currentClientIP . "] UPLOAD-COUNTER: " . $cnt);
endif;
endif;
// **** Write data into DB ****
// Get external databases (e.g. APP properties, mobile data, etc.)
$dbhostArray = getGlobalDbEnvironments();
$dbhostArrayLen = count($dbhostArray);
$dbConnectionArray = array();
if ($dbhostArrayLen > 0) :
$dbConnectionArray["app_property"] = getDbConnectionSpecial($dbhostArray["as_intern"], "sysadmin", $dblogin, $dbpassword);
if ($dbConnectionArray["app_property"] != "") :
$confPropRowMatched = false;
// Get tr_id from "metadata"
// <metadata><context>pp</context><type>jpg</type><cust>moebel_live</cust><jb_id>380311</jb_id></metadata>
// <metadata><context>lda</context><acc>HB105</acc><sess_key>77638762387464942387498723</sess_key><comm>77747888</comm></metadata>
$xmlContext = getSingleTagContent($metadata, "<context>", "</context>");
$xmlType = getSingleTagContent($metadata, "<type>", "</type>");
$xmlCust = getSingleTagContent($metadata, "<cust>", "</cust>");
$xmlJbId = getSingleTagContent($metadata, "<jb_id>", "</jb_id>");
$debugMode = false;
$xmlDebug = getSingleTagContent($metadata, "<debug>", "</debug>");
if ($xmlDebug != "") :
$debugMode = true;
endif;
if ($xmlContext == "lda") :
$xmlAcc = getSingleTagContent($metadata, "<acc>", "</acc>");
$xmlSessKey = getSingleTagContent($metadata, "<sess_key>", "</sess_key>");
$xmlComm = getSingleTagContent($metadata, "<comm>", "</comm>");
$xmlComm = trim($xmlComm); // !!!!
$custId = getFieldValueFromId("temp.user_session","us_key", $xmlSessKey,"cust_id",$dbConnectionArray["app_property"]);
$usrId = getFieldValueFromId("temp.user_session","us_key", $xmlSessKey,"usr_id",$dbConnectionArray["app_property"]);
$confPropRowMatched = true; // No entry in conf_prop, because of LDA mode, but ok to proceed!
else:
// Get cust_id, hq_id and usr_id from table conf_prop
$sqlquery = "SELECT cust_id, hq_id, usr_id FROM sysadmin.conf_prop WHERE prop_id = '1' AND cp_val = '" . $currentClientIP . "'";
$result = $dbConnectionArray["app_property"]->query($sqlquery);
if (DB::isError($result)) die ("$PHP_SELF: " . $result->getMessage());
while ($row = $result->fetch_assoc()):
$custId = $row["cust_id"];
$hqId = $row["hq_id"];
$usrId = $row["usr_id"];
$confPropRowMatched = true;
endwhile;
$result->free();
endif;
if ($confPropRowMatched) :
// Get special database from information in
$moMnemonicTargetDb = getOperationalDatabase($custId);
if ($moMnemonicTargetDb != "") :
$remDb = $db;
$db = getDbConnectionSpecial($moMnemonicTargetDb, $dbname, $dblogin, $dbpassword);
if ($custId == "3" || $custId == "103") :
// Decode BASE64 and uncompress
$filedata = base64_decode($filedata);
$filedata = gzinflate($filedata);
// Get cr_id from usr_id
$crId = getFieldValueFromId("phoenix.courier","usr_id", $usrId,"cr_id");
if ($crId != "" && $crId != "0") :
// Generate output file by writing $filedata
$path = "../upload/mbl_foto/";
// if (file_exists($path . $filename)) :
// unlink($path . $filename);
// endif;
writeToFile($path . $filename, $filedata);
// sleep(2);
// if (!file_exists($path . $filename)) :
// $opState = "ERR 113 : No bo_ext_id0 ID!";
// endif;
// Get b2b object
$boId = getFieldValueFromClause("phoenix_log.b2b_objects", "bo_id", $whereClauseStarttime . "bo_type = '101' AND bo_ext_id1=" . $crId . " AND bo_obj_data = '" . $filename . "'");
if ($boId != "" && $boId != "0") :
$res = updateStmt("phoenix_log.b2b_objects","bo_ext_id0",$boId,array("bo_state", "1"), "bo_type = '105'");
/*
if ($db->affected_rows = 0) :
$opState = "ERR 112 : No update by 105!";
endif;
*/
$boIdNew101 = $boId; // For error handling ONLY
else :
$sqlStmt = "INSERT INTO phoenix_log.b2b_objects (bo_ver,bo_type,bo_state,bo_ext_id0,bo_ext_id1,bo_ext_id2,bo_obj_data,bo_createtime)" .
" VALUES ('0','101','1','0','$crId','0','$filename','$currentTime')";
$res = $db->query($sqlStmt);
if (DB::isError($res)) : die ("$PHP_SELF: " . $res->getMessage()); endif;
$boIdNew101 = getLastInsertID();
// $opState = "ERR 111 : No bo_ext_id0 ID!";
endif;
else :
// $opState = "ERR 110 : No courier ID!";
endif;
elseif ($custId == "6" || $custId == "106" || $custId == "11" || $custId == "1" || $custId == "2" || $custId == "100" || $custId == "101" || $custId == "102") :
$xmlTrId = "";
if ($xmlComm != "" && ($custId == "1" || $custId == "2" || $custId == "100" || $custId == "101" || $custId == "102")) :
$xmlJbId = getFieldValueFromClause("phoenix.tour", "jb_id", "tr_commission_no = '" . $xmlComm . "' ORDER BY jb_id DESC LIMIT 0,1");
$xmlTrId = getFieldValueFromClause("phoenix.tour", "tr_id", "tr_commission_no = '" . $xmlComm . "' ORDER BY jb_id DESC LIMIT 0,1");
$hqId = getFieldValueFromId("phoenix.user","usr_id", $usrId,"hq_id");
endif;
if ($debugMode) :
echo "xmlJbId: " . $xmlJbId . "<br>";
echo "hqId: " . $hqId . "<br>";
endif;
// Decode BASE64 and uncompress
$filedata = base64_decode($filedata);
$filedata = gzinflate($filedata);
$filedata = base64_encode($filedata);
// writeToFile("debug.log", $filedata);
$filedataArray = str_split($filedata, 32768); // 32K
$filedataArrayLen = count($filedataArray);
for ($i = 0; $i < $filedataArrayLen; $i++) :
$tmpChunk = $filedataArray[$i];
$filedataArray[$i] = "<![CDATA[" . $tmpChunk . "]]>";
endfor;
// writeToFile("debug2.log", $tmpOut);
// Write main file
// writeToFile($filename, $filedata);
// $bo_ext_id0 = "";
// $bo_ext_id0 = $xmlJbId;
/*
if ($xmlCust == "moebel_live") :
if ($xmlJbId != "" && is_numeric($xmlJbId)) :
$bo_ext_id0 = getFieldValueFromClause("phoenix.tour","tr_id","jb_id = '" . $xmlJbId . "' AND tr_sort = '2'"); // equals tr_id
endif;
endif;
*/
if ($debugMode) :
echo "xmlJbId: " . $xmlJbId . "<br>";
echo "xmlTrId: " . $xmlTrId . "<br>";
echo "usrId: " . $usrId . "<br>";
echo "filename: " . $filename . "<br>";
echo "currentTime: " . $currentTime . "<br>";
endif;
// **** Insert data sets into b2b_objects ***
if ($xmlJbId != "" && $xmlContext != "lda") :
if (!existsEntry("phoenix_log.b2b_objects",array("bo_type","101","bo_ext_id0",$xmlJbId,"bo_obj_data",$filename))) :
// Insert "101"
$sqlStmt = "INSERT INTO phoenix_log.b2b_objects (bo_ver,bo_type,bo_state,bo_ext_id0,bo_ext_id1,bo_ext_id2,bo_obj_data,bo_createtime)" .
" VALUES ('0','101','0','$xmlJbId','$usrId','0','$filename','$currentTime')";
$res = $db->query($sqlStmt);
if (DB::isError($res)) : die ("$PHP_SELF: " . $res->getMessage()); endif;
$boIdNew101 = getLastInsertID();
if ($debugMode) :
echo "boIdNew101: " . $boIdNew101 . "<br>";
endif;
// Insert "102"
for ($i = 0; $i < $filedataArrayLen; $i++) :
$sqlStmt = "INSERT INTO phoenix_log.b2b_objects (bo_ver,bo_type,bo_state,bo_ext_id0,bo_ext_id1,bo_ext_id2,bo_obj_data,bo_createtime)" .
" VALUES ('0','102','0','$boIdNew101','$usrId','$i','$filedataArray[$i]','$currentTime')";
$res = $db->query($sqlStmt);
if (DB::isError($res)) : die ("$PHP_SELF: " . $res->getMessage()); endif;
$boIdNew102 = getLastInsertID();
endfor;
endif;
else :
// Existing "101"
$boIdNew101 = getFieldValueFromClause("phoenix_log.b2b_objects", "bo_id", "bo_type = '101' AND bo_createtime >= '" . $currentDateYesterday . "' AND bo_obj_data = '" . $filename . "'");
// Job ID
// $xmlJbId = getFieldValueFromClause("phoenix_log.b2b_objects", "bo_ext_id1", "bo_type = '120' AND bo_state > '0' AND bo_createtime >= '" . $currentDateYesterday . "' AND bo_obj_data LIKE '%" . $filename . "%'");
$xmlTrId = getFieldValueFromClause("phoenix_log.b2b_objects", "bo_ext_id2", "bo_type = '120' AND bo_createtime >= '" . $currentDateYesterday . "' AND bo_obj_data LIKE '%" . $filename . "%'");
if ($debugMode) :
echo "xmlTrId: " . $xmlTrId . "<br>";
endif;
if ($boIdNew101 == "") :
// Insert "101"
$sqlStmt = "INSERT INTO phoenix_log.b2b_objects (bo_ver,bo_type,bo_state,bo_ext_id0,bo_ext_id1,bo_ext_id2,bo_obj_data,bo_createtime)" .
" VALUES ('0','101','0','$xmlTrId','$usrId','0','$filename','$currentTime')";
$res = $db->query($sqlStmt);
if (DB::isError($res)) : die ("$PHP_SELF: " . $res->getMessage()); endif;
$boIdNew101 = getLastInsertID();
else :
// Update "101"
$sqlStmt = "UPDATE phoenix_log.b2b_objects SET bo_ext_id0 = '$xmlTrId' WHERE bo_id = '$boIdNew101'";
$res = $db->query($sqlStmt);
if (DB::isError($res)) : die ("$PHP_SELF: " . $res->getMessage()); endif;
endif;
if ($debugMode) :
echo "boIdNew101: " . $boIdNew101 . "<br>";
endif;
// Insert "102"
if ($boIdNew101 != "") :
for ($i = 0; $i < $filedataArrayLen; $i++) :
$sqlStmt = "INSERT INTO phoenix_log.b2b_objects (bo_ver,bo_type,bo_state,bo_ext_id0,bo_ext_id1,bo_ext_id2,bo_obj_data,bo_createtime)" .
" VALUES ('0','102','0','$boIdNew101','$usrId','$i','$filedataArray[$i]','$currentTime')";
$res = $db->query($sqlStmt);
if (DB::isError($res)) : die ("$PHP_SELF: " . $res->getMessage()); endif;
$boIdNew102 = getLastInsertID();
endfor;
endif;
endif;
endif;
$db = $remDb;
else :
$opState = "ERR 107 : No target database specified!";
endif;
else :
$opState = "ERR 106 : No row in table conf_prop matched!";
endif;
else :
$opState = "ERR 105 : metaobject not reachable!";
endif;
else :
$opState = "ERR 104 : No global environment definitions found!";
endif;
else :
$opState = "ERR 103 : No file data!";
endif;
else :
$opState = "ERR 102 : Filename empty!";
endif;
else :
$opState = "ERR 101 : Unknown client IP!";
endif;
// Write metadata to log
$logFilename = "upload.log";
if ($custId != "" && is_numeric($custId)) :
$logFilename = "upload_" . $custId . ".log";
endif;
writeToFile($logFilename, $custId . " | " . $currentTime . " | " . date("Y-m-d H:i:s") . " | " . $currentClientIP . " | " . $filename . " | " . $metadata . " | " . $opState . " | boIdNew101: " . $boIdNew101 . " | boIdNew102: " . $boIdNew102 . " | xmlJbId: " . $xmlJbId . " | xmlTrId: " . $xmlTrId);
// Write file data by error
if (($opState != "OK" || ($boIdNew101 == "" || !is_numeric($boIdNew101))) && $filename != "" && $filedata != "") :
$errPath = "../upload/photos_err/";
writeToFile($errPath . $filename, $filedata);
$opState = "OK";
endif;
// Response
//echo $opState;
// 01.09.2016 CA: always respond "OK" because the data will never be sent correctly if they are wrong
echo "OK";
?>