Initial import

This commit is contained in:
Thomas Misund committed 2009-10-13 15:43:04 +02:00
commit 057959cb8f
1198 files changed
+89467

No files matched your search

+2
View File
@@ -0,0 +1,2 @@
credentials.php
inside/credentials.php
+1388
View File
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+510
View File
@@ -0,0 +1,510 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* The PEAR DB driver for PHP's dbase extension
* for interacting with dBase databases
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category Database
* @package DB
* @author Tomas V.V. Cox <cox@idecnet.com>
* @author Daniel Convissor <danielc@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: dbase.php,v 1.39 2005/02/19 23:25:25 danielc Exp $
* @link http://pear.php.net/package/DB
*/
/**
* Obtain the DB_common class so it can be extended from
*/
require_once 'DB/common.php';
/**
* The methods PEAR DB uses to interact with PHP's dbase extension
* for interacting with dBase databases
*
* These methods overload the ones declared in DB_common.
*
* @category Database
* @package DB
* @author Tomas V.V. Cox <cox@idecnet.com>
* @author Daniel Convissor <danielc@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: 1.7.6
* @link http://pear.php.net/package/DB
*/
class DB_dbase extends DB_common
{
// {{{ properties
/**
* The DB driver type (mysql, oci8, odbc, etc.)
* @var string
*/
var $phptype = 'dbase';
/**
* The database syntax variant to be used (db2, access, etc.), if any
* @var string
*/
var $dbsyntax = 'dbase';
/**
* The capabilities of this DB implementation
*
* The 'new_link' element contains the PHP version that first provided
* new_link support for this DBMS. Contains false if it's unsupported.
*
* Meaning of the 'limit' element:
* + 'emulate' = emulate with fetch row by number
* + 'alter' = alter the query
* + false = skip rows
*
* @var array
*/
var $features = array(
'limit' => false,
'new_link' => false,
'numrows' => true,
'pconnect' => false,
'prepare' => false,
'ssl' => false,
'transactions' => false,
);
/**
* A mapping of native error codes to DB error codes
* @var array
*/
var $errorcode_map = array(
);
/**
* The raw database connection created by PHP
* @var resource
*/
var $connection;
/**
* The DSN information for connecting to a database
* @var array
*/
var $dsn = array();
/**
* A means of emulating result resources
* @var array
*/
var $res_row = array();
/**
* The quantity of results so far
*
* For emulating result resources.
*
* @var integer
*/
var $result = 0;
/**
* Maps dbase data type id's to human readable strings
*
* The human readable values are based on the output of PHP's
* dbase_get_header_info() function.
*
* @var array
* @since Property available since Release 1.7.0
*/
var $types = array(
'C' => 'character',
'D' => 'date',
'L' => 'boolean',
'M' => 'memo',
'N' => 'number',
);
// }}}
// {{{ constructor
/**
* This constructor calls <kbd>$this->DB_common()</kbd>
*
* @return void
*/
function DB_dbase()
{
$this->DB_common();
}
// }}}
// {{{ connect()
/**
* Connect to the database and create it if it doesn't exist
*
* Don't call this method directly. Use DB::connect() instead.
*
* PEAR DB's dbase driver supports the following extra DSN options:
* + mode An integer specifying the read/write mode to use
* (0 = read only, 1 = write only, 2 = read/write).
* Available since PEAR DB 1.7.0.
* + fields An array of arrays that PHP's dbase_create() function needs
* to create a new database. This information is used if the
* dBase file specified in the "database" segment of the DSN
* does not exist. For more info, see the PHP manual's
* {@link http://php.net/dbase_create dbase_create()} page.
* Available since PEAR DB 1.7.0.
*
* Example of how to connect and establish a new dBase file if necessary:
* <code>
* require_once 'DB.php';
*
* $dsn = array(
* 'phptype' => 'dbase',
* 'database' => '/path/and/name/of/dbase/file',
* 'mode' => 2,
* 'fields' => array(
* array('a', 'N', 5, 0),
* array('b', 'C', 40),
* array('c', 'C', 255),
* array('d', 'C', 20),
* ),
* );
* $options = array(
* 'debug' => 2,
* 'portability' => DB_PORTABILITY_ALL,
* );
*
* $db =& DB::connect($dsn, $options);
* if (PEAR::isError($db)) {
* die($db->getMessage());
* }
* </code>
*
* @param array $dsn the data source name
* @param bool $persistent should the connection be persistent?
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function connect($dsn, $persistent = false)
{
if (!PEAR::loadExtension('dbase')) {
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
}
$this->dsn = $dsn;
if ($dsn['dbsyntax']) {
$this->dbsyntax = $dsn['dbsyntax'];
}
/*
* Turn track_errors on for entire script since $php_errormsg
* is the only way to find errors from the dbase extension.
*/
ini_set('track_errors', 1);
$php_errormsg = '';
if (!file_exists($dsn['database'])) {
$this->dsn['mode'] = 2;
if (empty($dsn['fields']) || !is_array($dsn['fields'])) {
return $this->raiseError(DB_ERROR_CONNECT_FAILED,
null, null, null,
'the dbase file does not exist and '
. 'it could not be created because '
. 'the "fields" element of the DSN '
. 'is not properly set');
}
$this->connection = @dbase_create($dsn['database'],
$dsn['fields']);
if (!$this->connection) {
return $this->raiseError(DB_ERROR_CONNECT_FAILED,
null, null, null,
'the dbase file does not exist and '
. 'the attempt to create it failed: '
. $php_errormsg);
}
} else {
if (!isset($this->dsn['mode'])) {
$this->dsn['mode'] = 0;
}
$this->connection = @dbase_open($dsn['database'],
$this->dsn['mode']);
if (!$this->connection) {
return $this->raiseError(DB_ERROR_CONNECT_FAILED,
null, null, null,
$php_errormsg);
}
}
return DB_OK;
}
// }}}
// {{{ disconnect()
/**
* Disconnects from the database server
*
* @return bool TRUE on success, FALSE on failure
*/
function disconnect()
{
$ret = @dbase_close($this->connection);
$this->connection = null;
return $ret;
}
// }}}
// {{{ &query()
function &query($query = null)
{
// emulate result resources
$this->res_row[(int)$this->result] = 0;
$tmp =& new DB_result($this, $this->result++);
return $tmp;
}
// }}}
// {{{ fetchInto()
/**
* Places a row from the result set into the given array
*
* Formating of the array and the data therein are configurable.
* See DB_result::fetchInto() for more information.
*
* This method is not meant to be called directly. Use
* DB_result::fetchInto() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result the query result resource
* @param array $arr the referenced array to put the data in
* @param int $fetchmode how the resulting array should be indexed
* @param int $rownum the row number to fetch (0 = first row)
*
* @return mixed DB_OK on success, NULL when the end of a result set is
* reached or on failure
*
* @see DB_result::fetchInto()
*/
function fetchInto($result, &$arr, $fetchmode, $rownum = null)
{
if ($rownum === null) {
$rownum = $this->res_row[(int)$result]++;
}
if ($fetchmode & DB_FETCHMODE_ASSOC) {
$arr = @dbase_get_record_with_names($this->connection, $rownum);
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) {
$arr = array_change_key_case($arr, CASE_LOWER);
}
} else {
$arr = @dbase_get_record($this->connection, $rownum);
}
if (!$arr) {
return null;
}
if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
$this->_rtrimArrayValues($arr);
}
if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
$this->_convertNullArrayValuesToEmpty($arr);
}
return DB_OK;
}
// }}}
// {{{ numCols()
/**
* Gets the number of columns in a result set
*
* This method is not meant to be called directly. Use
* DB_result::numCols() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return int the number of columns. A DB_Error object on failure.
*
* @see DB_result::numCols()
*/
function numCols($foo)
{
return @dbase_numfields($this->connection);
}
// }}}
// {{{ numRows()
/**
* Gets the number of rows in a result set
*
* This method is not meant to be called directly. Use
* DB_result::numRows() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return int the number of rows. A DB_Error object on failure.
*
* @see DB_result::numRows()
*/
function numRows($foo)
{
return @dbase_numrecords($this->connection);
}
// }}}
// {{{ quoteSmart()
/**
* Formats input so it can be safely used in a query
*
* @param mixed $in the data to be formatted
*
* @return mixed the formatted data. The format depends on the input's
* PHP type:
* + null = the string <samp>NULL</samp>
* + boolean = <samp>T</samp> if true or
* <samp>F</samp> if false. Use the <kbd>Logical</kbd>
* data type.
* + integer or double = the unquoted number
* + other (including strings and numeric strings) =
* the data with single quotes escaped by preceeding
* single quotes then the whole string is encapsulated
* between single quotes
*
* @see DB_common::quoteSmart()
* @since Method available since Release 1.6.0
*/
function quoteSmart($in)
{
if (is_int($in) || is_double($in)) {
return $in;
} elseif (is_bool($in)) {
return $in ? 'T' : 'F';
} elseif (is_null($in)) {
return 'NULL';
} else {
return "'" . $this->escapeSimple($in) . "'";
}
}
// }}}
// {{{ tableInfo()
/**
* Returns information about the current database
*
* @param mixed $result THIS IS UNUSED IN DBASE. The current database
* is examined regardless of what is provided here.
* @param int $mode a valid tableInfo mode
*
* @return array an associative array with the information requested.
* A DB_Error object on failure.
*
* @see DB_common::tableInfo()
* @since Method available since Release 1.7.0
*/
function tableInfo($result = null, $mode = null)
{
if (function_exists('dbase_get_header_info')) {
$id = @dbase_get_header_info($this->connection);
if (!$id && $php_errormsg) {
return $this->raiseError(DB_ERROR,
null, null, null,
$php_errormsg);
}
} else {
/*
* This segment for PHP 4 is loosely based on code by
* Hadi Rusiah <deegos@yahoo.com> in the comments on
* the dBase reference page in the PHP manual.
*/
$db = @fopen($this->dsn['database'], 'r');
if (!$db) {
return $this->raiseError(DB_ERROR_CONNECT_FAILED,
null, null, null,
$php_errormsg);
}
$id = array();
$i = 0;
$line = fread($db, 32);
while (!feof($db)) {
$line = fread($db, 32);
if (substr($line, 0, 1) == chr(13)) {
break;
} else {
$pos = strpos(substr($line, 0, 10), chr(0));
$pos = ($pos == 0 ? 10 : $pos);
$id[$i] = array(
'name' => substr($line, 0, $pos),
'type' => $this->types[substr($line, 11, 1)],
'length' => ord(substr($line, 16, 1)),
'precision' => ord(substr($line, 17, 1)),
);
}
$i++;
}
fclose($db);
}
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
$case_func = 'strtolower';
} else {
$case_func = 'strval';
}
$res = array();
$count = count($id);
if ($mode) {
$res['num_fields'] = $count;
}
for ($i = 0; $i < $count; $i++) {
$res[$i] = array(
'table' => $this->dsn['database'],
'name' => $case_func($id[$i]['name']),
'type' => $id[$i]['type'],
'len' => $id[$i]['length'],
'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;
}
}
return $res;
}
// }}}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
*/
?>
+770
View File
@@ -0,0 +1,770 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* The PEAR DB driver for PHP's fbsql extension
* for interacting with FrontBase databases
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category Database
* @package DB
* @author Frank M. Kromann <frank@frontbase.com>
* @author Daniel Convissor <danielc@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: fbsql.php,v 1.82 2005/03/04 23:12:36 danielc Exp $
* @link http://pear.php.net/package/DB
*/
/**
* Obtain the DB_common class so it can be extended from
*/
require_once 'DB/common.php';
/**
* The methods PEAR DB uses to interact with PHP's fbsql extension
* for interacting with FrontBase databases
*
* These methods overload the ones declared in DB_common.
*
* @category Database
* @package DB
* @author Frank M. Kromann <frank@frontbase.com>
* @author Daniel Convissor <danielc@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: 1.7.6
* @link http://pear.php.net/package/DB
* @since Class functional since Release 1.7.0
*/
class DB_fbsql extends DB_common
{
// {{{ properties
/**
* The DB driver type (mysql, oci8, odbc, etc.)
* @var string
*/
var $phptype = 'fbsql';
/**
* The database syntax variant to be used (db2, access, etc.), if any
* @var string
*/
var $dbsyntax = 'fbsql';
/**
* The capabilities of this DB implementation
*
* The 'new_link' element contains the PHP version that first provided
* new_link support for this DBMS. Contains false if it's unsupported.
*
* Meaning of the 'limit' element:
* + 'emulate' = emulate with fetch row by number
* + 'alter' = alter the query
* + false = skip rows
*
* @var array
*/
var $features = array(
'limit' => 'alter',
'new_link' => false,
'numrows' => true,
'pconnect' => true,
'prepare' => false,
'ssl' => false,
'transactions' => true,
);
/**
* A mapping of native error codes to DB error codes
* @var array
*/
var $errorcode_map = array(
22 => DB_ERROR_SYNTAX,
85 => DB_ERROR_ALREADY_EXISTS,
108 => DB_ERROR_SYNTAX,
116 => DB_ERROR_NOSUCHTABLE,
124 => DB_ERROR_VALUE_COUNT_ON_ROW,
215 => DB_ERROR_NOSUCHFIELD,
217 => DB_ERROR_INVALID_NUMBER,
226 => DB_ERROR_NOSUCHFIELD,
231 => DB_ERROR_INVALID,
239 => DB_ERROR_TRUNCATED,
251 => DB_ERROR_SYNTAX,
266 => DB_ERROR_NOT_FOUND,
357 => DB_ERROR_CONSTRAINT_NOT_NULL,
358 => DB_ERROR_CONSTRAINT,
360 => DB_ERROR_CONSTRAINT,
361 => DB_ERROR_CONSTRAINT,
);
/**
* The raw database connection created by PHP
* @var resource
*/
var $connection;
/**
* The DSN information for connecting to a database
* @var array
*/
var $dsn = array();
// }}}
// {{{ constructor
/**
* This constructor calls <kbd>$this->DB_common()</kbd>
*
* @return void
*/
function DB_fbsql()
{
$this->DB_common();
}
// }}}
// {{{ connect()
/**
* Connect to the database server, log in and open the database
*
* Don't call this method directly. Use DB::connect() instead.
*
* @param array $dsn the data source name
* @param bool $persistent should the connection be persistent?
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function connect($dsn, $persistent = false)
{
if (!PEAR::loadExtension('fbsql')) {
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
}
$this->dsn = $dsn;
if ($dsn['dbsyntax']) {
$this->dbsyntax = $dsn['dbsyntax'];
}
$params = array(
$dsn['hostspec'] ? $dsn['hostspec'] : 'localhost',
$dsn['username'] ? $dsn['username'] : null,
$dsn['password'] ? $dsn['password'] : null,
);
$connect_function = $persistent ? 'fbsql_pconnect' : 'fbsql_connect';
$ini = ini_get('track_errors');
$php_errormsg = '';
if ($ini) {
$this->connection = @call_user_func_array($connect_function,
$params);
} else {
ini_set('track_errors', 1);
$this->connection = @call_user_func_array($connect_function,
$params);
ini_set('track_errors', $ini);
}
if (!$this->connection) {
return $this->raiseError(DB_ERROR_CONNECT_FAILED,
null, null, null,
$php_errormsg);
}
if ($dsn['database']) {
if (!@fbsql_select_db($dsn['database'], $this->connection)) {
return $this->fbsqlRaiseError();
}
}
return DB_OK;
}
// }}}
// {{{ disconnect()
/**
* Disconnects from the database server
*
* @return bool TRUE on success, FALSE on failure
*/
function disconnect()
{
$ret = @fbsql_close($this->connection);
$this->connection = null;
return $ret;
}
// }}}
// {{{ simpleQuery()
/**
* Sends a query to the database server
*
* @param string the SQL query string
*
* @return mixed + a PHP result resrouce for successful SELECT queries
* + the DB_OK constant for other successful queries
* + a DB_Error object 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;
}
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);
}
// }}}
// {{{ fetchInto()
/**
* Places a row from the result set into the given array
*
* Formating of the array and the data therein are configurable.
* See DB_result::fetchInto() for more information.
*
* This method is not meant to be called directly. Use
* DB_result::fetchInto() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result the query result resource
* @param array $arr the referenced array to put the data in
* @param int $fetchmode how the resulting array should be indexed
* @param int $rownum the row number to fetch (0 = first row)
*
* @return mixed DB_OK on success, NULL when the end of a result set is
* reached or on failure
*
* @see DB_result::fetchInto()
*/
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);
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) {
$arr = array_change_key_case($arr, CASE_LOWER);
}
} else {
$arr = @fbsql_fetch_row($result);
}
if (!$arr) {
return null;
}
if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
$this->_rtrimArrayValues($arr);
}
if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
$this->_convertNullArrayValuesToEmpty($arr);
}
return DB_OK;
}
// }}}
// {{{ freeResult()
/**
* Deletes the result set and frees the memory occupied by the result set
*
* This method is not meant to be called directly. Use
* DB_result::free() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return bool TRUE on success, FALSE if $result is invalid
*
* @see DB_result::free()
*/
function freeResult($result)
{
return @fbsql_free_result($result);
}
// }}}
// {{{ autoCommit()
/**
* Enables or disables automatic commits
*
* @param bool $onoff true turns it on, false turns it off
*
* @return int DB_OK on success. A DB_Error object if the driver
* doesn't support auto-committing transactions.
*/
function autoCommit($onoff=false)
{
if ($onoff) {
$this->query("SET COMMIT TRUE");
} else {
$this->query("SET COMMIT FALSE");
}
}
// }}}
// {{{ commit()
/**
* Commits the current transaction
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function commit()
{
@fbsql_commit();
}
// }}}
// {{{ rollback()
/**
* Reverts the current transaction
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function rollback()
{
@fbsql_rollback();
}
// }}}
// {{{ numCols()
/**
* Gets the number of columns in a result set
*
* This method is not meant to be called directly. Use
* DB_result::numCols() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return int the number of columns. A DB_Error object on failure.
*
* @see DB_result::numCols()
*/
function numCols($result)
{
$cols = @fbsql_num_fields($result);
if (!$cols) {
return $this->fbsqlRaiseError();
}
return $cols;
}
// }}}
// {{{ numRows()
/**
* Gets the number of rows in a result set
*
* This method is not meant to be called directly. Use
* DB_result::numRows() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return int the number of rows. A DB_Error object on failure.
*
* @see DB_result::numRows()
*/
function numRows($result)
{
$rows = @fbsql_num_rows($result);
if ($rows === null) {
return $this->fbsqlRaiseError();
}
return $rows;
}
// }}}
// {{{ affectedRows()
/**
* Determines the number of rows affected by a data maniuplation query
*
* 0 is returned for queries that don't manipulate data.
*
* @return int the number of rows. A DB_Error object on failure.
*/
function affectedRows()
{
if (DB::isManip($this->last_query)) {
$result = @fbsql_affected_rows($this->connection);
} else {
$result = 0;
}
return $result;
}
// }}}
// {{{ nextId()
/**
* Returns the next free id in a sequence
*
* @param string $seq_name name of the sequence
* @param boolean $ondemand when true, the seqence is automatically
* created if it does not exist
*
* @return int the next id number in the sequence.
* A DB_Error object on failure.
*
* @see DB_common::nextID(), DB_common::getSequenceName(),
* DB_fbsql::createSequence(), DB_fbsql::dropSequence()
*/
function nextId($seq_name, $ondemand = true)
{
$seqname = $this->getSequenceName($seq_name);
do {
$repeat = 0;
$this->pushErrorHandling(PEAR_ERROR_RETURN);
$result = $this->query('SELECT UNIQUE FROM ' . $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 $result;
}
} else {
$repeat = 0;
}
} while ($repeat);
if (DB::isError($result)) {
return $this->fbsqlRaiseError();
}
$result->fetchInto($tmp, DB_FETCHMODE_ORDERED);
return $tmp[0];
}
/**
* Creates a new sequence
*
* @param string $seq_name name of the new sequence
*
* @return int DB_OK on success. A DB_Error object on failure.
*
* @see DB_common::createSequence(), DB_common::getSequenceName(),
* DB_fbsql::nextID(), DB_fbsql::dropSequence()
*/
function createSequence($seq_name)
{
$seqname = $this->getSequenceName($seq_name);
$res = $this->query('CREATE TABLE ' . $seqname
. ' (id INTEGER NOT NULL,'
. ' PRIMARY KEY(id))');
if ($res) {
$res = $this->query('SET UNIQUE = 0 FOR ' . $seqname);
}
return $res;
}
// }}}
// {{{ dropSequence()
/**
* Deletes a sequence
*
* @param string $seq_name name of the sequence to be deleted
*
* @return int DB_OK on success. A DB_Error object on failure.
*
* @see DB_common::dropSequence(), DB_common::getSequenceName(),
* DB_fbsql::nextID(), DB_fbsql::createSequence()
*/
function dropSequence($seq_name)
{
return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name)
. ' RESTRICT');
}
// }}}
// {{{ modifyLimitQuery()
/**
* Adds LIMIT clauses to a query string according to current DBMS standards
*
* @param string $query the query to modify
* @param int $from the row to start to fetching (0 = the first row)
* @param int $count the numbers of rows to fetch
* @param mixed $params array, string or numeric data to be used in
* execution of the statement. Quantity of items
* passed must match quantity of placeholders in
* query: meaning 1 placeholder for non-array
* parameters or 1 placeholder per array element.
*
* @return string the query string with LIMIT clauses added
*
* @access protected
*/
function modifyLimitQuery($query, $from, $count, $params = array())
{
if (DB::isManip($query)) {
return preg_replace('/^([\s(])*SELECT/i',
"\\1SELECT TOP($count)", $query);
} else {
return preg_replace('/([\s(])*SELECT/i',
"\\1SELECT TOP($from, $count)", $query);
}
}
// }}}
// {{{ quoteSmart()
/**
* Formats input so it can be safely used in a query
*
* @param mixed $in the data to be formatted
*
* @return mixed the formatted data. The format depends on the input's
* PHP type:
* + null = the string <samp>NULL</samp>
* + boolean = string <samp>TRUE</samp> or <samp>FALSE</samp>
* + integer or double = the unquoted number
* + other (including strings and numeric strings) =
* the data escaped according to FrontBase's settings
* then encapsulated between single quotes
*
* @see DB_common::quoteSmart()
* @since Method available since Release 1.6.0
*/
function quoteSmart($in)
{
if (is_int($in) || is_double($in)) {
return $in;
} elseif (is_bool($in)) {
return $in ? 'TRUE' : 'FALSE';
} elseif (is_null($in)) {
return 'NULL';
} else {
return "'" . $this->escapeSimple($in) . "'";
}
}
// }}}
// {{{ fbsqlRaiseError()
/**
* Produces a DB_Error object regarding the current problem
*
* @param int $errno if the error is being manually raised pass a
* DB_ERROR* constant here. If this isn't passed
* the error information gathered from the DBMS.
*
* @return object the DB_Error object
*
* @see DB_common::raiseError(),
* DB_fbsql::errorNative(), DB_common::errorCode()
*/
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));
}
// }}}
// {{{ errorNative()
/**
* Gets the DBMS' native error code produced by the last query
*
* @return int the DBMS' error code
*/
function errorNative()
{
return @fbsql_errno($this->connection);
}
// }}}
// {{{ tableInfo()
/**
* Returns information about a table or a result set
*
* @param object|string $result DB_result object from a query or a
* string containing the name of a table.
* While this also accepts a query result
* resource identifier, this behavior is
* deprecated.
* @param int $mode a valid tableInfo mode
*
* @return array an associative array with the information requested.
* A DB_Error object on failure.
*
* @see DB_common::tableInfo()
*/
function tableInfo($result, $mode = null)
{
if (is_string($result)) {
/*
* Probably received a table name.
* Create a result resource identifier.
*/
$id = @fbsql_list_fields($this->dsn['database'],
$result, $this->connection);
$got_string = true;
} elseif (isset($result->result)) {
/*
* Probably received a result object.
* Extract the result resource identifier.
*/
$id = $result->result;
$got_string = false;
} else {
/*
* Probably received a result resource identifier.
* Copy it.
* Deprecated. Here for compatibility only.
*/
$id = $result;
$got_string = false;
}
if (!is_resource($id)) {
return $this->fbsqlRaiseError(DB_ERROR_NEED_MORE_DATA);
}
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
$case_func = 'strtolower';
} else {
$case_func = 'strval';
}
$count = @fbsql_num_fields($id);
$res = array();
if ($mode) {
$res['num_fields'] = $count;
}
for ($i = 0; $i < $count; $i++) {
$res[$i] = array(
'table' => $case_func(@fbsql_field_table($id, $i)),
'name' => $case_func(@fbsql_field_name($id, $i)),
'type' => @fbsql_field_type($id, $i),
'len' => @fbsql_field_len($id, $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 ($got_string) {
@fbsql_free_result($id);
}
return $res;
}
// }}}
// {{{ getSpecialQuery()
/**
* Obtains the query string needed for listing a given type of objects
*
* @param string $type the kind of objects you want to retrieve
*
* @return string the SQL query string or null if the driver doesn't
* support the object type requested
*
* @access protected
* @see DB_common::getListOf()
*/
function getSpecialQuery($type)
{
switch ($type) {
case 'tables':
return 'SELECT "table_name" FROM information_schema.tables'
. ' t0, information_schema.schemata t1'
. ' WHERE t0.schema_pk=t1.schema_pk AND'
. ' "table_type" = \'BASE TABLE\''
. ' AND "schema_name" = current_schema';
case 'views':
return 'SELECT "table_name" FROM information_schema.tables'
. ' t0, information_schema.schemata t1'
. ' WHERE t0.schema_pk=t1.schema_pk AND'
. ' "table_type" = \'VIEW\''
. ' AND "schema_name" = current_schema';
case 'users':
return 'SELECT "user_name" from information_schema.users';
case 'functions':
return 'SELECT "routine_name" FROM'
. ' information_schema.psm_routines'
. ' t0, information_schema.schemata t1'
. ' WHERE t0.schema_pk=t1.schema_pk'
. ' AND "routine_kind"=\'FUNCTION\''
. ' AND "schema_name" = current_schema';
case 'procedures':
return 'SELECT "routine_name" FROM'
. ' information_schema.psm_routines'
. ' t0, information_schema.schemata t1'
. ' WHERE t0.schema_pk=t1.schema_pk'
. ' AND "routine_kind"=\'PROCEDURE\''
. ' AND "schema_name" = current_schema';
default:
return null;
}
}
// }}}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
*/
?>
File diff suppressed because it is too large. Load diff
+681
View File
@@ -0,0 +1,681 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* The PEAR DB driver for PHP's ifx extension
* for interacting with Informix databases
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category Database
* @package DB
* @author Tomas V.V.Cox <cox@idecnet.com>
* @author Daniel Convissor <danielc@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: ifx.php,v 1.70 2005/02/20 00:44:48 danielc Exp $
* @link http://pear.php.net/package/DB
*/
/**
* Obtain the DB_common class so it can be extended from
*/
require_once 'DB/common.php';
/**
* The methods PEAR DB uses to interact with PHP's ifx extension
* for interacting with Informix databases
*
* These methods overload the ones declared in DB_common.
*
* More info on Informix errors can be found at:
* http://www.informix.com/answers/english/ierrors.htm
*
* TODO:
* - set needed env Informix vars on connect
* - implement native prepare/execute
*
* @category Database
* @package DB
* @author Tomas V.V.Cox <cox@idecnet.com>
* @author Daniel Convissor <danielc@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: 1.7.6
* @link http://pear.php.net/package/DB
*/
class DB_ifx extends DB_common
{
// {{{ properties
/**
* The DB driver type (mysql, oci8, odbc, etc.)
* @var string
*/
var $phptype = 'ifx';
/**
* The database syntax variant to be used (db2, access, etc.), if any
* @var string
*/
var $dbsyntax = 'ifx';
/**
* The capabilities of this DB implementation
*
* The 'new_link' element contains the PHP version that first provided
* new_link support for this DBMS. Contains false if it's unsupported.
*
* Meaning of the 'limit' element:
* + 'emulate' = emulate with fetch row by number
* + 'alter' = alter the query
* + false = skip rows
*
* @var array
*/
var $features = array(
'limit' => 'emulate',
'new_link' => false,
'numrows' => 'emulate',
'pconnect' => true,
'prepare' => false,
'ssl' => false,
'transactions' => true,
);
/**
* A mapping of native error codes to DB error codes
* @var array
*/
var $errorcode_map = array(
'-201' => DB_ERROR_SYNTAX,
'-206' => DB_ERROR_NOSUCHTABLE,
'-217' => DB_ERROR_NOSUCHFIELD,
'-236' => DB_ERROR_VALUE_COUNT_ON_ROW,
'-239' => DB_ERROR_CONSTRAINT,
'-253' => DB_ERROR_SYNTAX,
'-292' => DB_ERROR_CONSTRAINT_NOT_NULL,
'-310' => DB_ERROR_ALREADY_EXISTS,
'-316' => DB_ERROR_ALREADY_EXISTS,
'-319' => DB_ERROR_NOT_FOUND,
'-329' => DB_ERROR_NODBSELECTED,
'-346' => DB_ERROR_CONSTRAINT,
'-386' => DB_ERROR_CONSTRAINT_NOT_NULL,
'-391' => DB_ERROR_CONSTRAINT_NOT_NULL,
'-554' => DB_ERROR_SYNTAX,
'-691' => DB_ERROR_CONSTRAINT,
'-692' => DB_ERROR_CONSTRAINT,
'-703' => DB_ERROR_CONSTRAINT_NOT_NULL,
'-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,
'-1213' => DB_ERROR_INVALID_NUMBER,
);
/**
* The raw database connection created by PHP
* @var resource
*/
var $connection;
/**
* The DSN information for connecting to a database
* @var array
*/
var $dsn = array();
/**
* Should data manipulation queries be committed automatically?
* @var bool
* @access private
*/
var $autocommit = true;
/**
* The quantity of transactions begun
*
* {@internal While this is private, it can't actually be designated
* private in PHP 5 because it is directly accessed in the test suite.}}
*
* @var integer
* @access private
*/
var $transaction_opcount = 0;
/**
* The number of rows affected by a data manipulation query
* @var integer
* @access private
*/
var $affected = 0;
// }}}
// {{{ constructor
/**
* This constructor calls <kbd>$this->DB_common()</kbd>
*
* @return void
*/
function DB_ifx()
{
$this->DB_common();
}
// }}}
// {{{ connect()
/**
* Connect to the database server, log in and open the database
*
* Don't call this method directly. Use DB::connect() instead.
*
* @param array $dsn the data source name
* @param bool $persistent should the connection be persistent?
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function connect($dsn, $persistent = false)
{
if (!PEAR::loadExtension('informix') &&
!PEAR::loadExtension('Informix'))
{
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
}
$this->dsn = $dsn;
if ($dsn['dbsyntax']) {
$this->dbsyntax = $dsn['dbsyntax'];
}
$dbhost = $dsn['hostspec'] ? '@' . $dsn['hostspec'] : '';
$dbname = $dsn['database'] ? $dsn['database'] . $dbhost : '';
$user = $dsn['username'] ? $dsn['username'] : '';
$pw = $dsn['password'] ? $dsn['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;
}
// }}}
// {{{ disconnect()
/**
* Disconnects from the database server
*
* @return bool TRUE on success, FALSE on failure
*/
function disconnect()
{
$ret = @ifx_close($this->connection);
$this->connection = null;
return $ret;
}
// }}}
// {{{ simpleQuery()
/**
* Sends a query to the database server
*
* @param string the SQL query string
*
* @return mixed + a PHP result resrouce for successful SELECT queries
* + the DB_OK constant for other successful queries
* + a DB_Error object on failure
*/
function simpleQuery($query)
{
$ismanip = DB::isManip($query);
$this->last_query = $query;
$this->affected = null;
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 {
if (!$this->autocommit && $ismanip) {
if ($this->transaction_opcount == 0) {
$result = @ifx_query('BEGIN WORK', $this->connection);
if (!$result) {
return $this->ifxRaiseError();
}
}
$this->transaction_opcount++;
}
$result = @ifx_query($query, $this->connection);
}
if (!$result) {
return $this->ifxRaiseError();
}
$this->affected = @ifx_affected_rows($result);
// Determine which queries should return data, and which
// should return an error code only.
if (preg_match('/(SELECT)/i', $query)) {
return $result;
}
// XXX Testme: free results inside a transaction
// may cause to stop it and commit the work?
// Result has to be freed even with a insert or update
@ifx_free_result($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;
}
// }}}
// {{{ affectedRows()
/**
* Determines the number of rows affected by a data maniuplation query
*
* 0 is returned for queries that don't manipulate data.
*
* @return int the number of rows. A DB_Error object on failure.
*/
function affectedRows()
{
if (DB::isManip($this->last_query)) {
return $this->affected;
} else {
return 0;
}
}
// }}}
// {{{ fetchInto()
/**
* Places a row from the result set into the given array
*
* Formating of the array and the data therein are configurable.
* See DB_result::fetchInto() for more information.
*
* This method is not meant to be called directly. Use
* DB_result::fetchInto() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result the query result resource
* @param array $arr the referenced array to put the data in
* @param int $fetchmode how the resulting array should be indexed
* @param int $rownum the row number to fetch (0 = first row)
*
* @return mixed DB_OK on success, NULL when the end of a result set is
* reached or on failure
*
* @see DB_result::fetchInto()
*/
function fetchInto($result, &$arr, $fetchmode, $rownum = null)
{
if (($rownum !== null) && ($rownum < 0)) {
return null;
}
if ($rownum === null) {
/*
* Even though fetch_row() should return the next row if
* $rownum is null, it doesn't in all cases. Bug 598.
*/
$rownum = 'NEXT';
} else {
// Index starts at row 1, unlike most DBMS's starting at 0.
$rownum++;
}
if (!$arr = @ifx_fetch_row($result, $rownum)) {
return null;
}
if ($fetchmode !== DB_FETCHMODE_ASSOC) {
$i=0;
$order = array();
foreach ($arr as $val) {
$order[$i++] = $val;
}
$arr = $order;
} elseif ($fetchmode == DB_FETCHMODE_ASSOC &&
$this->options['portability'] & DB_PORTABILITY_LOWERCASE)
{
$arr = array_change_key_case($arr, CASE_LOWER);
}
if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
$this->_rtrimArrayValues($arr);
}
if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
$this->_convertNullArrayValuesToEmpty($arr);
}
return DB_OK;
}
// }}}
// {{{ numCols()
/**
* Gets the number of columns in a result set
*
* This method is not meant to be called directly. Use
* DB_result::numCols() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return int the number of columns. A DB_Error object on failure.
*
* @see DB_result::numCols()
*/
function numCols($result)
{
if (!$cols = @ifx_num_fields($result)) {
return $this->ifxRaiseError();
}
return $cols;
}
// }}}
// {{{ freeResult()
/**
* Deletes the result set and frees the memory occupied by the result set
*
* This method is not meant to be called directly. Use
* DB_result::free() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return bool TRUE on success, FALSE if $result is invalid
*
* @see DB_result::free()
*/
function freeResult($result)
{
return @ifx_free_result($result);
}
// }}}
// {{{ autoCommit()
/**
* Enables or disables automatic commits
*
* @param bool $onoff true turns it on, false turns it off
*
* @return int DB_OK on success. A DB_Error object if the driver
* doesn't support auto-committing transactions.
*/
function autoCommit($onoff = true)
{
// XXX if $this->transaction_opcount > 0, we should probably
// issue a warning here.
$this->autocommit = $onoff ? true : false;
return DB_OK;
}
// }}}
// {{{ commit()
/**
* Commits the current transaction
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function commit()
{
if ($this->transaction_opcount > 0) {
$result = @ifx_query('COMMIT WORK', $this->connection);
$this->transaction_opcount = 0;
if (!$result) {
return $this->ifxRaiseError();
}
}
return DB_OK;
}
// }}}
// {{{ rollback()
/**
* Reverts the current transaction
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function rollback()
{
if ($this->transaction_opcount > 0) {
$result = @ifx_query('ROLLBACK WORK', $this->connection);
$this->transaction_opcount = 0;
if (!$result) {
return $this->ifxRaiseError();
}
}
return DB_OK;
}
// }}}
// {{{ ifxRaiseError()
/**
* Produces a DB_Error object regarding the current problem
*
* @param int $errno if the error is being manually raised pass a
* DB_ERROR* constant here. If this isn't passed
* the error information gathered from the DBMS.
*
* @return object the DB_Error object
*
* @see DB_common::raiseError(),
* DB_ifx::errorNative(), DB_ifx::errorCode()
*/
function ifxRaiseError($errno = null)
{
if ($errno === null) {
$errno = $this->errorCode(ifx_error());
}
return $this->raiseError($errno, null, null, null,
$this->errorNative());
}
// }}}
// {{{ errorNative()
/**
* Gets the DBMS' native error code and message produced by the last query
*
* @return string the DBMS' error code and message
*/
function errorNative()
{
return @ifx_error() . ' ' . @ifx_errormsg();
}
// }}}
// {{{ errorCode()
/**
* Maps native error codes to DB's portable ones.
*
* Requires that the DB implementation's constructor fills
* in the <var>$errorcode_map</var> property.
*
* @param string $nativecode error code returned by the database
* @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;
}
// }}}
// {{{ tableInfo()
/**
* Returns information about a table or a result set
*
* NOTE: only supports 'table' if <var>$result</var> is a table name.
*
* If analyzing a query result and the result has duplicate field names,
* an error will be raised saying
* <samp>can't distinguish duplicate field names</samp>.
*
* @param object|string $result DB_result object from a query or a
* string containing the name of a table.
* While this also accepts a query result
* resource identifier, this behavior is
* deprecated.
* @param int $mode a valid tableInfo mode
*
* @return array an associative array with the information requested.
* A DB_Error object on failure.
*
* @see DB_common::tableInfo()
* @since Method available since Release 1.6.0
*/
function tableInfo($result, $mode = null)
{
if (is_string($result)) {
/*
* Probably received a table name.
* Create a result resource identifier.
*/
$id = @ifx_query("SELECT * FROM $result WHERE 1=0",
$this->connection);
$got_string = true;
} elseif (isset($result->result)) {
/*
* Probably received a result object.
* Extract the result resource identifier.
*/
$id = $result->result;
$got_string = false;
} else {
/*
* Probably received a result resource identifier.
* Copy it.
*/
$id = $result;
$got_string = false;
}
if (!is_resource($id)) {
return $this->ifxRaiseError(DB_ERROR_NEED_MORE_DATA);
}
$flds = @ifx_fieldproperties($id);
$count = @ifx_num_fields($id);
if (count($flds) != $count) {
return $this->raiseError("can't distinguish duplicate field names");
}
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
$case_func = 'strtolower';
} else {
$case_func = 'strval';
}
$i = 0;
$res = array();
if ($mode) {
$res['num_fields'] = $count;
}
foreach ($flds as $key => $value) {
$props = explode(';', $value);
$res[$i] = array(
'table' => $got_string ? $case_func($result) : '',
'name' => $case_func($key),
'type' => $props[0],
'len' => $props[1],
'flags' => $props[4] == 'N' ? 'not_null' : '',
);
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;
}
$i++;
}
// free the result only if we were called on a table
if ($got_string) {
@ifx_free_result($id);
}
return $res;
}
// }}}
// {{{ getSpecialQuery()
/**
* Obtains the query string needed for listing a given type of objects
*
* @param string $type the kind of objects you want to retrieve
*
* @return string the SQL query string or null if the driver doesn't
* support the object type requested
*
* @access protected
* @see DB_common::getListOf()
*/
function getSpecialQuery($type)
{
switch ($type) {
case 'tables':
return 'SELECT tabname FROM systables WHERE tabid >= 100';
default:
return null;
}
}
// }}}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
*/
?>
+810
View File
@@ -0,0 +1,810 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* The PEAR DB driver for PHP's msql extension
* for interacting with Mini SQL databases
*
* PHP's mSQL extension did weird things with NULL values prior to PHP
* 4.3.11 and 5.0.4. Make sure your version of PHP meets or exceeds
* those versions.
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category Database
* @package DB
* @author Daniel Convissor <danielc@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: msql.php,v 1.57 2005/02/22 07:26:46 danielc Exp $
* @link http://pear.php.net/package/DB
*/
/**
* Obtain the DB_common class so it can be extended from
*/
require_once 'DB/common.php';
/**
* The methods PEAR DB uses to interact with PHP's msql extension
* for interacting with Mini SQL databases
*
* These methods overload the ones declared in DB_common.
*
* PHP's mSQL extension did weird things with NULL values prior to PHP
* 4.3.11 and 5.0.4. Make sure your version of PHP meets or exceeds
* those versions.
*
* @category Database
* @package DB
* @author Daniel Convissor <danielc@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: 1.7.6
* @link http://pear.php.net/package/DB
* @since Class not functional until Release 1.7.0
*/
class DB_msql extends DB_common
{
// {{{ properties
/**
* The DB driver type (mysql, oci8, odbc, etc.)
* @var string
*/
var $phptype = 'msql';
/**
* The database syntax variant to be used (db2, access, etc.), if any
* @var string
*/
var $dbsyntax = 'msql';
/**
* The capabilities of this DB implementation
*
* The 'new_link' element contains the PHP version that first provided
* new_link support for this DBMS. Contains false if it's unsupported.
*
* Meaning of the 'limit' element:
* + 'emulate' = emulate with fetch row by number
* + 'alter' = alter the query
* + false = skip rows
*
* @var array
*/
var $features = array(
'limit' => 'emulate',
'new_link' => false,
'numrows' => true,
'pconnect' => true,
'prepare' => false,
'ssl' => false,
'transactions' => false,
);
/**
* A mapping of native error codes to DB error codes
* @var array
*/
var $errorcode_map = array(
);
/**
* The raw database connection created by PHP
* @var resource
*/
var $connection;
/**
* The DSN information for connecting to a database
* @var array
*/
var $dsn = array();
/**
* The query result resource created by PHP
*
* Used to make affectedRows() work. Only contains the result for
* data manipulation queries. Contains false for other queries.
*
* @var resource
* @access private
*/
var $_result;
// }}}
// {{{ constructor
/**
* This constructor calls <kbd>$this->DB_common()</kbd>
*
* @return void
*/
function DB_msql()
{
$this->DB_common();
}
// }}}
// {{{ connect()
/**
* Connect to the database server, log in and open the database
*
* Don't call this method directly. Use DB::connect() instead.
*
* Example of how to connect:
* <code>
* require_once 'DB.php';
*
* // $dsn = 'msql://hostname/dbname'; // use a TCP connection
* $dsn = 'msql:///dbname'; // use a socket
* $options = array(
* 'portability' => DB_PORTABILITY_ALL,
* );
*
* $db =& DB::connect($dsn, $options);
* if (PEAR::isError($db)) {
* die($db->getMessage());
* }
* </code>
*
* @param array $dsn the data source name
* @param bool $persistent should the connection be persistent?
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function connect($dsn, $persistent = false)
{
if (!PEAR::loadExtension('msql')) {
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
}
$this->dsn = $dsn;
if ($dsn['dbsyntax']) {
$this->dbsyntax = $dsn['dbsyntax'];
}
$params = array();
if ($dsn['hostspec']) {
$params[] = $dsn['port']
? $dsn['hostspec'] . ',' . $dsn['port']
: $dsn['hostspec'];
}
$connect_function = $persistent ? 'msql_pconnect' : 'msql_connect';
$ini = ini_get('track_errors');
$php_errormsg = '';
if ($ini) {
$this->connection = @call_user_func_array($connect_function,
$params);
} else {
ini_set('track_errors', 1);
$this->connection = @call_user_func_array($connect_function,
$params);
ini_set('track_errors', $ini);
}
if (!$this->connection) {
if (($err = @msql_error()) != '') {
return $this->raiseError(DB_ERROR_CONNECT_FAILED,
null, null, null,
$err);
} else {
return $this->raiseError(DB_ERROR_CONNECT_FAILED,
null, null, null,
$php_errormsg);
}
}
if (!@msql_select_db($dsn['database'], $this->connection)) {
return $this->msqlRaiseError();
}
return DB_OK;
}
// }}}
// {{{ disconnect()
/**
* Disconnects from the database server
*
* @return bool TRUE on success, FALSE on failure
*/
function disconnect()
{
$ret = @msql_close($this->connection);
$this->connection = null;
return $ret;
}
// }}}
// {{{ simpleQuery()
/**
* Sends a query to the database server
*
* @param string the SQL query string
*
* @return mixed + a PHP result resrouce for successful SELECT queries
* + the DB_OK constant for other successful queries
* + a DB_Error object on failure
*/
function simpleQuery($query)
{
$this->last_query = $query;
$query = $this->modifyQuery($query);
$result = @msql_query($query, $this->connection);
if (!$result) {
return $this->msqlRaiseError();
}
// Determine which queries that should return data, and which
// should return an error code only.
if (DB::isManip($query)) {
$this->_result = $result;
return DB_OK;
} else {
$this->_result = false;
return $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;
}
// }}}
// {{{ fetchInto()
/**
* Places a row from the result set into the given array
*
* Formating of the array and the data therein are configurable.
* See DB_result::fetchInto() for more information.
*
* This method is not meant to be called directly. Use
* DB_result::fetchInto() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* PHP's mSQL extension did weird things with NULL values prior to PHP
* 4.3.11 and 5.0.4. Make sure your version of PHP meets or exceeds
* those versions.
*
* @param resource $result the query result resource
* @param array $arr the referenced array to put the data in
* @param int $fetchmode how the resulting array should be indexed
* @param int $rownum the row number to fetch (0 = first row)
*
* @return mixed DB_OK on success, NULL when the end of a result set is
* reached or on failure
*
* @see DB_result::fetchInto()
*/
function fetchInto($result, &$arr, $fetchmode, $rownum = null)
{
if ($rownum !== null) {
if (!@msql_data_seek($result, $rownum)) {
return null;
}
}
if ($fetchmode & DB_FETCHMODE_ASSOC) {
$arr = @msql_fetch_array($result, MSQL_ASSOC);
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) {
$arr = array_change_key_case($arr, CASE_LOWER);
}
} else {
$arr = @msql_fetch_row($result);
}
if (!$arr) {
return null;
}
if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
$this->_rtrimArrayValues($arr);
}
if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
$this->_convertNullArrayValuesToEmpty($arr);
}
return DB_OK;
}
// }}}
// {{{ freeResult()
/**
* Deletes the result set and frees the memory occupied by the result set
*
* This method is not meant to be called directly. Use
* DB_result::free() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return bool TRUE on success, FALSE if $result is invalid
*
* @see DB_result::free()
*/
function freeResult($result)
{
return @msql_free_result($result);
}
// }}}
// {{{ numCols()
/**
* Gets the number of columns in a result set
*
* This method is not meant to be called directly. Use
* DB_result::numCols() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return int the number of columns. A DB_Error object on failure.
*
* @see DB_result::numCols()
*/
function numCols($result)
{
$cols = @msql_num_fields($result);
if (!$cols) {
return $this->msqlRaiseError();
}
return $cols;
}
// }}}
// {{{ numRows()
/**
* Gets the number of rows in a result set
*
* This method is not meant to be called directly. Use
* DB_result::numRows() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return int the number of rows. A DB_Error object on failure.
*
* @see DB_result::numRows()
*/
function numRows($result)
{
$rows = @msql_num_rows($result);
if ($rows === false) {
return $this->msqlRaiseError();
}
return $rows;
}
// }}}
// {{{ affected()
/**
* Determines the number of rows affected by a data maniuplation query
*
* 0 is returned for queries that don't manipulate data.
*
* @return int the number of rows. A DB_Error object on failure.
*/
function affectedRows()
{
if (!$this->_result) {
return 0;
}
return msql_affected_rows($this->_result);
}
// }}}
// {{{ nextId()
/**
* Returns the next free id in a sequence
*
* @param string $seq_name name of the sequence
* @param boolean $ondemand when true, the seqence is automatically
* created if it does not exist
*
* @return int the next id number in the sequence.
* A DB_Error object on failure.
*
* @see DB_common::nextID(), DB_common::getSequenceName(),
* DB_msql::createSequence(), DB_msql::dropSequence()
*/
function nextId($seq_name, $ondemand = true)
{
$seqname = $this->getSequenceName($seq_name);
$repeat = false;
do {
$this->pushErrorHandling(PEAR_ERROR_RETURN);
$result =& $this->query("SELECT _seq FROM ${seqname}");
$this->popErrorHandling();
if ($ondemand && DB::isError($result) &&
$result->getCode() == DB_ERROR_NOSUCHTABLE) {
$repeat = true;
$this->pushErrorHandling(PEAR_ERROR_RETURN);
$result = $this->createSequence($seq_name);
$this->popErrorHandling();
if (DB::isError($result)) {
return $this->raiseError($result);
}
} else {
$repeat = false;
}
} while ($repeat);
if (DB::isError($result)) {
return $this->raiseError($result);
}
$arr = $result->fetchRow(DB_FETCHMODE_ORDERED);
$result->free();
return $arr[0];
}
// }}}
// {{{ createSequence()
/**
* Creates a new sequence
*
* Also creates a new table to associate the sequence with. Uses
* a separate table to ensure portability with other drivers.
*
* @param string $seq_name name of the new sequence
*
* @return int DB_OK on success. A DB_Error object on failure.
*
* @see DB_common::createSequence(), DB_common::getSequenceName(),
* DB_msql::nextID(), DB_msql::dropSequence()
*/
function createSequence($seq_name)
{
$seqname = $this->getSequenceName($seq_name);
$res = $this->query('CREATE TABLE ' . $seqname
. ' (id INTEGER NOT NULL)');
if (DB::isError($res)) {
return $res;
}
$res = $this->query("CREATE SEQUENCE ON ${seqname}");
return $res;
}
// }}}
// {{{ dropSequence()
/**
* Deletes a sequence
*
* @param string $seq_name name of the sequence to be deleted
*
* @return int DB_OK on success. A DB_Error object on failure.
*
* @see DB_common::dropSequence(), DB_common::getSequenceName(),
* DB_msql::nextID(), DB_msql::createSequence()
*/
function dropSequence($seq_name)
{
return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name));
}
// }}}
// {{{ quoteIdentifier()
/**
* mSQL does not support delimited identifiers
*
* @param string $str the identifier name to be quoted
*
* @return object a DB_Error object
*
* @see DB_common::quoteIdentifier()
* @since Method available since Release 1.7.0
*/
function quoteIdentifier($str)
{
return $this->raiseError(DB_ERROR_UNSUPPORTED);
}
// }}}
// {{{ escapeSimple()
/**
* Escapes a string according to the current DBMS's standards
*
* @param string $str the string to be escaped
*
* @return string the escaped string
*
* @see DB_common::quoteSmart()
* @since Method available since Release 1.7.0
*/
function escapeSimple($str)
{
return addslashes($str);
}
// }}}
// {{{ msqlRaiseError()
/**
* Produces a DB_Error object regarding the current problem
*
* @param int $errno if the error is being manually raised pass a
* DB_ERROR* constant here. If this isn't passed
* the error information gathered from the DBMS.
*
* @return object the DB_Error object
*
* @see DB_common::raiseError(),
* DB_msql::errorNative(), DB_msql::errorCode()
*/
function msqlRaiseError($errno = null)
{
$native = $this->errorNative();
if ($errno === null) {
$errno = $this->errorCode($native);
}
return $this->raiseError($errno, null, null, null, $native);
}
// }}}
// {{{ errorNative()
/**
* Gets the DBMS' native error message produced by the last query
*
* @return string the DBMS' error message
*/
function errorNative()
{
return @msql_error();
}
// }}}
// {{{ errorCode()
/**
* Determines PEAR::DB error code from the database's text error message
*
* @param string $errormsg the error message returned from the database
*
* @return integer the error number from a DB_ERROR* constant
*/
function errorCode($errormsg)
{
static $error_regexps;
if (!isset($error_regexps)) {
$error_regexps = array(
'/^Access to database denied/i'
=> DB_ERROR_ACCESS_VIOLATION,
'/^Bad index name/i'
=> DB_ERROR_ALREADY_EXISTS,
'/^Bad order field/i'
=> DB_ERROR_SYNTAX,
'/^Bad type for comparison/i'
=> DB_ERROR_SYNTAX,
'/^Can\'t perform LIKE on/i'
=> DB_ERROR_SYNTAX,
'/^Can\'t use TEXT fields in LIKE comparison/i'
=> DB_ERROR_SYNTAX,
'/^Couldn\'t create temporary table/i'
=> DB_ERROR_CANNOT_CREATE,
'/^Error creating table file/i'
=> DB_ERROR_CANNOT_CREATE,
'/^Field .* cannot be null$/i'
=> DB_ERROR_CONSTRAINT_NOT_NULL,
'/^Index (field|condition) .* cannot be null$/i'
=> DB_ERROR_SYNTAX,
'/^Invalid date format/i'
=> DB_ERROR_INVALID_DATE,
'/^Invalid time format/i'
=> DB_ERROR_INVALID,
'/^Literal value for .* is wrong type$/i'
=> DB_ERROR_INVALID_NUMBER,
'/^No Database Selected/i'
=> DB_ERROR_NODBSELECTED,
'/^No value specified for field/i'
=> DB_ERROR_VALUE_COUNT_ON_ROW,
'/^Non unique value for unique index/i'
=> DB_ERROR_CONSTRAINT,
'/^Out of memory for temporary table/i'
=> DB_ERROR_CANNOT_CREATE,
'/^Permission denied/i'
=> DB_ERROR_ACCESS_VIOLATION,
'/^Reference to un-selected table/i'
=> DB_ERROR_SYNTAX,
'/^syntax error/i'
=> DB_ERROR_SYNTAX,
'/^Table .* exists$/i'
=> DB_ERROR_ALREADY_EXISTS,
'/^Unknown database/i'
=> DB_ERROR_NOSUCHDB,
'/^Unknown field/i'
=> DB_ERROR_NOSUCHFIELD,
'/^Unknown (index|system variable)/i'
=> DB_ERROR_NOT_FOUND,
'/^Unknown table/i'
=> DB_ERROR_NOSUCHTABLE,
'/^Unqualified field/i'
=> DB_ERROR_SYNTAX,
);
}
foreach ($error_regexps as $regexp => $code) {
if (preg_match($regexp, $errormsg)) {
return $code;
}
}
return DB_ERROR;
}
// }}}
// {{{ tableInfo()
/**
* Returns information about a table or a result set
*
* @param object|string $result DB_result object from a query or a
* string containing the name of a table.
* While this also accepts a query result
* resource identifier, this behavior is
* deprecated.
* @param int $mode a valid tableInfo mode
*
* @return array an associative array with the information requested.
* A DB_Error object on failure.
*
* @see DB_common::setOption()
*/
function tableInfo($result, $mode = null)
{
if (is_string($result)) {
/*
* Probably received a table name.
* Create a result resource identifier.
*/
$id = @msql_query("SELECT * FROM $result",
$this->connection);
$got_string = true;
} elseif (isset($result->result)) {
/*
* Probably received a result object.
* Extract the result resource identifier.
*/
$id = $result->result;
$got_string = false;
} else {
/*
* Probably received a result resource identifier.
* Copy it.
* Deprecated. Here for compatibility only.
*/
$id = $result;
$got_string = false;
}
if (!is_resource($id)) {
return $this->raiseError(DB_ERROR_NEED_MORE_DATA);
}
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
$case_func = 'strtolower';
} else {
$case_func = 'strval';
}
$count = @msql_num_fields($id);
$res = array();
if ($mode) {
$res['num_fields'] = $count;
}
for ($i = 0; $i < $count; $i++) {
$tmp = @msql_fetch_field($id);
$flags = '';
if ($tmp->not_null) {
$flags .= 'not_null ';
}
if ($tmp->unique) {
$flags .= 'unique_key ';
}
$flags = trim($flags);
$res[$i] = array(
'table' => $case_func($tmp->table),
'name' => $case_func($tmp->name),
'type' => $tmp->type,
'len' => msql_field_len($id, $i),
'flags' => $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 ($got_string) {
@msql_free_result($id);
}
return $res;
}
// }}}
// {{{ getSpecialQuery()
/**
* Obtain a list of a given type of objects
*
* @param string $type the kind of objects you want to retrieve
*
* @return array the array containing the list of objects requested
*
* @access protected
* @see DB_common::getListOf()
*/
function getSpecialQuery($type)
{
switch ($type) {
case 'databases':
$id = @msql_list_dbs($this->connection);
break;
case 'tables':
$id = @msql_list_tables($this->dsn['database'],
$this->connection);
break;
default:
return null;
}
if (!$id) {
return $this->msqlRaiseError();
}
$out = array();
while ($row = @msql_fetch_row($id)) {
$out[] = $row[0];
}
return $out;
}
// }}}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
*/
?>
+914
View File
@@ -0,0 +1,914 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* The PEAR DB driver for PHP's mssql extension
* for interacting with Microsoft SQL Server databases
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category Database
* @package DB
* @author Sterling Hughes <sterling@php.net>
* @author Daniel Convissor <danielc@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: mssql.php,v 1.83 2005/03/07 18:24:51 danielc Exp $
* @link http://pear.php.net/package/DB
*/
/**
* Obtain the DB_common class so it can be extended from
*/
require_once 'DB/common.php';
/**
* The methods PEAR DB uses to interact with PHP's mssql extension
* for interacting with Microsoft SQL Server databases
*
* These methods overload the ones declared in DB_common.
*
* @category Database
* @package DB
* @author Sterling Hughes <sterling@php.net>
* @author Daniel Convissor <danielc@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: 1.7.6
* @link http://pear.php.net/package/DB
*/
class DB_mssql extends DB_common
{
// {{{ properties
/**
* The DB driver type (mysql, oci8, odbc, etc.)
* @var string
*/
var $phptype = 'mssql';
/**
* The database syntax variant to be used (db2, access, etc.), if any
* @var string
*/
var $dbsyntax = 'mssql';
/**
* The capabilities of this DB implementation
*
* The 'new_link' element contains the PHP version that first provided
* new_link support for this DBMS. Contains false if it's unsupported.
*
* Meaning of the 'limit' element:
* + 'emulate' = emulate with fetch row by number
* + 'alter' = alter the query
* + false = skip rows
*
* @var array
*/
var $features = array(
'limit' => 'emulate',
'new_link' => false,
'numrows' => true,
'pconnect' => true,
'prepare' => false,
'ssl' => false,
'transactions' => true,
);
/**
* A mapping of native error codes to DB error codes
* @var array
*/
// XXX Add here error codes ie: 'S100E' => DB_ERROR_SYNTAX
var $errorcode_map = array(
110 => DB_ERROR_VALUE_COUNT_ON_ROW,
155 => DB_ERROR_NOSUCHFIELD,
170 => DB_ERROR_SYNTAX,
207 => DB_ERROR_NOSUCHFIELD,
208 => DB_ERROR_NOSUCHTABLE,
245 => DB_ERROR_INVALID_NUMBER,
515 => DB_ERROR_CONSTRAINT_NOT_NULL,
547 => DB_ERROR_CONSTRAINT,
1913 => DB_ERROR_ALREADY_EXISTS,
2627 => DB_ERROR_CONSTRAINT,
2714 => DB_ERROR_ALREADY_EXISTS,
3701 => DB_ERROR_NOSUCHTABLE,
8134 => DB_ERROR_DIVZERO,
);
/**
* The raw database connection created by PHP
* @var resource
*/
var $connection;
/**
* The DSN information for connecting to a database
* @var array
*/
var $dsn = array();
/**
* Should data manipulation queries be committed automatically?
* @var bool
* @access private
*/
var $autocommit = true;
/**
* The quantity of transactions begun
*
* {@internal While this is private, it can't actually be designated
* private in PHP 5 because it is directly accessed in the test suite.}}
*
* @var integer
* @access private
*/
var $transaction_opcount = 0;
/**
* The database specified in the DSN
*
* It's a fix to allow calls to different databases in the same script.
*
* @var string
* @access private
*/
var $_db = null;
// }}}
// {{{ constructor
/**
* This constructor calls <kbd>$this->DB_common()</kbd>
*
* @return void
*/
function DB_mssql()
{
$this->DB_common();
}
// }}}
// {{{ connect()
/**
* Connect to the database server, log in and open the database
*
* Don't call this method directly. Use DB::connect() instead.
*
* @param array $dsn the data source name
* @param bool $persistent should the connection be persistent?
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function connect($dsn, $persistent = false)
{
if (!PEAR::loadExtension('mssql') && !PEAR::loadExtension('sybase')
&& !PEAR::loadExtension('sybase_ct'))
{
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
}
$this->dsn = $dsn;
if ($dsn['dbsyntax']) {
$this->dbsyntax = $dsn['dbsyntax'];
}
$params = array(
$dsn['hostspec'] ? $dsn['hostspec'] : 'localhost',
$dsn['username'] ? $dsn['username'] : null,
$dsn['password'] ? $dsn['password'] : null,
);
if ($dsn['port']) {
$params[0] .= ((substr(PHP_OS, 0, 3) == 'WIN') ? ',' : ':')
. $dsn['port'];
}
$connect_function = $persistent ? 'mssql_pconnect' : 'mssql_connect';
$this->connection = @call_user_func_array($connect_function, $params);
if (!$this->connection) {
return $this->raiseError(DB_ERROR_CONNECT_FAILED,
null, null, null,
@mssql_get_last_message());
}
if ($dsn['database']) {
if (!@mssql_select_db($dsn['database'], $this->connection)) {
return $this->raiseError(DB_ERROR_NODBSELECTED,
null, null, null,
@mssql_get_last_message());
}
$this->_db = $dsn['database'];
}
return DB_OK;
}
// }}}
// {{{ disconnect()
/**
* Disconnects from the database server
*
* @return bool TRUE on success, FALSE on failure
*/
function disconnect()
{
$ret = @mssql_close($this->connection);
$this->connection = null;
return $ret;
}
// }}}
// {{{ simpleQuery()
/**
* Sends a query to the database server
*
* @param string the SQL query string
*
* @return mixed + a PHP result resrouce for successful SELECT queries
* + the DB_OK constant for other successful queries
* + a DB_Error object on failure
*/
function simpleQuery($query)
{
$ismanip = DB::isManip($query);
$this->last_query = $query;
if (!@mssql_select_db($this->_db, $this->connection)) {
return $this->mssqlRaiseError(DB_ERROR_NODBSELECTED);
}
$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);
}
// }}}
// {{{ fetchInto()
/**
* Places a row from the result set into the given array
*
* Formating of the array and the data therein are configurable.
* See DB_result::fetchInto() for more information.
*
* This method is not meant to be called directly. Use
* DB_result::fetchInto() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result the query result resource
* @param array $arr the referenced array to put the data in
* @param int $fetchmode how the resulting array should be indexed
* @param int $rownum the row number to fetch (0 = first row)
*
* @return mixed DB_OK on success, NULL when the end of a result set is
* reached or on failure
*
* @see DB_result::fetchInto()
*/
function fetchInto($result, &$arr, $fetchmode, $rownum = null)
{
if ($rownum !== null) {
if (!@mssql_data_seek($result, $rownum)) {
return null;
}
}
if ($fetchmode & DB_FETCHMODE_ASSOC) {
$arr = @mssql_fetch_array($result, MSSQL_ASSOC);
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) {
$arr = array_change_key_case($arr, CASE_LOWER);
}
} else {
$arr = @mssql_fetch_row($result);
}
if (!$arr) {
return null;
}
if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
$this->_rtrimArrayValues($arr);
}
if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
$this->_convertNullArrayValuesToEmpty($arr);
}
return DB_OK;
}
// }}}
// {{{ freeResult()
/**
* Deletes the result set and frees the memory occupied by the result set
*
* This method is not meant to be called directly. Use
* DB_result::free() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return bool TRUE on success, FALSE if $result is invalid
*
* @see DB_result::free()
*/
function freeResult($result)
{
return @mssql_free_result($result);
}
// }}}
// {{{ numCols()
/**
* Gets the number of columns in a result set
*
* This method is not meant to be called directly. Use
* DB_result::numCols() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return int the number of columns. A DB_Error object on failure.
*
* @see DB_result::numCols()
*/
function numCols($result)
{
$cols = @mssql_num_fields($result);
if (!$cols) {
return $this->mssqlRaiseError();
}
return $cols;
}
// }}}
// {{{ numRows()
/**
* Gets the number of rows in a result set
*
* This method is not meant to be called directly. Use
* DB_result::numRows() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return int the number of rows. A DB_Error object on failure.
*
* @see DB_result::numRows()
*/
function numRows($result)
{
$rows = @mssql_num_rows($result);
if ($rows === false) {
return $this->mssqlRaiseError();
}
return $rows;
}
// }}}
// {{{ autoCommit()
/**
* Enables or disables automatic commits
*
* @param bool $onoff true turns it on, false turns it off
*
* @return int DB_OK on success. A DB_Error object if the driver
* doesn't support auto-committing transactions.
*/
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()
/**
* Commits the current transaction
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function commit()
{
if ($this->transaction_opcount > 0) {
if (!@mssql_select_db($this->_db, $this->connection)) {
return $this->mssqlRaiseError(DB_ERROR_NODBSELECTED);
}
$result = @mssql_query('COMMIT TRAN', $this->connection);
$this->transaction_opcount = 0;
if (!$result) {
return $this->mssqlRaiseError();
}
}
return DB_OK;
}
// }}}
// {{{ rollback()
/**
* Reverts the current transaction
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function rollback()
{
if ($this->transaction_opcount > 0) {
if (!@mssql_select_db($this->_db, $this->connection)) {
return $this->mssqlRaiseError(DB_ERROR_NODBSELECTED);
}
$result = @mssql_query('ROLLBACK TRAN', $this->connection);
$this->transaction_opcount = 0;
if (!$result) {
return $this->mssqlRaiseError();
}
}
return DB_OK;
}
// }}}
// {{{ affectedRows()
/**
* Determines the number of rows affected by a data maniuplation query
*
* 0 is returned for queries that don't manipulate data.
*
* @return int the number of rows. A DB_Error object on failure.
*/
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()
/**
* Returns the next free id in a sequence
*
* @param string $seq_name name of the sequence
* @param boolean $ondemand when true, the seqence is automatically
* created if it does not exist
*
* @return int the next id number in the sequence.
* A DB_Error object on failure.
*
* @see DB_common::nextID(), DB_common::getSequenceName(),
* DB_mssql::createSequence(), DB_mssql::dropSequence()
*/
function nextId($seq_name, $ondemand = true)
{
$seqname = $this->getSequenceName($seq_name);
if (!@mssql_select_db($this->_db, $this->connection)) {
return $this->mssqlRaiseError(DB_ERROR_NODBSELECTED);
}
$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 $this->raiseError($result);
}
} elseif (!DB::isError($result)) {
$result =& $this->query("SELECT @@IDENTITY FROM $seqname");
$repeat = 0;
} else {
$repeat = false;
}
} while ($repeat);
if (DB::isError($result)) {
return $this->raiseError($result);
}
$result = $result->fetchRow(DB_FETCHMODE_ORDERED);
return $result[0];
}
/**
* Creates a new sequence
*
* @param string $seq_name name of the new sequence
*
* @return int DB_OK on success. A DB_Error object on failure.
*
* @see DB_common::createSequence(), DB_common::getSequenceName(),
* DB_mssql::nextID(), DB_mssql::dropSequence()
*/
function createSequence($seq_name)
{
return $this->query('CREATE TABLE '
. $this->getSequenceName($seq_name)
. ' ([id] [int] IDENTITY (1, 1) NOT NULL,'
. ' [vapor] [int] NULL)');
}
// }}}
// {{{ dropSequence()
/**
* Deletes a sequence
*
* @param string $seq_name name of the sequence to be deleted
*
* @return int DB_OK on success. A DB_Error object on failure.
*
* @see DB_common::dropSequence(), DB_common::getSequenceName(),
* DB_mssql::nextID(), DB_mssql::createSequence()
*/
function dropSequence($seq_name)
{
return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name));
}
// }}}
// {{{ quoteIdentifier()
/**
* Quotes a string so it can be safely used as a table or column name
*
* @param string $str identifier name to be quoted
*
* @return string quoted identifier string
*
* @see DB_common::quoteIdentifier()
* @since Method available since Release 1.6.0
*/
function quoteIdentifier($str)
{
return '[' . str_replace(']', ']]', $str) . ']';
}
// }}}
// {{{ mssqlRaiseError()
/**
* Produces a DB_Error object regarding the current problem
*
* @param int $errno if the error is being manually raised pass a
* DB_ERROR* constant here. If this isn't passed
* the error information gathered from the DBMS.
*
* @return object the DB_Error object
*
* @see DB_common::raiseError(),
* DB_mssql::errorNative(), DB_mssql::errorCode()
*/
function mssqlRaiseError($code = null)
{
$message = @mssql_get_last_message();
if (!$code) {
$code = $this->errorNative();
}
return $this->raiseError($this->errorCode($code, $message),
null, null, null, "$code - $message");
}
// }}}
// {{{ errorNative()
/**
* Gets the DBMS' native error code produced by the last query
*
* @return int the DBMS' error code
*/
function errorNative()
{
$res = @mssql_query('select @@ERROR as ErrorCode', $this->connection);
if (!$res) {
return DB_ERROR;
}
$row = @mssql_fetch_row($res);
return $row[0];
}
// }}}
// {{{ errorCode()
/**
* Determines PEAR::DB error code from mssql's native codes.
*
* If <var>$nativecode</var> isn't known yet, it will be looked up.
*
* @param mixed $nativecode mssql error code, if known
* @return integer an error number from a DB error constant
* @see errorNative()
*/
function errorCode($nativecode = null, $msg = '')
{
if (!$nativecode) {
$nativecode = $this->errorNative();
}
if (isset($this->errorcode_map[$nativecode])) {
if ($nativecode == 3701
&& preg_match('/Cannot drop the index/i', $msg))
{
return DB_ERROR_NOT_FOUND;
}
return $this->errorcode_map[$nativecode];
} else {
return DB_ERROR;
}
}
// }}}
// {{{ tableInfo()
/**
* Returns information about a table or a result set
*
* NOTE: only supports 'table' and 'flags' if <var>$result</var>
* is a table name.
*
* @param object|string $result DB_result object from a query or a
* string containing the name of a table.
* While this also accepts a query result
* resource identifier, this behavior is
* deprecated.
* @param int $mode a valid tableInfo mode
*
* @return array an associative array with the information requested.
* A DB_Error object on failure.
*
* @see DB_common::tableInfo()
*/
function tableInfo($result, $mode = null)
{
if (is_string($result)) {
/*
* Probably received a table name.
* Create a result resource identifier.
*/
if (!@mssql_select_db($this->_db, $this->connection)) {
return $this->mssqlRaiseError(DB_ERROR_NODBSELECTED);
}
$id = @mssql_query("SELECT * FROM $result WHERE 1=0",
$this->connection);
$got_string = true;
} elseif (isset($result->result)) {
/*
* Probably received a result object.
* Extract the result resource identifier.
*/
$id = $result->result;
$got_string = false;
} else {
/*
* Probably received a result resource identifier.
* Copy it.
* Deprecated. Here for compatibility only.
*/
$id = $result;
$got_string = false;
}
if (!is_resource($id)) {
return $this->mssqlRaiseError(DB_ERROR_NEED_MORE_DATA);
}
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
$case_func = 'strtolower';
} else {
$case_func = 'strval';
}
$count = @mssql_num_fields($id);
$res = array();
if ($mode) {
$res['num_fields'] = $count;
}
for ($i = 0; $i < $count; $i++) {
$res[$i] = array(
'table' => $got_string ? $case_func($result) : '',
'name' => $case_func(@mssql_field_name($id, $i)),
'type' => @mssql_field_type($id, $i),
'len' => @mssql_field_length($id, $i),
// We only support flags for table
'flags' => $got_string
? $this->_mssql_field_flags($result,
@mssql_field_name($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 ($got_string) {
@mssql_free_result($id);
}
return $res;
}
// }}}
// {{{ _mssql_field_flags()
/**
* Get a column's flags
*
* Supports "not_null", "primary_key",
* "auto_increment" (mssql identity), "timestamp" (mssql timestamp),
* "unique_key" (mssql unique index, unique check or primary_key) and
* "multiple_key" (multikey index)
*
* mssql timestamp is NOT similar to the mysql timestamp so this is maybe
* not useful at all - is the behaviour of mysql_field_flags that primary
* keys are alway unique? is the interpretation of multiple_key correct?
*
* @param string $table the table name
* @param string $column the field name
*
* @return string the flags
*
* @access private
* @author Joern Barthel <j_barthel@web.de>
*/
function _mssql_field_flags($table, $column)
{
static $tableName = null;
static $flags = array();
if ($table != $tableName) {
$flags = array();
$tableName = $table;
// get unique and primary keys
$res = $this->getAll("EXEC SP_HELPINDEX[$table]", DB_FETCHMODE_ASSOC);
foreach ($res as $val) {
$keys = explode(', ', $val['index_keys']);
if (sizeof($keys) > 1) {
foreach ($keys as $key) {
$this->_add_flag($flags[$key], 'multiple_key');
}
}
if (strpos($val['index_description'], 'primary key')) {
foreach ($keys as $key) {
$this->_add_flag($flags[$key], 'primary_key');
}
} elseif (strpos($val['index_description'], 'unique')) {
foreach ($keys as $key) {
$this->_add_flag($flags[$key], 'unique_key');
}
}
}
// get auto_increment, not_null and timestamp
$res = $this->getAll("EXEC SP_COLUMNS[$table]", DB_FETCHMODE_ASSOC);
foreach ($res as $val) {
$val = array_change_key_case($val, CASE_LOWER);
if ($val['nullable'] == '0') {
$this->_add_flag($flags[$val['column_name']], 'not_null');
}
if (strpos($val['type_name'], 'identity')) {
$this->_add_flag($flags[$val['column_name']], 'auto_increment');
}
if (strpos($val['type_name'], 'timestamp')) {
$this->_add_flag($flags[$val['column_name']], 'timestamp');
}
}
}
if (array_key_exists($column, $flags)) {
return(implode(' ', $flags[$column]));
}
return '';
}
// }}}
// {{{ _add_flag()
/**
* Adds a string to the flags array if the flag is not yet in there
* - if there is no flag present the array is created
*
* @param array &$array the reference to the flag-array
* @param string $value the flag value
*
* @return void
*
* @access private
* @author Joern Barthel <j_barthel@web.de>
*/
function _add_flag(&$array, $value)
{
if (!is_array($array)) {
$array = array($value);
} elseif (!in_array($value, $array)) {
array_push($array, $value);
}
}
// }}}
// {{{ getSpecialQuery()
/**
* Obtains the query string needed for listing a given type of objects
*
* @param string $type the kind of objects you want to retrieve
*
* @return string the SQL query string or null if the driver doesn't
* support the object type requested
*
* @access protected
* @see DB_common::getListOf()
*/
function getSpecialQuery($type)
{
switch ($type) {
case 'tables':
return "SELECT name FROM sysobjects WHERE type = 'U'"
. ' ORDER BY name';
case 'views':
return "SELECT name FROM sysobjects WHERE type = 'V'";
default:
return null;
}
}
// }}}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
*/
?>
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+1117
View File
File diff suppressed because it is too large. Load diff
+883
View File
@@ -0,0 +1,883 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* The PEAR DB driver for PHP's odbc extension
* for interacting with databases via ODBC connections
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category Database
* @package DB
* @author Stig Bakken <ssb@php.net>
* @author Daniel Convissor <danielc@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: odbc.php,v 1.78 2005/02/28 01:42:17 danielc Exp $
* @link http://pear.php.net/package/DB
*/
/**
* Obtain the DB_common class so it can be extended from
*/
require_once 'DB/common.php';
/**
* The methods PEAR DB uses to interact with PHP's odbc extension
* for interacting with databases via ODBC connections
*
* These methods overload the ones declared in DB_common.
*
* 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
*
* @category Database
* @package DB
* @author Stig Bakken <ssb@php.net>
* @author Daniel Convissor <danielc@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: 1.7.6
* @link http://pear.php.net/package/DB
*/
class DB_odbc extends DB_common
{
// {{{ properties
/**
* The DB driver type (mysql, oci8, odbc, etc.)
* @var string
*/
var $phptype = 'odbc';
/**
* The database syntax variant to be used (db2, access, etc.), if any
* @var string
*/
var $dbsyntax = 'sql92';
/**
* The capabilities of this DB implementation
*
* The 'new_link' element contains the PHP version that first provided
* new_link support for this DBMS. Contains false if it's unsupported.
*
* Meaning of the 'limit' element:
* + 'emulate' = emulate with fetch row by number
* + 'alter' = alter the query
* + false = skip rows
*
* NOTE: The feature set of the following drivers are different than
* the default:
* + solid: 'transactions' = true
* + navision: 'limit' = false
*
* @var array
*/
var $features = array(
'limit' => 'emulate',
'new_link' => false,
'numrows' => true,
'pconnect' => true,
'prepare' => false,
'ssl' => false,
'transactions' => false,
);
/**
* A mapping of native error codes to DB error codes
* @var array
*/
var $errorcode_map = array(
'01004' => DB_ERROR_TRUNCATED,
'07001' => DB_ERROR_MISMATCH,
'21S01' => DB_ERROR_VALUE_COUNT_ON_ROW,
'21S02' => DB_ERROR_MISMATCH,
'22001' => DB_ERROR_INVALID,
'22003' => DB_ERROR_INVALID_NUMBER,
'22005' => DB_ERROR_INVALID_NUMBER,
'22008' => DB_ERROR_INVALID_DATE,
'22012' => DB_ERROR_DIVZERO,
'23000' => DB_ERROR_CONSTRAINT,
'23502' => DB_ERROR_CONSTRAINT_NOT_NULL,
'23503' => DB_ERROR_CONSTRAINT,
'23504' => DB_ERROR_CONSTRAINT,
'23505' => DB_ERROR_CONSTRAINT,
'24000' => DB_ERROR_INVALID,
'34000' => DB_ERROR_INVALID,
'37000' => DB_ERROR_SYNTAX,
'42000' => DB_ERROR_SYNTAX,
'42601' => DB_ERROR_SYNTAX,
'IM001' => DB_ERROR_UNSUPPORTED,
'S0000' => DB_ERROR_NOSUCHTABLE,
'S0001' => DB_ERROR_ALREADY_EXISTS,
'S0002' => DB_ERROR_NOSUCHTABLE,
'S0011' => DB_ERROR_ALREADY_EXISTS,
'S0012' => DB_ERROR_NOT_FOUND,
'S0021' => DB_ERROR_ALREADY_EXISTS,
'S0022' => DB_ERROR_NOSUCHFIELD,
'S1009' => DB_ERROR_INVALID,
'S1090' => DB_ERROR_INVALID,
'S1C00' => DB_ERROR_NOT_CAPABLE,
);
/**
* The raw database connection created by PHP
* @var resource
*/
var $connection;
/**
* The DSN information for connecting to a database
* @var array
*/
var $dsn = array();
/**
* The number of rows affected by a data manipulation query
* @var integer
* @access private
*/
var $affected = 0;
// }}}
// {{{ constructor
/**
* This constructor calls <kbd>$this->DB_common()</kbd>
*
* @return void
*/
function DB_odbc()
{
$this->DB_common();
}
// }}}
// {{{ connect()
/**
* Connect to the database server, log in and open the database
*
* Don't call this method directly. Use DB::connect() instead.
*
* PEAR DB's odbc driver supports the following extra DSN options:
* + cursor The type of cursor to be used for this connection.
*
* @param array $dsn the data source name
* @param bool $persistent should the connection be persistent?
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function connect($dsn, $persistent = false)
{
if (!PEAR::loadExtension('odbc')) {
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
}
$this->dsn = $dsn;
if ($dsn['dbsyntax']) {
$this->dbsyntax = $dsn['dbsyntax'];
}
switch ($this->dbsyntax) {
case 'access':
case 'db2':
case 'solid':
$this->features['transactions'] = true;
break;
case 'navision':
$this->features['limit'] = false;
}
/*
* This is hear for backwards compatibility. Should have been using
* 'database' all along, but prior to 1.6.0RC3 'hostspec' was used.
*/
if ($dsn['database']) {
$odbcdsn = $dsn['database'];
} elseif ($dsn['hostspec']) {
$odbcdsn = $dsn['hostspec'];
} else {
$odbcdsn = 'localhost';
}
$connect_function = $persistent ? 'odbc_pconnect' : 'odbc_connect';
if (empty($dsn['cursor'])) {
$this->connection = @$connect_function($odbcdsn, $dsn['username'],
$dsn['password']);
} else {
$this->connection = @$connect_function($odbcdsn, $dsn['username'],
$dsn['password'],
$dsn['cursor']);
}
if (!is_resource($this->connection)) {
return $this->raiseError(DB_ERROR_CONNECT_FAILED,
null, null, null,
$this->errorNative());
}
return DB_OK;
}
// }}}
// {{{ disconnect()
/**
* Disconnects from the database server
*
* @return bool TRUE on success, FALSE on failure
*/
function disconnect()
{
$err = @odbc_close($this->connection);
$this->connection = null;
return $err;
}
// }}}
// {{{ simpleQuery()
/**
* Sends a query to the database server
*
* @param string the SQL query string
*
* @return mixed + a PHP result resrouce for successful SELECT queries
* + the DB_OK constant for other successful queries
* + a DB_Error object 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->affected = $result; // For affectedRows()
return DB_OK;
}
$this->affected = 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);
}
// }}}
// {{{ fetchInto()
/**
* Places a row from the result set into the given array
*
* Formating of the array and the data therein are configurable.
* See DB_result::fetchInto() for more information.
*
* This method is not meant to be called directly. Use
* DB_result::fetchInto() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result the query result resource
* @param array $arr the referenced array to put the data in
* @param int $fetchmode how the resulting array should be indexed
* @param int $rownum the row number to fetch (0 = first row)
*
* @return mixed DB_OK on success, NULL when the end of a result set is
* reached or on failure
*
* @see DB_result::fetchInto()
*/
function fetchInto($result, &$arr, $fetchmode, $rownum = null)
{
$arr = array();
if ($rownum !== null) {
$rownum++; // ODBC first row is 1
if (version_compare(phpversion(), '4.2.0', 'ge')) {
$cols = @odbc_fetch_into($result, $arr, $rownum);
} else {
$cols = @odbc_fetch_into($result, $rownum, $arr);
}
} else {
$cols = @odbc_fetch_into($result, $arr);
}
if (!$cols) {
return null;
}
if ($fetchmode !== DB_FETCHMODE_ORDERED) {
for ($i = 0; $i < count($arr); $i++) {
$colName = @odbc_field_name($result, $i+1);
$a[$colName] = $arr[$i];
}
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
$a = array_change_key_case($a, CASE_LOWER);
}
$arr = $a;
}
if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
$this->_rtrimArrayValues($arr);
}
if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
$this->_convertNullArrayValuesToEmpty($arr);
}
return DB_OK;
}
// }}}
// {{{ freeResult()
/**
* Deletes the result set and frees the memory occupied by the result set
*
* This method is not meant to be called directly. Use
* DB_result::free() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return bool TRUE on success, FALSE if $result is invalid
*
* @see DB_result::free()
*/
function freeResult($result)
{
return @odbc_free_result($result);
}
// }}}
// {{{ numCols()
/**
* Gets the number of columns in a result set
*
* This method is not meant to be called directly. Use
* DB_result::numCols() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return int the number of columns. A DB_Error object on failure.
*
* @see DB_result::numCols()
*/
function numCols($result)
{
$cols = @odbc_num_fields($result);
if (!$cols) {
return $this->odbcRaiseError();
}
return $cols;
}
// }}}
// {{{ affectedRows()
/**
* Determines the number of rows affected by a data maniuplation query
*
* 0 is returned for queries that don't manipulate data.
*
* @return int the number of rows. A DB_Error object on failure.
*/
function affectedRows()
{
if (empty($this->affected)) { // In case of SELECT stms
return 0;
}
$nrows = @odbc_num_rows($this->affected);
if ($nrows == -1) {
return $this->odbcRaiseError();
}
return $nrows;
}
// }}}
// {{{ numRows()
/**
* Gets the number of rows in a result set
*
* Not all ODBC drivers support this functionality. If they don't
* a DB_Error object for DB_ERROR_UNSUPPORTED is returned.
*
* This method is not meant to be called directly. Use
* DB_result::numRows() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return int the number of rows. A DB_Error object on failure.
*
* @see DB_result::numRows()
*/
function numRows($result)
{
$nrows = @odbc_num_rows($result);
if ($nrows == -1) {
return $this->odbcRaiseError(DB_ERROR_UNSUPPORTED);
}
if ($nrows === false) {
return $this->odbcRaiseError();
}
return $nrows;
}
// }}}
// {{{ quoteIdentifier()
/**
* Quotes a string so it can be safely used as a table or column name
*
* Use 'mssql' as the dbsyntax in the DB DSN only if you've unchecked
* "Use ANSI quoted identifiers" when setting up the ODBC data source.
*
* @param string $str identifier name to be quoted
*
* @return string quoted identifier string
*
* @see DB_common::quoteIdentifier()
* @since Method available since Release 1.6.0
*/
function quoteIdentifier($str)
{
switch ($this->dsn['dbsyntax']) {
case 'access':
return '[' . $str . ']';
case 'mssql':
case 'sybase':
return '[' . str_replace(']', ']]', $str) . ']';
case 'mysql':
case 'mysqli':
return '`' . $str . '`';
default:
return '"' . str_replace('"', '""', $str) . '"';
}
}
// }}}
// {{{ quote()
/**
* @deprecated Deprecated in release 1.6.0
* @internal
*/
function quote($str)
{
return $this->quoteSmart($str);
}
// }}}
// {{{ nextId()
/**
* Returns the next free id in a sequence
*
* @param string $seq_name name of the sequence
* @param boolean $ondemand when true, the seqence is automatically
* created if it does not exist
*
* @return int the next id number in the sequence.
* A DB_Error object on failure.
*
* @see DB_common::nextID(), DB_common::getSequenceName(),
* DB_odbc::createSequence(), DB_odbc::dropSequence()
*/
function nextId($seq_name, $ondemand = true)
{
$seqname = $this->getSequenceName($seq_name);
$repeat = 0;
do {
$this->pushErrorHandling(PEAR_ERROR_RETURN);
$result = $this->query("update ${seqname} set id = id + 1");
$this->popErrorHandling();
if ($ondemand && DB::isError($result) &&
$result->getCode() == DB_ERROR_NOSUCHTABLE) {
$repeat = 1;
$this->pushErrorHandling(PEAR_ERROR_RETURN);
$result = $this->createSequence($seq_name);
$this->popErrorHandling();
if (DB::isError($result)) {
return $this->raiseError($result);
}
$result = $this->query("insert into ${seqname} (id) values(0)");
} else {
$repeat = 0;
}
} while ($repeat);
if (DB::isError($result)) {
return $this->raiseError($result);
}
$result = $this->query("select id from ${seqname}");
if (DB::isError($result)) {
return $result;
}
$row = $result->fetchRow(DB_FETCHMODE_ORDERED);
if (DB::isError($row || !$row)) {
return $row;
}
return $row[0];
}
/**
* Creates a new sequence
*
* @param string $seq_name name of the new sequence
*
* @return int DB_OK on success. A DB_Error object on failure.
*
* @see DB_common::createSequence(), DB_common::getSequenceName(),
* DB_odbc::nextID(), DB_odbc::dropSequence()
*/
function createSequence($seq_name)
{
return $this->query('CREATE TABLE '
. $this->getSequenceName($seq_name)
. ' (id integer NOT NULL,'
. ' PRIMARY KEY(id))');
}
// }}}
// {{{ dropSequence()
/**
* Deletes a sequence
*
* @param string $seq_name name of the sequence to be deleted
*
* @return int DB_OK on success. A DB_Error object on failure.
*
* @see DB_common::dropSequence(), DB_common::getSequenceName(),
* DB_odbc::nextID(), DB_odbc::createSequence()
*/
function dropSequence($seq_name)
{
return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name));
}
// }}}
// {{{ autoCommit()
/**
* Enables or disables automatic commits
*
* @param bool $onoff true turns it on, false turns it off
*
* @return int DB_OK on success. A DB_Error object if the driver
* doesn't support auto-committing transactions.
*/
function autoCommit($onoff = false)
{
if (!@odbc_autocommit($this->connection, $onoff)) {
return $this->odbcRaiseError();
}
return DB_OK;
}
// }}}
// {{{ commit()
/**
* Commits the current transaction
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function commit()
{
if (!@odbc_commit($this->connection)) {
return $this->odbcRaiseError();
}
return DB_OK;
}
// }}}
// {{{ rollback()
/**
* Reverts the current transaction
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function rollback()
{
if (!@odbc_rollback($this->connection)) {
return $this->odbcRaiseError();
}
return DB_OK;
}
// }}}
// {{{ odbcRaiseError()
/**
* Produces a DB_Error object regarding the current problem
*
* @param int $errno if the error is being manually raised pass a
* DB_ERROR* constant here. If this isn't passed
* the error information gathered from the DBMS.
*
* @return object the DB_Error object
*
* @see DB_common::raiseError(),
* DB_odbc::errorNative(), DB_common::errorCode()
*/
function odbcRaiseError($errno = null)
{
if ($errno === null) {
switch ($this->dbsyntax) {
case 'access':
if ($this->options['portability'] & DB_PORTABILITY_ERRORS) {
$this->errorcode_map['07001'] = DB_ERROR_NOSUCHFIELD;
} else {
// Doing this in case mode changes during runtime.
$this->errorcode_map['07001'] = DB_ERROR_MISMATCH;
}
$native_code = odbc_error($this->connection);
// S1000 is for "General Error." Let's be more specific.
if ($native_code == 'S1000') {
$errormsg = odbc_errormsg($this->connection);
static $error_regexps;
if (!isset($error_regexps)) {
$error_regexps = array(
'/includes related records.$/i' => DB_ERROR_CONSTRAINT,
'/cannot contain a Null value/i' => DB_ERROR_CONSTRAINT_NOT_NULL,
);
}
foreach ($error_regexps as $regexp => $code) {
if (preg_match($regexp, $errormsg)) {
return $this->raiseError($code,
null, null, null,
$native_code . ' ' . $errormsg);
}
}
$errno = DB_ERROR;
} else {
$errno = $this->errorCode($native_code);
}
break;
default:
$errno = $this->errorCode(odbc_error($this->connection));
}
}
return $this->raiseError($errno, null, null, null,
$this->errorNative());
}
// }}}
// {{{ errorNative()
/**
* Gets the DBMS' native error code and message produced by the last query
*
* @return string the DBMS' error code and message
*/
function errorNative()
{
if (!is_resource($this->connection)) {
return @odbc_error() . ' ' . @odbc_errormsg();
}
return @odbc_error($this->connection) . ' ' . @odbc_errormsg($this->connection);
}
// }}}
// {{{ tableInfo()
/**
* Returns information about a table or a result set
*
* @param object|string $result DB_result object from a query or a
* string containing the name of a table.
* While this also accepts a query result
* resource identifier, this behavior is
* deprecated.
* @param int $mode a valid tableInfo mode
*
* @return array an associative array with the information requested.
* A DB_Error object on failure.
*
* @see DB_common::tableInfo()
* @since Method available since Release 1.7.0
*/
function tableInfo($result, $mode = null)
{
if (is_string($result)) {
/*
* Probably received a table name.
* Create a result resource identifier.
*/
$id = @odbc_exec($this->connection, "SELECT * FROM $result");
if (!$id) {
return $this->odbcRaiseError();
}
$got_string = true;
} elseif (isset($result->result)) {
/*
* Probably received a result object.
* Extract the result resource identifier.
*/
$id = $result->result;
$got_string = false;
} else {
/*
* Probably received a result resource identifier.
* Copy it.
* Deprecated. Here for compatibility only.
*/
$id = $result;
$got_string = false;
}
if (!is_resource($id)) {
return $this->odbcRaiseError(DB_ERROR_NEED_MORE_DATA);
}
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
$case_func = 'strtolower';
} else {
$case_func = 'strval';
}
$count = @odbc_num_fields($id);
$res = array();
if ($mode) {
$res['num_fields'] = $count;
}
for ($i = 0; $i < $count; $i++) {
$col = $i + 1;
$res[$i] = array(
'table' => $got_string ? $case_func($result) : '',
'name' => $case_func(@odbc_field_name($id, $col)),
'type' => @odbc_field_type($id, $col),
'len' => @odbc_field_len($id, $col),
'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 ($got_string) {
@odbc_free_result($id);
}
return $res;
}
// }}}
// {{{ getSpecialQuery()
/**
* Obtains the query string needed for listing a given type of objects
*
* Thanks to symbol1@gmail.com and Philippe.Jausions@11abacus.com.
*
* @param string $type the kind of objects you want to retrieve
*
* @return string the list of objects requested
*
* @access protected
* @see DB_common::getListOf()
* @since Method available since Release 1.7.0
*/
function getSpecialQuery($type)
{
switch ($type) {
case 'databases':
if (!function_exists('odbc_data_source')) {
return null;
}
$res = @odbc_data_source($this->connection, SQL_FETCH_FIRST);
if (is_array($res)) {
$out = array($res['server']);
while($res = @odbc_data_source($this->connection,
SQL_FETCH_NEXT))
{
$out[] = $res['server'];
}
return $out;
} else {
return $this->odbcRaiseError();
}
break;
case 'tables':
case 'schema.tables':
$keep = 'TABLE';
break;
case 'views':
$keep = 'VIEW';
break;
default:
return null;
}
/*
* Removing non-conforming items in the while loop rather than
* in the odbc_tables() call because some backends choke on this:
* odbc_tables($this->connection, '', '', '', 'TABLE')
*/
$res = @odbc_tables($this->connection);
if (!$res) {
return $this->odbcRaiseError();
}
$out = array();
while ($row = odbc_fetch_array($res)) {
if ($row['TABLE_TYPE'] != $keep) {
continue;
}
if ($type == 'schema.tables') {
$out[] = $row['TABLE_SCHEM'] . '.' . $row['TABLE_NAME'];
} else {
$out[] = $row['TABLE_NAME'];
}
}
return $out;
}
// }}}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
*/
?>
File diff suppressed because it is too large. Load diff
+942
View File
@@ -0,0 +1,942 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* The PEAR DB driver for PHP's sqlite extension
* for interacting with SQLite databases
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category Database
* @package DB
* @author Urs Gehrig <urs@circle.ch>
* @author Mika Tuupola <tuupola@appelsiini.net>
* @author Daniel Convissor <danielc@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0 3.0
* @version CVS: $Id: sqlite.php,v 1.109 2005/03/10 01:22:48 danielc Exp $
* @link http://pear.php.net/package/DB
*/
/**
* Obtain the DB_common class so it can be extended from
*/
require_once 'DB/common.php';
/**
* The methods PEAR DB uses to interact with PHP's sqlite extension
* for interacting with SQLite databases
*
* These methods overload the ones declared in DB_common.
*
* NOTICE: This driver needs PHP's track_errors ini setting to be on.
* It is automatically turned on when connecting to the database.
* Make sure your scripts don't turn it off.
*
* @category Database
* @package DB
* @author Urs Gehrig <urs@circle.ch>
* @author Mika Tuupola <tuupola@appelsiini.net>
* @author Daniel Convissor <danielc@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0 3.0
* @version Release: 1.7.6
* @link http://pear.php.net/package/DB
*/
class DB_sqlite extends DB_common
{
// {{{ properties
/**
* The DB driver type (mysql, oci8, odbc, etc.)
* @var string
*/
var $phptype = 'sqlite';
/**
* The database syntax variant to be used (db2, access, etc.), if any
* @var string
*/
var $dbsyntax = 'sqlite';
/**
* The capabilities of this DB implementation
*
* The 'new_link' element contains the PHP version that first provided
* new_link support for this DBMS. Contains false if it's unsupported.
*
* Meaning of the 'limit' element:
* + 'emulate' = emulate with fetch row by number
* + 'alter' = alter the query
* + false = skip rows
*
* @var array
*/
var $features = array(
'limit' => 'alter',
'new_link' => false,
'numrows' => true,
'pconnect' => true,
'prepare' => false,
'ssl' => false,
'transactions' => false,
);
/**
* A mapping of native error codes to DB error codes
*
* {@internal Error codes according to sqlite_exec. See the online
* manual at http://sqlite.org/c_interface.html for info.
* This error handling based on sqlite_exec is not yet implemented.}}
*
* @var array
*/
var $errorcode_map = array(
);
/**
* The raw database connection created by PHP
* @var resource
*/
var $connection;
/**
* The DSN information for connecting to a database
* @var array
*/
var $dsn = array();
/**
* SQLite data types
*
* @link http://www.sqlite.org/datatypes.html
*
* @var array
*/
var $keywords = array (
'BLOB' => '',
'BOOLEAN' => '',
'CHARACTER' => '',
'CLOB' => '',
'FLOAT' => '',
'INTEGER' => '',
'KEY' => '',
'NATIONAL' => '',
'NUMERIC' => '',
'NVARCHAR' => '',
'PRIMARY' => '',
'TEXT' => '',
'TIMESTAMP' => '',
'UNIQUE' => '',
'VARCHAR' => '',
'VARYING' => '',
);
/**
* The most recent error message from $php_errormsg
* @var string
* @access private
*/
var $_lasterror = '';
// }}}
// {{{ constructor
/**
* This constructor calls <kbd>$this->DB_common()</kbd>
*
* @return void
*/
function DB_sqlite()
{
$this->DB_common();
}
// }}}
// {{{ connect()
/**
* Connect to the database server, log in and open the database
*
* Don't call this method directly. Use DB::connect() instead.
*
* PEAR DB's sqlite driver supports the following extra DSN options:
* + mode The permissions for the database file, in four digit
* chmod octal format (eg "0600").
*
* Example of connecting to a database in read-only mode:
* <code>
* require_once 'DB.php';
*
* $dsn = 'sqlite:///path/and/name/of/db/file?mode=0400';
* $options = array(
* 'portability' => DB_PORTABILITY_ALL,
* );
*
* $db =& DB::connect($dsn, $options);
* if (PEAR::isError($db)) {
* die($db->getMessage());
* }
* </code>
*
* @param array $dsn the data source name
* @param bool $persistent should the connection be persistent?
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function connect($dsn, $persistent = false)
{
if (!PEAR::loadExtension('sqlite')) {
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
}
$this->dsn = $dsn;
if ($dsn['dbsyntax']) {
$this->dbsyntax = $dsn['dbsyntax'];
}
if ($dsn['database']) {
if (!file_exists($dsn['database'])) {
if (!touch($dsn['database'])) {
return $this->sqliteRaiseError(DB_ERROR_NOT_FOUND);
}
if (!isset($dsn['mode']) ||
!is_numeric($dsn['mode']))
{
$mode = 0644;
} else {
$mode = octdec($dsn['mode']);
}
if (!chmod($dsn['database'], $mode)) {
return $this->sqliteRaiseError(DB_ERROR_NOT_FOUND);
}
if (!file_exists($dsn['database'])) {
return $this->sqliteRaiseError(DB_ERROR_NOT_FOUND);
}
}
if (!is_file($dsn['database'])) {
return $this->sqliteRaiseError(DB_ERROR_INVALID);
}
if (!is_readable($dsn['database'])) {
return $this->sqliteRaiseError(DB_ERROR_ACCESS_VIOLATION);
}
} else {
return $this->sqliteRaiseError(DB_ERROR_ACCESS_VIOLATION);
}
$connect_function = $persistent ? 'sqlite_popen' : 'sqlite_open';
// track_errors must remain on for simpleQuery()
ini_set('track_errors', 1);
$php_errormsg = '';
if (!$this->connection = @$connect_function($dsn['database'])) {
return $this->raiseError(DB_ERROR_NODBSELECTED,
null, null, null,
$php_errormsg);
}
return DB_OK;
}
// }}}
// {{{ disconnect()
/**
* Disconnects from the database server
*
* @return bool TRUE on success, FALSE on failure
*/
function disconnect()
{
$ret = @sqlite_close($this->connection);
$this->connection = null;
return $ret;
}
// }}}
// {{{ simpleQuery()
/**
* Sends a query to the database server
*
* NOTICE: This method needs PHP's track_errors ini setting to be on.
* It is automatically turned on when connecting to the database.
* Make sure your scripts don't turn it off.
*
* @param string the SQL query string
*
* @return mixed + a PHP result resrouce for successful SELECT queries
* + the DB_OK constant for other successful queries
* + a DB_Error object on failure
*/
function simpleQuery($query)
{
$ismanip = DB::isManip($query);
$this->last_query = $query;
$query = $this->modifyQuery($query);
$php_errormsg = '';
$result = @sqlite_query($query, $this->connection);
$this->_lasterror = $php_errormsg ? $php_errormsg : '';
$this->result = $result;
if (!$this->result) {
return $this->sqliteRaiseError(null);
}
// sqlite_query() seems to allways return a resource
// so cant use that. Using $ismanip instead
if (!$ismanip) {
$numRows = $this->numRows($result);
if (is_object($numRows)) {
// we've got PEAR_Error
return $numRows;
}
return $result;
}
return DB_OK;
}
// }}}
// {{{ nextResult()
/**
* Move the internal sqlite result pointer to the next available result
*
* @param resource $result the valid sqlite result resource
*
* @return bool true if a result is available otherwise return false
*/
function nextResult($result)
{
return false;
}
// }}}
// {{{ fetchInto()
/**
* Places a row from the result set into the given array
*
* Formating of the array and the data therein are configurable.
* See DB_result::fetchInto() for more information.
*
* This method is not meant to be called directly. Use
* DB_result::fetchInto() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result the query result resource
* @param array $arr the referenced array to put the data in
* @param int $fetchmode how the resulting array should be indexed
* @param int $rownum the row number to fetch (0 = first row)
*
* @return mixed DB_OK on success, NULL when the end of a result set is
* reached or on failure
*
* @see DB_result::fetchInto()
*/
function fetchInto($result, &$arr, $fetchmode, $rownum = null)
{
if ($rownum !== null) {
if (!@sqlite_seek($this->result, $rownum)) {
return null;
}
}
if ($fetchmode & DB_FETCHMODE_ASSOC) {
$arr = @sqlite_fetch_array($result, SQLITE_ASSOC);
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) {
$arr = array_change_key_case($arr, CASE_LOWER);
}
} else {
$arr = @sqlite_fetch_array($result, SQLITE_NUM);
}
if (!$arr) {
return null;
}
if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
/*
* Even though this DBMS already trims output, we do this because
* a field might have intentional whitespace at the end that
* gets removed by DB_PORTABILITY_RTRIM under another driver.
*/
$this->_rtrimArrayValues($arr);
}
if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
$this->_convertNullArrayValuesToEmpty($arr);
}
return DB_OK;
}
// }}}
// {{{ freeResult()
/**
* Deletes the result set and frees the memory occupied by the result set
*
* This method is not meant to be called directly. Use
* DB_result::free() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return bool TRUE on success, FALSE if $result is invalid
*
* @see DB_result::free()
*/
function freeResult(&$result)
{
// XXX No native free?
if (!is_resource($result)) {
return false;
}
$result = null;
return true;
}
// }}}
// {{{ numCols()
/**
* Gets the number of columns in a result set
*
* This method is not meant to be called directly. Use
* DB_result::numCols() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return int the number of columns. A DB_Error object on failure.
*
* @see DB_result::numCols()
*/
function numCols($result)
{
$cols = @sqlite_num_fields($result);
if (!$cols) {
return $this->sqliteRaiseError();
}
return $cols;
}
// }}}
// {{{ numRows()
/**
* Gets the number of rows in a result set
*
* This method is not meant to be called directly. Use
* DB_result::numRows() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return int the number of rows. A DB_Error object on failure.
*
* @see DB_result::numRows()
*/
function numRows($result)
{
$rows = @sqlite_num_rows($result);
if ($rows === null) {
return $this->sqliteRaiseError();
}
return $rows;
}
// }}}
// {{{ affected()
/**
* Determines the number of rows affected by a data maniuplation query
*
* 0 is returned for queries that don't manipulate data.
*
* @return int the number of rows. A DB_Error object on failure.
*/
function affectedRows()
{
return @sqlite_changes($this->connection);
}
// }}}
// {{{ dropSequence()
/**
* Deletes a sequence
*
* @param string $seq_name name of the sequence to be deleted
*
* @return int DB_OK on success. A DB_Error object on failure.
*
* @see DB_common::dropSequence(), DB_common::getSequenceName(),
* DB_sqlite::nextID(), DB_sqlite::createSequence()
*/
function dropSequence($seq_name)
{
return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name));
}
/**
* Creates a new sequence
*
* @param string $seq_name name of the new sequence
*
* @return int DB_OK on success. A DB_Error object on failure.
*
* @see DB_common::createSequence(), DB_common::getSequenceName(),
* DB_sqlite::nextID(), DB_sqlite::dropSequence()
*/
function createSequence($seq_name)
{
$seqname = $this->getSequenceName($seq_name);
$query = 'CREATE TABLE ' . $seqname .
' (id INTEGER UNSIGNED PRIMARY KEY) ';
$result = $this->query($query);
if (DB::isError($result)) {
return($result);
}
$query = "CREATE TRIGGER ${seqname}_cleanup AFTER INSERT ON $seqname
BEGIN
DELETE FROM $seqname WHERE id<LAST_INSERT_ROWID();
END ";
$result = $this->query($query);
if (DB::isError($result)) {
return($result);
}
}
// }}}
// {{{ nextId()
/**
* Returns the next free id in a sequence
*
* @param string $seq_name name of the sequence
* @param boolean $ondemand when true, the seqence is automatically
* created if it does not exist
*
* @return int the next id number in the sequence.
* A DB_Error object on failure.
*
* @see DB_common::nextID(), DB_common::getSequenceName(),
* DB_sqlite::createSequence(), DB_sqlite::dropSequence()
*/
function nextId($seq_name, $ondemand = true)
{
$seqname = $this->getSequenceName($seq_name);
do {
$repeat = 0;
$this->pushErrorHandling(PEAR_ERROR_RETURN);
$result = $this->query("INSERT INTO $seqname (id) VALUES (NULL)");
$this->popErrorHandling();
if ($result === DB_OK) {
$id = @sqlite_last_insert_rowid($this->connection);
if ($id != 0) {
return $id;
}
} elseif ($ondemand && DB::isError($result) &&
$result->getCode() == DB_ERROR_NOSUCHTABLE)
{
$result = $this->createSequence($seq_name);
if (DB::isError($result)) {
return $this->raiseError($result);
} else {
$repeat = 1;
}
}
} while ($repeat);
return $this->raiseError($result);
}
// }}}
// {{{ getDbFileStats()
/**
* Get the file stats for the current database
*
* Possible arguments are dev, ino, mode, nlink, uid, gid, rdev, size,
* atime, mtime, ctime, blksize, blocks or a numeric key between
* 0 and 12.
*
* @param string $arg the array key for stats()
*
* @return mixed an array on an unspecified key, integer on a passed
* arg and false at a stats error
*/
function getDbFileStats($arg = '')
{
$stats = stat($this->dsn['database']);
if ($stats == false) {
return false;
}
if (is_array($stats)) {
if (is_numeric($arg)) {
if (((int)$arg <= 12) & ((int)$arg >= 0)) {
return false;
}
return $stats[$arg ];
}
if (array_key_exists(trim($arg), $stats)) {
return $stats[$arg ];
}
}
return $stats;
}
// }}}
// {{{ escapeSimple()
/**
* Escapes a string according to the current DBMS's standards
*
* In SQLite, this makes things safe for inserts/updates, but may
* cause problems when performing text comparisons against columns
* containing binary data. See the
* {@link http://php.net/sqlite_escape_string PHP manual} for more info.
*
* @param string $str the string to be escaped
*
* @return string the escaped string
*
* @since Method available since Release 1.6.1
* @see DB_common::escapeSimple()
*/
function escapeSimple($str)
{
return @sqlite_escape_string($str);
}
// }}}
// {{{ modifyLimitQuery()
/**
* Adds LIMIT clauses to a query string according to current DBMS standards
*
* @param string $query the query to modify
* @param int $from the row to start to fetching (0 = the first row)
* @param int $count the numbers of rows to fetch
* @param mixed $params array, string or numeric data to be used in
* execution of the statement. Quantity of items
* passed must match quantity of placeholders in
* query: meaning 1 placeholder for non-array
* parameters or 1 placeholder per array element.
*
* @return string the query string with LIMIT clauses added
*
* @access protected
*/
function modifyLimitQuery($query, $from, $count, $params = array())
{
return "$query LIMIT $count OFFSET $from";
}
// }}}
// {{{ modifyQuery()
/**
* Changes a query string for various DBMS specific reasons
*
* This little hack lets you know how many rows were deleted
* when running a "DELETE FROM table" query. Only implemented
* if the DB_PORTABILITY_DELETE_COUNT portability option is on.
*
* @param string $query the query string to modify
*
* @return string the modified query string
*
* @access protected
* @see DB_common::setOption()
*/
function modifyQuery($query)
{
if ($this->options['portability'] & DB_PORTABILITY_DELETE_COUNT) {
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;
}
// }}}
// {{{ sqliteRaiseError()
/**
* Produces a DB_Error object regarding the current problem
*
* @param int $errno if the error is being manually raised pass a
* DB_ERROR* constant here. If this isn't passed
* the error information gathered from the DBMS.
*
* @return object the DB_Error object
*
* @see DB_common::raiseError(),
* DB_sqlite::errorNative(), DB_sqlite::errorCode()
*/
function sqliteRaiseError($errno = null)
{
$native = $this->errorNative();
if ($errno === null) {
$errno = $this->errorCode($native);
}
$errorcode = @sqlite_last_error($this->connection);
$userinfo = "$errorcode ** $this->last_query";
return $this->raiseError($errno, null, null, $userinfo, $native);
}
// }}}
// {{{ errorNative()
/**
* Gets the DBMS' native error message produced by the last query
*
* {@internal This is used to retrieve more meaningfull error messages
* because sqlite_last_error() does not provide adequate info.}}
*
* @return string the DBMS' error message
*/
function errorNative()
{
return $this->_lasterror;
}
// }}}
// {{{ errorCode()
/**
* Determines PEAR::DB error code from the database's text error message
*
* @param string $errormsg the error message returned from the database
*
* @return integer the DB error number
*/
function errorCode($errormsg)
{
static $error_regexps;
if (!isset($error_regexps)) {
$error_regexps = array(
'/^no such table:/' => DB_ERROR_NOSUCHTABLE,
'/^no such index:/' => DB_ERROR_NOT_FOUND,
'/^(table|index) .* already exists$/' => DB_ERROR_ALREADY_EXISTS,
'/PRIMARY KEY must be unique/i' => DB_ERROR_CONSTRAINT,
'/is not unique/' => DB_ERROR_CONSTRAINT,
'/columns .* are not unique/i' => DB_ERROR_CONSTRAINT,
'/uniqueness constraint failed/' => DB_ERROR_CONSTRAINT,
'/may not be NULL/' => DB_ERROR_CONSTRAINT_NOT_NULL,
'/^no such column:/' => DB_ERROR_NOSUCHFIELD,
'/column not present in both tables/i' => DB_ERROR_NOSUCHFIELD,
'/^near ".*": syntax error$/' => DB_ERROR_SYNTAX,
'/[0-9]+ values for [0-9]+ columns/i' => DB_ERROR_VALUE_COUNT_ON_ROW,
);
}
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;
}
// }}}
// {{{ tableInfo()
/**
* Returns information about a table
*
* @param string $result a string containing the name of a table
* @param int $mode a valid tableInfo mode
*
* @return array an associative array with the information requested.
* A DB_Error object on failure.
*
* @see DB_common::tableInfo()
* @since Method available since Release 1.7.0
*/
function tableInfo($result, $mode = null)
{
if (is_string($result)) {
/*
* Probably received a table name.
* Create a result resource identifier.
*/
$id = @sqlite_array_query($this->connection,
"PRAGMA table_info('$result');",
SQLITE_ASSOC);
$got_string = true;
} else {
$this->last_query = '';
return $this->raiseError(DB_ERROR_NOT_CAPABLE, null, null, null,
'This DBMS can not obtain tableInfo' .
' from result sets');
}
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
$case_func = 'strtolower';
} else {
$case_func = 'strval';
}
$count = count($id);
$res = array();
if ($mode) {
$res['num_fields'] = $count;
}
for ($i = 0; $i < $count; $i++) {
if (strpos($id[$i]['type'], '(') !== false) {
$bits = explode('(', $id[$i]['type']);
$type = $bits[0];
$len = rtrim($bits[1],')');
} else {
$type = $id[$i]['type'];
$len = 0;
}
$flags = '';
if ($id[$i]['pk']) {
$flags .= 'primary_key ';
}
if ($id[$i]['notnull']) {
$flags .= 'not_null ';
}
if ($id[$i]['dflt_value'] !== null) {
$flags .= 'default_' . rawurlencode($id[$i]['dflt_value']);
}
$flags = trim($flags);
$res[$i] = array(
'table' => $case_func($result),
'name' => $case_func($id[$i]['name']),
'type' => $type,
'len' => $len,
'flags' => $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;
}
}
return $res;
}
// }}}
// {{{ getSpecialQuery()
/**
* Obtains the query string needed for listing a given type of objects
*
* @param string $type the kind of objects you want to retrieve
* @param array $args SQLITE DRIVER ONLY: a private array of arguments
* used by the getSpecialQuery(). Do not use
* this directly.
*
* @return string the SQL query string or null if the driver doesn't
* support the object type requested
*
* @access protected
* @see DB_common::getListOf()
*/
function getSpecialQuery($type, $args = array())
{
if (!is_array($args)) {
return $this->raiseError('no key specified', null, null, null,
'Argument has to be an array.');
}
switch ($type) {
case 'master':
return 'SELECT * FROM sqlite_master;';
case 'tables':
return "SELECT name FROM sqlite_master WHERE type='table' "
. 'UNION ALL SELECT name FROM sqlite_temp_master '
. "WHERE type='table' ORDER BY name;";
case 'schema':
return 'SELECT sql FROM (SELECT * FROM sqlite_master '
. 'UNION ALL SELECT * FROM sqlite_temp_master) '
. "WHERE type!='meta' "
. 'ORDER BY tbl_name, type DESC, name;';
case 'schemax':
case 'schema_x':
/*
* Use like:
* $res = $db->query($db->getSpecialQuery('schema_x',
* array('table' => 'table3')));
*/
return 'SELECT sql FROM (SELECT * FROM sqlite_master '
. 'UNION ALL SELECT * FROM sqlite_temp_master) '
. "WHERE tbl_name LIKE '{$args['table']}' "
. "AND type!='meta' "
. 'ORDER BY type DESC, name;';
case 'alter':
/*
* SQLite does not support ALTER TABLE; this is a helper query
* to handle this. 'table' represents the table name, 'rows'
* the news rows to create, 'save' the row(s) to keep _with_
* the data.
*
* Use like:
* $args = array(
* 'table' => $table,
* 'rows' => "id INTEGER PRIMARY KEY, firstname TEXT, surname TEXT, datetime TEXT",
* 'save' => "NULL, titel, content, datetime"
* );
* $res = $db->query( $db->getSpecialQuery('alter', $args));
*/
$rows = strtr($args['rows'], $this->keywords);
$q = array(
'BEGIN TRANSACTION',
"CREATE TEMPORARY TABLE {$args['table']}_backup ({$args['rows']})",
"INSERT INTO {$args['table']}_backup SELECT {$args['save']} FROM {$args['table']}",
"DROP TABLE {$args['table']}",
"CREATE TABLE {$args['table']} ({$args['rows']})",
"INSERT INTO {$args['table']} SELECT {$rows} FROM {$args['table']}_backup",
"DROP TABLE {$args['table']}_backup",
'COMMIT',
);
/*
* This is a dirty hack, since the above query will not get
* executed with a single query call so here the query method
* will be called directly and return a select instead.
*/
foreach ($q as $query) {
$this->query($query);
}
return "SELECT * FROM {$args['table']};";
default:
return null;
}
}
// }}}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
*/
?>
+504
View File
@@ -0,0 +1,504 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* Provides an object interface to a table row
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category Database
* @package DB
* @author Stig Bakken <stig@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: storage.php,v 1.21 2005/02/02 02:54:51 danielc Exp $
* @link http://pear.php.net/package/DB
*/
/**
* Obtain the DB class so it can be extended from
*/
require_once 'DB.php';
/**
* Provides an object interface to a table row
*
* It lets you add, delete and change rows using objects rather than SQL
* statements.
*
* @category Database
* @package DB
* @author Stig Bakken <stig@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: 1.7.6
* @link http://pear.php.net/package/DB
*/
class DB_storage extends PEAR
{
// {{{ properties
/** 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
/**
* 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;
}
// }}}
// {{{ _makeWhere()
/**
* 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;
}
// }}}
// {{{ setup()
/**
* 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)
{
$whereclause = $this->_makeWhere($keyval);
$query = 'SELECT * FROM ' . $this->_table . ' WHERE ' . $whereclause;
$sth = $this->_dbh->query($query);
if (DB::isError($sth)) {
return $sth;
}
$row = $sth->fetchRow(DB_FETCHMODE_ASSOC);
if (DB::isError($row)) {
return $row;
}
if (!$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;
}
// }}}
// {{{ insert()
/**
* 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);
}
// }}}
// {{{ toString()
/**
* Output a simple description of this DB_storage object.
* @return string object description
*/
function toString()
{
$info = strtolower(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()
/**
* Dump the contents of this object to "standard output".
*/
function dump()
{
foreach ($this->_properties as $prop => $foo) {
print "$prop = ";
print htmlentities($this->$prop);
print "<br />\n";
}
}
// }}}
// {{{ &create()
/**
* 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 = strtolower(get_class($this));
$obj =& new $classname($table);
foreach ($data as $name => $value) {
$obj->_properties[$name] = true;
$obj->$name = &$value;
}
return $obj;
}
// }}}
// {{{ loadFromQuery()
/**
* 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;
}
*/
// }}}
// {{{ set()
/**
* 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;
if (empty($this->_changes[$property])) {
$this->_changes[$property] = 0;
} else {
$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);
}
// }}}
// {{{ &get()
/**
* 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;
}
$tmp = null;
return $tmp;
}
// }}}
// {{{ _DB_storage()
/**
* Destructor, calls DB_storage::store() if there are changes
* that are to be kept.
*/
function _DB_storage()
{
if (sizeof($this->_changes)) {
$this->store();
}
$this->_properties = array();
$this->_changes = array();
$this->_table = null;
}
// }}}
// {{{ store()
/**
* Stores changes to this object in the database.
*
* @return DB_OK or a DB error
*/
function store()
{
foreach ($this->_changes as $name => $foo) {
$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()
/**
* 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;
}
// }}}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
*/
?>
+907
View File
@@ -0,0 +1,907 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* The PEAR DB driver for PHP's sybase extension
* for interacting with Sybase databases
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category Database
* @package DB
* @author Sterling Hughes <sterling@php.net>
* @author Antônio Carlos Venâncio Júnior <floripa@php.net>
* @author Daniel Convissor <danielc@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: sybase.php,v 1.78 2005/02/20 00:44:48 danielc Exp $
* @link http://pear.php.net/package/DB
*/
/**
* Obtain the DB_common class so it can be extended from
*/
require_once 'DB/common.php';
/**
* The methods PEAR DB uses to interact with PHP's sybase extension
* for interacting with Sybase databases
*
* These methods overload the ones declared in DB_common.
*
* WARNING: This driver may fail with multiple connections under the
* same user/pass/host and different databases.
*
* @category Database
* @package DB
* @author Sterling Hughes <sterling@php.net>
* @author Antônio Carlos Venâncio Júnior <floripa@php.net>
* @author Daniel Convissor <danielc@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: 1.7.6
* @link http://pear.php.net/package/DB
*/
class DB_sybase extends DB_common
{
// {{{ properties
/**
* The DB driver type (mysql, oci8, odbc, etc.)
* @var string
*/
var $phptype = 'sybase';
/**
* The database syntax variant to be used (db2, access, etc.), if any
* @var string
*/
var $dbsyntax = 'sybase';
/**
* The capabilities of this DB implementation
*
* The 'new_link' element contains the PHP version that first provided
* new_link support for this DBMS. Contains false if it's unsupported.
*
* Meaning of the 'limit' element:
* + 'emulate' = emulate with fetch row by number
* + 'alter' = alter the query
* + false = skip rows
*
* @var array
*/
var $features = array(
'limit' => 'emulate',
'new_link' => false,
'numrows' => true,
'pconnect' => true,
'prepare' => false,
'ssl' => false,
'transactions' => true,
);
/**
* A mapping of native error codes to DB error codes
* @var array
*/
var $errorcode_map = array(
);
/**
* The raw database connection created by PHP
* @var resource
*/
var $connection;
/**
* The DSN information for connecting to a database
* @var array
*/
var $dsn = array();
/**
* Should data manipulation queries be committed automatically?
* @var bool
* @access private
*/
var $autocommit = true;
/**
* The quantity of transactions begun
*
* {@internal While this is private, it can't actually be designated
* private in PHP 5 because it is directly accessed in the test suite.}}
*
* @var integer
* @access private
*/
var $transaction_opcount = 0;
/**
* The database specified in the DSN
*
* It's a fix to allow calls to different databases in the same script.
*
* @var string
* @access private
*/
var $_db = '';
// }}}
// {{{ constructor
/**
* This constructor calls <kbd>$this->DB_common()</kbd>
*
* @return void
*/
function DB_sybase()
{
$this->DB_common();
}
// }}}
// {{{ connect()
/**
* Connect to the database server, log in and open the database
*
* Don't call this method directly. Use DB::connect() instead.
*
* PEAR DB's sybase driver supports the following extra DSN options:
* + appname The application name to use on this connection.
* Available since PEAR DB 1.7.0.
* + charset The character set to use on this connection.
* Available since PEAR DB 1.7.0.
*
* @param array $dsn the data source name
* @param bool $persistent should the connection be persistent?
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function connect($dsn, $persistent = false)
{
if (!PEAR::loadExtension('sybase') &&
!PEAR::loadExtension('sybase_ct'))
{
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
}
$this->dsn = $dsn;
if ($dsn['dbsyntax']) {
$this->dbsyntax = $dsn['dbsyntax'];
}
$dsn['hostspec'] = $dsn['hostspec'] ? $dsn['hostspec'] : 'localhost';
$dsn['password'] = !empty($dsn['password']) ? $dsn['password'] : false;
$dsn['charset'] = isset($dsn['charset']) ? $dsn['charset'] : false;
$dsn['appname'] = isset($dsn['appname']) ? $dsn['appname'] : false;
$connect_function = $persistent ? 'sybase_pconnect' : 'sybase_connect';
if ($dsn['username']) {
$this->connection = @$connect_function($dsn['hostspec'],
$dsn['username'],
$dsn['password'],
$dsn['charset'],
$dsn['appname']);
} else {
return $this->raiseError(DB_ERROR_CONNECT_FAILED,
null, null, null,
'The DSN did not contain a username.');
}
if (!$this->connection) {
return $this->raiseError(DB_ERROR_CONNECT_FAILED,
null, null, null,
@sybase_get_last_message());
}
if ($dsn['database']) {
if (!@sybase_select_db($dsn['database'], $this->connection)) {
return $this->raiseError(DB_ERROR_NODBSELECTED,
null, null, null,
@sybase_get_last_message());
}
$this->_db = $dsn['database'];
}
return DB_OK;
}
// }}}
// {{{ disconnect()
/**
* Disconnects from the database server
*
* @return bool TRUE on success, FALSE on failure
*/
function disconnect()
{
$ret = @sybase_close($this->connection);
$this->connection = null;
return $ret;
}
// }}}
// {{{ simpleQuery()
/**
* Sends a query to the database server
*
* @param string the SQL query string
*
* @return mixed + a PHP result resrouce for successful SELECT queries
* + the DB_OK constant for other successful queries
* + a DB_Error object on failure
*/
function simpleQuery($query)
{
$ismanip = DB::isManip($query);
$this->last_query = $query;
if (!@sybase_select_db($this->_db, $this->connection)) {
return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED);
}
$query = $this->modifyQuery($query);
if (!$this->autocommit && $ismanip) {
if ($this->transaction_opcount == 0) {
$result = @sybase_query('BEGIN TRANSACTION', $this->connection);
if (!$result) {
return $this->sybaseRaiseError();
}
}
$this->transaction_opcount++;
}
$result = @sybase_query($query, $this->connection);
if (!$result) {
return $this->sybaseRaiseError();
}
if (is_resource($result)) {
return $result;
}
// Determine which queries that should return data, and which
// should return an error code only.
return $ismanip ? DB_OK : $result;
}
// }}}
// {{{ nextResult()
/**
* Move the internal sybase result pointer to the next available result
*
* @param a valid sybase result resource
*
* @access public
*
* @return true if a result is available otherwise return false
*/
function nextResult($result)
{
return false;
}
// }}}
// {{{ fetchInto()
/**
* Places a row from the result set into the given array
*
* Formating of the array and the data therein are configurable.
* See DB_result::fetchInto() for more information.
*
* This method is not meant to be called directly. Use
* DB_result::fetchInto() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result the query result resource
* @param array $arr the referenced array to put the data in
* @param int $fetchmode how the resulting array should be indexed
* @param int $rownum the row number to fetch (0 = first row)
*
* @return mixed DB_OK on success, NULL when the end of a result set is
* reached or on failure
*
* @see DB_result::fetchInto()
*/
function fetchInto($result, &$arr, $fetchmode, $rownum = null)
{
if ($rownum !== null) {
if (!@sybase_data_seek($result, $rownum)) {
return null;
}
}
if ($fetchmode & DB_FETCHMODE_ASSOC) {
if (function_exists('sybase_fetch_assoc')) {
$arr = @sybase_fetch_assoc($result);
} else {
if ($arr = @sybase_fetch_array($result)) {
foreach ($arr as $key => $value) {
if (is_int($key)) {
unset($arr[$key]);
}
}
}
}
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) {
$arr = array_change_key_case($arr, CASE_LOWER);
}
} else {
$arr = @sybase_fetch_row($result);
}
if (!$arr) {
return null;
}
if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
$this->_rtrimArrayValues($arr);
}
if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
$this->_convertNullArrayValuesToEmpty($arr);
}
return DB_OK;
}
// }}}
// {{{ freeResult()
/**
* Deletes the result set and frees the memory occupied by the result set
*
* This method is not meant to be called directly. Use
* DB_result::free() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return bool TRUE on success, FALSE if $result is invalid
*
* @see DB_result::free()
*/
function freeResult($result)
{
return @sybase_free_result($result);
}
// }}}
// {{{ numCols()
/**
* Gets the number of columns in a result set
*
* This method is not meant to be called directly. Use
* DB_result::numCols() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return int the number of columns. A DB_Error object on failure.
*
* @see DB_result::numCols()
*/
function numCols($result)
{
$cols = @sybase_num_fields($result);
if (!$cols) {
return $this->sybaseRaiseError();
}
return $cols;
}
// }}}
// {{{ numRows()
/**
* Gets the number of rows in a result set
*
* This method is not meant to be called directly. Use
* DB_result::numRows() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return int the number of rows. A DB_Error object on failure.
*
* @see DB_result::numRows()
*/
function numRows($result)
{
$rows = @sybase_num_rows($result);
if ($rows === false) {
return $this->sybaseRaiseError();
}
return $rows;
}
// }}}
// {{{ affectedRows()
/**
* Determines the number of rows affected by a data maniuplation query
*
* 0 is returned for queries that don't manipulate data.
*
* @return int the number of rows. A DB_Error object on failure.
*/
function affectedRows()
{
if (DB::isManip($this->last_query)) {
$result = @sybase_affected_rows($this->connection);
} else {
$result = 0;
}
return $result;
}
// }}}
// {{{ nextId()
/**
* Returns the next free id in a sequence
*
* @param string $seq_name name of the sequence
* @param boolean $ondemand when true, the seqence is automatically
* created if it does not exist
*
* @return int the next id number in the sequence.
* A DB_Error object on failure.
*
* @see DB_common::nextID(), DB_common::getSequenceName(),
* DB_sybase::createSequence(), DB_sybase::dropSequence()
*/
function nextId($seq_name, $ondemand = true)
{
$seqname = $this->getSequenceName($seq_name);
if (!@sybase_select_db($this->_db, $this->connection)) {
return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED);
}
$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 $this->raiseError($result);
}
} elseif (!DB::isError($result)) {
$result =& $this->query("SELECT @@IDENTITY FROM $seqname");
$repeat = 0;
} else {
$repeat = false;
}
} while ($repeat);
if (DB::isError($result)) {
return $this->raiseError($result);
}
$result = $result->fetchRow(DB_FETCHMODE_ORDERED);
return $result[0];
}
/**
* Creates a new sequence
*
* @param string $seq_name name of the new sequence
*
* @return int DB_OK on success. A DB_Error object on failure.
*
* @see DB_common::createSequence(), DB_common::getSequenceName(),
* DB_sybase::nextID(), DB_sybase::dropSequence()
*/
function createSequence($seq_name)
{
return $this->query('CREATE TABLE '
. $this->getSequenceName($seq_name)
. ' (id numeric(10, 0) IDENTITY NOT NULL,'
. ' vapor int NULL)');
}
// }}}
// {{{ dropSequence()
/**
* Deletes a sequence
*
* @param string $seq_name name of the sequence to be deleted
*
* @return int DB_OK on success. A DB_Error object on failure.
*
* @see DB_common::dropSequence(), DB_common::getSequenceName(),
* DB_sybase::nextID(), DB_sybase::createSequence()
*/
function dropSequence($seq_name)
{
return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name));
}
// }}}
// {{{ autoCommit()
/**
* Enables or disables automatic commits
*
* @param bool $onoff true turns it on, false turns it off
*
* @return int DB_OK on success. A DB_Error object if the driver
* doesn't support auto-committing transactions.
*/
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()
/**
* Commits the current transaction
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function commit()
{
if ($this->transaction_opcount > 0) {
if (!@sybase_select_db($this->_db, $this->connection)) {
return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED);
}
$result = @sybase_query('COMMIT', $this->connection);
$this->transaction_opcount = 0;
if (!$result) {
return $this->sybaseRaiseError();
}
}
return DB_OK;
}
// }}}
// {{{ rollback()
/**
* Reverts the current transaction
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function rollback()
{
if ($this->transaction_opcount > 0) {
if (!@sybase_select_db($this->_db, $this->connection)) {
return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED);
}
$result = @sybase_query('ROLLBACK', $this->connection);
$this->transaction_opcount = 0;
if (!$result) {
return $this->sybaseRaiseError();
}
}
return DB_OK;
}
// }}}
// {{{ sybaseRaiseError()
/**
* Produces a DB_Error object regarding the current problem
*
* @param int $errno if the error is being manually raised pass a
* DB_ERROR* constant here. If this isn't passed
* the error information gathered from the DBMS.
*
* @return object the DB_Error object
*
* @see DB_common::raiseError(),
* DB_sybase::errorNative(), DB_sybase::errorCode()
*/
function sybaseRaiseError($errno = null)
{
$native = $this->errorNative();
if ($errno === null) {
$errno = $this->errorCode($native);
}
return $this->raiseError($errno, null, null, null, $native);
}
// }}}
// {{{ errorNative()
/**
* Gets the DBMS' native error message produced by the last query
*
* @return string the DBMS' error message
*/
function errorNative()
{
return @sybase_get_last_message();
}
// }}}
// {{{ errorCode()
/**
* Determines PEAR::DB error code from the database's text error message.
*
* @param string $errormsg error message returned from the database
* @return integer an error number from a DB error constant
*/
function errorCode($errormsg)
{
static $error_regexps;
if (!isset($error_regexps)) {
$error_regexps = array(
'/Incorrect syntax near/'
=> DB_ERROR_SYNTAX,
'/^Unclosed quote before the character string [\"\'].*[\"\']\./'
=> DB_ERROR_SYNTAX,
'/Implicit conversion (from datatype|of NUMERIC value)/i'
=> DB_ERROR_INVALID_NUMBER,
'/Cannot drop the table [\"\'].+[\"\'], because it doesn\'t exist in the system catalogs\./'
=> DB_ERROR_NOSUCHTABLE,
'/Only the owner of object [\"\'].+[\"\'] or a user with System Administrator \(SA\) role can run this command\./'
=> DB_ERROR_ACCESS_VIOLATION,
'/^.+ permission denied on object .+, database .+, owner .+/'
=> DB_ERROR_ACCESS_VIOLATION,
'/^.* permission denied, database .+, owner .+/'
=> DB_ERROR_ACCESS_VIOLATION,
'/[^.*] not found\./'
=> DB_ERROR_NOSUCHTABLE,
'/There is already an object named/'
=> DB_ERROR_ALREADY_EXISTS,
'/Invalid column name/'
=> DB_ERROR_NOSUCHFIELD,
'/does not allow null values/'
=> DB_ERROR_CONSTRAINT_NOT_NULL,
'/Command has been aborted/'
=> DB_ERROR_CONSTRAINT,
'/^Cannot drop the index .* because it doesn\'t exist/i'
=> DB_ERROR_NOT_FOUND,
'/^There is already an index/i'
=> DB_ERROR_ALREADY_EXISTS,
'/^There are fewer columns in the INSERT statement than values specified/i'
=> DB_ERROR_VALUE_COUNT_ON_ROW,
);
}
foreach ($error_regexps as $regexp => $code) {
if (preg_match($regexp, $errormsg)) {
return $code;
}
}
return DB_ERROR;
}
// }}}
// {{{ tableInfo()
/**
* Returns information about a table or a result set
*
* NOTE: only supports 'table' and 'flags' if <var>$result</var>
* is a table name.
*
* @param object|string $result DB_result object from a query or a
* string containing the name of a table.
* While this also accepts a query result
* resource identifier, this behavior is
* deprecated.
* @param int $mode a valid tableInfo mode
*
* @return array an associative array with the information requested.
* A DB_Error object on failure.
*
* @see DB_common::tableInfo()
* @since Method available since Release 1.6.0
*/
function tableInfo($result, $mode = null)
{
if (is_string($result)) {
/*
* Probably received a table name.
* Create a result resource identifier.
*/
if (!@sybase_select_db($this->_db, $this->connection)) {
return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED);
}
$id = @sybase_query("SELECT * FROM $result WHERE 1=0",
$this->connection);
$got_string = true;
} elseif (isset($result->result)) {
/*
* Probably received a result object.
* Extract the result resource identifier.
*/
$id = $result->result;
$got_string = false;
} else {
/*
* Probably received a result resource identifier.
* Copy it.
* Deprecated. Here for compatibility only.
*/
$id = $result;
$got_string = false;
}
if (!is_resource($id)) {
return $this->sybaseRaiseError(DB_ERROR_NEED_MORE_DATA);
}
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
$case_func = 'strtolower';
} else {
$case_func = 'strval';
}
$count = @sybase_num_fields($id);
$res = array();
if ($mode) {
$res['num_fields'] = $count;
}
for ($i = 0; $i < $count; $i++) {
$f = @sybase_fetch_field($id, $i);
// column_source is often blank
$res[$i] = array(
'table' => $got_string
? $case_func($result)
: $case_func($f->column_source),
'name' => $case_func($f->name),
'type' => $f->type,
'len' => $f->max_length,
'flags' => '',
);
if ($res[$i]['table']) {
$res[$i]['flags'] = $this->_sybase_field_flags(
$res[$i]['table'], $res[$i]['name']);
}
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 ($got_string) {
@sybase_free_result($id);
}
return $res;
}
// }}}
// {{{ _sybase_field_flags()
/**
* Get the flags for a field
*
* Currently supports:
* + <samp>unique_key</samp> (unique index, unique check or primary_key)
* + <samp>multiple_key</samp> (multi-key index)
*
* @param string $table the table name
* @param string $column the field name
*
* @return string space delimited string of flags. Empty string if none.
*
* @access private
*/
function _sybase_field_flags($table, $column)
{
static $tableName = null;
static $flags = array();
if ($table != $tableName) {
$flags = array();
$tableName = $table;
// get unique/primary keys
$res = $this->getAll("sp_helpindex $table", DB_FETCHMODE_ASSOC);
if (!isset($res[0]['index_description'])) {
return '';
}
foreach ($res as $val) {
$keys = explode(', ', trim($val['index_keys']));
if (sizeof($keys) > 1) {
foreach ($keys as $key) {
$this->_add_flag($flags[$key], 'multiple_key');
}
}
if (strpos($val['index_description'], 'unique')) {
foreach ($keys as $key) {
$this->_add_flag($flags[$key], 'unique_key');
}
}
}
}
if (array_key_exists($column, $flags)) {
return(implode(' ', $flags[$column]));
}
return '';
}
// }}}
// {{{ _add_flag()
/**
* Adds a string to the flags array if the flag is not yet in there
* - if there is no flag present the array is created
*
* @param array $array reference of flags array to add a value to
* @param mixed $value value to add to the flag array
*
* @return void
*
* @access private
*/
function _add_flag(&$array, $value)
{
if (!is_array($array)) {
$array = array($value);
} elseif (!in_array($value, $array)) {
array_push($array, $value);
}
}
// }}}
// {{{ getSpecialQuery()
/**
* Obtains the query string needed for listing a given type of objects
*
* @param string $type the kind of objects you want to retrieve
*
* @return string the SQL query string or null if the driver doesn't
* support the object type requested
*
* @access protected
* @see DB_common::getListOf()
*/
function getSpecialQuery($type)
{
switch ($type) {
case 'tables':
return "SELECT name FROM sysobjects WHERE type = 'U'"
. ' ORDER BY name';
case 'views':
return "SELECT name FROM sysobjects WHERE type = 'V'";
default:
return null;
}
}
// }}}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
*/
?>
+1055
View File
File diff suppressed because it is too large. Load diff
+208
View File
@@ -0,0 +1,208 @@
<?php
// /* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | PHP Version 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2004 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 3.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available through the world-wide-web at the following url: |
// | http://www.php.net/license/3_0.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@php.net> |
// | |
// +----------------------------------------------------------------------+
//
// $Id: Autoloader.php,v 1.11 2004/02/27 02:21:29 cellog Exp $
if (!extension_loaded("overload")) {
// die hard without ext/overload
die("Rebuild PHP with the `overload' extension to use PEAR_Autoloader");
}
require_once "PEAR.php";
/**
* This class is for objects where you want to separate the code for
* some methods into separate classes. This is useful if you have a
* class with not-frequently-used methods that contain lots of code
* that you would like to avoid always parsing.
*
* The PEAR_Autoloader class provides autoloading and aggregation.
* The autoloading lets you set up in which classes the separated
* methods are found. Aggregation is the technique used to import new
* methods, an instance of each class providing separated methods is
* stored and called every time the aggregated method is called.
*
* @author Stig Sæther Bakken <ssb@php.net>
*/
class PEAR_Autoloader extends PEAR
{
// {{{ properties
/**
* Map of methods and classes where they are defined
*
* @var array
*
* @access private
*/
var $_autoload_map = array();
/**
* Map of methods and aggregate objects
*
* @var array
*
* @access private
*/
var $_method_map = array();
// }}}
// {{{ addAutoload()
/**
* Add one or more autoload entries.
*
* @param string $method which method to autoload
*
* @param string $classname (optional) which class to find the method in.
* If the $method parameter is an array, this
* parameter may be omitted (and will be ignored
* if not), and the $method parameter will be
* treated as an associative array with method
* names as keys and class names as values.
*
* @return void
*
* @access public
*/
function addAutoload($method, $classname = null)
{
if (is_array($method)) {
array_walk($method, create_function('$a,&$b', '$b = strtolower($b);'));
$this->_autoload_map = array_merge($this->_autoload_map, $method);
} else {
$this->_autoload_map[strtolower($method)] = $classname;
}
}
// }}}
// {{{ removeAutoload()
/**
* Remove an autoload entry.
*
* @param string $method which method to remove the autoload entry for
*
* @return bool TRUE if an entry was removed, FALSE if not
*
* @access public
*/
function removeAutoload($method)
{
$method = strtolower($method);
$ok = isset($this->_autoload_map[$method]);
unset($this->_autoload_map[$method]);
return $ok;
}
// }}}
// {{{ addAggregateObject()
/**
* Add an aggregate object to this object. If the specified class
* is not defined, loading it will be attempted following PEAR's
* file naming scheme. All the methods in the class will be
* aggregated, except private ones (name starting with an
* underscore) and constructors.
*
* @param string $classname what class to instantiate for the object.
*
* @return void
*
* @access public
*/
function addAggregateObject($classname)
{
$classname = strtolower($classname);
if (!class_exists($classname)) {
$include_file = preg_replace('/[^a-z0-9]/i', '_', $classname);
include_once $include_file;
}
$obj =& new $classname;
$methods = get_class_methods($classname);
foreach ($methods as $method) {
// don't import priviate methods and constructors
if ($method{0} != '_' && $method != $classname) {
$this->_method_map[$method] = $obj;
}
}
}
// }}}
// {{{ removeAggregateObject()
/**
* Remove an aggregate object.
*
* @param string $classname the class of the object to remove
*
* @return bool TRUE if an object was removed, FALSE if not
*
* @access public
*/
function removeAggregateObject($classname)
{
$ok = false;
$classname = strtolower($classname);
reset($this->_method_map);
while (list($method, $obj) = each($this->_method_map)) {
if (is_a($obj, $classname)) {
unset($this->_method_map[$method]);
$ok = true;
}
}
return $ok;
}
// }}}
// {{{ __call()
/**
* Overloaded object call handler, called each time an
* undefined/aggregated method is invoked. This method repeats
* the call in the right aggregate object and passes on the return
* value.
*
* @param string $method which method that was called
*
* @param string $args An array of the parameters passed in the
* original call
*
* @return mixed The return value from the aggregated method, or a PEAR
* error if the called method was unknown.
*/
function __call($method, $args, &$retval)
{
$method = strtolower($method);
if (empty($this->_method_map[$method]) && isset($this->_autoload_map[$method])) {
$this->addAggregateObject($this->_autoload_map[$method]);
}
if (isset($this->_method_map[$method])) {
$retval = call_user_func_array(array($this->_method_map[$method], $method), $args);
return true;
}
return false;
}
// }}}
}
overload("PEAR_Autoloader");
?>
+426
View File
@@ -0,0 +1,426 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2004 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 3.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available through the world-wide-web at the following url: |
// | http://www.php.net/license/3_0.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 Sæther Bakken <ssb@php.net> |
// +----------------------------------------------------------------------+
//
// $Id: Builder.php,v 1.16.2.3 2005/02/17 17:55:01 cellog Exp $
require_once 'PEAR/Common.php';
/**
* Class to handle building (compiling) extensions.
*
* @author Stig Sæther Bakken <ssb@php.net>
*/
class PEAR_Builder extends PEAR_Common
{
// {{{ properties
var $php_api_version = 0;
var $zend_module_api_no = 0;
var $zend_extension_api_no = 0;
var $extensions_built = array();
var $current_callback = null;
// used for msdev builds
var $_lastline = null;
var $_firstline = null;
// }}}
// {{{ constructor
/**
* PEAR_Builder constructor.
*
* @param object $ui user interface object (instance of PEAR_Frontend_*)
*
* @access public
*/
function PEAR_Builder(&$ui)
{
parent::PEAR_Common();
$this->setFrontendObject($ui);
}
// }}}
// {{{ _build_win32()
/**
* Build an extension from source on windows.
* requires msdev
*/
function _build_win32($descfile, $callback = null)
{
if (PEAR::isError($info = $this->infoFromDescriptionFile($descfile))) {
return $info;
}
$dir = dirname($descfile);
$old_cwd = getcwd();
if (!@chdir($dir)) {
return $this->raiseError("could not chdir to $dir");
}
$this->log(2, "building in $dir");
$dsp = $info['package'].'.dsp';
if (!@is_file("$dir/$dsp")) {
return $this->raiseError("The DSP $dsp does not exist.");
}
// XXX TODO: make release build type configurable
$command = 'msdev '.$dsp.' /MAKE "'.$info['package']. ' - Release"';
$this->current_callback = $callback;
$err = $this->_runCommand($command, array(&$this, 'msdevCallback'));
if (PEAR::isError($err)) {
return $err;
}
// figure out the build platform and type
$platform = 'Win32';
$buildtype = 'Release';
if (preg_match('/.*?'.$info['package'].'\s-\s(\w+)\s(.*?)-+/i',$this->_firstline,$matches)) {
$platform = $matches[1];
$buildtype = $matches[2];
}
if (preg_match('/(.*)?\s-\s(\d+).*?(\d+)/',$this->_lastline,$matches)) {
if ($matches[2]) {
// there were errors in the build
return $this->raiseError("There were errors during compilation.");
}
$out = $matches[1];
} else {
return $this->raiseError("Did not understand the completion status returned from msdev.exe.");
}
// msdev doesn't tell us the output directory :/
// open the dsp, find /out and use that directory
$dsptext = join(file($dsp),'');
// this regex depends on the build platform and type having been
// correctly identified above.
$regex ='/.*?!IF\s+"\$\(CFG\)"\s+==\s+("'.
$info['package'].'\s-\s'.
$platform.'\s'.
$buildtype.'").*?'.
'\/out:"(.*?)"/is';
if ($dsptext && preg_match($regex,$dsptext,$matches)) {
// what we get back is a relative path to the output file itself.
$outfile = realpath($matches[2]);
} else {
return $this->raiseError("Could not retrieve output information from $dsp.");
}
if (@copy($outfile, "$dir/$out")) {
$outfile = "$dir/$out";
}
$built_files[] = array(
'file' => "$outfile",
'php_api' => $this->php_api_version,
'zend_mod_api' => $this->zend_module_api_no,
'zend_ext_api' => $this->zend_extension_api_no,
);
return $built_files;
}
// }}}
// {{{ msdevCallback()
function msdevCallback($what, $data)
{
if (!$this->_firstline)
$this->_firstline = $data;
$this->_lastline = $data;
}
// }}}
// {{{ _harventInstDir
/**
* @param string
* @param string
* @param array
* @access private
*/
function _harvestInstDir($dest_prefix, $dirname, &$built_files)
{
$d = opendir($dirname);
if (!$d)
return false;
$ret = true;
while (($ent = readdir($d)) !== false) {
if ($ent{0} == '.')
continue;
$full = $dirname . DIRECTORY_SEPARATOR . $ent;
if (is_dir($full)) {
if (!$this->_harvestInstDir(
$dest_prefix . DIRECTORY_SEPARATOR . $ent,
$full, $built_files)) {
$ret = false;
break;
}
} else {
$dest = $dest_prefix . DIRECTORY_SEPARATOR . $ent;
$built_files[] = array(
'file' => $full,
'dest' => $dest,
'php_api' => $this->php_api_version,
'zend_mod_api' => $this->zend_module_api_no,
'zend_ext_api' => $this->zend_extension_api_no,
);
}
}
closedir($d);
return $ret;
}
// }}}
// {{{ build()
/**
* Build an extension from source. Runs "phpize" in the source
* directory, but compiles in a temporary directory
* (/var/tmp/pear-build-USER/PACKAGE-VERSION).
*
* @param string $descfile path to XML package description file
*
* @param mixed $callback callback function used to report output,
* see PEAR_Builder::_runCommand for details
*
* @return array an array of associative arrays with built files,
* format:
* array( array( 'file' => '/path/to/ext.so',
* 'php_api' => YYYYMMDD,
* 'zend_mod_api' => YYYYMMDD,
* 'zend_ext_api' => YYYYMMDD ),
* ... )
*
* @access public
*
* @see PEAR_Builder::_runCommand
* @see PEAR_Common::infoFromDescriptionFile
*/
function build($descfile, $callback = null)
{
if (PEAR_OS == "Windows") {
return $this->_build_win32($descfile,$callback);
}
if (PEAR_OS != 'Unix') {
return $this->raiseError("building extensions not supported on this platform");
}
if (PEAR::isError($info = $this->infoFromDescriptionFile($descfile))) {
return $info;
}
$dir = dirname($descfile);
$old_cwd = getcwd();
if (!@chdir($dir)) {
return $this->raiseError("could not chdir to $dir");
}
$vdir = "$info[package]-$info[version]";
if (is_dir($vdir)) {
chdir($vdir);
}
$dir = getcwd();
$this->log(2, "building in $dir");
$this->current_callback = $callback;
putenv('PATH=' . $this->config->get('bin_dir') . ':' . getenv('PATH'));
$err = $this->_runCommand("phpize", array(&$this, 'phpizeCallback'));
if (PEAR::isError($err)) {
return $err;
}
if (!$err) {
return $this->raiseError("`phpize' failed");
}
// {{{ start of interactive part
$configure_command = "$dir/configure";
if (isset($info['configure_options'])) {
foreach ($info['configure_options'] as $o) {
list($r) = $this->ui->userDialog('build',
array($o['prompt']),
array('text'),
array(@$o['default']));
if (substr($o['name'], 0, 5) == 'with-' &&
($r == 'yes' || $r == 'autodetect')) {
$configure_command .= " --$o[name]";
} else {
$configure_command .= " --$o[name]=".trim($r);
}
}
}
// }}} end of interactive part
// FIXME make configurable
if(!$user=getenv('USER')){
$user='defaultuser';
}
$build_basedir = "/var/tmp/pear-build-$user";
$build_dir = "$build_basedir/$info[package]-$info[version]";
$inst_dir = "$build_basedir/install-$info[package]-$info[version]";
$this->log(1, "building in $build_dir");
if (is_dir($build_dir)) {
System::rm('-rf', $build_dir);
}
if (!System::mkDir(array('-p', $build_dir))) {
return $this->raiseError("could not create build dir: $build_dir");
}
$this->addTempFile($build_dir);
if (!System::mkDir(array('-p', $inst_dir))) {
return $this->raiseError("could not create temporary install dir: $inst_dir");
}
$this->addTempFile($inst_dir);
if (getenv('MAKE')) {
$make_command = getenv('MAKE');
} else {
$make_command = 'make';
}
$to_run = array(
$configure_command,
$make_command,
"$make_command INSTALL_ROOT=\"$inst_dir\" install",
"find \"$inst_dir\" -ls"
);
if (!@chdir($build_dir)) {
return $this->raiseError("could not chdir to $build_dir");
}
putenv('PHP_PEAR_VERSION=1.3.5');
foreach ($to_run as $cmd) {
$err = $this->_runCommand($cmd, $callback);
if (PEAR::isError($err)) {
chdir($old_cwd);
return $err;
}
if (!$err) {
chdir($old_cwd);
return $this->raiseError("`$cmd' failed");
}
}
if (!($dp = opendir("modules"))) {
chdir($old_cwd);
return $this->raiseError("no `modules' directory found");
}
$built_files = array();
$prefix = exec("php-config --prefix");
$this->_harvestInstDir($prefix, $inst_dir . DIRECTORY_SEPARATOR . $prefix, $built_files);
chdir($old_cwd);
return $built_files;
}
// }}}
// {{{ phpizeCallback()
/**
* Message callback function used when running the "phpize"
* program. Extracts the API numbers used. Ignores other message
* types than "cmdoutput".
*
* @param string $what the type of message
* @param mixed $data the message
*
* @return void
*
* @access public
*/
function phpizeCallback($what, $data)
{
if ($what != 'cmdoutput') {
return;
}
$this->log(1, rtrim($data));
if (preg_match('/You should update your .aclocal.m4/', $data)) {
return;
}
$matches = array();
if (preg_match('/^\s+(\S[^:]+):\s+(\d{8})/', $data, $matches)) {
$member = preg_replace('/[^a-z]/', '_', strtolower($matches[1]));
$apino = (int)$matches[2];
if (isset($this->$member)) {
$this->$member = $apino;
//$msg = sprintf("%-22s : %d", $matches[1], $apino);
//$this->log(1, $msg);
}
}
}
// }}}
// {{{ _runCommand()
/**
* Run an external command, using a message callback to report
* output. The command will be run through popen and output is
* reported for every line with a "cmdoutput" message with the
* line string, including newlines, as payload.
*
* @param string $command the command to run
*
* @param mixed $callback (optional) function to use as message
* callback
*
* @return bool whether the command was successful (exit code 0
* means success, any other means failure)
*
* @access private
*/
function _runCommand($command, $callback = null)
{
$this->log(1, "running: $command");
$pp = @popen("$command 2>&1", "r");
if (!$pp) {
return $this->raiseError("failed to run `$command'");
}
if ($callback && $callback[0]->debug == 1) {
$olddbg = $callback[0]->debug;
$callback[0]->debug = 2;
}
while ($line = fgets($pp, 1024)) {
if ($callback) {
call_user_func($callback, 'cmdoutput', $line);
} else {
$this->log(2, rtrim($line));
}
}
if ($callback && isset($olddbg)) {
$callback[0]->debug = $olddbg;
}
$exitcode = @pclose($pp);
return ($exitcode == 0);
}
// }}}
// {{{ log()
function log($level, $msg)
{
if ($this->current_callback) {
if ($this->debug >= $level) {
call_user_func($this->current_callback, 'output', $msg);
}
return;
}
return PEAR_Common::log($level, $msg);
}
// }}}
}
?>
+398
View File
@@ -0,0 +1,398 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2004 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 3.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available through the world-wide-web at the following url: |
// | http://www.php.net/license/3_0.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@php.net> |
// +----------------------------------------------------------------------+
//
// $Id: Command.php,v 1.24 2004/05/16 15:43:30 pajoye Exp $
require_once "PEAR.php";
/**
* List of commands and what classes they are implemented in.
* @var array command => implementing class
*/
$GLOBALS['_PEAR_Command_commandlist'] = array();
/**
* List of shortcuts to common commands.
* @var array shortcut => command
*/
$GLOBALS['_PEAR_Command_shortcuts'] = array();
/**
* Array of command objects
* @var array class => object
*/
$GLOBALS['_PEAR_Command_objects'] = array();
/**
* Which user interface class is being used.
* @var string class name
*/
$GLOBALS['_PEAR_Command_uiclass'] = 'PEAR_Frontend_CLI';
/**
* Instance of $_PEAR_Command_uiclass.
* @var object
*/
$GLOBALS['_PEAR_Command_uiobject'] = null;
/**
* PEAR command class, a simple factory class for administrative
* commands.
*
* How to implement command classes:
*
* - The class must be called PEAR_Command_Nnn, installed in the
* "PEAR/Common" subdir, with a method called getCommands() that
* returns an array of the commands implemented by the class (see
* PEAR/Command/Install.php for an example).
*
* - The class must implement a run() function that is called with three
* params:
*
* (string) command name
* (array) assoc array with options, freely defined by each
* command, for example:
* array('force' => true)
* (array) list of the other parameters
*
* The run() function returns a PEAR_CommandResponse object. Use
* these methods to get information:
*
* int getStatus() Returns PEAR_COMMAND_(SUCCESS|FAILURE|PARTIAL)
* *_PARTIAL means that you need to issue at least
* one more command to complete the operation
* (used for example for validation steps).
*
* string getMessage() Returns a message for the user. Remember,
* no HTML or other interface-specific markup.
*
* If something unexpected happens, run() returns a PEAR error.
*
* - DON'T OUTPUT ANYTHING! Return text for output instead.
*
* - DON'T USE HTML! The text you return will be used from both Gtk,
* web and command-line interfaces, so for now, keep everything to
* plain text.
*
* - DON'T USE EXIT OR DIE! Always use pear errors. From static
* classes do PEAR::raiseError(), from other classes do
* $this->raiseError().
*/
class PEAR_Command
{
// {{{ factory()
/**
* Get the right object for executing a command.
*
* @param string $command The name of the command
* @param object $config Instance of PEAR_Config object
*
* @return object the command object or a PEAR error
*
* @access public
* @static
*/
function factory($command, &$config)
{
if (empty($GLOBALS['_PEAR_Command_commandlist'])) {
PEAR_Command::registerCommands();
}
if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) {
$command = $GLOBALS['_PEAR_Command_shortcuts'][$command];
}
if (!isset($GLOBALS['_PEAR_Command_commandlist'][$command])) {
return PEAR::raiseError("unknown command `$command'");
}
$class = $GLOBALS['_PEAR_Command_commandlist'][$command];
if (!class_exists($class)) {
return PEAR::raiseError("unknown command `$command'");
}
$ui =& PEAR_Command::getFrontendObject();
$obj = &new $class($ui, $config);
return $obj;
}
// }}}
// {{{ & getFrontendObject()
/**
* Get instance of frontend object.
*
* @return object
* @static
*/
function &getFrontendObject()
{
if (empty($GLOBALS['_PEAR_Command_uiobject'])) {
$GLOBALS['_PEAR_Command_uiobject'] = &new $GLOBALS['_PEAR_Command_uiclass'];
}
return $GLOBALS['_PEAR_Command_uiobject'];
}
// }}}
// {{{ & setFrontendClass()
/**
* Load current frontend class.
*
* @param string $uiclass Name of class implementing the frontend
*
* @return object the frontend object, or a PEAR error
* @static
*/
function &setFrontendClass($uiclass)
{
if (is_object($GLOBALS['_PEAR_Command_uiobject']) &&
is_a($GLOBALS['_PEAR_Command_uiobject'], $uiclass)) {
return $GLOBALS['_PEAR_Command_uiobject'];
}
if (!class_exists($uiclass)) {
$file = str_replace('_', '/', $uiclass) . '.php';
if (PEAR_Command::isIncludeable($file)) {
include_once $file;
}
}
if (class_exists($uiclass)) {
$obj = &new $uiclass;
// quick test to see if this class implements a few of the most
// important frontend methods
if (method_exists($obj, 'userConfirm')) {
$GLOBALS['_PEAR_Command_uiobject'] = &$obj;
$GLOBALS['_PEAR_Command_uiclass'] = $uiclass;
return $obj;
} else {
$err = PEAR::raiseError("not a frontend class: $uiclass");
return $err;
}
}
$err = PEAR::raiseError("no such class: $uiclass");
return $err;
}
// }}}
// {{{ setFrontendType()
// }}}
// {{{ isIncludeable()
/**
* @param string $path relative or absolute include path
* @return boolean
* @static
*/
function isIncludeable($path)
{
if (file_exists($path) && is_readable($path)) {
return true;
}
$ipath = explode(PATH_SEPARATOR, ini_get('include_path'));
foreach ($ipath as $include) {
$test = realpath($include . DIRECTORY_SEPARATOR . $path);
if (file_exists($test) && is_readable($test)) {
return true;
}
}
return false;
}
/**
* Set current frontend.
*
* @param string $uitype Name of the frontend type (for example "CLI")
*
* @return object the frontend object, or a PEAR error
* @static
*/
function setFrontendType($uitype)
{
$uiclass = 'PEAR_Frontend_' . $uitype;
return PEAR_Command::setFrontendClass($uiclass);
}
// }}}
// {{{ registerCommands()
/**
* Scan through the Command directory looking for classes
* and see what commands they implement.
*
* @param bool (optional) if FALSE (default), the new list of
* commands should replace the current one. If TRUE,
* new entries will be merged with old.
*
* @param string (optional) where (what directory) to look for
* classes, defaults to the Command subdirectory of
* the directory from where this file (__FILE__) is
* included.
*
* @return bool TRUE on success, a PEAR error on failure
*
* @access public
* @static
*/
function registerCommands($merge = false, $dir = null)
{
if ($dir === null) {
$dir = dirname(__FILE__) . '/Command';
}
$dp = @opendir($dir);
if (empty($dp)) {
return PEAR::raiseError("registerCommands: opendir($dir) failed");
}
if (!$merge) {
$GLOBALS['_PEAR_Command_commandlist'] = array();
}
while ($entry = readdir($dp)) {
if ($entry{0} == '.' || substr($entry, -4) != '.php' || $entry == 'Common.php') {
continue;
}
$class = "PEAR_Command_".substr($entry, 0, -4);
$file = "$dir/$entry";
include_once $file;
// List of commands
if (empty($GLOBALS['_PEAR_Command_objects'][$class])) {
$GLOBALS['_PEAR_Command_objects'][$class] = &new $class($ui, $config);
}
$implements = $GLOBALS['_PEAR_Command_objects'][$class]->getCommands();
foreach ($implements as $command => $desc) {
$GLOBALS['_PEAR_Command_commandlist'][$command] = $class;
$GLOBALS['_PEAR_Command_commanddesc'][$command] = $desc;
}
$shortcuts = $GLOBALS['_PEAR_Command_objects'][$class]->getShortcuts();
foreach ($shortcuts as $shortcut => $command) {
$GLOBALS['_PEAR_Command_shortcuts'][$shortcut] = $command;
}
}
@closedir($dp);
return true;
}
// }}}
// {{{ getCommands()
/**
* Get the list of currently supported commands, and what
* classes implement them.
*
* @return array command => implementing class
*
* @access public
* @static
*/
function getCommands()
{
if (empty($GLOBALS['_PEAR_Command_commandlist'])) {
PEAR_Command::registerCommands();
}
return $GLOBALS['_PEAR_Command_commandlist'];
}
// }}}
// {{{ getShortcuts()
/**
* Get the list of command shortcuts.
*
* @return array shortcut => command
*
* @access public
* @static
*/
function getShortcuts()
{
if (empty($GLOBALS['_PEAR_Command_shortcuts'])) {
PEAR_Command::registerCommands();
}
return $GLOBALS['_PEAR_Command_shortcuts'];
}
// }}}
// {{{ getGetoptArgs()
/**
* Compiles arguments for getopt.
*
* @param string $command command to get optstring for
* @param string $short_args (reference) short getopt format
* @param array $long_args (reference) long getopt format
*
* @return void
*
* @access public
* @static
*/
function getGetoptArgs($command, &$short_args, &$long_args)
{
if (empty($GLOBALS['_PEAR_Command_commandlist'])) {
PEAR_Command::registerCommands();
}
if (!isset($GLOBALS['_PEAR_Command_commandlist'][$command])) {
return null;
}
$class = $GLOBALS['_PEAR_Command_commandlist'][$command];
$obj = &$GLOBALS['_PEAR_Command_objects'][$class];
return $obj->getGetoptArgs($command, $short_args, $long_args);
}
// }}}
// {{{ getDescription()
/**
* Get description for a command.
*
* @param string $command Name of the command
*
* @return string command description
*
* @access public
* @static
*/
function getDescription($command)
{
if (!isset($GLOBALS['_PEAR_Command_commanddesc'][$command])) {
return null;
}
return $GLOBALS['_PEAR_Command_commanddesc'][$command];
}
// }}}
// {{{ getHelp()
/**
* Get help for command.
*
* @param string $command Name of the command to return help for
*
* @access public
* @static
*/
function getHelp($command)
{
$cmds = PEAR_Command::getCommands();
if (isset($cmds[$command])) {
$class = $cmds[$command];
return $GLOBALS['_PEAR_Command_objects'][$class]->getHelp($command);
}
return false;
}
// }}}
}
?>
+155
View File
@@ -0,0 +1,155 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2004 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 3.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available through the world-wide-web at the following url: |
// | http://www.php.net/license/3_0.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@php.net> |
// +----------------------------------------------------------------------+
//
// $Id: Auth.php,v 1.15 2004/01/08 17:33:13 sniper Exp $
require_once "PEAR/Command/Common.php";
require_once "PEAR/Remote.php";
require_once "PEAR/Config.php";
/**
* PEAR commands for managing configuration data.
*
*/
class PEAR_Command_Auth extends PEAR_Command_Common
{
// {{{ properties
var $commands = array(
'login' => array(
'summary' => 'Connects and authenticates to remote server',
'shortcut' => 'li',
'function' => 'doLogin',
'options' => array(),
'doc' => '
Log in to the remote server. To use remote functions in the installer
that require any kind of privileges, you need to log in first. The
username and password you enter here will be stored in your per-user
PEAR configuration (~/.pearrc on Unix-like systems). After logging
in, your username and password will be sent along in subsequent
operations on the remote server.',
),
'logout' => array(
'summary' => 'Logs out from the remote server',
'shortcut' => 'lo',
'function' => 'doLogout',
'options' => array(),
'doc' => '
Logs out from the remote server. This command does not actually
connect to the remote server, it only deletes the stored username and
password from your user configuration.',
)
);
// }}}
// {{{ constructor
/**
* PEAR_Command_Auth constructor.
*
* @access public
*/
function PEAR_Command_Auth(&$ui, &$config)
{
parent::PEAR_Command_Common($ui, $config);
}
// }}}
// {{{ doLogin()
/**
* Execute the 'login' command.
*
* @param string $command command name
*
* @param array $options option_name => value
*
* @param array $params list of additional parameters
*
* @return bool TRUE on success, FALSE for unknown commands, or
* a PEAR error on failure
*
* @access public
*/
function doLogin($command, $options, $params)
{
$server = $this->config->get('master_server');
$remote = new PEAR_Remote($this->config);
$username = $this->config->get('username');
if (empty($username)) {
$username = @$_ENV['USER'];
}
$this->ui->outputData("Logging in to $server.", $command);
list($username, $password) = $this->ui->userDialog(
$command,
array('Username', 'Password'),
array('text', 'password'),
array($username, '')
);
$username = trim($username);
$password = trim($password);
$this->config->set('username', $username);
$this->config->set('password', $password);
$remote->expectError(401);
$ok = $remote->call('logintest');
$remote->popExpect();
if ($ok === true) {
$this->ui->outputData("Logged in.", $command);
$this->config->store();
} else {
return $this->raiseError("Login failed!");
}
}
// }}}
// {{{ doLogout()
/**
* Execute the 'logout' command.
*
* @param string $command command name
*
* @param array $options option_name => value
*
* @param array $params list of additional parameters
*
* @return bool TRUE on success, FALSE for unknown commands, or
* a PEAR error on failure
*
* @access public
*/
function doLogout($command, $options, $params)
{
$server = $this->config->get('master_server');
$this->ui->outputData("Logging out from $server.", $command);
$this->config->remove('username');
$this->config->remove('password');
$this->config->store();
}
// }}}
}
?>
+89
View File
@@ -0,0 +1,89 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2004 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 3.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available through the world-wide-web at the following url: |
// | http://www.php.net/license/3_0.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@php.net> |
// | Tomas V.V.Cox <cox@idecnet.com> |
// | |
// +----------------------------------------------------------------------+
//
// $Id: Build.php,v 1.9 2004/01/08 17:33:13 sniper Exp $
require_once "PEAR/Command/Common.php";
require_once "PEAR/Builder.php";
/**
* PEAR commands for building extensions.
*
*/
class PEAR_Command_Build extends PEAR_Command_Common
{
// {{{ properties
var $commands = array(
'build' => array(
'summary' => 'Build an Extension From C Source',
'function' => 'doBuild',
'shortcut' => 'b',
'options' => array(),
'doc' => '[package.xml]
Builds one or more extensions contained in a package.'
),
);
// }}}
// {{{ constructor
/**
* PEAR_Command_Build constructor.
*
* @access public
*/
function PEAR_Command_Build(&$ui, &$config)
{
parent::PEAR_Command_Common($ui, $config);
}
// }}}
// {{{ doBuild()
function doBuild($command, $options, $params)
{
if (sizeof($params) < 1) {
$params[0] = 'package.xml';
}
$builder = &new PEAR_Builder($this->ui);
$this->debug = $this->config->get('verbose');
$err = $builder->build($params[0], array(&$this, 'buildCallback'));
if (PEAR::isError($err)) {
return $err;
}
return true;
}
// }}}
// {{{ buildCallback()
function buildCallback($what, $data)
{
if (($what == 'cmdoutput' && $this->debug > 1) ||
($what == 'output' && $this->debug > 0)) {
$this->ui->outputData(rtrim($data), 'build');
}
}
// }}}
}
+249
View File
@@ -0,0 +1,249 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2004 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 3.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available through the world-wide-web at the following url: |
// | http://www.php.net/license/3_0.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 Sæther Bakken <ssb@php.net> |
// +----------------------------------------------------------------------+
//
// $Id: Common.php,v 1.24 2004/01/08 17:33:13 sniper Exp $
require_once "PEAR.php";
class PEAR_Command_Common extends PEAR
{
// {{{ properties
/**
* PEAR_Config object used to pass user system and configuration
* on when executing commands
*
* @var object
*/
var $config;
/**
* User Interface object, for all interaction with the user.
* @var object
*/
var $ui;
var $_deps_rel_trans = array(
'lt' => '<',
'le' => '<=',
'eq' => '=',
'ne' => '!=',
'gt' => '>',
'ge' => '>=',
'has' => '=='
);
var $_deps_type_trans = array(
'pkg' => 'package',
'extension' => 'extension',
'php' => 'PHP',
'prog' => 'external program',
'ldlib' => 'external library for linking',
'rtlib' => 'external runtime library',
'os' => 'operating system',
'websrv' => 'web server',
'sapi' => 'SAPI backend'
);
// }}}
// {{{ constructor
/**
* PEAR_Command_Common constructor.
*
* @access public
*/
function PEAR_Command_Common(&$ui, &$config)
{
parent::PEAR();
$this->config = &$config;
$this->ui = &$ui;
}
// }}}
// {{{ getCommands()
/**
* Return a list of all the commands defined by this class.
* @return array list of commands
* @access public
*/
function getCommands()
{
$ret = array();
foreach (array_keys($this->commands) as $command) {
$ret[$command] = $this->commands[$command]['summary'];
}
return $ret;
}
// }}}
// {{{ getShortcuts()
/**
* Return a list of all the command shortcuts defined by this class.
* @return array shortcut => command
* @access public
*/
function getShortcuts()
{
$ret = array();
foreach (array_keys($this->commands) as $command) {
if (isset($this->commands[$command]['shortcut'])) {
$ret[$this->commands[$command]['shortcut']] = $command;
}
}
return $ret;
}
// }}}
// {{{ getOptions()
function getOptions($command)
{
return @$this->commands[$command]['options'];
}
// }}}
// {{{ getGetoptArgs()
function getGetoptArgs($command, &$short_args, &$long_args)
{
$short_args = "";
$long_args = array();
if (empty($this->commands[$command])) {
return;
}
reset($this->commands[$command]);
while (list($option, $info) = each($this->commands[$command]['options'])) {
$larg = $sarg = '';
if (isset($info['arg'])) {
if ($info['arg']{0} == '(') {
$larg = '==';
$sarg = '::';
$arg = substr($info['arg'], 1, -1);
} else {
$larg = '=';
$sarg = ':';
$arg = $info['arg'];
}
}
if (isset($info['shortopt'])) {
$short_args .= $info['shortopt'] . $sarg;
}
$long_args[] = $option . $larg;
}
}
// }}}
// {{{ getHelp()
/**
* Returns the help message for the given command
*
* @param string $command The command
* @return mixed A fail string if the command does not have help or
* a two elements array containing [0]=>help string,
* [1]=> help string for the accepted cmd args
*/
function getHelp($command)
{
$config = &PEAR_Config::singleton();
$help = @$this->commands[$command]['doc'];
if (empty($help)) {
// XXX (cox) Fallback to summary if there is no doc (show both?)
if (!$help = @$this->commands[$command]['summary']) {
return "No help for command \"$command\"";
}
}
if (preg_match_all('/{config\s+([^\}]+)}/e', $help, $matches)) {
foreach($matches[0] as $k => $v) {
$help = preg_replace("/$v/", $config->get($matches[1][$k]), $help);
}
}
return array($help, $this->getHelpArgs($command));
}
// }}}
// {{{ getHelpArgs()
/**
* Returns the help for the accepted arguments of a command
*
* @param string $command
* @return string The help string
*/
function getHelpArgs($command)
{
if (isset($this->commands[$command]['options']) &&
count($this->commands[$command]['options']))
{
$help = "Options:\n";
foreach ($this->commands[$command]['options'] as $k => $v) {
if (isset($v['arg'])) {
if ($v['arg']{0} == '(') {
$arg = substr($v['arg'], 1, -1);
$sapp = " [$arg]";
$lapp = "[=$arg]";
} else {
$sapp = " $v[arg]";
$lapp = "=$v[arg]";
}
} else {
$sapp = $lapp = "";
}
if (isset($v['shortopt'])) {
$s = $v['shortopt'];
@$help .= " -$s$sapp, --$k$lapp\n";
} else {
@$help .= " --$k$lapp\n";
}
$p = " ";
$doc = rtrim(str_replace("\n", "\n$p", $v['doc']));
$help .= " $doc\n";
}
return $help;
}
return null;
}
// }}}
// {{{ run()
function run($command, $options, $params)
{
$func = @$this->commands[$command]['function'];
if (empty($func)) {
// look for shortcuts
foreach (array_keys($this->commands) as $cmd) {
if (@$this->commands[$cmd]['shortcut'] == $command) {
$command = $cmd;
$func = @$this->commands[$command]['function'];
if (empty($func)) {
return $this->raiseError("unknown command `$command'");
}
break;
}
}
}
return $this->$func($command, $options, $params);
}
// }}}
}
?>
+225
View File
@@ -0,0 +1,225 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2004 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 3.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available through the world-wide-web at the following url: |
// | http://www.php.net/license/3_0.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@php.net> |
// | Tomas V.V.Cox <cox@idecnet.com> |
// | |
// +----------------------------------------------------------------------+
//
// $Id: Config.php,v 1.27 2004/06/15 16:48:49 pajoye Exp $
require_once "PEAR/Command/Common.php";
require_once "PEAR/Config.php";
/**
* PEAR commands for managing configuration data.
*
*/
class PEAR_Command_Config extends PEAR_Command_Common
{
// {{{ properties
var $commands = array(
'config-show' => array(
'summary' => 'Show All Settings',
'function' => 'doConfigShow',
'shortcut' => 'csh',
'options' => array(),
'doc' => '
Displays all configuration values. An optional argument
may be used to tell which configuration layer to display. Valid
configuration layers are "user", "system" and "default".
',
),
'config-get' => array(
'summary' => 'Show One Setting',
'function' => 'doConfigGet',
'shortcut' => 'cg',
'options' => array(),
'doc' => '<parameter> [layer]
Displays the value of one configuration parameter. The
first argument is the name of the parameter, an optional second argument
may be used to tell which configuration layer to look in. Valid configuration
layers are "user", "system" and "default". If no layer is specified, a value
will be picked from the first layer that defines the parameter, in the order
just specified.
',
),
'config-set' => array(
'summary' => 'Change Setting',
'function' => 'doConfigSet',
'shortcut' => 'cs',
'options' => array(),
'doc' => '<parameter> <value> [layer]
Sets the value of one configuration parameter. The first argument is
the name of the parameter, the second argument is the new value. Some
parameters are subject to validation, and the command will fail with
an error message if the new value does not make sense. An optional
third argument may be used to specify in which layer to set the
configuration parameter. The default layer is "user".
',
),
'config-help' => array(
'summary' => 'Show Information About Setting',
'function' => 'doConfigHelp',
'shortcut' => 'ch',
'options' => array(),
'doc' => '[parameter]
Displays help for a configuration parameter. Without arguments it
displays help for all configuration parameters.
',
),
);
// }}}
// {{{ constructor
/**
* PEAR_Command_Config constructor.
*
* @access public
*/
function PEAR_Command_Config(&$ui, &$config)
{
parent::PEAR_Command_Common($ui, $config);
}
// }}}
// {{{ doConfigShow()
function doConfigShow($command, $options, $params)
{
// $params[0] -> the layer
if ($error = $this->_checkLayer(@$params[0])) {
return $this->raiseError($error);
}
$keys = $this->config->getKeys();
sort($keys);
$data = array('caption' => 'Configuration:');
foreach ($keys as $key) {
$type = $this->config->getType($key);
$value = $this->config->get($key, @$params[0]);
if ($type == 'password' && $value) {
$value = '********';
}
if ($value === false) {
$value = 'false';
} elseif ($value === true) {
$value = 'true';
}
$data['data'][$this->config->getGroup($key)][] = array($this->config->getPrompt($key) , $key, $value);
}
$this->ui->outputData($data, $command);
return true;
}
// }}}
// {{{ doConfigGet()
function doConfigGet($command, $options, $params)
{
// $params[0] -> the parameter
// $params[1] -> the layer
if ($error = $this->_checkLayer(@$params[1])) {
return $this->raiseError($error);
}
if (sizeof($params) < 1 || sizeof($params) > 2) {
return $this->raiseError("config-get expects 1 or 2 parameters");
} elseif (sizeof($params) == 1) {
$this->ui->outputData($this->config->get($params[0]), $command);
} else {
$data = $this->config->get($params[0], $params[1]);
$this->ui->outputData($data, $command);
}
return true;
}
// }}}
// {{{ doConfigSet()
function doConfigSet($command, $options, $params)
{
// $param[0] -> a parameter to set
// $param[1] -> the value for the parameter
// $param[2] -> the layer
$failmsg = '';
if (sizeof($params) < 2 || sizeof($params) > 3) {
$failmsg .= "config-set expects 2 or 3 parameters";
return PEAR::raiseError($failmsg);
}
if ($error = $this->_checkLayer(@$params[2])) {
$failmsg .= $error;
return PEAR::raiseError($failmsg);
}
if (!call_user_func_array(array(&$this->config, 'set'), $params))
{
$failmsg = "config-set (" . implode(", ", $params) . ") failed";
} else {
$this->config->store();
}
if ($failmsg) {
return $this->raiseError($failmsg);
}
return true;
}
// }}}
// {{{ doConfigHelp()
function doConfigHelp($command, $options, $params)
{
if (empty($params)) {
$params = $this->config->getKeys();
}
$data['caption'] = "Config help" . ((count($params) == 1) ? " for $params[0]" : '');
$data['headline'] = array('Name', 'Type', 'Description');
$data['border'] = true;
foreach ($params as $name) {
$type = $this->config->getType($name);
$docs = $this->config->getDocs($name);
if ($type == 'set') {
$docs = rtrim($docs) . "\nValid set: " .
implode(' ', $this->config->getSetValues($name));
}
$data['data'][] = array($name, $type, $docs);
}
$this->ui->outputData($data, $command);
}
// }}}
// {{{ _checkLayer()
/**
* Checks if a layer is defined or not
*
* @param string $layer The layer to search for
* @return mixed False on no error or the error message
*/
function _checkLayer($layer = null)
{
if (!empty($layer) && $layer != 'default') {
$layers = $this->config->getLayers();
if (!in_array($layer, $layers)) {
return " only the layers: \"" . implode('" or "', $layers) . "\" are supported";
}
}
return false;
}
// }}}
}
?>
+470
View File
@@ -0,0 +1,470 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2004 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 3.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available through the world-wide-web at the following url: |
// | http://www.php.net/license/3_0.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 Sæther Bakken <ssb@php.net> |
// +----------------------------------------------------------------------+
//
// $Id: Install.php,v 1.53.2.1 2004/10/19 04:08:42 cellog Exp $
require_once "PEAR/Command/Common.php";
require_once "PEAR/Installer.php";
/**
* PEAR commands for installation or deinstallation/upgrading of
* packages.
*
*/
class PEAR_Command_Install extends PEAR_Command_Common
{
// {{{ properties
var $commands = array(
'install' => array(
'summary' => 'Install Package',
'function' => 'doInstall',
'shortcut' => 'i',
'options' => array(
'force' => array(
'shortopt' => 'f',
'doc' => 'will overwrite newer installed packages',
),
'nodeps' => array(
'shortopt' => 'n',
'doc' => 'ignore dependencies, install anyway',
),
'register-only' => array(
'shortopt' => 'r',
'doc' => 'do not install files, only register the package as installed',
),
'soft' => array(
'shortopt' => 's',
'doc' => 'soft install, fail silently, or upgrade if already installed',
),
'nobuild' => array(
'shortopt' => 'B',
'doc' => 'don\'t build C extensions',
),
'nocompress' => array(
'shortopt' => 'Z',
'doc' => 'request uncompressed files when downloading',
),
'installroot' => array(
'shortopt' => 'R',
'arg' => 'DIR',
'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)',
),
'ignore-errors' => array(
'doc' => 'force install even if there were errors',
),
'alldeps' => array(
'shortopt' => 'a',
'doc' => 'install all required and optional dependencies',
),
'onlyreqdeps' => array(
'shortopt' => 'o',
'doc' => 'install all required dependencies',
),
),
'doc' => '<package> ...
Installs one or more PEAR packages. You can specify a package to
install in four ways:
"Package-1.0.tgz" : installs from a local file
"http://example.com/Package-1.0.tgz" : installs from
anywhere on the net.
"package.xml" : installs the package described in
package.xml. Useful for testing, or for wrapping a PEAR package in
another package manager such as RPM.
"Package" : queries your configured server
({config master_server}) and downloads the newest package with
the preferred quality/state ({config preferred_state}).
More than one package may be specified at once. It is ok to mix these
four ways of specifying packages.
'),
'upgrade' => array(
'summary' => 'Upgrade Package',
'function' => 'doInstall',
'shortcut' => 'up',
'options' => array(
'force' => array(
'shortopt' => 'f',
'doc' => 'overwrite newer installed packages',
),
'nodeps' => array(
'shortopt' => 'n',
'doc' => 'ignore dependencies, upgrade anyway',
),
'register-only' => array(
'shortopt' => 'r',
'doc' => 'do not install files, only register the package as upgraded',
),
'nobuild' => array(
'shortopt' => 'B',
'doc' => 'don\'t build C extensions',
),
'nocompress' => array(
'shortopt' => 'Z',
'doc' => 'request uncompressed files when downloading',
),
'installroot' => array(
'shortopt' => 'R',
'arg' => 'DIR',
'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)',
),
'ignore-errors' => array(
'doc' => 'force install even if there were errors',
),
'alldeps' => array(
'shortopt' => 'a',
'doc' => 'install all required and optional dependencies',
),
'onlyreqdeps' => array(
'shortopt' => 'o',
'doc' => 'install all required dependencies',
),
),
'doc' => '<package> ...
Upgrades one or more PEAR packages. See documentation for the
"install" command for ways to specify a package.
When upgrading, your package will be updated if the provided new
package has a higher version number (use the -f option if you need to
upgrade anyway).
More than one package may be specified at once.
'),
'upgrade-all' => array(
'summary' => 'Upgrade All Packages',
'function' => 'doInstall',
'shortcut' => 'ua',
'options' => array(
'nodeps' => array(
'shortopt' => 'n',
'doc' => 'ignore dependencies, upgrade anyway',
),
'register-only' => array(
'shortopt' => 'r',
'doc' => 'do not install files, only register the package as upgraded',
),
'nobuild' => array(
'shortopt' => 'B',
'doc' => 'don\'t build C extensions',
),
'nocompress' => array(
'shortopt' => 'Z',
'doc' => 'request uncompressed files when downloading',
),
'installroot' => array(
'shortopt' => 'R',
'arg' => 'DIR',
'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)',
),
'ignore-errors' => array(
'doc' => 'force install even if there were errors',
),
),
'doc' => '
Upgrades all packages that have a newer release available. Upgrades are
done only if there is a release available of the state specified in
"preferred_state" (currently {config preferred_state}), or a state considered
more stable.
'),
'uninstall' => array(
'summary' => 'Un-install Package',
'function' => 'doUninstall',
'shortcut' => 'un',
'options' => array(
'nodeps' => array(
'shortopt' => 'n',
'doc' => 'ignore dependencies, uninstall anyway',
),
'register-only' => array(
'shortopt' => 'r',
'doc' => 'do not remove files, only register the packages as not installed',
),
'installroot' => array(
'shortopt' => 'R',
'arg' => 'DIR',
'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)',
),
'ignore-errors' => array(
'doc' => 'force install even if there were errors',
),
),
'doc' => '<package> ...
Uninstalls one or more PEAR packages. More than one package may be
specified at once.
'),
'bundle' => array(
'summary' => 'Unpacks a Pecl Package',
'function' => 'doBundle',
'shortcut' => 'bun',
'options' => array(
'destination' => array(
'shortopt' => 'd',
'arg' => 'DIR',
'doc' => 'Optional destination directory for unpacking (defaults to current path or "ext" if exists)',
),
'force' => array(
'shortopt' => 'f',
'doc' => 'Force the unpacking even if there were errors in the package',
),
),
'doc' => '<package>
Unpacks a Pecl Package into the selected location. It will download the
package if needed.
'),
);
// }}}
// {{{ constructor
/**
* PEAR_Command_Install constructor.
*
* @access public
*/
function PEAR_Command_Install(&$ui, &$config)
{
parent::PEAR_Command_Common($ui, $config);
}
// }}}
// {{{ doInstall()
function doInstall($command, $options, $params)
{
require_once 'PEAR/Downloader.php';
if (empty($this->installer)) {
$this->installer = &new PEAR_Installer($this->ui);
}
if ($command == 'upgrade') {
$options['upgrade'] = true;
}
if ($command == 'upgrade-all') {
include_once "PEAR/Remote.php";
$options['upgrade'] = true;
$remote = &new PEAR_Remote($this->config);
$state = $this->config->get('preferred_state');
if (empty($state) || $state == 'any') {
$latest = $remote->call("package.listLatestReleases");
} else {
$latest = $remote->call("package.listLatestReleases", $state);
}
if (PEAR::isError($latest)) {
return $latest;
}
$reg = new PEAR_Registry($this->config->get('php_dir'));
$installed = array_flip($reg->listPackages());
$params = array();
foreach ($latest as $package => $info) {
$package = strtolower($package);
if (!isset($installed[$package])) {
// skip packages we don't have installed
continue;
}
$inst_version = $reg->packageInfo($package, 'version');
if (version_compare("$info[version]", "$inst_version", "le")) {
// installed version is up-to-date
continue;
}
$params[] = $package;
$this->ui->outputData(array('data' => "Will upgrade $package"), $command);
}
}
$this->downloader = &new PEAR_Downloader($this->ui, $options, $this->config);
$errors = array();
$downloaded = array();
$this->downloader->download($params);
$errors = $this->downloader->getErrorMsgs();
if (count($errors)) {
$err['data'] = array($errors);
$err['headline'] = 'Install Errors';
$this->ui->outputData($err);
return $this->raiseError("$command failed");
}
$downloaded = $this->downloader->getDownloadedPackages();
$this->installer->sortPkgDeps($downloaded);
foreach ($downloaded as $pkg) {
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
$info = $this->installer->install($pkg['file'], $options, $this->config);
PEAR::popErrorHandling();
if (PEAR::isError($info)) {
$this->ui->outputData('ERROR: ' .$info->getMessage());
continue;
}
if (is_array($info)) {
if ($this->config->get('verbose') > 0) {
$label = "$info[package] $info[version]";
$out = array('data' => "$command ok: $label");
if (isset($info['release_warnings'])) {
$out['release_warnings'] = $info['release_warnings'];
}
$this->ui->outputData($out, $command);
}
} else {
return $this->raiseError("$command failed");
}
}
return true;
}
// }}}
// {{{ doUninstall()
function doUninstall($command, $options, $params)
{
if (empty($this->installer)) {
$this->installer = &new PEAR_Installer($this->ui);
}
if (sizeof($params) < 1) {
return $this->raiseError("Please supply the package(s) you want to uninstall");
}
include_once 'PEAR/Registry.php';
$reg = new PEAR_Registry($this->config->get('php_dir'));
$newparams = array();
$badparams = array();
foreach ($params as $pkg) {
$info = $reg->packageInfo($pkg);
if ($info === null) {
$badparams[] = $pkg;
} else {
$newparams[] = $info;
}
}
$this->installer->sortPkgDeps($newparams, true);
$params = array();
foreach($newparams as $info) {
$params[] = $info['info']['package'];
}
$params = array_merge($params, $badparams);
foreach ($params as $pkg) {
if ($this->installer->uninstall($pkg, $options)) {
if ($this->config->get('verbose') > 0) {
$this->ui->outputData("uninstall ok: $pkg", $command);
}
} else {
return $this->raiseError("uninstall failed: $pkg");
}
}
return true;
}
// }}}
// }}}
// {{{ doBundle()
/*
(cox) It just downloads and untars the package, does not do
any check that the PEAR_Installer::_installFile() does.
*/
function doBundle($command, $options, $params)
{
if (empty($this->installer)) {
$this->installer = &new PEAR_Downloader($this->ui);
}
$installer = &$this->installer;
if (sizeof($params) < 1) {
return $this->raiseError("Please supply the package you want to bundle");
}
$pkgfile = $params[0];
$need_download = false;
if (preg_match('#^(http|ftp)://#', $pkgfile)) {
$need_download = true;
} elseif (!@is_file($pkgfile)) {
if ($installer->validPackageName($pkgfile)) {
$pkgfile = $installer->getPackageDownloadUrl($pkgfile);
$need_download = true;
} else {
if (strlen($pkgfile)) {
return $this->raiseError("Could not open the package file: $pkgfile");
} else {
return $this->raiseError("No package file given");
}
}
}
// Download package -----------------------------------------------
if ($need_download) {
$downloaddir = $installer->config->get('download_dir');
if (empty($downloaddir)) {
if (PEAR::isError($downloaddir = System::mktemp('-d'))) {
return $downloaddir;
}
$installer->log(2, '+ tmp dir created at ' . $downloaddir);
}
$callback = $this->ui ? array(&$installer, '_downloadCallback') : null;
$file = $installer->downloadHttp($pkgfile, $this->ui, $downloaddir, $callback);
if (PEAR::isError($file)) {
return $this->raiseError($file);
}
$pkgfile = $file;
}
// Parse xml file -----------------------------------------------
$pkginfo = $installer->infoFromTgzFile($pkgfile);
if (PEAR::isError($pkginfo)) {
return $this->raiseError($pkginfo);
}
$installer->validatePackageInfo($pkginfo, $errors, $warnings);
// XXX We allow warnings, do we have to do it?
if (count($errors)) {
if (empty($options['force'])) {
return $this->raiseError("The following errors where found:\n".
implode("\n", $errors));
} else {
$this->log(0, "warning : the following errors were found:\n".
implode("\n", $errors));
}
}
$pkgname = $pkginfo['package'];
// Unpacking -------------------------------------------------
if (isset($options['destination'])) {
if (!is_dir($options['destination'])) {
System::mkdir('-p ' . $options['destination']);
}
$dest = realpath($options['destination']);
} else {
$pwd = getcwd();
if (is_dir($pwd . DIRECTORY_SEPARATOR . 'ext')) {
$dest = $pwd . DIRECTORY_SEPARATOR . 'ext';
} else {
$dest = $pwd;
}
}
$dest .= DIRECTORY_SEPARATOR . $pkgname;
$orig = $pkgname . '-' . $pkginfo['version'];
$tar = new Archive_Tar($pkgfile);
if (!@$tar->extractModify($dest, $orig)) {
return $this->raiseError("unable to unpack $pkgfile");
}
$this->ui->outputData("Package ready at '$dest'");
// }}}
}
// }}}
}
?>
+101
View File
@@ -0,0 +1,101 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2004 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 3.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available through the world-wide-web at the following url: |
// | http://www.php.net/license/3_0.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: Alexander Merz <alexmerz@php.net> |
// | |
// +----------------------------------------------------------------------+
//
// $Id: Mirror.php,v 1.5 2004/03/18 12:23:57 mj Exp $
require_once "PEAR/Command/Common.php";
require_once "PEAR/Command.php";
require_once "PEAR/Remote.php";
require_once "PEAR.php";
/**
* PEAR commands for providing file mirrors
*
*/
class PEAR_Command_Mirror extends PEAR_Command_Common
{
// {{{ properties
var $commands = array(
'download-all' => array(
'summary' => 'Downloads each available package from master_server',
'function' => 'doDownloadAll',
'shortcut' => 'da',
'options' => array(),
'doc' => '
Requests a list of available packages from the package server
(master_server) and downloads them to current working directory'
),
);
// }}}
// {{{ constructor
/**
* PEAR_Command_Mirror constructor.
*
* @access public
* @param object PEAR_Frontend a reference to an frontend
* @param object PEAR_Config a reference to the configuration data
*/
function PEAR_Command_Mirror(&$ui, &$config)
{
parent::PEAR_Command_Common($ui, $config);
}
// }}}
// {{{ doDownloadAll()
/**
* retrieves a list of avaible Packages from master server
* and downloads them
*
* @access public
* @param string $command the command
* @param array $options the command options before the command
* @param array $params the stuff after the command name
* @return bool true if succesful
* @throw PEAR_Error
*/
function doDownloadAll($command, $options, $params)
{
$this->config->set("php_dir", ".");
$remote = &new PEAR_Remote($this->config);
$remoteInfo = $remote->call("package.listAll");
if (PEAR::isError($remoteInfo)) {
return $remoteInfo;
}
$cmd = &PEAR_Command::factory("download", $this->config);
if (PEAR::isError($cmd)) {
return $cmd;
}
foreach ($remoteInfo as $pkgn => $pkg) {
/**
* Error handling not neccesary, because already done by
* the download command
*/
$cmd->run("download", array(), array($pkgn));
}
return true;
}
// }}}
}
+819
View File
@@ -0,0 +1,819 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2004 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 3.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available through the world-wide-web at the following url: |
// | http://www.php.net/license/3_0.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@php.net> |
// | Martin Jansen <mj@php.net> |
// | Greg Beaver <cellog@php.net> |
// +----------------------------------------------------------------------+
//
// $Id: Package.php,v 1.61.2.7 2005/02/17 17:47:55 cellog Exp $
require_once 'PEAR/Common.php';
require_once 'PEAR/Command/Common.php';
class PEAR_Command_Package extends PEAR_Command_Common
{
// {{{ properties
var $commands = array(
'package' => array(
'summary' => 'Build Package',
'function' => 'doPackage',
'shortcut' => 'p',
'options' => array(
'nocompress' => array(
'shortopt' => 'Z',
'doc' => 'Do not gzip the package file'
),
'showname' => array(
'shortopt' => 'n',
'doc' => 'Print the name of the packaged file.',
),
),
'doc' => '[descfile]
Creates a PEAR package from its description file (usually called
package.xml).
'
),
'package-validate' => array(
'summary' => 'Validate Package Consistency',
'function' => 'doPackageValidate',
'shortcut' => 'pv',
'options' => array(),
'doc' => '
',
),
'cvsdiff' => array(
'summary' => 'Run a "cvs diff" for all files in a package',
'function' => 'doCvsDiff',
'shortcut' => 'cd',
'options' => array(
'quiet' => array(
'shortopt' => 'q',
'doc' => 'Be quiet',
),
'reallyquiet' => array(
'shortopt' => 'Q',
'doc' => 'Be really quiet',
),
'date' => array(
'shortopt' => 'D',
'doc' => 'Diff against revision of DATE',
'arg' => 'DATE',
),
'release' => array(
'shortopt' => 'R',
'doc' => 'Diff against tag for package release REL',
'arg' => 'REL',
),
'revision' => array(
'shortopt' => 'r',
'doc' => 'Diff against revision REV',
'arg' => 'REV',
),
'context' => array(
'shortopt' => 'c',
'doc' => 'Generate context diff',
),
'unified' => array(
'shortopt' => 'u',
'doc' => 'Generate unified diff',
),
'ignore-case' => array(
'shortopt' => 'i',
'doc' => 'Ignore case, consider upper- and lower-case letters equivalent',
),
'ignore-whitespace' => array(
'shortopt' => 'b',
'doc' => 'Ignore changes in amount of white space',
),
'ignore-blank-lines' => array(
'shortopt' => 'B',
'doc' => 'Ignore changes that insert or delete blank lines',
),
'brief' => array(
'doc' => 'Report only whether the files differ, no details',
),
'dry-run' => array(
'shortopt' => 'n',
'doc' => 'Don\'t do anything, just pretend',
),
),
'doc' => '<package.xml>
Compares all the files in a package. Without any options, this
command will compare the current code with the last checked-in code.
Using the -r or -R option you may compare the current code with that
of a specific release.
',
),
'cvstag' => array(
'summary' => 'Set CVS Release Tag',
'function' => 'doCvsTag',
'shortcut' => 'ct',
'options' => array(
'quiet' => array(
'shortopt' => 'q',
'doc' => 'Be quiet',
),
'reallyquiet' => array(
'shortopt' => 'Q',
'doc' => 'Be really quiet',
),
'slide' => array(
'shortopt' => 'F',
'doc' => 'Move (slide) tag if it exists',
),
'delete' => array(
'shortopt' => 'd',
'doc' => 'Remove tag',
),
'dry-run' => array(
'shortopt' => 'n',
'doc' => 'Don\'t do anything, just pretend',
),
),
'doc' => '<package.xml>
Sets a CVS tag on all files in a package. Use this command after you have
packaged a distribution tarball with the "package" command to tag what
revisions of what files were in that release. If need to fix something
after running cvstag once, but before the tarball is released to the public,
use the "slide" option to move the release tag.
',
),
'run-tests' => array(
'summary' => 'Run Regression Tests',
'function' => 'doRunTests',
'shortcut' => 'rt',
'options' => array(
'recur' => array(
'shortopt' => 'r',
'doc' => 'Run tests in child directories, recursively. 4 dirs deep maximum',
),
'ini' => array(
'shortopt' => 'i',
'doc' => 'actual string of settings to pass to php in format " -d setting=blah"',
'arg' => 'SETTINGS'
),
'realtimelog' => array(
'shortopt' => 'l',
'doc' => 'Log test runs/results as they are run',
),
),
'doc' => '[testfile|dir ...]
Run regression tests with PHP\'s regression testing script (run-tests.php).',
),
'package-dependencies' => array(
'summary' => 'Show package dependencies',
'function' => 'doPackageDependencies',
'shortcut' => 'pd',
'options' => array(),
'doc' => '
List all depencies the package has.'
),
'sign' => array(
'summary' => 'Sign a package distribution file',
'function' => 'doSign',
'shortcut' => 'si',
'options' => array(),
'doc' => '<package-file>
Signs a package distribution (.tar or .tgz) file with GnuPG.',
),
'makerpm' => array(
'summary' => 'Builds an RPM spec file from a PEAR package',
'function' => 'doMakeRPM',
'shortcut' => 'rpm',
'options' => array(
'spec-template' => array(
'shortopt' => 't',
'arg' => 'FILE',
'doc' => 'Use FILE as RPM spec file template'
),
'rpm-pkgname' => array(
'shortopt' => 'p',
'arg' => 'FORMAT',
'doc' => 'Use FORMAT as format string for RPM package name, %s is replaced
by the PEAR package name, defaults to "PEAR::%s".',
),
),
'doc' => '<package-file>
Creates an RPM .spec file for wrapping a PEAR package inside an RPM
package. Intended to be used from the SPECS directory, with the PEAR
package tarball in the SOURCES directory:
$ pear makerpm ../SOURCES/Net_Socket-1.0.tgz
Wrote RPM spec file PEAR::Net_Geo-1.0.spec
$ rpm -bb PEAR::Net_Socket-1.0.spec
...
Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm
',
),
);
var $output;
// }}}
// {{{ constructor
/**
* PEAR_Command_Package constructor.
*
* @access public
*/
function PEAR_Command_Package(&$ui, &$config)
{
parent::PEAR_Command_Common($ui, $config);
}
// }}}
// {{{ _displayValidationResults()
function _displayValidationResults($err, $warn, $strict = false)
{
foreach ($err as $e) {
$this->output .= "Error: $e\n";
}
foreach ($warn as $w) {
$this->output .= "Warning: $w\n";
}
$this->output .= sprintf('Validation: %d error(s), %d warning(s)'."\n",
sizeof($err), sizeof($warn));
if ($strict && sizeof($err) > 0) {
$this->output .= "Fix these errors and try again.";
return false;
}
return true;
}
// }}}
// {{{ doPackage()
function doPackage($command, $options, $params)
{
$this->output = '';
include_once 'PEAR/Packager.php';
if (sizeof($params) < 1) {
$params[0] = "package.xml";
}
$pkginfofile = isset($params[0]) ? $params[0] : 'package.xml';
$packager =& new PEAR_Packager();
$err = $warn = array();
$dir = dirname($pkginfofile);
$compress = empty($options['nocompress']) ? true : false;
$result = $packager->package($pkginfofile, $compress);
if (PEAR::isError($result)) {
$this->ui->outputData($this->output, $command);
return $this->raiseError($result);
}
// Don't want output, only the package file name just created
if (isset($options['showname'])) {
$this->output = $result;
}
if (PEAR::isError($result)) {
$this->output .= "Package failed: ".$result->getMessage();
}
$this->ui->outputData($this->output, $command);
return true;
}
// }}}
// {{{ doPackageValidate()
function doPackageValidate($command, $options, $params)
{
$this->output = '';
if (sizeof($params) < 1) {
$params[0] = "package.xml";
}
$obj = new PEAR_Common;
$info = null;
if ($fp = @fopen($params[0], "r")) {
$test = fread($fp, 5);
fclose($fp);
if ($test == "<?xml") {
$info = $obj->infoFromDescriptionFile($params[0]);
}
}
if (empty($info)) {
$info = $obj->infoFromTgzFile($params[0]);
}
if (PEAR::isError($info)) {
return $this->raiseError($info);
}
$obj->validatePackageInfo($info, $err, $warn);
$this->_displayValidationResults($err, $warn);
$this->ui->outputData($this->output, $command);
return true;
}
// }}}
// {{{ doCvsTag()
function doCvsTag($command, $options, $params)
{
$this->output = '';
$_cmd = $command;
if (sizeof($params) < 1) {
$help = $this->getHelp($command);
return $this->raiseError("$command: missing parameter: $help[0]");
}
$obj = new PEAR_Common;
$info = $obj->infoFromDescriptionFile($params[0]);
if (PEAR::isError($info)) {
return $this->raiseError($info);
}
$err = $warn = array();
$obj->validatePackageInfo($info, $err, $warn);
if (!$this->_displayValidationResults($err, $warn, true)) {
$this->ui->outputData($this->output, $command);
break;
}
$version = $info['version'];
$cvsversion = preg_replace('/[^a-z0-9]/i', '_', $version);
$cvstag = "RELEASE_$cvsversion";
$files = array_keys($info['filelist']);
$command = "cvs";
if (isset($options['quiet'])) {
$command .= ' -q';
}
if (isset($options['reallyquiet'])) {
$command .= ' -Q';
}
$command .= ' tag';
if (isset($options['slide'])) {
$command .= ' -F';
}
if (isset($options['delete'])) {
$command .= ' -d';
}
$command .= ' ' . $cvstag . ' ' . escapeshellarg($params[0]);
foreach ($files as $file) {
$command .= ' ' . escapeshellarg($file);
}
if ($this->config->get('verbose') > 1) {
$this->output .= "+ $command\n";
}
$this->output .= "+ $command\n";
if (empty($options['dry-run'])) {
$fp = popen($command, "r");
while ($line = fgets($fp, 1024)) {
$this->output .= rtrim($line)."\n";
}
pclose($fp);
}
$this->ui->outputData($this->output, $_cmd);
return true;
}
// }}}
// {{{ doCvsDiff()
function doCvsDiff($command, $options, $params)
{
$this->output = '';
if (sizeof($params) < 1) {
$help = $this->getHelp($command);
return $this->raiseError("$command: missing parameter: $help[0]");
}
$obj = new PEAR_Common;
$info = $obj->infoFromDescriptionFile($params[0]);
if (PEAR::isError($info)) {
return $this->raiseError($info);
}
$files = array_keys($info['filelist']);
$cmd = "cvs";
if (isset($options['quiet'])) {
$cmd .= ' -q';
unset($options['quiet']);
}
if (isset($options['reallyquiet'])) {
$cmd .= ' -Q';
unset($options['reallyquiet']);
}
if (isset($options['release'])) {
$cvsversion = preg_replace('/[^a-z0-9]/i', '_', $options['release']);
$cvstag = "RELEASE_$cvsversion";
$options['revision'] = $cvstag;
unset($options['release']);
}
$execute = true;
if (isset($options['dry-run'])) {
$execute = false;
unset($options['dry-run']);
}
$cmd .= ' diff';
// the rest of the options are passed right on to "cvs diff"
foreach ($options as $option => $optarg) {
$arg = @$this->commands[$command]['options'][$option]['arg'];
$short = @$this->commands[$command]['options'][$option]['shortopt'];
$cmd .= $short ? " -$short" : " --$option";
if ($arg && $optarg) {
$cmd .= ($short ? '' : '=') . escapeshellarg($optarg);
}
}
foreach ($files as $file) {
$cmd .= ' ' . escapeshellarg($file);
}
if ($this->config->get('verbose') > 1) {
$this->output .= "+ $cmd\n";
}
if ($execute) {
$fp = popen($cmd, "r");
while ($line = fgets($fp, 1024)) {
$this->output .= rtrim($line)."\n";
}
pclose($fp);
}
$this->ui->outputData($this->output, $command);
return true;
}
// }}}
// {{{ doRunTests()
function doRunTests($command, $options, $params)
{
include_once 'PEAR/RunTest.php';
$log = new PEAR_Common;
$log->ui = &$this->ui; // slightly hacky, but it will work
$run = new PEAR_RunTest($log);
$tests = array();
if (isset($options['recur'])) {
$depth = 4;
} else {
$depth = 1;
}
if (!count($params)) {
$params[] = '.';
}
foreach ($params as $p) {
if (is_dir($p)) {
$dir = System::find(array($p, '-type', 'f',
'-maxdepth', $depth,
'-name', '*.phpt'));
$tests = array_merge($tests, $dir);
} else {
if (!@file_exists($p)) {
if (!preg_match('/\.phpt$/', $p)) {
$p .= '.phpt';
}
$dir = System::find(array(dirname($p), '-type', 'f',
'-maxdepth', $depth,
'-name', $p));
$tests = array_merge($tests, $dir);
} else {
$tests[] = $p;
}
}
}
$ini_settings = '';
if (isset($options['ini'])) {
$ini_settings .= $options['ini'];
}
if (isset($_ENV['TEST_PHP_INCLUDE_PATH'])) {
$ini_settings .= " -d include_path={$_ENV['TEST_PHP_INCLUDE_PATH']}";
}
if ($ini_settings) {
$this->ui->outputData('Using INI settings: "' . $ini_settings . '"');
}
$skipped = $passed = $failed = array();
$this->ui->outputData('Running ' . count($tests) . ' tests', $command);
$start = time();
if (isset($options['realtimelog'])) {
@unlink('run-tests.log');
}
foreach ($tests as $t) {
if (isset($options['realtimelog'])) {
$fp = @fopen('run-tests.log', 'a');
if ($fp) {
fwrite($fp, "Running test $t...");
fclose($fp);
}
}
$result = $run->run($t, $ini_settings);
if (OS_WINDOWS) {
for($i=0;$i<2000;$i++) {
$i = $i; // delay - race conditions on windows
}
}
if (isset($options['realtimelog'])) {
$fp = @fopen('run-tests.log', 'a');
if ($fp) {
fwrite($fp, "$result\n");
fclose($fp);
}
}
if ($result == 'FAILED') {
$failed[] = $t;
}
if ($result == 'PASSED') {
$passed[] = $t;
}
if ($result == 'SKIPPED') {
$skipped[] = $t;
}
}
$total = date('i:s', time() - $start);
if (count($failed)) {
$output = "TOTAL TIME: $total\n";
$output .= count($passed) . " PASSED TESTS\n";
$output .= count($skipped) . " SKIPPED TESTS\n";
$output .= count($failed) . " FAILED TESTS:\n";
foreach ($failed as $failure) {
$output .= $failure . "\n";
}
if (isset($options['realtimelog'])) {
$fp = @fopen('run-tests.log', 'a');
} else {
$fp = @fopen('run-tests.log', 'w');
}
if ($fp) {
fwrite($fp, $output, strlen($output));
fclose($fp);
$this->ui->outputData('wrote log to "' . realpath('run-tests.log') . '"', $command);
}
} elseif (@file_exists('run-tests.log') && !@is_dir('run-tests.log')) {
@unlink('run-tests.log');
}
$this->ui->outputData('TOTAL TIME: ' . $total);
$this->ui->outputData(count($passed) . ' PASSED TESTS', $command);
$this->ui->outputData(count($skipped) . ' SKIPPED TESTS', $command);
if (count($failed)) {
$this->ui->outputData(count($failed) . ' FAILED TESTS:', $command);
foreach ($failed as $failure) {
$this->ui->outputData($failure, $command);
}
}
return true;
}
// }}}
// {{{ doPackageDependencies()
function doPackageDependencies($command, $options, $params)
{
// $params[0] -> the PEAR package to list its information
if (sizeof($params) != 1) {
return $this->raiseError("bad parameter(s), try \"help $command\"");
}
$obj = new PEAR_Common();
if (PEAR::isError($info = $obj->infoFromAny($params[0]))) {
return $this->raiseError($info);
}
if (is_array($info['release_deps'])) {
$data = array(
'caption' => 'Dependencies for ' . $info['package'],
'border' => true,
'headline' => array("Type", "Name", "Relation", "Version"),
);
foreach ($info['release_deps'] as $d) {
if (isset($this->_deps_rel_trans[$d['rel']])) {
$rel = $this->_deps_rel_trans[$d['rel']];
} else {
$rel = $d['rel'];
}
if (isset($this->_deps_type_trans[$d['type']])) {
$type = ucfirst($this->_deps_type_trans[$d['type']]);
} else {
$type = $d['type'];
}
if (isset($d['name'])) {
$name = $d['name'];
} else {
$name = '';
}
if (isset($d['version'])) {
$version = $d['version'];
} else {
$version = '';
}
$data['data'][] = array($type, $name, $rel, $version);
}
$this->ui->outputData($data, $command);
return true;
}
// Fallback
$this->ui->outputData("This package does not have any dependencies.", $command);
}
// }}}
// {{{ doSign()
function doSign($command, $options, $params)
{
// should move most of this code into PEAR_Packager
// so it'll be easy to implement "pear package --sign"
if (sizeof($params) != 1) {
return $this->raiseError("bad parameter(s), try \"help $command\"");
}
if (!file_exists($params[0])) {
return $this->raiseError("file does not exist: $params[0]");
}
$obj = new PEAR_Common;
$info = $obj->infoFromTgzFile($params[0]);
if (PEAR::isError($info)) {
return $this->raiseError($info);
}
include_once "Archive/Tar.php";
include_once "System.php";
$tar = new Archive_Tar($params[0]);
$tmpdir = System::mktemp('-d pearsign');
if (!$tar->extractList('package.xml package.sig', $tmpdir)) {
return $this->raiseError("failed to extract tar file");
}
if (file_exists("$tmpdir/package.sig")) {
return $this->raiseError("package already signed");
}
@unlink("$tmpdir/package.sig");
$input = $this->ui->userDialog($command,
array('GnuPG Passphrase'),
array('password'));
$gpg = popen("gpg --batch --passphrase-fd 0 --armor --detach-sign --output $tmpdir/package.sig $tmpdir/package.xml 2>/dev/null", "w");
if (!$gpg) {
return $this->raiseError("gpg command failed");
}
fwrite($gpg, "$input[0]\r");
if (pclose($gpg) || !file_exists("$tmpdir/package.sig")) {
return $this->raiseError("gpg sign failed");
}
$tar->addModify("$tmpdir/package.sig", '', $tmpdir);
return true;
}
// }}}
// {{{ doMakeRPM()
/*
(cox)
TODO:
- Fill the rpm dependencies in the template file.
IDEAS:
- Instead of mapping the role to rpm vars, perhaps it's better
to use directly the pear cmd to install the files by itself
in %postrun so:
pear -d php_dir=%{_libdir}/php/pear -d test_dir=.. <package>
*/
function doMakeRPM($command, $options, $params)
{
if (sizeof($params) != 1) {
return $this->raiseError("bad parameter(s), try \"help $command\"");
}
if (!file_exists($params[0])) {
return $this->raiseError("file does not exist: $params[0]");
}
include_once "Archive/Tar.php";
include_once "PEAR/Installer.php";
include_once "System.php";
$tar = new Archive_Tar($params[0]);
$tmpdir = System::mktemp('-d pear2rpm');
$instroot = System::mktemp('-d pear2rpm');
$tmp = $this->config->get('verbose');
$this->config->set('verbose', 0);
$installer = new PEAR_Installer($this->ui);
$info = $installer->install($params[0],
array('installroot' => $instroot,
'nodeps' => true));
$pkgdir = "$info[package]-$info[version]";
$info['rpm_xml_dir'] = '/var/lib/pear';
$this->config->set('verbose', $tmp);
if (!$tar->extractList("package.xml", $tmpdir, $pkgdir)) {
return $this->raiseError("failed to extract $params[0]");
}
if (!file_exists("$tmpdir/package.xml")) {
return $this->raiseError("no package.xml found in $params[0]");
}
if (isset($options['spec-template'])) {
$spec_template = $options['spec-template'];
} else {
$spec_template = $this->config->get('data_dir') .
'/PEAR/template.spec';
}
if (isset($options['rpm-pkgname'])) {
$rpm_pkgname_format = $options['rpm-pkgname'];
} else {
$rpm_pkgname_format = "PEAR::%s";
}
$info['extra_headers'] = '';
$info['doc_files'] = '';
$info['files'] = '';
$info['rpm_package'] = sprintf($rpm_pkgname_format, $info['package']);
$srcfiles = 0;
foreach ($info['filelist'] as $name => $attr) {
if (!isset($attr['role'])) {
continue;
}
$name = preg_replace('![/:\\\\]!', '/', $name);
if ($attr['role'] == 'doc') {
$info['doc_files'] .= " $name";
// Map role to the rpm vars
} else {
$c_prefix = '%{_libdir}/php/pear';
switch ($attr['role']) {
case 'php':
$prefix = $c_prefix; break;
case 'ext':
$prefix = '%{_libdir}/php'; break; // XXX good place?
case 'src':
$srcfiles++;
$prefix = '%{_includedir}/php'; break; // XXX good place?
case 'test':
$prefix = "$c_prefix/tests/" . $info['package']; break;
case 'data':
$prefix = "$c_prefix/data/" . $info['package']; break;
case 'script':
$prefix = '%{_bindir}'; break;
}
$name = str_replace('\\', '/', $name);
$info['files'] .= "$prefix/$name\n";
}
}
if ($srcfiles > 0) {
include_once "OS/Guess.php";
$os = new OS_Guess;
$arch = $os->getCpu();
} else {
$arch = 'noarch';
}
$cfg = array('master_server', 'php_dir', 'ext_dir', 'doc_dir',
'bin_dir', 'data_dir', 'test_dir');
foreach ($cfg as $k) {
$info[$k] = $this->config->get($k);
}
$info['arch'] = $arch;
$fp = @fopen($spec_template, "r");
if (!$fp) {
return $this->raiseError("could not open RPM spec file template $spec_template: $php_errormsg");
}
$spec_contents = preg_replace('/@([a-z0-9_-]+)@/e', '$info["\1"]', fread($fp, filesize($spec_template)));
fclose($fp);
$spec_file = "$info[rpm_package]-$info[version].spec";
$wp = fopen($spec_file, "wb");
if (!$wp) {
return $this->raiseError("could not write RPM spec file $spec_file: $php_errormsg");
}
fwrite($wp, $spec_contents);
fclose($wp);
$this->ui->outputData("Wrote RPM spec file $spec_file", $command);
return true;
}
// }}}
}
?>
+351
View File
@@ -0,0 +1,351 @@
<?php
// /* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | PHP Version 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2004 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 3.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available through the world-wide-web at the following url: |
// | http://www.php.net/license/3_0.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@php.net> |
// | |
// +----------------------------------------------------------------------+
//
// $Id: Registry.php,v 1.36 2004/01/08 17:33:13 sniper Exp $
require_once 'PEAR/Command/Common.php';
require_once 'PEAR/Registry.php';
require_once 'PEAR/Config.php';
class PEAR_Command_Registry extends PEAR_Command_Common
{
// {{{ properties
var $commands = array(
'list' => array(
'summary' => 'List Installed Packages',
'function' => 'doList',
'shortcut' => 'l',
'options' => array(),
'doc' => '[package]
If invoked without parameters, this command lists the PEAR packages
installed in your php_dir ({config php_dir)). With a parameter, it
lists the files in that package.
',
),
'shell-test' => array(
'summary' => 'Shell Script Test',
'function' => 'doShellTest',
'shortcut' => 'st',
'options' => array(),
'doc' => '<package> [[relation] version]
Tests if a package is installed in the system. Will exit(1) if it is not.
<relation> The version comparison operator. One of:
<, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne
<version> The version to compare with
'),
'info' => array(
'summary' => 'Display information about a package',
'function' => 'doInfo',
'shortcut' => 'in',
'options' => array(),
'doc' => '<package>
Displays information about a package. The package argument may be a
local package file, an URL to a package file, or the name of an
installed package.'
)
);
// }}}
// {{{ constructor
/**
* PEAR_Command_Registry constructor.
*
* @access public
*/
function PEAR_Command_Registry(&$ui, &$config)
{
parent::PEAR_Command_Common($ui, $config);
}
// }}}
// {{{ doList()
function _sortinfo($a, $b)
{
return strcmp($a['package'], $b['package']);
}
function doList($command, $options, $params)
{
$reg = new PEAR_Registry($this->config->get('php_dir'));
if (sizeof($params) == 0) {
$installed = $reg->packageInfo();
usort($installed, array(&$this, '_sortinfo'));
$i = $j = 0;
$data = array(
'caption' => 'Installed packages:',
'border' => true,
'headline' => array('Package', 'Version', 'State')
);
foreach ($installed as $package) {
$data['data'][] = array($package['package'],
$package['version'],
@$package['release_state']);
}
if (count($installed)==0) {
$data = '(no packages installed)';
}
$this->ui->outputData($data, $command);
} else {
if (file_exists($params[0]) && !is_dir($params[0])) {
include_once "PEAR/Common.php";
$obj = &new PEAR_Common;
$info = $obj->infoFromAny($params[0]);
$headings = array('Package File', 'Install Path');
$installed = false;
} else {
$info = $reg->packageInfo($params[0]);
$headings = array('Type', 'Install Path');
$installed = true;
}
if (PEAR::isError($info)) {
return $this->raiseError($info);
}
if ($info === null) {
return $this->raiseError("`$params[0]' not installed");
}
$list = $info['filelist'];
if ($installed) {
$caption = 'Installed Files For ' . $params[0];
} else {
$caption = 'Contents of ' . basename($params[0]);
}
$data = array(
'caption' => $caption,
'border' => true,
'headline' => $headings);
foreach ($list as $file => $att) {
if ($installed) {
if (empty($att['installed_as'])) {
continue;
}
$data['data'][] = array($att['role'], $att['installed_as']);
} else {
if (isset($att['baseinstalldir'])) {
$dest = $att['baseinstalldir'] . DIRECTORY_SEPARATOR .
$file;
} else {
$dest = $file;
}
switch ($att['role']) {
case 'test':
case 'data':
if ($installed) {
break 2;
}
$dest = '-- will not be installed --';
break;
case 'doc':
$dest = $this->config->get('doc_dir') . DIRECTORY_SEPARATOR .
$dest;
break;
case 'php':
default:
$dest = $this->config->get('php_dir') . DIRECTORY_SEPARATOR .
$dest;
}
$dest = preg_replace('!/+!', '/', $dest);
$file = preg_replace('!/+!', '/', $file);
$data['data'][] = array($file, $dest);
}
}
$this->ui->outputData($data, $command);
}
return true;
}
// }}}
// {{{ doShellTest()
function doShellTest($command, $options, $params)
{
$this->pushErrorHandling(PEAR_ERROR_RETURN);
$reg = &new PEAR_Registry($this->config->get('php_dir'));
// "pear shell-test Foo"
if (sizeof($params) == 1) {
if (!$reg->packageExists($params[0])) {
exit(1);
}
// "pear shell-test Foo 1.0"
} elseif (sizeof($params) == 2) {
$v = $reg->packageInfo($params[0], 'version');
if (!$v || !version_compare("$v", "{$params[1]}", "ge")) {
exit(1);
}
// "pear shell-test Foo ge 1.0"
} elseif (sizeof($params) == 3) {
$v = $reg->packageInfo($params[0], 'version');
if (!$v || !version_compare("$v", "{$params[2]}", $params[1])) {
exit(1);
}
} else {
$this->popErrorHandling();
$this->raiseError("$command: expects 1 to 3 parameters");
exit(1);
}
}
// }}}
// {{{ doInfo
function doInfo($command, $options, $params)
{
// $params[0] The package for showing info
if (sizeof($params) != 1) {
return $this->raiseError("This command only accepts one param: ".
"the package you want information");
}
if (@is_file($params[0])) {
$obj = &new PEAR_Common();
$info = $obj->infoFromAny($params[0]);
} else {
$reg = &new PEAR_Registry($this->config->get('php_dir'));
$info = $reg->packageInfo($params[0]);
}
if (PEAR::isError($info)) {
return $info;
}
if (empty($info)) {
$this->raiseError("Nothing found for `$params[0]'");
return;
}
unset($info['filelist']);
unset($info['changelog']);
$keys = array_keys($info);
$longtext = array('description', 'summary');
foreach ($keys as $key) {
if (is_array($info[$key])) {
switch ($key) {
case 'maintainers': {
$i = 0;
$mstr = '';
foreach ($info[$key] as $m) {
if ($i++ > 0) {
$mstr .= "\n";
}
$mstr .= $m['name'] . " <";
if (isset($m['email'])) {
$mstr .= $m['email'];
} else {
$mstr .= $m['handle'] . '@php.net';
}
$mstr .= "> ($m[role])";
}
$info[$key] = $mstr;
break;
}
case 'release_deps': {
$i = 0;
$dstr = '';
foreach ($info[$key] as $d) {
if (isset($this->_deps_rel_trans[$d['rel']])) {
$rel = $this->_deps_rel_trans[$d['rel']];
} else {
$rel = $d['rel'];
}
if (isset($this->_deps_type_trans[$d['type']])) {
$type = ucfirst($this->_deps_type_trans[$d['type']]);
} else {
$type = $d['type'];
}
if (isset($d['name'])) {
$name = $d['name'] . ' ';
} else {
$name = '';
}
if (isset($d['version'])) {
$version = $d['version'] . ' ';
} else {
$version = '';
}
$dstr .= "$type $name$rel $version\n";
}
$info[$key] = $dstr;
break;
}
case 'provides' : {
$debug = $this->config->get('verbose');
if ($debug < 2) {
$pstr = 'Classes: ';
} else {
$pstr = '';
}
$i = 0;
foreach ($info[$key] as $p) {
if ($debug < 2 && $p['type'] != "class") {
continue;
}
// Only print classes when verbosity mode is < 2
if ($debug < 2) {
if ($i++ > 0) {
$pstr .= ", ";
}
$pstr .= $p['name'];
} else {
if ($i++ > 0) {
$pstr .= "\n";
}
$pstr .= ucfirst($p['type']) . " " . $p['name'];
if (isset($p['explicit']) && $p['explicit'] == 1) {
$pstr .= " (explicit)";
}
}
}
$info[$key] = $pstr;
break;
}
default: {
$info[$key] = implode(", ", $info[$key]);
break;
}
}
}
if ($key == '_lastmodified') {
$hdate = date('Y-m-d', $info[$key]);
unset($info[$key]);
$info['Last Modified'] = $hdate;
} else {
$info[$key] = trim($info[$key]);
if (in_array($key, $longtext)) {
$info[$key] = preg_replace('/ +/', ' ', $info[$key]);
}
}
}
$caption = 'About ' . $info['package'] . '-' . $info['version'];
$data = array(
'caption' => $caption,
'border' => true);
foreach ($info as $key => $value) {
$key = ucwords(trim(str_replace('_', ' ', $key)));
$data['data'][] = array($key, $value);
}
$data['raw'] = $info;
$this->ui->outputData($data, 'package-info');
}
// }}}
}
?>
+435
View File
@@ -0,0 +1,435 @@
<?php
// /* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | PHP Version 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2004 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 3.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available through the world-wide-web at the following url: |
// | http://www.php.net/license/3_0.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@php.net> |
// | |
// +----------------------------------------------------------------------+
//
// $Id: Remote.php,v 1.39 2004/04/03 15:56:00 cellog Exp $
require_once 'PEAR/Command/Common.php';
require_once 'PEAR/Common.php';
require_once 'PEAR/Remote.php';
require_once 'PEAR/Registry.php';
class PEAR_Command_Remote extends PEAR_Command_Common
{
// {{{ command definitions
var $commands = array(
'remote-info' => array(
'summary' => 'Information About Remote Packages',
'function' => 'doRemoteInfo',
'shortcut' => 'ri',
'options' => array(),
'doc' => '<package>
Get details on a package from the server.',
),
'list-upgrades' => array(
'summary' => 'List Available Upgrades',
'function' => 'doListUpgrades',
'shortcut' => 'lu',
'options' => array(),
'doc' => '
List releases on the server of packages you have installed where
a newer version is available with the same release state (stable etc.).'
),
'remote-list' => array(
'summary' => 'List Remote Packages',
'function' => 'doRemoteList',
'shortcut' => 'rl',
'options' => array(),
'doc' => '
Lists the packages available on the configured server along with the
latest stable release of each package.',
),
'search' => array(
'summary' => 'Search remote package database',
'function' => 'doSearch',
'shortcut' => 'sp',
'options' => array(),
'doc' => '
Lists all packages which match the search parameters (first param
is package name, second package info)',
),
'list-all' => array(
'summary' => 'List All Packages',
'function' => 'doListAll',
'shortcut' => 'la',
'options' => array(),
'doc' => '
Lists the packages available on the configured server along with the
latest stable release of each package.',
),
'download' => array(
'summary' => 'Download Package',
'function' => 'doDownload',
'shortcut' => 'd',
'options' => array(
'nocompress' => array(
'shortopt' => 'Z',
'doc' => 'download an uncompressed (.tar) file',
),
),
'doc' => '{package|package-version}
Download a package tarball. The file will be named as suggested by the
server, for example if you download the DB package and the latest stable
version of DB is 1.2, the downloaded file will be DB-1.2.tgz.',
),
'clear-cache' => array(
'summary' => 'Clear XML-RPC Cache',
'function' => 'doClearCache',
'shortcut' => 'cc',
'options' => array(),
'doc' => '
Clear the XML-RPC cache. See also the cache_ttl configuration
parameter.
',
),
);
// }}}
// {{{ constructor
/**
* PEAR_Command_Remote constructor.
*
* @access public
*/
function PEAR_Command_Remote(&$ui, &$config)
{
parent::PEAR_Command_Common($ui, $config);
}
// }}}
// {{{ doRemoteInfo()
function doRemoteInfo($command, $options, $params)
{
if (sizeof($params) != 1) {
return $this->raiseError("$command expects one param: the remote package name");
}
$r = new PEAR_Remote($this->config);
$info = $r->call('package.info', $params[0]);
if (PEAR::isError($info)) {
return $this->raiseError($info);
}
$reg = new PEAR_Registry($this->config->get('php_dir'));
$installed = $reg->packageInfo($info['name']);
$info['installed'] = $installed['version'] ? $installed['version'] : '- no -';
$this->ui->outputData($info, $command);
return true;
}
// }}}
// {{{ doRemoteList()
function doRemoteList($command, $options, $params)
{
$r = new PEAR_Remote($this->config);
$list_options = false;
if ($this->config->get('preferred_state') == 'stable')
$list_options = true;
$available = $r->call('package.listAll', $list_options);
if (PEAR::isError($available)) {
return $this->raiseError($available);
}
$i = $j = 0;
$data = array(
'caption' => 'Available packages:',
'border' => true,
'headline' => array('Package', 'Version'),
);
foreach ($available as $name => $info) {
$data['data'][] = array($name, isset($info['stable']) ? $info['stable'] : '-n/a-');
}
if (count($available)==0) {
$data = '(no packages installed yet)';
}
$this->ui->outputData($data, $command);
return true;
}
// }}}
// {{{ doListAll()
function doListAll($command, $options, $params)
{
$r = new PEAR_Remote($this->config);
$reg = new PEAR_Registry($this->config->get('php_dir'));
$list_options = false;
if ($this->config->get('preferred_state') == 'stable')
$list_options = true;
$available = $r->call('package.listAll', $list_options);
if (PEAR::isError($available)) {
return $this->raiseError($available);
}
if (!is_array($available)) {
return $this->raiseError('The package list could not be fetched from the remote server. Please try again. (Debug info: "'.$available.'")');
}
$data = array(
'caption' => 'All packages:',
'border' => true,
'headline' => array('Package', 'Latest', 'Local'),
);
$local_pkgs = $reg->listPackages();
foreach ($available as $name => $info) {
$installed = $reg->packageInfo($name);
$desc = $info['summary'];
if (isset($params[$name]))
$desc .= "\n\n".$info['description'];
if (isset($options['mode']))
{
if ($options['mode'] == 'installed' && !isset($installed['version']))
continue;
if ($options['mode'] == 'notinstalled' && isset($installed['version']))
continue;
if ($options['mode'] == 'upgrades'
&& (!isset($installed['version']) || $installed['version'] == $info['stable']))
{
continue;
}
}
$pos = array_search(strtolower($name), $local_pkgs);
if ($pos !== false) {
unset($local_pkgs[$pos]);
}
$data['data'][$info['category']][] = array(
$name,
@$info['stable'],
@$installed['version'],
@$desc,
@$info['deps'],
);
}
foreach ($local_pkgs as $name) {
$info = $reg->packageInfo($name);
$data['data']['Local'][] = array(
$info['package'],
'',
$info['version'],
$info['summary'],
@$info['release_deps']
);
}
$this->ui->outputData($data, $command);
return true;
}
// }}}
// {{{ doSearch()
function doSearch($command, $options, $params)
{
if ((!isset($params[0]) || empty($params[0]))
&& (!isset($params[1]) || empty($params[1])))
{
return $this->raiseError('no valid search string supplied');
};
$r = new PEAR_Remote($this->config);
$reg = new PEAR_Registry($this->config->get('php_dir'));
$available = $r->call('package.listAll', true, false);
if (PEAR::isError($available)) {
return $this->raiseError($available);
}
$data = array(
'caption' => 'Matched packages:',
'border' => true,
'headline' => array('Package', 'Stable/(Latest)', 'Local'),
);
foreach ($available as $name => $info) {
$found = (!empty($params[0]) && stristr($name, $params[0]) !== false);
if (!$found && !(isset($params[1]) && !empty($params[1])
&& (stristr($info['summary'], $params[1]) !== false
|| stristr($info['description'], $params[1]) !== false)))
{
continue;
};
$installed = $reg->packageInfo($name);
$desc = $info['summary'];
if (isset($params[$name]))
$desc .= "\n\n".$info['description'];
$unstable = '';
if ($info['unstable']) {
$unstable = '/(' . $info['unstable'] . $info['state'] . ')';
}
if (!isset($info['stable']) || !$info['stable']) {
$info['stable'] = 'none';
}
$data['data'][$info['category']][] = array(
$name,
$info['stable'] . $unstable,
$installed['version'],
$desc,
);
}
if (!isset($data['data'])) {
return $this->raiseError('no packages found');
}
$this->ui->outputData($data, $command);
return true;
}
// }}}
// {{{ doDownload()
function doDownload($command, $options, $params)
{
//$params[0] -> The package to download
if (count($params) != 1) {
return PEAR::raiseError("download expects one argument: the package to download");
}
$server = $this->config->get('master_server');
if (!ereg('^http://', $params[0])) {
$getoption = isset($options['nocompress'])&&$options['nocompress']==1?'?uncompress=on':'';
$pkgfile = "http://$server/get/$params[0]".$getoption;
} else {
$pkgfile = $params[0];
}
$this->bytes_downloaded = 0;
$saved = PEAR_Common::downloadHttp($pkgfile, $this->ui, '.',
array(&$this, 'downloadCallback'));
if (PEAR::isError($saved)) {
return $this->raiseError($saved);
}
$fname = basename($saved);
$this->ui->outputData("File $fname downloaded ($this->bytes_downloaded bytes)", $command);
return true;
}
function downloadCallback($msg, $params = null)
{
if ($msg == 'done') {
$this->bytes_downloaded = $params;
}
}
// }}}
// {{{ doListUpgrades()
function doListUpgrades($command, $options, $params)
{
include_once "PEAR/Registry.php";
$remote = new PEAR_Remote($this->config);
if (empty($params[0])) {
$state = $this->config->get('preferred_state');
} else {
$state = $params[0];
}
$caption = 'Available Upgrades';
if (empty($state) || $state == 'any') {
$latest = $remote->call("package.listLatestReleases");
} else {
$latest = $remote->call("package.listLatestReleases", $state);
$caption .= ' (' . implode(', ', PEAR_Common::betterStates($state, true)) . ')';
}
$caption .= ':';
if (PEAR::isError($latest)) {
return $latest;
}
$reg = new PEAR_Registry($this->config->get('php_dir'));
$inst = array_flip($reg->listPackages());
$data = array(
'caption' => $caption,
'border' => 1,
'headline' => array('Package', 'Local', 'Remote', 'Size'),
);
foreach ((array)$latest as $pkg => $info) {
$package = strtolower($pkg);
if (!isset($inst[$package])) {
// skip packages we don't have installed
continue;
}
extract($info);
$pkginfo = $reg->packageInfo($package);
$inst_version = $pkginfo['version'];
$inst_state = $pkginfo['release_state'];
if (version_compare("$version", "$inst_version", "le")) {
// installed version is up-to-date
continue;
}
if ($filesize >= 20480) {
$filesize += 1024 - ($filesize % 1024);
$fs = sprintf("%dkB", $filesize / 1024);
} elseif ($filesize > 0) {
$filesize += 103 - ($filesize % 103);
$fs = sprintf("%.1fkB", $filesize / 1024.0);
} else {
$fs = " -"; // XXX center instead
}
$data['data'][] = array($pkg, "$inst_version ($inst_state)", "$version ($state)", $fs);
}
if (empty($data['data'])) {
$this->ui->outputData('No upgrades available');
} else {
$this->ui->outputData($data, $command);
}
return true;
}
// }}}
// {{{ doClearCache()
function doClearCache($command, $options, $params)
{
$cache_dir = $this->config->get('cache_dir');
$verbose = $this->config->get('verbose');
$output = '';
if (!($dp = @opendir($cache_dir))) {
return $this->raiseError("opendir($cache_dir) failed: $php_errormsg");
}
if ($verbose >= 1) {
$output .= "reading directory $cache_dir\n";
}
$num = 0;
while ($ent = readdir($dp)) {
if (preg_match('/^xmlrpc_cache_[a-z0-9]{32}$/', $ent)) {
$path = $cache_dir . DIRECTORY_SEPARATOR . $ent;
$ok = @unlink($path);
if ($ok) {
if ($verbose >= 2) {
$output .= "deleted $path\n";
}
$num++;
} elseif ($verbose >= 1) {
$output .= "failed to delete $path\n";
}
}
}
closedir($dp);
if ($verbose >= 1) {
$output .= "$num cache entries cleared\n";
}
$this->ui->outputData(rtrim($output), $command);
return $num;
}
// }}}
}
?>
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+487
View File
@@ -0,0 +1,487 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2004 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 3.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available through the world-wide-web at the following url: |
// | http://www.php.net/license/3_0.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: Tomas V.V.Cox <cox@idecnet.com> |
// | Stig Bakken <ssb@php.net> |
// +----------------------------------------------------------------------+
//
// $Id: Dependency.php,v 1.36.4.1 2004/12/27 07:04:19 cellog Exp $
require_once "PEAR.php";
define('PEAR_DEPENDENCY_MISSING', -1);
define('PEAR_DEPENDENCY_CONFLICT', -2);
define('PEAR_DEPENDENCY_UPGRADE_MINOR', -3);
define('PEAR_DEPENDENCY_UPGRADE_MAJOR', -4);
define('PEAR_DEPENDENCY_BAD_DEPENDENCY', -5);
define('PEAR_DEPENDENCY_MISSING_OPTIONAL', -6);
define('PEAR_DEPENDENCY_CONFLICT_OPTIONAL', -7);
define('PEAR_DEPENDENCY_UPGRADE_MINOR_OPTIONAL', -8);
define('PEAR_DEPENDENCY_UPGRADE_MAJOR_OPTIONAL', -9);
/**
* Dependency check for PEAR packages
*
* The class is based on the dependency RFC that can be found at
* http://cvs.php.net/cvs.php/pearweb/rfc. It requires PHP >= 4.1
*
* @author Tomas V.V.Vox <cox@idecnet.com>
* @author Stig Bakken <ssb@php.net>
*/
class PEAR_Dependency
{
// {{{ constructor
/**
* Constructor
*
* @access public
* @param object Registry object
* @return void
*/
function PEAR_Dependency(&$registry)
{
$this->registry = &$registry;
}
// }}}
// {{{ callCheckMethod()
/**
* This method maps the XML dependency definition to the
* corresponding one from PEAR_Dependency
*
* <pre>
* $opts => Array
* (
* [type] => pkg
* [rel] => ge
* [version] => 3.4
* [name] => HTML_Common
* [optional] => false
* )
* </pre>
*
* @param string Error message
* @param array Options
* @return boolean
*/
function callCheckMethod(&$errmsg, $opts)
{
$rel = isset($opts['rel']) ? $opts['rel'] : 'has';
$req = isset($opts['version']) ? $opts['version'] : null;
$name = isset($opts['name']) ? $opts['name'] : null;
$opt = (isset($opts['optional']) && $opts['optional'] == 'yes') ?
$opts['optional'] : null;
$errmsg = '';
switch ($opts['type']) {
case 'pkg':
return $this->checkPackage($errmsg, $name, $req, $rel, $opt);
break;
case 'ext':
return $this->checkExtension($errmsg, $name, $req, $rel, $opt);
break;
case 'php':
return $this->checkPHP($errmsg, $req, $rel);
break;
case 'prog':
return $this->checkProgram($errmsg, $name);
break;
case 'os':
return $this->checkOS($errmsg, $name);
break;
case 'sapi':
return $this->checkSAPI($errmsg, $name);
break;
case 'zend':
return $this->checkZend($errmsg, $name);
break;
default:
return "'{$opts['type']}' dependency type not supported";
}
}
// }}}
// {{{ checkPackage()
/**
* Package dependencies check method
*
* @param string $errmsg Empty string, it will be populated with an error message, if any
* @param string $name Name of the package to test
* @param string $req The package version required
* @param string $relation How to compare versions with each other
* @param bool $opt Whether the relationship is optional
*
* @return mixed bool false if no error or the error string
*/
function checkPackage(&$errmsg, $name, $req = null, $relation = 'has',
$opt = false)
{
if (is_string($req) && substr($req, 0, 2) == 'v.') {
$req = substr($req, 2);
}
switch ($relation) {
case 'has':
if (!$this->registry->packageExists($name)) {
if ($opt) {
$errmsg = "package `$name' is recommended to utilize some features.";
return PEAR_DEPENDENCY_MISSING_OPTIONAL;
}
$errmsg = "requires package `$name'";
return PEAR_DEPENDENCY_MISSING;
}
return false;
case 'not':
if ($this->registry->packageExists($name)) {
$errmsg = "conflicts with package `$name'";
return PEAR_DEPENDENCY_CONFLICT;
}
return false;
case 'lt':
case 'le':
case 'eq':
case 'ne':
case 'ge':
case 'gt':
$version = $this->registry->packageInfo($name, 'version');
if (!$this->registry->packageExists($name)
|| !version_compare("$version", "$req", $relation))
{
$code = $this->codeFromRelation($relation, $version, $req, $opt);
if ($opt) {
$errmsg = "package `$name' version " . $this->signOperator($relation) .
" $req is recommended to utilize some features.";
if ($version) {
$errmsg .= " Installed version is $version";
}
return $code;
}
$errmsg = "requires package `$name' " .
$this->signOperator($relation) . " $req";
return $code;
}
return false;
}
$errmsg = "relation '$relation' with requirement '$req' is not supported (name=$name)";
return PEAR_DEPENDENCY_BAD_DEPENDENCY;
}
// }}}
// {{{ checkPackageUninstall()
/**
* Check package dependencies on uninstall
*
* @param string $error The resultant error string
* @param string $warning The resultant warning string
* @param string $name Name of the package to test
*
* @return bool true if there were errors
*/
function checkPackageUninstall(&$error, &$warning, $package)
{
$error = null;
$packages = $this->registry->listPackages();
foreach ($packages as $pkg) {
if ($pkg == $package) {
continue;
}
$deps = $this->registry->packageInfo($pkg, 'release_deps');
if (empty($deps)) {
continue;
}
foreach ($deps as $dep) {
if ($dep['type'] == 'pkg' && strcasecmp($dep['name'], $package) == 0) {
if ($dep['rel'] == 'ne' || $dep['rel'] == 'not') {
continue;
}
if (isset($dep['optional']) && $dep['optional'] == 'yes') {
$warning .= "\nWarning: Package '$pkg' optionally depends on '$package'";
} else {
$error .= "Package '$pkg' depends on '$package'\n";
}
}
}
}
return ($error) ? true : false;
}
// }}}
// {{{ checkExtension()
/**
* Extension dependencies check method
*
* @param string $name Name of the extension to test
* @param string $req_ext_ver Required extension version to compare with
* @param string $relation How to compare versions with eachother
* @param bool $opt Whether the relationship is optional
*
* @return mixed bool false if no error or the error string
*/
function checkExtension(&$errmsg, $name, $req = null, $relation = 'has',
$opt = false)
{
if ($relation == 'not') {
if (extension_loaded($name)) {
$errmsg = "conflicts with PHP extension '$name'";
return PEAR_DEPENDENCY_CONFLICT;
} else {
return false;
}
}
if (!extension_loaded($name)) {
if ($relation == 'not') {
return false;
}
if ($opt) {
$errmsg = "'$name' PHP extension is recommended to utilize some features";
return PEAR_DEPENDENCY_MISSING_OPTIONAL;
}
$errmsg = "'$name' PHP extension is not installed";
return PEAR_DEPENDENCY_MISSING;
}
if ($relation == 'has') {
return false;
}
$code = false;
if (is_string($req) && substr($req, 0, 2) == 'v.') {
$req = substr($req, 2);
}
$ext_ver = phpversion($name);
$operator = $relation;
// Force params to be strings, otherwise the comparation will fail (ex. 0.9==0.90)
if (!version_compare("$ext_ver", "$req", $operator)) {
$errmsg = "'$name' PHP extension version " .
$this->signOperator($operator) . " $req is required";
$code = $this->codeFromRelation($relation, $ext_ver, $req, $opt);
if ($opt) {
$errmsg = "'$name' PHP extension version " . $this->signOperator($operator) .
" $req is recommended to utilize some features";
return $code;
}
}
return $code;
}
// }}}
// {{{ checkOS()
/**
* Operating system dependencies check method
*
* @param string $os Name of the operating system
*
* @return mixed bool false if no error or the error string
*/
function checkOS(&$errmsg, $os)
{
// XXX Fixme: Implement a more flexible way, like
// comma separated values or something similar to PEAR_OS
static $myos;
if (empty($myos)) {
include_once "OS/Guess.php";
$myos = new OS_Guess();
}
// only 'has' relation is currently supported
if ($myos->matchSignature($os)) {
return false;
}
$errmsg = "'$os' operating system not supported";
return PEAR_DEPENDENCY_CONFLICT;
}
// }}}
// {{{ checkPHP()
/**
* PHP version check method
*
* @param string $req which version to compare
* @param string $relation how to compare the version
*
* @return mixed bool false if no error or the error string
*/
function checkPHP(&$errmsg, $req, $relation = 'ge')
{
// this would be a bit stupid, but oh well :)
if ($relation == 'has') {
return false;
}
if ($relation == 'not') {
$errmsg = 'Invalid dependency - "not" is not allowed for php dependencies, ' .
'php cannot conflict with itself';
return PEAR_DEPENDENCY_BAD_DEPENDENCY;
}
if (substr($req, 0, 2) == 'v.') {
$req = substr($req,2, strlen($req) - 2);
}
$php_ver = phpversion();
$operator = $relation;
if (!version_compare("$php_ver", "$req", $operator)) {
$errmsg = "PHP version " . $this->signOperator($operator) .
" $req is required";
return PEAR_DEPENDENCY_CONFLICT;
}
return false;
}
// }}}
// {{{ checkProgram()
/**
* External program check method. Looks for executable files in
* directories listed in the PATH environment variable.
*
* @param string $program which program to look for
*
* @return mixed bool false if no error or the error string
*/
function checkProgram(&$errmsg, $program)
{
// XXX FIXME honor safe mode
$exe_suffix = OS_WINDOWS ? '.exe' : '';
$path_elements = explode(PATH_SEPARATOR, getenv('PATH'));
foreach ($path_elements as $dir) {
$file = $dir . DIRECTORY_SEPARATOR . $program . $exe_suffix;
if (@file_exists($file) && @is_executable($file)) {
return false;
}
}
$errmsg = "'$program' program is not present in the PATH";
return PEAR_DEPENDENCY_MISSING;
}
// }}}
// {{{ checkSAPI()
/**
* SAPI backend check method. Version comparison is not yet
* available here.
*
* @param string $name name of SAPI backend
* @param string $req which version to compare
* @param string $relation how to compare versions (currently
* hardcoded to 'has')
* @return mixed bool false if no error or the error string
*/
function checkSAPI(&$errmsg, $name, $req = null, $relation = 'has')
{
// XXX Fixme: There is no way to know if the user has or
// not other SAPI backends installed than the installer one
$sapi_backend = php_sapi_name();
// Version comparisons not supported, sapi backends don't have
// version information yet.
if ($sapi_backend == $name) {
return false;
}
$errmsg = "'$sapi_backend' SAPI backend not supported";
return PEAR_DEPENDENCY_CONFLICT;
}
// }}}
// {{{ checkZend()
/**
* Zend version check method
*
* @param string $req which version to compare
* @param string $relation how to compare the version
*
* @return mixed bool false if no error or the error string
*/
function checkZend(&$errmsg, $req, $relation = 'ge')
{
if (substr($req, 0, 2) == 'v.') {
$req = substr($req,2, strlen($req) - 2);
}
$zend_ver = zend_version();
$operator = substr($relation,0,2);
if (!version_compare("$zend_ver", "$req", $operator)) {
$errmsg = "Zend version " . $this->signOperator($operator) .
" $req is required";
return PEAR_DEPENDENCY_CONFLICT;
}
return false;
}
// }}}
// {{{ signOperator()
/**
* Converts text comparing operators to them sign equivalents
*
* Example: 'ge' to '>='
*
* @access public
* @param string Operator
* @return string Sign equivalent
*/
function signOperator($operator)
{
switch($operator) {
case 'lt': return '<';
case 'le': return '<=';
case 'gt': return '>';
case 'ge': return '>=';
case 'eq': return '==';
case 'ne': return '!=';
default:
return $operator;
}
}
// }}}
// {{{ codeFromRelation()
/**
* Convert relation into corresponding code
*
* @access public
* @param string Relation
* @param string Version
* @param string Requirement
* @param bool Optional dependency indicator
* @return integer
*/
function codeFromRelation($relation, $version, $req, $opt = false)
{
$code = PEAR_DEPENDENCY_BAD_DEPENDENCY;
switch ($relation) {
case 'gt': case 'ge': case 'eq':
// upgrade
$have_major = preg_replace('/\D.*/', '', $version);
$need_major = preg_replace('/\D.*/', '', $req);
if ($need_major > $have_major) {
$code = $opt ? PEAR_DEPENDENCY_UPGRADE_MAJOR_OPTIONAL :
PEAR_DEPENDENCY_UPGRADE_MAJOR;
} else {
$code = $opt ? PEAR_DEPENDENCY_UPGRADE_MINOR_OPTIONAL :
PEAR_DEPENDENCY_UPGRADE_MINOR;
}
break;
case 'lt': case 'le': case 'ne':
$code = $opt ? PEAR_DEPENDENCY_CONFLICT_OPTIONAL :
PEAR_DEPENDENCY_CONFLICT;
break;
}
return $code;
}
// }}}
}
?>
+680
View File
@@ -0,0 +1,680 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2004 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 3.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available through the world-wide-web at the following url: |
// | http://www.php.net/license/3_0.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@php.net> |
// | Tomas V.V.Cox <cox@idecnet.com> |
// | Martin Jansen <mj@php.net> |
// +----------------------------------------------------------------------+
//
// $Id: Downloader.php,v 1.17.2.1 2004/10/22 22:54:03 cellog Exp $
require_once 'PEAR/Common.php';
require_once 'PEAR/Registry.php';
require_once 'PEAR/Dependency.php';
require_once 'PEAR/Remote.php';
require_once 'System.php';
define('PEAR_INSTALLER_OK', 1);
define('PEAR_INSTALLER_FAILED', 0);
define('PEAR_INSTALLER_SKIPPED', -1);
define('PEAR_INSTALLER_ERROR_NO_PREF_STATE', 2);
/**
* Administration class used to download PEAR packages and maintain the
* installed package database.
*
* @since PEAR 1.4
* @author Greg Beaver <cellog@php.net>
*/
class PEAR_Downloader extends PEAR_Common
{
/**
* @var PEAR_Config
* @access private
*/
var $_config;
/**
* @var PEAR_Registry
* @access private
*/
var $_registry;
/**
* @var PEAR_Remote
* @access private
*/
var $_remote;
/**
* Preferred Installation State (snapshot, devel, alpha, beta, stable)
* @var string|null
* @access private
*/
var $_preferredState;
/**
* Options from command-line passed to Install.
*
* Recognized options:<br />
* - onlyreqdeps : install all required dependencies as well
* - alldeps : install all dependencies, including optional
* - installroot : base relative path to install files in
* - force : force a download even if warnings would prevent it
* @see PEAR_Command_Install
* @access private
* @var array
*/
var $_options;
/**
* Downloaded Packages after a call to download().
*
* Format of each entry:
*
* <code>
* array('pkg' => 'package_name', 'file' => '/path/to/local/file',
* 'info' => array() // parsed package.xml
* );
* </code>
* @access private
* @var array
*/
var $_downloadedPackages = array();
/**
* Packages slated for download.
*
* This is used to prevent downloading a package more than once should it be a dependency
* for two packages to be installed.
* Format of each entry:
*
* <pre>
* array('package_name1' => parsed package.xml, 'package_name2' => parsed package.xml,
* );
* </pre>
* @access private
* @var array
*/
var $_toDownload = array();
/**
* Array of every package installed, with names lower-cased.
*
* Format:
* <code>
* array('package1' => 0, 'package2' => 1, );
* </code>
* @var array
*/
var $_installed = array();
/**
* @var array
* @access private
*/
var $_errorStack = array();
// {{{ PEAR_Downloader()
function PEAR_Downloader(&$ui, $options, &$config)
{
$this->_options = $options;
$this->_config = &$config;
$this->_preferredState = $this->_config->get('preferred_state');
$this->ui = &$ui;
if (!$this->_preferredState) {
// don't inadvertantly use a non-set preferred_state
$this->_preferredState = null;
}
$php_dir = $this->_config->get('php_dir');
if (isset($this->_options['installroot'])) {
if (substr($this->_options['installroot'], -1) == DIRECTORY_SEPARATOR) {
$this->_options['installroot'] = substr($this->_options['installroot'], 0, -1);
}
$php_dir = $this->_prependPath($php_dir, $this->_options['installroot']);
}
$this->_registry = &new PEAR_Registry($php_dir);
$this->_remote = &new PEAR_Remote($config);
if (isset($this->_options['alldeps']) || isset($this->_options['onlyreqdeps'])) {
$this->_installed = $this->_registry->listPackages();
array_walk($this->_installed, create_function('&$v,$k','$v = strtolower($v);'));
$this->_installed = array_flip($this->_installed);
}
parent::PEAR_Common();
}
// }}}
// {{{ configSet()
function configSet($key, $value, $layer = 'user')
{
$this->_config->set($key, $value, $layer);
$this->_preferredState = $this->_config->get('preferred_state');
if (!$this->_preferredState) {
// don't inadvertantly use a non-set preferred_state
$this->_preferredState = null;
}
}
// }}}
// {{{ setOptions()
function setOptions($options)
{
$this->_options = $options;
}
// }}}
// {{{ _downloadFile()
/**
* @param string filename to download
* @param string version/state
* @param string original value passed to command-line
* @param string|null preferred state (snapshot/devel/alpha/beta/stable)
* Defaults to configuration preferred state
* @return null|PEAR_Error|string
* @access private
*/
function _downloadFile($pkgfile, $version, $origpkgfile, $state = null)
{
if (is_null($state)) {
$state = $this->_preferredState;
}
// {{{ check the package filename, and whether it's already installed
$need_download = false;
if (preg_match('#^(http|ftp)://#', $pkgfile)) {
$need_download = true;
} elseif (!@is_file($pkgfile)) {
if ($this->validPackageName($pkgfile)) {
if ($this->_registry->packageExists($pkgfile)) {
if (empty($this->_options['upgrade']) && empty($this->_options['force'])) {
$errors[] = "$pkgfile already installed";
return;
}
}
$pkgfile = $this->getPackageDownloadUrl($pkgfile, $version);
$need_download = true;
} else {
if (strlen($pkgfile)) {
$errors[] = "Could not open the package file: $pkgfile";
} else {
$errors[] = "No package file given";
}
return;
}
}
// }}}
// {{{ Download package -----------------------------------------------
if ($need_download) {
$downloaddir = $this->_config->get('download_dir');
if (empty($downloaddir)) {
if (PEAR::isError($downloaddir = System::mktemp('-d'))) {
return $downloaddir;
}
$this->log(3, '+ tmp dir created at ' . $downloaddir);
}
$callback = $this->ui ? array(&$this, '_downloadCallback') : null;
$this->pushErrorHandling(PEAR_ERROR_RETURN);
$file = $this->downloadHttp($pkgfile, $this->ui, $downloaddir, $callback);
$this->popErrorHandling();
if (PEAR::isError($file)) {
if ($this->validPackageName($origpkgfile)) {
if (!PEAR::isError($info = $this->_remote->call('package.info',
$origpkgfile))) {
if (!count($info['releases'])) {
return $this->raiseError('Package ' . $origpkgfile .
' has no releases');
} else {
return $this->raiseError('No releases of preferred state "'
. $state . '" exist for package ' . $origpkgfile .
'. Use ' . $origpkgfile . '-state to install another' .
' state (like ' . $origpkgfile .'-beta)',
PEAR_INSTALLER_ERROR_NO_PREF_STATE);
}
} else {
return $pkgfile;
}
} else {
return $this->raiseError($file);
}
}
$pkgfile = $file;
}
// }}}
return $pkgfile;
}
// }}}
// {{{ getPackageDownloadUrl()
function getPackageDownloadUrl($package, $version = null)
{
if ($version) {
$package .= "-$version";
}
if ($this === null || $this->_config === null) {
$package = "http://pear.php.net/get/$package";
} else {
$package = "http://" . $this->_config->get('master_server') .
"/get/$package";
}
if (!extension_loaded("zlib")) {
$package .= '?uncompress=yes';
}
return $package;
}
// }}}
// {{{ extractDownloadFileName($pkgfile, &$version)
function extractDownloadFileName($pkgfile, &$version)
{
if (@is_file($pkgfile)) {
return $pkgfile;
}
// regex defined in Common.php
if (preg_match(PEAR_COMMON_PACKAGE_DOWNLOAD_PREG, $pkgfile, $m)) {
$version = (isset($m[3])) ? $m[3] : null;
return $m[1];
}
$version = null;
return $pkgfile;
}
// }}}
// }}}
// {{{ getDownloadedPackages()
/**
* Retrieve a list of downloaded packages after a call to {@link download()}.
*
* Also resets the list of downloaded packages.
* @return array
*/
function getDownloadedPackages()
{
$ret = $this->_downloadedPackages;
$this->_downloadedPackages = array();
$this->_toDownload = array();
return $ret;
}
// }}}
// {{{ download()
/**
* Download any files and their dependencies, if necessary
*
* BC-compatible method name
* @param array a mixed list of package names, local files, or package.xml
*/
function download($packages)
{
return $this->doDownload($packages);
}
// }}}
// {{{ doDownload()
/**
* Download any files and their dependencies, if necessary
*
* @param array a mixed list of package names, local files, or package.xml
*/
function doDownload($packages)
{
$mywillinstall = array();
$state = $this->_preferredState;
// {{{ download files in this list if necessary
foreach($packages as $pkgfile) {
$need_download = false;
if (!is_file($pkgfile)) {
if (preg_match('#^(http|ftp)://#', $pkgfile)) {
$need_download = true;
}
$pkgfile = $this->_downloadNonFile($pkgfile);
if (PEAR::isError($pkgfile)) {
return $pkgfile;
}
if ($pkgfile === false) {
continue;
}
} // end is_file()
$tempinfo = $this->infoFromAny($pkgfile);
if ($need_download) {
$this->_toDownload[] = $tempinfo['package'];
}
if (isset($this->_options['alldeps']) || isset($this->_options['onlyreqdeps'])) {
// ignore dependencies if there are any errors
if (!PEAR::isError($tempinfo)) {
$mywillinstall[strtolower($tempinfo['package'])] = @$tempinfo['release_deps'];
}
}
$this->_downloadedPackages[] = array('pkg' => $tempinfo['package'],
'file' => $pkgfile, 'info' => $tempinfo);
} // end foreach($packages)
// }}}
// {{{ extract dependencies from downloaded files and then download
// them if necessary
if (isset($this->_options['alldeps']) || isset($this->_options['onlyreqdeps'])) {
$deppackages = array();
foreach ($mywillinstall as $package => $alldeps) {
if (!is_array($alldeps)) {
// there are no dependencies
continue;
}
$fail = false;
foreach ($alldeps as $info) {
if ($info['type'] != 'pkg') {
continue;
}
$ret = $this->_processDependency($package, $info, $mywillinstall);
if ($ret === false) {
continue;
}
if ($ret === 0) {
$fail = true;
continue;
}
if (PEAR::isError($ret)) {
return $ret;
}
$deppackages[] = $ret;
} // foreach($alldeps
if ($fail) {
$deppackages = array();
}
}
if (count($deppackages)) {
$this->doDownload($deppackages);
}
} // }}} if --alldeps or --onlyreqdeps
}
// }}}
// {{{ _downloadNonFile($pkgfile)
/**
* @return false|PEAR_Error|string false if loop should be broken out of,
* string if the file was downloaded,
* PEAR_Error on exception
* @access private
*/
function _downloadNonFile($pkgfile)
{
$origpkgfile = $pkgfile;
$state = null;
$pkgfile = $this->extractDownloadFileName($pkgfile, $version);
if (preg_match('#^(http|ftp)://#', $pkgfile)) {
return $this->_downloadFile($pkgfile, $version, $origpkgfile);
}
if (!$this->validPackageName($pkgfile)) {
return $this->raiseError("Package name '$pkgfile' not valid");
}
// ignore packages that are installed unless we are upgrading
$curinfo = $this->_registry->packageInfo($pkgfile);
if ($this->_registry->packageExists($pkgfile)
&& empty($this->_options['upgrade']) && empty($this->_options['force'])) {
$this->log(0, "Package '{$curinfo['package']}' already installed, skipping");
return false;
}
if (in_array($pkgfile, $this->_toDownload)) {
return false;
}
$releases = $this->_remote->call('package.info', $pkgfile, 'releases', true);
if (!count($releases)) {
return $this->raiseError("No releases found for package '$pkgfile'");
}
// Want a specific version/state
if ($version !== null) {
// Passed Foo-1.2
if ($this->validPackageVersion($version)) {
if (!isset($releases[$version])) {
return $this->raiseError("No release with version '$version' found for '$pkgfile'");
}
// Passed Foo-alpha
} elseif (in_array($version, $this->getReleaseStates())) {
$state = $version;
$version = 0;
foreach ($releases as $ver => $inf) {
if ($inf['state'] == $state && version_compare("$version", "$ver") < 0) {
$version = $ver;
break;
}
}
if ($version == 0) {
return $this->raiseError("No release with state '$state' found for '$pkgfile'");
}
// invalid suffix passed
} else {
return $this->raiseError("Invalid suffix '-$version', be sure to pass a valid PEAR ".
"version number or release state");
}
// Guess what to download
} else {
$states = $this->betterStates($this->_preferredState, true);
$possible = false;
$version = 0;
$higher_version = 0;
$prev_hi_ver = 0;
foreach ($releases as $ver => $inf) {
if (in_array($inf['state'], $states) && version_compare("$version", "$ver") < 0) {
$version = $ver;
break;
} else {
$ver = (string)$ver;
if (version_compare($prev_hi_ver, $ver) < 0) {
$prev_hi_ver = $higher_version = $ver;
}
}
}
if ($version === 0 && !isset($this->_options['force'])) {
return $this->raiseError('No release with state equal to: \'' . implode(', ', $states) .
"' found for '$pkgfile'");
} elseif ($version === 0) {
$this->log(0, "Warning: $pkgfile is state '" . $releases[$higher_version]['state'] . "' which is less stable " .
"than state '$this->_preferredState'");
}
}
// Check if we haven't already the version
if (empty($this->_options['force']) && !is_null($curinfo)) {
if ($curinfo['version'] == $version) {
$this->log(0, "Package '{$curinfo['package']}-{$curinfo['version']}' already installed, skipping");
return false;
} elseif (version_compare("$version", "{$curinfo['version']}") < 0) {
$this->log(0, "Package '{$curinfo['package']}' version '{$curinfo['version']}' " .
" is installed and {$curinfo['version']} is > requested '$version', skipping");
return false;
}
}
$this->_toDownload[] = $pkgfile;
return $this->_downloadFile($pkgfile, $version, $origpkgfile, $state);
}
// }}}
// {{{ _processDependency($package, $info, $mywillinstall)
/**
* Process a dependency, download if necessary
* @param array dependency information from PEAR_Remote call
* @param array packages that will be installed in this iteration
* @return false|string|PEAR_Error
* @access private
* @todo Add test for relation 'lt'/'le' -> make sure that the dependency requested is
* in fact lower than the required value. This will be very important for BC dependencies
*/
function _processDependency($package, $info, $mywillinstall)
{
$state = $this->_preferredState;
if (!isset($this->_options['alldeps']) && isset($info['optional']) &&
$info['optional'] == 'yes') {
// skip optional deps
$this->log(0, "skipping Package '$package' optional dependency '$info[name]'");
return false;
}
// {{{ get releases
$releases = $this->_remote->call('package.info', $info['name'], 'releases', true);
if (PEAR::isError($releases)) {
return $releases;
}
if (!count($releases)) {
if (!isset($this->_installed[strtolower($info['name'])])) {
$this->pushError("Package '$package' dependency '$info[name]' ".
"has no releases");
}
return false;
}
$found = false;
$save = $releases;
while(count($releases) && !$found) {
if (!empty($state) && $state != 'any') {
list($release_version, $release) = each($releases);
if ($state != $release['state'] &&
!in_array($release['state'], $this->betterStates($state)))
{
// drop this release - it ain't stable enough
array_shift($releases);
} else {
$found = true;
}
} else {
$found = true;
}
}
if (!count($releases) && !$found) {
$get = array();
foreach($save as $release) {
$get = array_merge($get,
$this->betterStates($release['state'], true));
}
$savestate = array_shift($get);
$this->pushError( "Release for '$package' dependency '$info[name]' " .
"has state '$savestate', requires '$state'");
return 0;
}
if (in_array(strtolower($info['name']), $this->_toDownload) ||
isset($mywillinstall[strtolower($info['name'])])) {
// skip upgrade check for packages we will install
return false;
}
if (!isset($this->_installed[strtolower($info['name'])])) {
// check to see if we can install the specific version required
if ($info['rel'] == 'eq') {
return $info['name'] . '-' . $info['version'];
}
// skip upgrade check for packages we don't have installed
return $info['name'];
}
// }}}
// {{{ see if a dependency must be upgraded
$inst_version = $this->_registry->packageInfo($info['name'], 'version');
if (!isset($info['version'])) {
// this is a rel='has' dependency, check against latest
if (version_compare($release_version, $inst_version, 'le')) {
return false;
} else {
return $info['name'];
}
}
if (version_compare($info['version'], $inst_version, 'le')) {
// installed version is up-to-date
return false;
}
return $info['name'];
}
// }}}
// {{{ _downloadCallback()
function _downloadCallback($msg, $params = null)
{
switch ($msg) {
case 'saveas':
$this->log(1, "downloading $params ...");
break;
case 'done':
$this->log(1, '...done: ' . number_format($params, 0, '', ',') . ' bytes');
break;
case 'bytesread':
static $bytes;
if (empty($bytes)) {
$bytes = 0;
}
if (!($bytes % 10240)) {
$this->log(1, '.', false);
}
$bytes += $params;
break;
case 'start':
$this->log(1, "Starting to download {$params[0]} (".number_format($params[1], 0, '', ',')." bytes)");
break;
}
if (method_exists($this->ui, '_downloadCallback'))
$this->ui->_downloadCallback($msg, $params);
}
// }}}
// {{{ _prependPath($path, $prepend)
function _prependPath($path, $prepend)
{
if (strlen($prepend) > 0) {
if (OS_WINDOWS && preg_match('/^[a-z]:/i', $path)) {
$path = $prepend . substr($path, 2);
} else {
$path = $prepend . $path;
}
}
return $path;
}
// }}}
// {{{ pushError($errmsg, $code)
/**
* @param string
* @param integer
*/
function pushError($errmsg, $code = -1)
{
array_push($this->_errorStack, array($errmsg, $code));
}
// }}}
// {{{ getErrorMsgs()
function getErrorMsgs()
{
$msgs = array();
$errs = $this->_errorStack;
foreach ($errs as $err) {
$msgs[] = $err[0];
}
$this->_errorStack = array();
return $msgs;
}
// }}}
}
// }}}
?>
+981
View File
@@ -0,0 +1,981 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2004 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 3.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available through the world-wide-web at the following url: |
// | http://www.php.net/license/3_0.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: Gregory Beaver <cellog@php.net> |
// | |
// +----------------------------------------------------------------------+
//
// $Id: ErrorStack.php,v 1.7.2.5 2005/01/01 21:26:51 cellog Exp $
/**
* Error Stack Implementation
*
* This is an incredibly simple implementation of a very complex error handling
* facility. It contains the ability
* to track multiple errors from multiple packages simultaneously. In addition,
* it can track errors of many levels, save data along with the error, context
* information such as the exact file, line number, class and function that
* generated the error, and if necessary, it can raise a traditional PEAR_Error.
* It has built-in support for PEAR::Log, to log errors as they occur
*
* Since version 0.2alpha, it is also possible to selectively ignore errors,
* through the use of an error callback, see {@link pushCallback()}
*
* Since version 0.3alpha, it is possible to specify the exception class
* returned from {@link push()}
*
* Since version PEAR1.3.2, ErrorStack no longer instantiates an exception class. This can
* still be done quite handily in an error callback or by manipulating the returned array
* @author Greg Beaver <cellog@php.net>
* @version PEAR1.3.2 (beta)
* @package PEAR_ErrorStack
* @category Debugging
* @license http://www.php.net/license/3_0.txt PHP License v3.0
*/
/**
* Singleton storage
*
* Format:
* <pre>
* array(
* 'package1' => PEAR_ErrorStack object,
* 'package2' => PEAR_ErrorStack object,
* ...
* )
* </pre>
* @access private
* @global array $GLOBALS['_PEAR_ERRORSTACK_SINGLETON']
*/
$GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] = array();
/**
* Global error callback (default)
*
* This is only used if set to non-false. * is the default callback for
* all packages, whereas specific packages may set a default callback
* for all instances, regardless of whether they are a singleton or not.
*
* To exclude non-singletons, only set the local callback for the singleton
* @see PEAR_ErrorStack::setDefaultCallback()
* @access private
* @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK']
*/
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'] = array(
'*' => false,
);
/**
* Global Log object (default)
*
* This is only used if set to non-false. Use to set a default log object for
* all stacks, regardless of instantiation order or location
* @see PEAR_ErrorStack::setDefaultLogger()
* @access private
* @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']
*/
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = false;
/**
* Global Overriding Callback
*
* This callback will override any error callbacks that specific loggers have set.
* Use with EXTREME caution
* @see PEAR_ErrorStack::staticPushCallback()
* @access private
* @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']
*/
$GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array();
/**#@+
* One of four possible return values from the error Callback
* @see PEAR_ErrorStack::_errorCallback()
*/
/**
* If this is returned, then the error will be both pushed onto the stack
* and logged.
*/
define('PEAR_ERRORSTACK_PUSHANDLOG', 1);
/**
* If this is returned, then the error will only be pushed onto the stack,
* and not logged.
*/
define('PEAR_ERRORSTACK_PUSH', 2);
/**
* If this is returned, then the error will only be logged, but not pushed
* onto the error stack.
*/
define('PEAR_ERRORSTACK_LOG', 3);
/**
* If this is returned, then the error is completely ignored.
*/
define('PEAR_ERRORSTACK_IGNORE', 4);
/**
* If this is returned, then the error is logged and die() is called.
*/
define('PEAR_ERRORSTACK_DIE', 5);
/**#@-*/
/**
* Error code for an attempt to instantiate a non-class as a PEAR_ErrorStack in
* the singleton method.
*/
define('PEAR_ERRORSTACK_ERR_NONCLASS', 1);
/**
* Error code for an attempt to pass an object into {@link PEAR_ErrorStack::getMessage()}
* that has no __toString() method
*/
define('PEAR_ERRORSTACK_ERR_OBJTOSTRING', 2);
/**
* Error Stack Implementation
*
* Usage:
* <code>
* // global error stack
* $global_stack = &PEAR_ErrorStack::singleton('MyPackage');
* // local error stack
* $local_stack = new PEAR_ErrorStack('MyPackage');
* </code>
* @copyright 2004 Gregory Beaver
* @package PEAR_ErrorStack
* @license http://www.php.net/license/3_0.txt PHP License
*/
class PEAR_ErrorStack {
/**
* Errors are stored in the order that they are pushed on the stack.
* @since 0.4alpha Errors are no longer organized by error level.
* This renders pop() nearly unusable, and levels could be more easily
* handled in a callback anyway
* @var array
* @access private
*/
var $_errors = array();
/**
* Storage of errors by level.
*
* Allows easy retrieval and deletion of only errors from a particular level
* @since PEAR 1.4.0dev
* @var array
* @access private
*/
var $_errorsByLevel = array();
/**
* Package name this error stack represents
* @var string
* @access protected
*/
var $_package;
/**
* Determines whether a PEAR_Error is thrown upon every error addition
* @var boolean
* @access private
*/
var $_compat = false;
/**
* If set to a valid callback, this will be used to generate the error
* message from the error code, otherwise the message passed in will be
* used
* @var false|string|array
* @access private
*/
var $_msgCallback = false;
/**
* If set to a valid callback, this will be used to generate the error
* context for an error. For PHP-related errors, this will be a file
* and line number as retrieved from debug_backtrace(), but can be
* customized for other purposes. The error might actually be in a separate
* configuration file, or in a database query.
* @var false|string|array
* @access protected
*/
var $_contextCallback = false;
/**
* If set to a valid callback, this will be called every time an error
* is pushed onto the stack. The return value will be used to determine
* whether to allow an error to be pushed or logged.
*
* The return value must be one an PEAR_ERRORSTACK_* constant
* @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG
* @var false|string|array
* @access protected
*/
var $_errorCallback = array();
/**
* PEAR::Log object for logging errors
* @var false|Log
* @access protected
*/
var $_logger = false;
/**
* Error messages - designed to be overridden
* @var array
* @abstract
*/
var $_errorMsgs = array();
/**
* Set up a new error stack
*
* @param string $package name of the package this error stack represents
* @param callback $msgCallback callback used for error message generation
* @param callback $contextCallback callback used for context generation,
* defaults to {@link getFileLine()}
* @param boolean $throwPEAR_Error
*/
function PEAR_ErrorStack($package, $msgCallback = false, $contextCallback = false,
$throwPEAR_Error = false)
{
$this->_package = $package;
$this->setMessageCallback($msgCallback);
$this->setContextCallback($contextCallback);
$this->_compat = $throwPEAR_Error;
}
/**
* Return a single error stack for this package.
*
* Note that all parameters are ignored if the stack for package $package
* has already been instantiated
* @param string $package name of the package this error stack represents
* @param callback $msgCallback callback used for error message generation
* @param callback $contextCallback callback used for context generation,
* defaults to {@link getFileLine()}
* @param boolean $throwPEAR_Error
* @param string $stackClass class to instantiate
* @static
* @return PEAR_ErrorStack
*/
function &singleton($package, $msgCallback = false, $contextCallback = false,
$throwPEAR_Error = false, $stackClass = 'PEAR_ErrorStack')
{
if (isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) {
return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package];
}
if (!class_exists($stackClass)) {
if (function_exists('debug_backtrace')) {
$trace = debug_backtrace();
}
PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_NONCLASS,
'exception', array('stackclass' => $stackClass),
'stack class "%stackclass%" is not a valid class name (should be like PEAR_ErrorStack)',
false, $trace);
}
return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package] =
&new $stackClass($package, $msgCallback, $contextCallback, $throwPEAR_Error);
}
/**
* Internal error handler for PEAR_ErrorStack class
*
* Dies if the error is an exception (and would have died anyway)
* @access private
*/
function _handleError($err)
{
if ($err['level'] == 'exception') {
$message = $err['message'];
if (isset($_SERVER['REQUEST_URI'])) {
echo '<br />';
} else {
echo "\n";
}
var_dump($err['context']);
die($message);
}
}
/**
* Set up a PEAR::Log object for all error stacks that don't have one
* @param Log $log
* @static
*/
function setDefaultLogger(&$log)
{
if (is_object($log) && method_exists($log, 'log') ) {
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log;
} elseif (is_callable($log)) {
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log;
}
}
/**
* Set up a PEAR::Log object for this error stack
* @param Log $log
*/
function setLogger(&$log)
{
if (is_object($log) && method_exists($log, 'log') ) {
$this->_logger = &$log;
} elseif (is_callable($log)) {
$this->_logger = &$log;
}
}
/**
* Set an error code => error message mapping callback
*
* This method sets the callback that can be used to generate error
* messages for any instance
* @param array|string Callback function/method
*/
function setMessageCallback($msgCallback)
{
if (!$msgCallback) {
$this->_msgCallback = array(&$this, 'getErrorMessage');
} else {
if (is_callable($msgCallback)) {
$this->_msgCallback = $msgCallback;
}
}
}
/**
* Get an error code => error message mapping callback
*
* This method returns the current callback that can be used to generate error
* messages
* @return array|string|false Callback function/method or false if none
*/
function getMessageCallback()
{
return $this->_msgCallback;
}
/**
* Sets a default callback to be used by all error stacks
*
* This method sets the callback that can be used to generate error
* messages for a singleton
* @param array|string Callback function/method
* @param string Package name, or false for all packages
* @static
*/
function setDefaultCallback($callback = false, $package = false)
{
if (!is_callable($callback)) {
$callback = false;
}
$package = $package ? $package : '*';
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$package] = $callback;
}
/**
* Set a callback that generates context information (location of error) for an error stack
*
* This method sets the callback that can be used to generate context
* information for an error. Passing in NULL will disable context generation
* and remove the expensive call to debug_backtrace()
* @param array|string|null Callback function/method
*/
function setContextCallback($contextCallback)
{
if ($contextCallback === null) {
return $this->_contextCallback = false;
}
if (!$contextCallback) {
$this->_contextCallback = array(&$this, 'getFileLine');
} else {
if (is_callable($contextCallback)) {
$this->_contextCallback = $contextCallback;
}
}
}
/**
* Set an error Callback
* If set to a valid callback, this will be called every time an error
* is pushed onto the stack. The return value will be used to determine
* whether to allow an error to be pushed or logged.
*
* The return value must be one of the ERRORSTACK_* constants.
*
* This functionality can be used to emulate PEAR's pushErrorHandling, and
* the PEAR_ERROR_CALLBACK mode, without affecting the integrity of
* the error stack or logging
* @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG
* @see popCallback()
* @param string|array $cb
*/
function pushCallback($cb)
{
array_push($this->_errorCallback, $cb);
}
/**
* Remove a callback from the error callback stack
* @see pushCallback()
* @return array|string|false
*/
function popCallback()
{
if (!count($this->_errorCallback)) {
return false;
}
return array_pop($this->_errorCallback);
}
/**
* Set a temporary overriding error callback for every package error stack
*
* Use this to temporarily disable all existing callbacks (can be used
* to emulate the @ operator, for instance)
* @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG
* @see staticPopCallback(), pushCallback()
* @param string|array $cb
* @static
*/
function staticPushCallback($cb)
{
array_push($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'], $cb);
}
/**
* Remove a temporary overriding error callback
* @see staticPushCallback()
* @return array|string|false
* @static
*/
function staticPopCallback()
{
$ret = array_pop($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK']);
if (!is_array($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'])) {
$GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array();
}
return $ret;
}
/**
* Add an error to the stack
*
* If the message generator exists, it is called with 2 parameters.
* - the current Error Stack object
* - an array that is in the same format as an error. Available indices
* are 'code', 'package', 'time', 'params', 'level', and 'context'
*
* Next, if the error should contain context information, this is
* handled by the context grabbing method.
* Finally, the error is pushed onto the proper error stack
* @param int $code Package-specific error code
* @param string $level Error level. This is NOT spell-checked
* @param array $params associative array of error parameters
* @param string $msg Error message, or a portion of it if the message
* is to be generated
* @param array $repackage If this error re-packages an error pushed by
* another package, place the array returned from
* {@link pop()} in this parameter
* @param array $backtrace Protected parameter: use this to pass in the
* {@link debug_backtrace()} that should be used
* to find error context
* @return PEAR_Error|array|Exception
* if compatibility mode is on, a PEAR_Error is also
* thrown. If the class Exception exists, then one
* is returned to allow code like:
* <code>
* throw ($stack->push(MY_ERROR_CODE, 'error', array('username' => 'grob')));
* </code>
*
* The errorData property of the exception class will be set to the array
* that would normally be returned. If a PEAR_Error is returned, the userinfo
* property is set to the array
*
* Otherwise, an array is returned in this format:
* <code>
* array(
* 'code' => $code,
* 'params' => $params,
* 'package' => $this->_package,
* 'level' => $level,
* 'time' => time(),
* 'context' => $context,
* 'message' => $msg,
* //['repackage' => $err] repackaged error array/Exception class
* );
* </code>
*/
function push($code, $level = 'error', $params = array(), $msg = false,
$repackage = false, $backtrace = false)
{
$context = false;
// grab error context
if ($this->_contextCallback) {
if (!$backtrace) {
$backtrace = debug_backtrace();
}
$context = call_user_func($this->_contextCallback, $code, $params, $backtrace);
}
// save error
$time = explode(' ', microtime());
$time = $time[1] + $time[0];
$err = array(
'code' => $code,
'params' => $params,
'package' => $this->_package,
'level' => $level,
'time' => $time,
'context' => $context,
'message' => $msg,
);
// set up the error message, if necessary
if ($this->_msgCallback) {
$msg = call_user_func_array($this->_msgCallback,
array(&$this, $err));
$err['message'] = $msg;
}
if ($repackage) {
$err['repackage'] = $repackage;
}
$push = $log = true;
$die = false;
// try the overriding callback first
$callback = $this->staticPopCallback();
if ($callback) {
$this->staticPushCallback($callback);
}
if (!is_callable($callback)) {
// try the local callback next
$callback = $this->popCallback();
if (is_callable($callback)) {
$this->pushCallback($callback);
} else {
// try the default callback
$callback = isset($GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package]) ?
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package] :
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK']['*'];
}
}
if (is_callable($callback)) {
switch(call_user_func($callback, $err)){
case PEAR_ERRORSTACK_IGNORE:
return $err;
break;
case PEAR_ERRORSTACK_PUSH:
$log = false;
break;
case PEAR_ERRORSTACK_LOG:
$push = false;
break;
case PEAR_ERRORSTACK_DIE:
$die = true;
break;
// anything else returned has the same effect as pushandlog
}
}
if ($push) {
array_unshift($this->_errors, $err);
$this->_errorsByLevel[$err['level']][] = &$this->_errors[0];
}
if ($log) {
if ($this->_logger || $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']) {
$this->_log($err);
}
}
if ($die) {
die();
}
if ($this->_compat && $push) {
return $this->raiseError($msg, $code, null, null, $err);
}
return $err;
}
/**
* Static version of {@link push()}
*
* @param string $package Package name this error belongs to
* @param int $code Package-specific error code
* @param string $level Error level. This is NOT spell-checked
* @param array $params associative array of error parameters
* @param string $msg Error message, or a portion of it if the message
* is to be generated
* @param array $repackage If this error re-packages an error pushed by
* another package, place the array returned from
* {@link pop()} in this parameter
* @param array $backtrace Protected parameter: use this to pass in the
* {@link debug_backtrace()} that should be used
* to find error context
* @return PEAR_Error|null|Exception
* if compatibility mode is on, a PEAR_Error is also
* thrown. If the class Exception exists, then one
* is returned to allow code like:
* <code>
* throw ($stack->push(MY_ERROR_CODE, 'error', array('username' => 'grob')));
* </code>
* @static
*/
function staticPush($package, $code, $level = 'error', $params = array(),
$msg = false, $repackage = false, $backtrace = false)
{
$s = &PEAR_ErrorStack::singleton($package);
if ($s->_contextCallback) {
if (!$backtrace) {
if (function_exists('debug_backtrace')) {
$backtrace = debug_backtrace();
}
}
}
return $s->push($code, $level, $params, $msg, $repackage, $backtrace);
}
/**
* Log an error using PEAR::Log
* @param array $err Error array
* @param array $levels Error level => Log constant map
* @access protected
*/
function _log($err)
{
if ($this->_logger) {
$logger = &$this->_logger;
} else {
$logger = &$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'];
}
if (is_a($logger, 'Log')) {
$levels = array(
'exception' => PEAR_LOG_CRIT,
'alert' => PEAR_LOG_ALERT,
'critical' => PEAR_LOG_CRIT,
'error' => PEAR_LOG_ERR,
'warning' => PEAR_LOG_WARNING,
'notice' => PEAR_LOG_NOTICE,
'info' => PEAR_LOG_INFO,
'debug' => PEAR_LOG_DEBUG);
if (isset($levels[$err['level']])) {
$level = $levels[$err['level']];
} else {
$level = PEAR_LOG_INFO;
}
$logger->log($err['message'], $level, $err);
} else { // support non-standard logs
call_user_func($logger, $err);
}
}
/**
* Pop an error off of the error stack
*
* @return false|array
* @since 0.4alpha it is no longer possible to specify a specific error
* level to return - the last error pushed will be returned, instead
*/
function pop()
{
return @array_shift($this->_errors);
}
/**
* Determine whether there are any errors on the stack
* @param string|array Level name. Use to determine if any errors
* of level (string), or levels (array) have been pushed
* @return boolean
*/
function hasErrors($level = false)
{
if ($level) {
return isset($this->_errorsByLevel[$level]);
}
return count($this->_errors);
}
/**
* Retrieve all errors since last purge
*
* @param boolean set in order to empty the error stack
* @param string level name, to return only errors of a particular severity
* @return array
*/
function getErrors($purge = false, $level = false)
{
if (!$purge) {
if ($level) {
if (!isset($this->_errorsByLevel[$level])) {
return array();
} else {
return $this->_errorsByLevel[$level];
}
} else {
return $this->_errors;
}
}
if ($level) {
$ret = $this->_errorsByLevel[$level];
foreach ($this->_errorsByLevel[$level] as $i => $unused) {
// entries are references to the $_errors array
$this->_errorsByLevel[$level][$i] = false;
}
// array_filter removes all entries === false
$this->_errors = array_filter($this->_errors);
unset($this->_errorsByLevel[$level]);
return $ret;
}
$ret = $this->_errors;
$this->_errors = array();
$this->_errorsByLevel = array();
return $ret;
}
/**
* Determine whether there are any errors on a single error stack, or on any error stack
*
* The optional parameter can be used to test the existence of any errors without the need of
* singleton instantiation
* @param string|false Package name to check for errors
* @param string Level name to check for a particular severity
* @return boolean
* @static
*/
function staticHasErrors($package = false, $level = false)
{
if ($package) {
if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) {
return false;
}
return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->hasErrors($level);
}
foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) {
if ($obj->hasErrors($level)) {
return true;
}
}
return false;
}
/**
* Get a list of all errors since last purge, organized by package
* @since PEAR 1.4.0dev BC break! $level is now in the place $merge used to be
* @param boolean $purge Set to purge the error stack of existing errors
* @param string $level Set to a level name in order to retrieve only errors of a particular level
* @param boolean $merge Set to return a flat array, not organized by package
* @param array $sortfunc Function used to sort a merged array - default
* sorts by time, and should be good for most cases
* @static
* @return array
*/
function staticGetErrors($purge = false, $level = false, $merge = false,
$sortfunc = array('PEAR_ErrorStack', '_sortErrors'))
{
$ret = array();
if (!is_callable($sortfunc)) {
$sortfunc = array('PEAR_ErrorStack', '_sortErrors');
}
foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) {
$test = $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->getErrors($purge, $level);
if ($test) {
if ($merge) {
$ret = array_merge($ret, $test);
} else {
$ret[$package] = $test;
}
}
}
if ($merge) {
usort($ret, $sortfunc);
}
return $ret;
}
/**
* Error sorting function, sorts by time
* @access private
*/
function _sortErrors($a, $b)
{
if ($a['time'] == $b['time']) {
return 0;
}
if ($a['time'] < $b['time']) {
return 1;
}
return -1;
}
/**
* Standard file/line number/function/class context callback
*
* This function uses a backtrace generated from {@link debug_backtrace()}
* and so will not work at all in PHP < 4.3.0. The frame should
* reference the frame that contains the source of the error.
* @return array|false either array('file' => file, 'line' => line,
* 'function' => function name, 'class' => class name) or
* if this doesn't work, then false
* @param unused
* @param integer backtrace frame.
* @param array Results of debug_backtrace()
* @static
*/
function getFileLine($code, $params, $backtrace = null)
{
if ($backtrace === null) {
return false;
}
$frame = 0;
$functionframe = 1;
if (!isset($backtrace[1])) {
$functionframe = 0;
} else {
while (isset($backtrace[$functionframe]['function']) &&
$backtrace[$functionframe]['function'] == 'eval' &&
isset($backtrace[$functionframe + 1])) {
$functionframe++;
}
}
if (isset($backtrace[$frame])) {
if (!isset($backtrace[$frame]['file'])) {
$frame++;
}
$funcbacktrace = $backtrace[$functionframe];
$filebacktrace = $backtrace[$frame];
$ret = array('file' => $filebacktrace['file'],
'line' => $filebacktrace['line']);
// rearrange for eval'd code or create function errors
if (strpos($filebacktrace['file'], '(') &&
preg_match(';^(.*?)\((\d+)\) : (.*?)$;', $filebacktrace['file'],
$matches)) {
$ret['file'] = $matches[1];
$ret['line'] = $matches[2] + 0;
}
if (isset($funcbacktrace['function']) && isset($backtrace[1])) {
if ($funcbacktrace['function'] != 'eval') {
if ($funcbacktrace['function'] == '__lambda_func') {
$ret['function'] = 'create_function() code';
} else {
$ret['function'] = $funcbacktrace['function'];
}
}
}
if (isset($funcbacktrace['class']) && isset($backtrace[1])) {
$ret['class'] = $funcbacktrace['class'];
}
return $ret;
}
return false;
}
/**
* Standard error message generation callback
*
* This method may also be called by a custom error message generator
* to fill in template values from the params array, simply
* set the third parameter to the error message template string to use
*
* The special variable %__msg% is reserved: use it only to specify
* where a message passed in by the user should be placed in the template,
* like so:
*
* Error message: %msg% - internal error
*
* If the message passed like so:
*
* <code>
* $stack->push(ERROR_CODE, 'error', array(), 'server error 500');
* </code>
*
* The returned error message will be "Error message: server error 500 -
* internal error"
* @param PEAR_ErrorStack
* @param array
* @param string|false Pre-generated error message template
* @static
* @return string
*/
function getErrorMessage(&$stack, $err, $template = false)
{
if ($template) {
$mainmsg = $template;
} else {
$mainmsg = $stack->getErrorMessageTemplate($err['code']);
}
$mainmsg = str_replace('%__msg%', $err['message'], $mainmsg);
if (count($err['params'])) {
foreach ($err['params'] as $name => $val) {
if (is_array($val)) {
// @ is needed in case $val is a multi-dimensional array
$val = @implode(', ', $val);
}
if (is_object($val)) {
if (method_exists($val, '__toString')) {
$val = $val->__toString();
} else {
PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_OBJTOSTRING,
'warning', array('obj' => get_class($val)),
'object %obj% passed into getErrorMessage, but has no __toString() method');
$val = 'Object';
}
}
$mainmsg = str_replace('%' . $name . '%', $val, $mainmsg);
}
}
return $mainmsg;
}
/**
* Standard Error Message Template generator from code
* @return string
*/
function getErrorMessageTemplate($code)
{
if (!isset($this->_errorMsgs[$code])) {
return '%__msg%';
}
return $this->_errorMsgs[$code];
}
/**
* Set the Error Message Template array
*
* The array format must be:
* <pre>
* array(error code => 'message template',...)
* </pre>
*
* Error message parameters passed into {@link push()} will be used as input
* for the error message. If the template is 'message %foo% was %bar%', and the
* parameters are array('foo' => 'one', 'bar' => 'six'), the error message returned will
* be 'message one was six'
* @return string
*/
function setErrorMessageTemplate($template)
{
$this->_errorMsgs = $template;
}
/**
* emulate PEAR::raiseError()
*
* @return PEAR_Error
*/
function raiseError()
{
require_once 'PEAR.php';
$args = func_get_args();
return call_user_func_array(array('PEAR', 'raiseError'), $args);
}
}
$stack = &PEAR_ErrorStack::singleton('PEAR_ErrorStack');
$stack->pushCallback(array('PEAR_ErrorStack', '_handleError'));
?>
+359
View File
@@ -0,0 +1,359 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
// +----------------------------------------------------------------------+
// | PEAR_Exception |
// +----------------------------------------------------------------------+
// | Copyright (c) 2004 The PEAR Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 3.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/3_0.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: Tomas V.V.Cox <cox@idecnet.com> |
// | Hans Lellelid <hans@velum.net> |
// | Bertrand Mansion <bmansion@mamasam.com> |
// | Greg Beaver <cellog@php.net> |
// +----------------------------------------------------------------------+
//
// $Id: Exception.php,v 1.4.2.2 2004/12/31 19:01:52 cellog Exp $
/**
* Base PEAR_Exception Class
*
* WARNING: This code should be considered stable, but the API is
* subject to immediate and drastic change, so API stability is
* at best alpha
*
* 1) Features:
*
* - Nestable exceptions (throw new PEAR_Exception($msg, $prev_exception))
* - Definable triggers, shot when exceptions occur
* - Pretty and informative error messages
* - Added more context info available (like class, method or cause)
* - cause can be a PEAR_Exception or an array of mixed
* PEAR_Exceptions/PEAR_ErrorStack warnings
* - callbacks for specific exception classes and their children
*
* 2) Ideas:
*
* - Maybe a way to define a 'template' for the output
*
* 3) Inherited properties from PHP Exception Class:
*
* protected $message
* protected $code
* protected $line
* protected $file
* private $trace
*
* 4) Inherited methods from PHP Exception Class:
*
* __clone
* __construct
* getMessage
* getCode
* getFile
* getLine
* getTraceSafe
* getTraceSafeAsString
* __toString
*
* 5) Usage example
*
* <code>
* require_once 'PEAR/Exception.php';
*
* class Test {
* function foo() {
* throw new PEAR_Exception('Error Message', ERROR_CODE);
* }
* }
*
* function myLogger($pear_exception) {
* echo $pear_exception->getMessage();
* }
* // each time a exception is thrown the 'myLogger' will be called
* // (its use is completely optional)
* PEAR_Exception::addObserver('myLogger');
* $test = new Test;
* try {
* $test->foo();
* } catch (PEAR_Exception $e) {
* print $e;
* }
* </code>
*
* @since PHP 5
* @package PEAR
* @version $Revision: 1.4.2.2 $
* @author Tomas V.V.Cox <cox@idecnet.com>
* @author Hans Lellelid <hans@velum.net>
* @author Bertrand Mansion <bmansion@mamasam.com>
*
*/
class PEAR_Exception extends Exception
{
const OBSERVER_PRINT = -2;
const OBSERVER_TRIGGER = -4;
const OBSERVER_DIE = -8;
protected $cause;
private static $_observers = array();
private static $_uniqueid = 0;
private $_trace;
/**
* Supported signatures:
* PEAR_Exception(string $message);
* PEAR_Exception(string $message, int $code);
* PEAR_Exception(string $message, Exception $cause);
* PEAR_Exception(string $message, Exception $cause, int $code);
* PEAR_Exception(string $message, array $causes);
* PEAR_Exception(string $message, array $causes, int $code);
*/
public function __construct($message, $p2 = null, $p3 = null)
{
if (is_int($p2)) {
$code = $p2;
$this->cause = null;
} elseif ($p2 instanceof Exception || is_array($p2)) {
$code = $p3;
if (is_array($p2) && isset($p2['message'])) {
// fix potential problem of passing in a single warning
$p2 = array($p2);
}
$this->cause = $p2;
} else {
$code = null;
$this->cause = null;
}
parent::__construct($message, $code);
$this->signal();
}
/**
* @param mixed $callback - A valid php callback, see php func is_callable()
* - A PEAR_Exception::OBSERVER_* constant
* - An array(const PEAR_Exception::OBSERVER_*,
* mixed $options)
* @param string $label The name of the observer. Use this if you want
* to remove it later with removeObserver()
*/
public static function addObserver($callback, $label = 'default')
{
self::$_observers[$label] = $callback;
}
public static function removeObserver($label = 'default')
{
unset(self::$_observers[$label]);
}
/**
* @return int unique identifier for an observer
*/
public static function getUniqueId()
{
return self::$_uniqueid++;
}
private function signal()
{
foreach (self::$_observers as $func) {
if (is_callable($func)) {
call_user_func($func, $this);
continue;
}
settype($func, 'array');
switch ($func[0]) {
case self::OBSERVER_PRINT :
$f = (isset($func[1])) ? $func[1] : '%s';
printf($f, $this->getMessage());
break;
case self::OBSERVER_TRIGGER :
$f = (isset($func[1])) ? $func[1] : E_USER_NOTICE;
trigger_error($this->getMessage(), $f);
break;
case self::OBSERVER_DIE :
$f = (isset($func[1])) ? $func[1] : '%s';
die(printf($f, $this->getMessage()));
break;
default:
trigger_error('invalid observer type', E_USER_WARNING);
}
}
}
/**
* Return specific error information that can be used for more detailed
* error messages or translation.
*
* This method may be overridden in child exception classes in order
* to add functionality not present in PEAR_Exception and is a placeholder
* to define API
*
* The returned array must be an associative array of parameter => value like so:
* <pre>
* array('name' => $name, 'context' => array(...))
* </pre>
* @return array
*/
public function getErrorData()
{
return array();
}
/**
* Returns the exception that caused this exception to be thrown
* @access public
* @return Exception|array The context of the exception
*/
public function getCause()
{
return $this->cause;
}
/**
* Function must be public to call on caused exceptions
* @param array
*/
public function getCauseMessage(&$causes)
{
$trace = $this->getTraceSafe();
$cause = array('class' => get_class($this),
'message' => $this->message,
'file' => 'unknown',
'line' => 'unknown');
if (isset($trace[0])) {
if (isset($trace[0]['file'])) {
$cause['file'] = $trace[0]['file'];
$cause['line'] = $trace[0]['line'];
}
}
if ($this->cause instanceof PEAR_Exception) {
$this->cause->getCauseMessage($causes);
}
if (is_array($this->cause)) {
foreach ($this->cause as $cause) {
if ($cause instanceof PEAR_Exception) {
$cause->getCauseMessage($causes);
} elseif (is_array($cause) && isset($cause['message'])) {
// PEAR_ErrorStack warning
$causes[] = array(
'class' => $cause['package'],
'message' => $cause['message'],
'file' => isset($cause['context']['file']) ?
$cause['context']['file'] :
'unknown',
'line' => isset($cause['context']['line']) ?
$cause['context']['line'] :
'unknown',
);
}
}
}
}
public function getTraceSafe()
{
if (!isset($this->_trace)) {
$this->_trace = $this->getTrace();
if (empty($this->_trace)) {
$backtrace = debug_backtrace();
$this->_trace = array($backtrace[count($backtrace)-1]);
}
}
return $this->_trace;
}
public function getErrorClass()
{
$trace = $this->getTraceSafe();
return $trace[0]['class'];
}
public function getErrorMethod()
{
$trace = $this->getTraceSafe();
return $trace[0]['function'];
}
public function __toString()
{
if (isset($_SERVER['REQUEST_URI'])) {
return $this->toHtml();
}
return $this->toText();
}
public function toHtml()
{
$trace = $this->getTraceSafe();
$causes = array();
$this->getCauseMessage($causes);
$html = '<table border="1" cellspacing="0">' . "\n";
foreach ($causes as $i => $cause) {
$html .= '<tr><td colspan="3" bgcolor="#ff9999">'
. str_repeat('-', $i) . ' <b>' . $cause['class'] . '</b>: '
. htmlspecialchars($cause['message']) . ' in <b>' . $cause['file'] . '</b> '
. 'on line <b>' . $cause['line'] . '</b>'
. "</td></tr>\n";
}
$html .= '<tr><td colspan="3" bgcolor="#aaaaaa" align="center"><b>Exception trace</b></td></tr>' . "\n"
. '<tr><td align="center" bgcolor="#cccccc" width="20"><b>#</b></td>'
. '<td align="center" bgcolor="#cccccc"><b>Function</b></td>'
. '<td align="center" bgcolor="#cccccc"><b>Location</b></td></tr>' . "\n";
foreach ($trace as $k => $v) {
$html .= '<tr><td align="center">' . $k . '</td>'
. '<td>';
if (!empty($v['class'])) {
$html .= $v['class'] . $v['type'];
}
$html .= $v['function'];
$args = array();
if (!empty($v['args'])) {
foreach ($v['args'] as $arg) {
if (is_null($arg)) $args[] = 'null';
elseif (is_array($arg)) $args[] = 'Array';
elseif (is_object($arg)) $args[] = 'Object('.get_class($arg).')';
elseif (is_bool($arg)) $args[] = $arg ? 'true' : 'false';
elseif (is_int($arg) || is_double($arg)) $args[] = $arg;
else {
$arg = (string)$arg;
$str = htmlspecialchars(substr($arg, 0, 16));
if (strlen($arg) > 16) $str .= '&hellip;';
$args[] = "'" . $str . "'";
}
}
}
$html .= '(' . implode(', ',$args) . ')'
. '</td>'
. '<td>' . $v['file'] . ':' . $v['line'] . '</td></tr>' . "\n";
}
$html .= '<tr><td align="center">' . ($k+1) . '</td>'
. '<td>{main}</td>'
. '<td>&nbsp;</td></tr>' . "\n"
. '</table>';
return $html;
}
public function toText()
{
$causes = array();
$this->getCauseMessage($causes);
$causeMsg = '';
foreach ($causes as $i => $cause) {
$causeMsg .= str_repeat(' ', $i) . $cause['class'] . ': '
. $cause['message'] . ' in ' . $cause['file']
. ' on line ' . $cause['line'] . "\n";
}
return $causeMsg . $this->getTraceAsString();
}
}
?>
+509
View File
@@ -0,0 +1,509 @@
<?php
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2004 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_0.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 Sæther Bakken <ssb@php.net> |
+----------------------------------------------------------------------+
$Id: CLI.php,v 1.41 2004/02/17 05:49:16 ssb Exp $
*/
require_once "PEAR.php";
class PEAR_Frontend_CLI extends PEAR
{
// {{{ properties
/**
* What type of user interface this frontend is for.
* @var string
* @access public
*/
var $type = 'CLI';
var $lp = ''; // line prefix
var $params = array();
var $term = array(
'bold' => '',
'normal' => '',
);
// }}}
// {{{ constructor
function PEAR_Frontend_CLI()
{
parent::PEAR();
$term = getenv('TERM'); //(cox) $_ENV is empty for me in 4.1.1
if (function_exists('posix_isatty') && !posix_isatty(1)) {
// output is being redirected to a file or through a pipe
} elseif ($term) {
// XXX can use ncurses extension here, if available
if (preg_match('/^(xterm|vt220|linux)/', $term)) {
$this->term['bold'] = sprintf("%c%c%c%c", 27, 91, 49, 109);
$this->term['normal']=sprintf("%c%c%c", 27, 91, 109);
} elseif (preg_match('/^vt100/', $term)) {
$this->term['bold'] = sprintf("%c%c%c%c%c%c", 27, 91, 49, 109, 0, 0);
$this->term['normal']=sprintf("%c%c%c%c%c", 27, 91, 109, 0, 0);
}
} elseif (OS_WINDOWS) {
// XXX add ANSI codes here
}
}
// }}}
// {{{ displayLine(text)
function displayLine($text)
{
trigger_error("PEAR_Frontend_CLI::displayLine deprecated", E_USER_ERROR);
}
function _displayLine($text)
{
print "$this->lp$text\n";
}
// }}}
// {{{ display(text)
function display($text)
{
trigger_error("PEAR_Frontend_CLI::display deprecated", E_USER_ERROR);
}
function _display($text)
{
print $text;
}
// }}}
// {{{ displayError(eobj)
/**
* @param object PEAR_Error object
*/
function displayError($eobj)
{
return $this->_displayLine($eobj->getMessage());
}
// }}}
// {{{ displayFatalError(eobj)
/**
* @param object PEAR_Error object
*/
function displayFatalError($eobj)
{
$this->displayError($eobj);
exit(1);
}
// }}}
// {{{ displayHeading(title)
function displayHeading($title)
{
trigger_error("PEAR_Frontend_CLI::displayHeading deprecated", E_USER_ERROR);
}
function _displayHeading($title)
{
print $this->lp.$this->bold($title)."\n";
print $this->lp.str_repeat("=", strlen($title))."\n";
}
// }}}
// {{{ userDialog(prompt, [type], [default])
function userDialog($command, $prompts, $types = array(), $defaults = array())
{
$result = array();
if (is_array($prompts)) {
$fp = fopen("php://stdin", "r");
foreach ($prompts as $key => $prompt) {
$type = $types[$key];
$default = @$defaults[$key];
if ($type == 'password') {
system('stty -echo');
}
print "$this->lp$prompt ";
if ($default) {
print "[$default] ";
}
print ": ";
$line = fgets($fp, 2048);
if ($type == 'password') {
system('stty echo');
print "\n";
}
if ($default && trim($line) == "") {
$result[$key] = $default;
} else {
$result[$key] = $line;
}
}
fclose($fp);
}
return $result;
}
// }}}
// {{{ userConfirm(prompt, [default])
function userConfirm($prompt, $default = 'yes')
{
trigger_error("PEAR_Frontend_CLI::userConfirm not yet converted", E_USER_ERROR);
static $positives = array('y', 'yes', 'on', '1');
static $negatives = array('n', 'no', 'off', '0');
print "$this->lp$prompt [$default] : ";
$fp = fopen("php://stdin", "r");
$line = fgets($fp, 2048);
fclose($fp);
$answer = strtolower(trim($line));
if (empty($answer)) {
$answer = $default;
}
if (in_array($answer, $positives)) {
return true;
}
if (in_array($answer, $negatives)) {
return false;
}
if (in_array($default, $positives)) {
return true;
}
return false;
}
// }}}
// {{{ startTable([params])
function startTable($params = array())
{
trigger_error("PEAR_Frontend_CLI::startTable deprecated", E_USER_ERROR);
}
function _startTable($params = array())
{
$params['table_data'] = array();
$params['widest'] = array(); // indexed by column
$params['highest'] = array(); // indexed by row
$params['ncols'] = 0;
$this->params = $params;
}
// }}}
// {{{ tableRow(columns, [rowparams], [colparams])
function tableRow($columns, $rowparams = array(), $colparams = array())
{
trigger_error("PEAR_Frontend_CLI::tableRow deprecated", E_USER_ERROR);
}
function _tableRow($columns, $rowparams = array(), $colparams = array())
{
$highest = 1;
for ($i = 0; $i < sizeof($columns); $i++) {
$col = &$columns[$i];
if (isset($colparams[$i]) && !empty($colparams[$i]['wrap'])) {
$col = wordwrap($col, $colparams[$i]['wrap'], "\n", 0);
}
if (strpos($col, "\n") !== false) {
$multiline = explode("\n", $col);
$w = 0;
foreach ($multiline as $n => $line) {
if (strlen($line) > $w) {
$w = strlen($line);
}
}
$lines = sizeof($multiline);
} else {
$w = strlen($col);
}
if ($w > @$this->params['widest'][$i]) {
$this->params['widest'][$i] = $w;
}
$tmp = count_chars($columns[$i], 1);
// handle unix, mac and windows formats
$lines = (isset($tmp[10]) ? $tmp[10] : @$tmp[13]) + 1;
if ($lines > $highest) {
$highest = $lines;
}
}
if (sizeof($columns) > $this->params['ncols']) {
$this->params['ncols'] = sizeof($columns);
}
$new_row = array(
'data' => $columns,
'height' => $highest,
'rowparams' => $rowparams,
'colparams' => $colparams,
);
$this->params['table_data'][] = $new_row;
}
// }}}
// {{{ endTable()
function endTable()
{
trigger_error("PEAR_Frontend_CLI::endTable deprecated", E_USER_ERROR);
}
function _endTable()
{
extract($this->params);
if (!empty($caption)) {
$this->_displayHeading($caption);
}
if (count($table_data) == 0) {
return;
}
if (!isset($width)) {
$width = $widest;
} else {
for ($i = 0; $i < $ncols; $i++) {
if (!isset($width[$i])) {
$width[$i] = $widest[$i];
}
}
}
$border = false;
if (empty($border)) {
$cellstart = '';
$cellend = ' ';
$rowend = '';
$padrowend = false;
$borderline = '';
} else {
$cellstart = '| ';
$cellend = ' ';
$rowend = '|';
$padrowend = true;
$borderline = '+';
foreach ($width as $w) {
$borderline .= str_repeat('-', $w + strlen($cellstart) + strlen($cellend) - 1);
$borderline .= '+';
}
}
if ($borderline) {
$this->_displayLine($borderline);
}
for ($i = 0; $i < sizeof($table_data); $i++) {
extract($table_data[$i]);
if (!is_array($rowparams)) {
$rowparams = array();
}
if (!is_array($colparams)) {
$colparams = array();
}
$rowlines = array();
if ($height > 1) {
for ($c = 0; $c < sizeof($data); $c++) {
$rowlines[$c] = preg_split('/(\r?\n|\r)/', $data[$c]);
if (sizeof($rowlines[$c]) < $height) {
$rowlines[$c] = array_pad($rowlines[$c], $height, '');
}
}
} else {
for ($c = 0; $c < sizeof($data); $c++) {
$rowlines[$c] = array($data[$c]);
}
}
for ($r = 0; $r < $height; $r++) {
$rowtext = '';
for ($c = 0; $c < sizeof($data); $c++) {
if (isset($colparams[$c])) {
$attribs = array_merge($rowparams, $colparams);
} else {
$attribs = $rowparams;
}
$w = isset($width[$c]) ? $width[$c] : 0;
//$cell = $data[$c];
$cell = $rowlines[$c][$r];
$l = strlen($cell);
if ($l > $w) {
$cell = substr($cell, 0, $w);
}
if (isset($attribs['bold'])) {
$cell = $this->bold($cell);
}
if ($l < $w) {
// not using str_pad here because we may
// add bold escape characters to $cell
$cell .= str_repeat(' ', $w - $l);
}
$rowtext .= $cellstart . $cell . $cellend;
}
if (!$border) {
$rowtext = rtrim($rowtext);
}
$rowtext .= $rowend;
$this->_displayLine($rowtext);
}
}
if ($borderline) {
$this->_displayLine($borderline);
}
}
// }}}
// {{{ outputData()
function outputData($data, $command = '_default')
{
switch ($command) {
case 'install':
case 'upgrade':
case 'upgrade-all':
if (isset($data['release_warnings'])) {
$this->_displayLine('');
$this->_startTable(array(
'border' => false,
'caption' => 'Release Warnings'
));
$this->_tableRow(array($data['release_warnings']), null, array(1 => array('wrap' => 55)));
$this->_endTable();
$this->_displayLine('');
}
$this->_displayLine($data['data']);
break;
case 'search':
$this->_startTable($data);
if (isset($data['headline']) && is_array($data['headline'])) {
$this->_tableRow($data['headline'], array('bold' => true), array(1 => array('wrap' => 55)));
}
foreach($data['data'] as $category) {
foreach($category as $pkg) {
$this->_tableRow($pkg, null, array(1 => array('wrap' => 55)));
}
};
$this->_endTable();
break;
case 'list-all':
$this->_startTable($data);
if (isset($data['headline']) && is_array($data['headline'])) {
$this->_tableRow($data['headline'], array('bold' => true), array(1 => array('wrap' => 55)));
}
foreach($data['data'] as $category) {
foreach($category as $pkg) {
unset($pkg[3]);
unset($pkg[4]);
$this->_tableRow($pkg, null, array(1 => array('wrap' => 55)));
}
};
$this->_endTable();
break;
case 'config-show':
$data['border'] = false;
$opts = array(0 => array('wrap' => 30),
1 => array('wrap' => 20),
2 => array('wrap' => 35));
$this->_startTable($data);
if (isset($data['headline']) && is_array($data['headline'])) {
$this->_tableRow($data['headline'],
array('bold' => true),
$opts);
}
foreach($data['data'] as $group) {
foreach($group as $value) {
if ($value[2] == '') {
$value[2] = "<not set>";
}
$this->_tableRow($value, null, $opts);
}
}
$this->_endTable();
break;
case 'remote-info':
$data = array(
'caption' => 'Package details:',
'border' => false,
'data' => array(
array("Latest", $data['stable']),
array("Installed", $data['installed']),
array("Package", $data['name']),
array("License", $data['license']),
array("Category", $data['category']),
array("Summary", $data['summary']),
array("Description", $data['description']),
),
);
default: {
if (is_array($data)) {
$this->_startTable($data);
$count = count($data['data'][0]);
if ($count == 2) {
$opts = array(0 => array('wrap' => 25),
1 => array('wrap' => 48)
);
} elseif ($count == 3) {
$opts = array(0 => array('wrap' => 30),
1 => array('wrap' => 20),
2 => array('wrap' => 35)
);
} else {
$opts = null;
}
if (isset($data['headline']) && is_array($data['headline'])) {
$this->_tableRow($data['headline'],
array('bold' => true),
$opts);
}
foreach($data['data'] as $row) {
$this->_tableRow($row, null, $opts);
}
$this->_endTable();
} else {
$this->_displayLine($data);
}
}
}
}
// }}}
// {{{ log(text)
function log($text, $append_crlf = true)
{
if ($append_crlf) {
return $this->_displayLine($text);
}
return $this->_display($text);
}
// }}}
// {{{ bold($text)
function bold($text)
{
if (empty($this->term['bold'])) {
return strtoupper($text);
}
return $this->term['bold'] . $text . $this->term['normal'];
}
// }}}
}
?>
File diff suppressed because it is too large. Load diff
+165
View File
@@ -0,0 +1,165 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2004 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 3.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available through the world-wide-web at the following url: |
// | http://www.php.net/license/3_0.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@php.net> |
// | Tomas V.V.Cox <cox@idecnet.com> |
// +----------------------------------------------------------------------+
//
// $Id: Packager.php,v 1.53 2004/06/13 14:06:01 pajoye Exp $
require_once 'PEAR/Common.php';
require_once 'System.php';
/**
* Administration class used to make a PEAR release tarball.
*
* TODO:
* - add an extra param the dir where to place the created package
*
* @since PHP 4.0.2
* @author Stig Bakken <ssb@php.net>
*/
class PEAR_Packager extends PEAR_Common
{
// {{{ constructor
function PEAR_Packager()
{
parent::PEAR_Common();
}
// }}}
// {{{ destructor
function _PEAR_Packager()
{
parent::_PEAR_Common();
}
// }}}
// {{{ package()
function package($pkgfile = null, $compress = true)
{
// {{{ validate supplied package.xml file
if (empty($pkgfile)) {
$pkgfile = 'package.xml';
}
// $this->pkginfo gets populated inside
$pkginfo = $this->infoFromDescriptionFile($pkgfile);
if (PEAR::isError($pkginfo)) {
return $this->raiseError($pkginfo);
}
$pkgdir = dirname(realpath($pkgfile));
$pkgfile = basename($pkgfile);
$errors = $warnings = array();
$this->validatePackageInfo($pkginfo, $errors, $warnings, $pkgdir);
foreach ($warnings as $w) {
$this->log(1, "Warning: $w");
}
foreach ($errors as $e) {
$this->log(0, "Error: $e");
}
if (sizeof($errors) > 0) {
return $this->raiseError('Errors in package');
}
// }}}
$pkgver = $pkginfo['package'] . '-' . $pkginfo['version'];
// {{{ Create the package file list
$filelist = array();
$i = 0;
foreach ($pkginfo['filelist'] as $fname => $atts) {
$file = $pkgdir . DIRECTORY_SEPARATOR . $fname;
if (!file_exists($file)) {
return $this->raiseError("File does not exist: $fname");
} else {
$filelist[$i++] = $file;
if (empty($pkginfo['filelist'][$fname]['md5sum'])) {
$md5sum = md5_file($file);
$pkginfo['filelist'][$fname]['md5sum'] = $md5sum;
}
$this->log(2, "Adding file $fname");
}
}
// }}}
// {{{ regenerate package.xml
$new_xml = $this->xmlFromInfo($pkginfo);
if (PEAR::isError($new_xml)) {
return $this->raiseError($new_xml);
}
if (!($tmpdir = System::mktemp(array('-d')))) {
return $this->raiseError("PEAR_Packager: mktemp failed");
}
$newpkgfile = $tmpdir . DIRECTORY_SEPARATOR . 'package.xml';
$np = @fopen($newpkgfile, 'wb');
if (!$np) {
return $this->raiseError("PEAR_Packager: unable to rewrite $pkgfile as $newpkgfile");
}
fwrite($np, $new_xml);
fclose($np);
// }}}
// {{{ TAR the Package -------------------------------------------
$ext = $compress ? '.tgz' : '.tar';
$dest_package = getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext;
$tar =& new Archive_Tar($dest_package, $compress);
$tar->setErrorHandling(PEAR_ERROR_RETURN); // XXX Don't print errors
// ----- Creates with the package.xml file
$ok = $tar->createModify(array($newpkgfile), '', $tmpdir);
if (PEAR::isError($ok)) {
return $this->raiseError($ok);
} elseif (!$ok) {
return $this->raiseError('PEAR_Packager: tarball creation failed');
}
// ----- Add the content of the package
if (!$tar->addModify($filelist, $pkgver, $pkgdir)) {
return $this->raiseError('PEAR_Packager: tarball creation failed');
}
$this->log(1, "Package $dest_package done");
if (file_exists("$pkgdir/CVS/Root")) {
$cvsversion = preg_replace('/[^a-z0-9]/i', '_', $pkginfo['version']);
$cvstag = "RELEASE_$cvsversion";
$this->log(1, "Tag the released code with `pear cvstag $pkgfile'");
$this->log(1, "(or set the CVS tag $cvstag by hand)");
}
// }}}
return $dest_package;
}
// }}}
}
// {{{ md5_file() utility function
if (!function_exists('md5_file')) {
function md5_file($file) {
if (!$fd = @fopen($file, 'r')) {
return false;
}
$md5 = md5(fread($fd, filesize($file)));
fclose($fd);
return $md5;
}
}
// }}}
?>
+538
View File
@@ -0,0 +1,538 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2004 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 3.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available through the world-wide-web at the following url: |
// | http://www.php.net/license/3_0.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@php.net> |
// | Tomas V.V.Cox <cox@idecnet.com> |
// | |
// +----------------------------------------------------------------------+
//
// $Id: Registry.php,v 1.50.4.3 2004/10/26 19:19:56 cellog Exp $
/*
TODO:
- Transform into singleton()
- Add application level lock (avoid change the registry from the cmdline
while using the GTK interface, for ex.)
*/
require_once "System.php";
require_once "PEAR.php";
define('PEAR_REGISTRY_ERROR_LOCK', -2);
define('PEAR_REGISTRY_ERROR_FORMAT', -3);
define('PEAR_REGISTRY_ERROR_FILE', -4);
/**
* Administration class used to maintain the installed package database.
*/
class PEAR_Registry extends PEAR
{
// {{{ properties
/** Directory where registry files are stored.
* @var string
*/
var $statedir = '';
/** File where the file map is stored
* @var string
*/
var $filemap = '';
/** Name of file used for locking the registry
* @var string
*/
var $lockfile = '';
/** File descriptor used during locking
* @var resource
*/
var $lock_fp = null;
/** Mode used during locking
* @var int
*/
var $lock_mode = 0; // XXX UNUSED
/** Cache of package information. Structure:
* array(
* 'package' => array('id' => ... ),
* ... )
* @var array
*/
var $pkginfo_cache = array();
/** Cache of file map. Structure:
* array( '/path/to/file' => 'package', ... )
* @var array
*/
var $filemap_cache = array();
// }}}
// {{{ constructor
/**
* PEAR_Registry constructor.
*
* @param string (optional) PEAR install directory (for .php files)
*
* @access public
*/
function PEAR_Registry($pear_install_dir = PEAR_INSTALL_DIR)
{
parent::PEAR();
$ds = DIRECTORY_SEPARATOR;
$this->install_dir = $pear_install_dir;
$this->statedir = $pear_install_dir.$ds.'.registry';
$this->filemap = $pear_install_dir.$ds.'.filemap';
$this->lockfile = $pear_install_dir.$ds.'.lock';
// XXX Compatibility code should be removed in the future
// rename all registry files if any to lowercase
if (!OS_WINDOWS && $handle = @opendir($this->statedir)) {
$dest = $this->statedir . DIRECTORY_SEPARATOR;
while (false !== ($file = readdir($handle))) {
if (preg_match('/^.*[A-Z].*\.reg$/', $file)) {
rename($dest . $file, $dest . strtolower($file));
}
}
closedir($handle);
}
if (!file_exists($this->filemap)) {
$this->rebuildFileMap();
}
}
// }}}
// {{{ destructor
/**
* PEAR_Registry destructor. Makes sure no locks are forgotten.
*
* @access private
*/
function _PEAR_Registry()
{
parent::_PEAR();
if (is_resource($this->lock_fp)) {
$this->_unlock();
}
}
// }}}
// {{{ _assertStateDir()
/**
* Make sure the directory where we keep registry files exists.
*
* @return bool TRUE if directory exists, FALSE if it could not be
* created
*
* @access private
*/
function _assertStateDir()
{
if (!@is_dir($this->statedir)) {
if (!System::mkdir(array('-p', $this->statedir))) {
return $this->raiseError("could not create directory '{$this->statedir}'");
}
}
return true;
}
// }}}
// {{{ _packageFileName()
/**
* Get the name of the file where data for a given package is stored.
*
* @param string package name
*
* @return string registry file name
*
* @access public
*/
function _packageFileName($package)
{
return $this->statedir . DIRECTORY_SEPARATOR . strtolower($package) . '.reg';
}
// }}}
// {{{ _openPackageFile()
function _openPackageFile($package, $mode)
{
$this->_assertStateDir();
$file = $this->_packageFileName($package);
$fp = @fopen($file, $mode);
if (!$fp) {
return null;
}
return $fp;
}
// }}}
// {{{ _closePackageFile()
function _closePackageFile($fp)
{
fclose($fp);
}
// }}}
// {{{ rebuildFileMap()
function rebuildFileMap()
{
$packages = $this->listPackages();
$files = array();
foreach ($packages as $package) {
$version = $this->packageInfo($package, 'version');
$filelist = $this->packageInfo($package, 'filelist');
if (!is_array($filelist)) {
continue;
}
foreach ($filelist as $name => $attrs) {
if (isset($attrs['role']) && $attrs['role'] != 'php') {
continue;
}
if (isset($attrs['baseinstalldir'])) {
$file = $attrs['baseinstalldir'].DIRECTORY_SEPARATOR.$name;
} else {
$file = $name;
}
$file = preg_replace(',^/+,', '', $file);
$files[$file] = $package;
}
}
$this->_assertStateDir();
$fp = @fopen($this->filemap, 'wb');
if (!$fp) {
return false;
}
$this->filemap_cache = $files;
fwrite($fp, serialize($files));
fclose($fp);
return true;
}
// }}}
// {{{ readFileMap()
function readFileMap()
{
$fp = @fopen($this->filemap, 'r');
if (!$fp) {
return $this->raiseError('PEAR_Registry: could not open filemap', PEAR_REGISTRY_ERROR_FILE, null, null, $php_errormsg);
}
$fsize = filesize($this->filemap);
$rt = get_magic_quotes_runtime();
set_magic_quotes_runtime(0);
$data = fread($fp, $fsize);
set_magic_quotes_runtime($rt);
fclose($fp);
$tmp = unserialize($data);
if (!$tmp && $fsize > 7) {
return $this->raiseError('PEAR_Registry: invalid filemap data', PEAR_REGISTRY_ERROR_FORMAT, null, null, $data);
}
$this->filemap_cache = $tmp;
return true;
}
// }}}
// {{{ _lock()
/**
* Lock the registry.
*
* @param integer lock mode, one of LOCK_EX, LOCK_SH or LOCK_UN.
* See flock manual for more information.
*
* @return bool TRUE on success, FALSE if locking failed, or a
* PEAR error if some other error occurs (such as the
* lock file not being writable).
*
* @access private
*/
function _lock($mode = LOCK_EX)
{
if (!eregi('Windows 9', php_uname())) {
if ($mode != LOCK_UN && is_resource($this->lock_fp)) {
// XXX does not check type of lock (LOCK_SH/LOCK_EX)
return true;
}
if (PEAR::isError($err = $this->_assertStateDir())) {
return $err;
}
$open_mode = 'w';
// XXX People reported problems with LOCK_SH and 'w'
if ($mode === LOCK_SH || $mode === LOCK_UN) {
if (@!is_file($this->lockfile)) {
touch($this->lockfile);
}
$open_mode = 'r';
}
if (!is_resource($this->lock_fp)) {
$this->lock_fp = @fopen($this->lockfile, $open_mode);
}
if (!is_resource($this->lock_fp)) {
return $this->raiseError("could not create lock file" .
(isset($php_errormsg) ? ": " . $php_errormsg : ""));
}
if (!(int)flock($this->lock_fp, $mode)) {
switch ($mode) {
case LOCK_SH: $str = 'shared'; break;
case LOCK_EX: $str = 'exclusive'; break;
case LOCK_UN: $str = 'unlock'; break;
default: $str = 'unknown'; break;
}
return $this->raiseError("could not acquire $str lock ($this->lockfile)",
PEAR_REGISTRY_ERROR_LOCK);
}
}
return true;
}
// }}}
// {{{ _unlock()
function _unlock()
{
$ret = $this->_lock(LOCK_UN);
if (is_resource($this->lock_fp)) {
fclose($this->lock_fp);
}
$this->lock_fp = null;
return $ret;
}
// }}}
// {{{ _packageExists()
function _packageExists($package)
{
return file_exists($this->_packageFileName($package));
}
// }}}
// {{{ _packageInfo()
function _packageInfo($package = null, $key = null)
{
if ($package === null) {
return array_map(array($this, '_packageInfo'),
$this->_listPackages());
}
$fp = $this->_openPackageFile($package, 'r');
if ($fp === null) {
return null;
}
$rt = get_magic_quotes_runtime();
set_magic_quotes_runtime(0);
$data = fread($fp, filesize($this->_packageFileName($package)));
set_magic_quotes_runtime($rt);
$this->_closePackageFile($fp);
$data = unserialize($data);
if ($key === null) {
return $data;
}
if (isset($data[$key])) {
return $data[$key];
}
return null;
}
// }}}
// {{{ _listPackages()
function _listPackages()
{
$pkglist = array();
$dp = @opendir($this->statedir);
if (!$dp) {
return $pkglist;
}
while ($ent = readdir($dp)) {
if ($ent{0} == '.' || substr($ent, -4) != '.reg') {
continue;
}
$pkglist[] = substr($ent, 0, -4);
}
return $pkglist;
}
// }}}
// {{{ packageExists()
function packageExists($package)
{
if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
return $e;
}
$ret = $this->_packageExists($package);
$this->_unlock();
return $ret;
}
// }}}
// {{{ packageInfo()
function packageInfo($package = null, $key = null)
{
if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
return $e;
}
$ret = $this->_packageInfo($package, $key);
$this->_unlock();
return $ret;
}
// }}}
// {{{ listPackages()
function listPackages()
{
if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
return $e;
}
$ret = $this->_listPackages();
$this->_unlock();
return $ret;
}
// }}}
// {{{ addPackage()
function addPackage($package, $info)
{
if ($this->packageExists($package)) {
return false;
}
if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
return $e;
}
$fp = $this->_openPackageFile($package, 'wb');
if ($fp === null) {
$this->_unlock();
return false;
}
$info['_lastmodified'] = time();
fwrite($fp, serialize($info));
$this->_closePackageFile($fp);
$this->_unlock();
return true;
}
// }}}
// {{{ deletePackage()
function deletePackage($package)
{
if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
return $e;
}
$file = $this->_packageFileName($package);
$ret = @unlink($file);
$this->rebuildFileMap();
$this->_unlock();
return $ret;
}
// }}}
// {{{ updatePackage()
function updatePackage($package, $info, $merge = true)
{
$oldinfo = $this->packageInfo($package);
if (empty($oldinfo)) {
return false;
}
if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
return $e;
}
$fp = $this->_openPackageFile($package, 'w');
if ($fp === null) {
$this->_unlock();
return false;
}
$info['_lastmodified'] = time();
if ($merge) {
fwrite($fp, serialize(array_merge($oldinfo, $info)));
} else {
fwrite($fp, serialize($info));
}
$this->_closePackageFile($fp);
if (isset($info['filelist'])) {
$this->rebuildFileMap();
}
$this->_unlock();
return true;
}
// }}}
// {{{ checkFileMap()
/**
* Test whether a file belongs to a package.
*
* @param string $path file path, absolute or relative to the pear
* install dir
*
* @return string which package the file belongs to, or an empty
* string if the file does not belong to an installed package
*
* @access public
*/
function checkFileMap($path)
{
if (is_array($path)) {
static $notempty;
if (empty($notempty)) {
$notempty = create_function('$a','return !empty($a);');
}
$pkgs = array();
foreach ($path as $name => $attrs) {
if (is_array($attrs) && isset($attrs['baseinstalldir'])) {
$name = $attrs['baseinstalldir'].DIRECTORY_SEPARATOR.$name;
}
$pkgs[$name] = $this->checkFileMap($name);
}
return array_filter($pkgs, $notempty);
}
if (empty($this->filemap_cache) && PEAR::isError($this->readFileMap())) {
return $err;
}
if (isset($this->filemap_cache[$path])) {
return $this->filemap_cache[$path];
}
$l = strlen($this->install_dir);
if (substr($path, 0, $l) == $this->install_dir) {
$path = preg_replace('!^'.DIRECTORY_SEPARATOR.'+!', '', substr($path, $l));
}
if (isset($this->filemap_cache[$path])) {
return $this->filemap_cache[$path];
}
return '';
}
// }}}
}
?>
+394
View File
@@ -0,0 +1,394 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2004 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 3.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available through the world-wide-web at the following url: |
// | http://www.php.net/license/3_0.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@php.net> |
// +----------------------------------------------------------------------+
//
// $Id: Remote.php,v 1.50 2004/06/08 18:03:46 cellog Exp $
require_once 'PEAR.php';
require_once 'PEAR/Config.php';
/**
* This is a class for doing remote operations against the central
* PEAR database.
*
* @nodep XML_RPC_Value
* @nodep XML_RPC_Message
* @nodep XML_RPC_Client
*/
class PEAR_Remote extends PEAR
{
// {{{ properties
var $config = null;
var $cache = null;
// }}}
// {{{ PEAR_Remote(config_object)
function PEAR_Remote(&$config)
{
$this->PEAR();
$this->config = &$config;
}
// }}}
// {{{ getCache()
function getCache($args)
{
$id = md5(serialize($args));
$cachedir = $this->config->get('cache_dir');
$filename = $cachedir . DIRECTORY_SEPARATOR . 'xmlrpc_cache_' . $id;
if (!file_exists($filename)) {
return null;
};
$fp = fopen($filename, 'rb');
if (!$fp) {
return null;
}
$content = fread($fp, filesize($filename));
fclose($fp);
$result = array(
'age' => time() - filemtime($filename),
'lastChange' => filemtime($filename),
'content' => unserialize($content),
);
return $result;
}
// }}}
// {{{ saveCache()
function saveCache($args, $data)
{
$id = md5(serialize($args));
$cachedir = $this->config->get('cache_dir');
if (!file_exists($cachedir)) {
System::mkdir(array('-p', $cachedir));
}
$filename = $cachedir.'/xmlrpc_cache_'.$id;
$fp = @fopen($filename, "wb");
if ($fp) {
fwrite($fp, serialize($data));
fclose($fp);
};
}
// }}}
// {{{ call(method, [args...])
function call($method)
{
$_args = $args = func_get_args();
$this->cache = $this->getCache($args);
$cachettl = $this->config->get('cache_ttl');
// If cache is newer than $cachettl seconds, we use the cache!
if ($this->cache !== null && $this->cache['age'] < $cachettl) {
return $this->cache['content'];
};
if (extension_loaded("xmlrpc")) {
$result = call_user_func_array(array(&$this, 'call_epi'), $args);
if (!PEAR::isError($result)) {
$this->saveCache($_args, $result);
};
return $result;
}
if (!@include_once("XML/RPC.php")) {
return $this->raiseError("For this remote PEAR operation you need to install the XML_RPC package");
}
array_shift($args);
$server_host = $this->config->get('master_server');
$username = $this->config->get('username');
$password = $this->config->get('password');
$eargs = array();
foreach($args as $arg) $eargs[] = $this->_encode($arg);
$f = new XML_RPC_Message($method, $eargs);
if ($this->cache !== null) {
$maxAge = '?maxAge='.$this->cache['lastChange'];
} else {
$maxAge = '';
};
$proxy_host = $proxy_port = $proxy_user = $proxy_pass = '';
if ($proxy = parse_url($this->config->get('http_proxy'))) {
$proxy_host = @$proxy['host'];
$proxy_port = @$proxy['port'];
$proxy_user = @urldecode(@$proxy['user']);
$proxy_pass = @urldecode(@$proxy['pass']);
}
$c = new XML_RPC_Client('/xmlrpc.php'.$maxAge, $server_host, 80, $proxy_host, $proxy_port, $proxy_user, $proxy_pass);
if ($username && $password) {
$c->setCredentials($username, $password);
}
if ($this->config->get('verbose') >= 3) {
$c->setDebug(1);
}
$r = $c->send($f);
if (!$r) {
return $this->raiseError("XML_RPC send failed");
}
$v = $r->value();
if ($e = $r->faultCode()) {
if ($e == $GLOBALS['XML_RPC_err']['http_error'] && strstr($r->faultString(), '304 Not Modified') !== false) {
return $this->cache['content'];
}
return $this->raiseError($r->faultString(), $e);
}
$result = XML_RPC_decode($v);
$this->saveCache($_args, $result);
return $result;
}
// }}}
// {{{ call_epi(method, [args...])
function call_epi($method)
{
do {
if (extension_loaded("xmlrpc")) {
break;
}
if (OS_WINDOWS) {
$ext = 'dll';
} elseif (PHP_OS == 'HP-UX') {
$ext = 'sl';
} elseif (PHP_OS == 'AIX') {
$ext = 'a';
} else {
$ext = 'so';
}
$ext = OS_WINDOWS ? 'dll' : 'so';
@dl("xmlrpc-epi.$ext");
if (extension_loaded("xmlrpc")) {
break;
}
@dl("xmlrpc.$ext");
if (extension_loaded("xmlrpc")) {
break;
}
return $this->raiseError("unable to load xmlrpc extension");
} while (false);
$params = func_get_args();
array_shift($params);
$method = str_replace("_", ".", $method);
$request = xmlrpc_encode_request($method, $params);
$server_host = $this->config->get("master_server");
if (empty($server_host)) {
return $this->raiseError("PEAR_Remote::call: no master_server configured");
}
$server_port = 80;
if ($http_proxy = $this->config->get('http_proxy')) {
$proxy = parse_url($http_proxy);
$proxy_host = $proxy_port = $proxy_user = $proxy_pass = '';
$proxy_host = @$proxy['host'];
$proxy_port = @$proxy['port'];
$proxy_user = @urldecode(@$proxy['user']);
$proxy_pass = @urldecode(@$proxy['pass']);
$fp = @fsockopen($proxy_host, $proxy_port);
$use_proxy = true;
} else {
$use_proxy = false;
$fp = @fsockopen($server_host, $server_port);
}
if (!$fp && $http_proxy) {
return $this->raiseError("PEAR_Remote::call: fsockopen(`$proxy_host', $proxy_port) failed");
} elseif (!$fp) {
return $this->raiseError("PEAR_Remote::call: fsockopen(`$server_host', $server_port) failed");
}
$len = strlen($request);
$req_headers = "Host: $server_host:$server_port\r\n" .
"Content-type: text/xml\r\n" .
"Content-length: $len\r\n";
$username = $this->config->get('username');
$password = $this->config->get('password');
if ($username && $password) {
$req_headers .= "Cookie: PEAR_USER=$username; PEAR_PW=$password\r\n";
$tmp = base64_encode("$username:$password");
$req_headers .= "Authorization: Basic $tmp\r\n";
}
if ($this->cache !== null) {
$maxAge = '?maxAge='.$this->cache['lastChange'];
} else {
$maxAge = '';
};
if ($use_proxy && $proxy_host != '' && $proxy_user != '') {
$req_headers .= 'Proxy-Authorization: Basic '
.base64_encode($proxy_user.':'.$proxy_pass)
."\r\n";
}
if ($this->config->get('verbose') > 3) {
print "XMLRPC REQUEST HEADERS:\n";
var_dump($req_headers);
print "XMLRPC REQUEST BODY:\n";
var_dump($request);
}
if ($use_proxy && $proxy_host != '') {
$post_string = "POST http://".$server_host;
if ($proxy_port > '') {
$post_string .= ':'.$server_port;
}
} else {
$post_string = "POST ";
}
fwrite($fp, ($post_string."/xmlrpc.php$maxAge HTTP/1.0\r\n$req_headers\r\n$request"));
$response = '';
$line1 = fgets($fp, 2048);
if (!preg_match('!^HTTP/[0-9\.]+ (\d+) (.*)!', $line1, $matches)) {
return $this->raiseError("PEAR_Remote: invalid HTTP response from XML-RPC server");
}
switch ($matches[1]) {
case "200": // OK
break;
case "304": // Not Modified
return $this->cache['content'];
case "401": // Unauthorized
if ($username && $password) {
return $this->raiseError("PEAR_Remote: authorization failed", 401);
} else {
return $this->raiseError("PEAR_Remote: authorization required, please log in first", 401);
}
default:
return $this->raiseError("PEAR_Remote: unexpected HTTP response", (int)$matches[1], null, null, "$matches[1] $matches[2]");
}
while (trim(fgets($fp, 2048)) != ''); // skip rest of headers
while ($chunk = fread($fp, 10240)) {
$response .= $chunk;
}
fclose($fp);
if ($this->config->get('verbose') > 3) {
print "XMLRPC RESPONSE:\n";
var_dump($response);
}
$ret = xmlrpc_decode($response);
if (is_array($ret) && isset($ret['__PEAR_TYPE__'])) {
if ($ret['__PEAR_TYPE__'] == 'error') {
if (isset($ret['__PEAR_CLASS__'])) {
$class = $ret['__PEAR_CLASS__'];
} else {
$class = "PEAR_Error";
}
if ($ret['code'] === '') $ret['code'] = null;
if ($ret['message'] === '') $ret['message'] = null;
if ($ret['userinfo'] === '') $ret['userinfo'] = null;
if (strtolower($class) == 'db_error') {
$ret = $this->raiseError(PEAR::errorMessage($ret['code']),
$ret['code'], null, null,
$ret['userinfo']);
} else {
$ret = $this->raiseError($ret['message'], $ret['code'],
null, null, $ret['userinfo']);
}
}
} elseif (is_array($ret) && sizeof($ret) == 1 && isset($ret[0])
&& is_array($ret[0]) &&
!empty($ret[0]['faultString']) &&
!empty($ret[0]['faultCode'])) {
extract($ret[0]);
$faultString = "XML-RPC Server Fault: " .
str_replace("\n", " ", $faultString);
return $this->raiseError($faultString, $faultCode);
}
return $ret;
}
// }}}
// {{{ _encode
// a slightly extended version of XML_RPC_encode
function _encode($php_val)
{
global $XML_RPC_Boolean, $XML_RPC_Int, $XML_RPC_Double;
global $XML_RPC_String, $XML_RPC_Array, $XML_RPC_Struct;
$type = gettype($php_val);
$xmlrpcval = new XML_RPC_Value;
switch($type) {
case "array":
reset($php_val);
$firstkey = key($php_val);
end($php_val);
$lastkey = key($php_val);
if ($firstkey === 0 && is_int($lastkey) &&
($lastkey + 1) == count($php_val)) {
$is_continuous = true;
reset($php_val);
$size = count($php_val);
for ($expect = 0; $expect < $size; $expect++, next($php_val)) {
if (key($php_val) !== $expect) {
$is_continuous = false;
break;
}
}
if ($is_continuous) {
reset($php_val);
$arr = array();
while (list($k, $v) = each($php_val)) {
$arr[$k] = $this->_encode($v);
}
$xmlrpcval->addArray($arr);
break;
}
}
// fall though if not numerical and continuous
case "object":
$arr = array();
while (list($k, $v) = each($php_val)) {
$arr[$k] = $this->_encode($v);
}
$xmlrpcval->addStruct($arr);
break;
case "integer":
$xmlrpcval->addScalar($php_val, $XML_RPC_Int);
break;
case "double":
$xmlrpcval->addScalar($php_val, $XML_RPC_Double);
break;
case "string":
case "NULL":
$xmlrpcval->addScalar($php_val, $XML_RPC_String);
break;
case "boolean":
$xmlrpcval->addScalar($php_val, $XML_RPC_Boolean);
break;
case "unknown type":
default:
return null;
}
return $xmlrpcval;
}
// }}}
}
?>
+363
View File
@@ -0,0 +1,363 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2004 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 3.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available through the world-wide-web at the following url: |
// | http://www.php.net/license/3_0.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: Tomas V.V.Cox <cox@idecnet.com> |
// | Greg Beaver <cellog@php.net> |
// | |
// +----------------------------------------------------------------------+
//
// $Id: RunTest.php,v 1.3.2.4 2005/02/17 17:47:55 cellog Exp $
//
/**
* Simplified version of PHP's test suite
* -- EXPERIMENTAL --
Try it with:
$ php -r 'include "../PEAR/RunTest.php"; $t=new PEAR_RunTest; $o=$t->run("./pear_system.phpt");print_r($o);'
TODO:
Actually finish the development and testing
*/
require_once 'PEAR.php';
require_once 'PEAR/Config.php';
define('DETAILED', 1);
putenv("PHP_PEAR_RUNTESTS=1");
class PEAR_RunTest
{
var $_logger;
/**
* An object that supports the PEAR_Common->log() signature, or null
* @param PEAR_Common|null
*/
function PEAR_RunTest($logger = null)
{
$this->_logger = $logger;
}
//
// Run an individual test case.
//
function run($file, $ini_settings = '')
{
$cwd = getcwd();
$conf = &PEAR_Config::singleton();
$php = $conf->get('php_bin');
//var_dump($php);exit;
global $log_format, $info_params, $ini_overwrites;
$info_params = '';
$log_format = 'LEOD';
// Load the sections of the test file.
$section_text = array(
'TEST' => '(unnamed test)',
'SKIPIF' => '',
'GET' => '',
'ARGS' => '',
);
if (!is_file($file) || !$fp = fopen($file, "r")) {
return PEAR::raiseError("Cannot open test file: $file");
}
$section = '';
while (!feof($fp)) {
$line = fgets($fp);
// Match the beginning of a section.
if (ereg('^--([A-Z]+)--',$line,$r)) {
$section = $r[1];
$section_text[$section] = '';
continue;
}
// Add to the section text.
$section_text[$section] .= $line;
}
fclose($fp);
$shortname = str_replace($cwd.'/', '', $file);
$tested = trim($section_text['TEST'])." [$shortname]";
$tmp = realpath(dirname($file));
$tmp_skipif = $tmp . uniqid('/phpt.');
$tmp_file = ereg_replace('\.phpt$','.php',$file);
$tmp_post = $tmp . uniqid('/phpt.');
@unlink($tmp_skipif);
@unlink($tmp_file);
@unlink($tmp_post);
// unlink old test results
@unlink(ereg_replace('\.phpt$','.diff',$file));
@unlink(ereg_replace('\.phpt$','.log',$file));
@unlink(ereg_replace('\.phpt$','.exp',$file));
@unlink(ereg_replace('\.phpt$','.out',$file));
// Check if test should be skipped.
$info = '';
$warn = false;
if (array_key_exists('SKIPIF', $section_text)) {
if (trim($section_text['SKIPIF'])) {
$this->save_text($tmp_skipif, $section_text['SKIPIF']);
//$extra = substr(PHP_OS, 0, 3) !== "WIN" ?
// "unset REQUEST_METHOD;": "";
//$output = `$extra $php $info_params -f $tmp_skipif`;
$output = `$php $info_params -f $tmp_skipif`;
unlink($tmp_skipif);
if (eregi("^skip", trim($output))) {
$skipreason = "SKIP $tested";
$reason = (eregi("^skip[[:space:]]*(.+)\$", trim($output))) ? eregi_replace("^skip[[:space:]]*(.+)\$", "\\1", trim($output)) : FALSE;
if ($reason) {
$skipreason .= " (reason: $reason)";
}
$this->_logger->log(0, $skipreason);
if (isset($old_php)) {
$php = $old_php;
}
return 'SKIPPED';
}
if (eregi("^info", trim($output))) {
$reason = (ereg("^info[[:space:]]*(.+)\$", trim($output))) ? ereg_replace("^info[[:space:]]*(.+)\$", "\\1", trim($output)) : FALSE;
if ($reason) {
$info = " (info: $reason)";
}
}
if (eregi("^warn", trim($output))) {
$reason = (ereg("^warn[[:space:]]*(.+)\$", trim($output))) ? ereg_replace("^warn[[:space:]]*(.+)\$", "\\1", trim($output)) : FALSE;
if ($reason) {
$warn = true; /* only if there is a reason */
$info = " (warn: $reason)";
}
}
}
}
// We've satisfied the preconditions - run the test!
$this->save_text($tmp_file,$section_text['FILE']);
$args = $section_text['ARGS'] ? ' -- '.$section_text['ARGS'] : '';
$cmd = "$php$ini_settings -f $tmp_file$args 2>&1";
if (isset($this->_logger)) {
$this->_logger->log(2, 'Running command "' . $cmd . '"');
}
$savedir = getcwd(); // in case the test moves us around
if (isset($section_text['RETURNS'])) {
ob_start();
system($cmd, $return_value);
$out = ob_get_contents();
ob_end_clean();
@unlink($tmp_post);
$section_text['RETURNS'] = (int) trim($section_text['RETURNS']);
$returnfail = ($return_value != $section_text['RETURNS']);
} else {
$out = `$cmd`;
$returnfail = false;
}
chdir($savedir);
// Does the output match what is expected?
$output = trim($out);
$output = preg_replace('/\r\n/', "\n", $output);
if (isset($section_text['EXPECTF']) || isset($section_text['EXPECTREGEX'])) {
if (isset($section_text['EXPECTF'])) {
$wanted = trim($section_text['EXPECTF']);
} else {
$wanted = trim($section_text['EXPECTREGEX']);
}
$wanted_re = preg_replace('/\r\n/',"\n",$wanted);
if (isset($section_text['EXPECTF'])) {
$wanted_re = preg_quote($wanted_re, '/');
// Stick to basics
$wanted_re = str_replace("%s", ".+?", $wanted_re); //not greedy
$wanted_re = str_replace("%i", "[+\-]?[0-9]+", $wanted_re);
$wanted_re = str_replace("%d", "[0-9]+", $wanted_re);
$wanted_re = str_replace("%x", "[0-9a-fA-F]+", $wanted_re);
$wanted_re = str_replace("%f", "[+\-]?\.?[0-9]+\.?[0-9]*(E-?[0-9]+)?", $wanted_re);
$wanted_re = str_replace("%c", ".", $wanted_re);
// %f allows two points "-.0.0" but that is the best *simple* expression
}
/* DEBUG YOUR REGEX HERE
var_dump($wanted_re);
print(str_repeat('=', 80) . "\n");
var_dump($output);
*/
if (!$returnfail && preg_match("/^$wanted_re\$/s", $output)) {
@unlink($tmp_file);
$this->_logger->log(0, "PASS $tested$info");
if (isset($old_php)) {
$php = $old_php;
}
return 'PASSED';
}
} else {
$wanted = trim($section_text['EXPECT']);
$wanted = preg_replace('/\r\n/',"\n",$wanted);
// compare and leave on success
$ok = (0 == strcmp($output,$wanted));
if (!$returnfail && $ok) {
@unlink($tmp_file);
$this->_logger->log(0, "PASS $tested$info");
if (isset($old_php)) {
$php = $old_php;
}
return 'PASSED';
}
}
// Test failed so we need to report details.
if ($warn) {
$this->_logger->log(0, "WARN $tested$info");
} else {
$this->_logger->log(0, "FAIL $tested$info");
}
if (isset($section_text['RETURNS'])) {
$GLOBALS['__PHP_FAILED_TESTS__'][] = array(
'name' => $file,
'test_name' => $tested,
'output' => ereg_replace('\.phpt$','.log', $file),
'diff' => ereg_replace('\.phpt$','.diff', $file),
'info' => $info,
'return' => $return_value
);
} else {
$GLOBALS['__PHP_FAILED_TESTS__'][] = array(
'name' => $file,
'test_name' => $tested,
'output' => ereg_replace('\.phpt$','.log', $file),
'diff' => ereg_replace('\.phpt$','.diff', $file),
'info' => $info,
);
}
// write .exp
if (strpos($log_format,'E') !== FALSE) {
$logname = ereg_replace('\.phpt$','.exp',$file);
if (!$log = fopen($logname,'w')) {
return PEAR::raiseError("Cannot create test log - $logname");
}
fwrite($log,$wanted);
fclose($log);
}
// write .out
if (strpos($log_format,'O') !== FALSE) {
$logname = ereg_replace('\.phpt$','.out',$file);
if (!$log = fopen($logname,'w')) {
return PEAR::raiseError("Cannot create test log - $logname");
}
fwrite($log,$output);
fclose($log);
}
// write .diff
if (strpos($log_format,'D') !== FALSE) {
$logname = ereg_replace('\.phpt$','.diff',$file);
if (!$log = fopen($logname,'w')) {
return PEAR::raiseError("Cannot create test log - $logname");
}
fwrite($log, $this->generate_diff($wanted, $output,
isset($section_text['RETURNS']) ? array(trim($section_text['RETURNS']),
$return_value) : null));
fclose($log);
}
// write .log
if (strpos($log_format,'L') !== FALSE) {
$logname = ereg_replace('\.phpt$','.log',$file);
if (!$log = fopen($logname,'w')) {
return PEAR::raiseError("Cannot create test log - $logname");
}
fwrite($log,"
---- EXPECTED OUTPUT
$wanted
---- ACTUAL OUTPUT
$output
---- FAILED
");
if ($returnfail) {
fwrite($log,"
---- EXPECTED RETURN
$section_text[RETURNS]
---- ACTUAL RETURN
$return_value
");
}
fclose($log);
//error_report($file,$logname,$tested);
}
if (isset($old_php)) {
$php = $old_php;
}
return $warn ? 'WARNED' : 'FAILED';
}
function generate_diff($wanted, $output, $return_value)
{
$w = explode("\n", $wanted);
$o = explode("\n", $output);
$w1 = array_diff_assoc($w,$o);
$o1 = array_diff_assoc($o,$w);
$w2 = array();
$o2 = array();
foreach($w1 as $idx => $val) $w2[sprintf("%03d<",$idx)] = sprintf("%03d- ", $idx+1).$val;
foreach($o1 as $idx => $val) $o2[sprintf("%03d>",$idx)] = sprintf("%03d+ ", $idx+1).$val;
$diff = array_merge($w2, $o2);
ksort($diff);
if ($return_value) {
$extra = "##EXPECTED: $return_value[0]\r\n##RETURNED: $return_value[1]";
} else {
$extra = '';
}
return implode("\r\n", $diff) . $extra;
}
//
// Write the given text to a temporary file, and return the filename.
//
function save_text($filename, $text)
{
if (!$fp = fopen($filename, 'w')) {
return PEAR::raiseError("Cannot open file '" . $filename . "' (save_text)");
}
fwrite($fp,$text);
fclose($fp);
if (1 < DETAILED) echo "
FILE $filename {{{
$text
}}}
";
}
}
?>
+9
View File
@@ -0,0 +1,9 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>blank_page</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body class="mceContentBody">
</body>
</html>
+43
View File
@@ -0,0 +1,43 @@
// arabic lang variables
// Toolbar Items and Context Menu
tinyMCE.addToLang('',{
dir : 'rtl',
bold_desc : '&#1594;&#1575;&#1605;&#1602;',
italic_desc : '&#1605;&#1575;&#1574;&#1604;',
underline_desc : '&#1578;&#1587;&#1591;&#1610;&#1585;',
striketrough_desc : '&#1610;&#1578;&#1608;&#1587;&#1591;&#1607; &#1582;&#1591;',
justifyleft_desc : '&#1605;&#1581;&#1575;&#1584;&#1575;&#1577; &#1573;&#1604;&#1609; &#1575;&#1604;&#1610;&#1587;&#1575;&#1585;',
justifycenter_desc : '&#1578;&#1608;&#1587;&#1610;&#1591;',
justifyright_desc : '&#1605;&#1581;&#1575;&#1584;&#1575;&#1577; &#1573;&#1604;&#1609; &#1575;&#1604;&#1610;&#1605;&#1610;&#1606;',
justifyfull_desc : '&#1590;&#1576;&#1591;',
bullist_desc : '&#1578;&#1593;&#1583;&#1575;&#1583; &#1606;&#1602;&#1591;&#1610;',
numlist_desc : '&#1578;&#1593;&#1583;&#1575;&#1583; &#1585;&#1602;&#1605;&#1610;',
outdent_desc : '&#1573;&#1606;&#1602;&#1575;&#1589; &#1575;&#1604;&#1605;&#1587;&#1575;&#1601;&#1577; &#1575;&#1604;&#1576;&#1575;&#1583;&#1574;&#1577;',
indent_desc : '&#1586;&#1610;&#1575;&#1583;&#1577; &#1575;&#1604;&#1605;&#1587;&#1575;&#1601;&#1577; &#1575;&#1604;&#1576;&#1575;&#1583;&#1574;&#1577;',
undo_desc : '&#1578;&#1585;&#1575;&#1580;&#1593;',
redo_desc : '&#1573;&#1593;&#1575;&#1583;&#1577;',
link_desc : '&#1573;&#1583;&#1585;&#1575;&#1580;/&#1578;&#1581;&#1585;&#1610;&#1585; &#1585;&#1575;&#1576;&#1591;',
unlink_desc : '&#1573;&#1586;&#1575;&#1604;&#1577; &#1585;&#1575;&#1576;&#1591;',
image_desc : '&#1573;&#1583;&#1585;&#1575;&#1580;/&#1578;&#1581;&#1585;&#1610;&#1585; &#1589;&#1608;&#1585;&#1577;',
cleanup_desc : 'Cleanup messy code',
focus_alert : 'A editor instance must be focused before using this command.',
edit_confirm : 'Do you want to use the WYSIWYG mode for this textarea?',
insert_link_title : '&#1573;&#1583;&#1585;&#1575;&#1580;/&#1578;&#1581;&#1585;&#1610;&#1585; &#1585;&#1575;&#1576;&#1591;',
insert : '&#1573;&#1583;&#1585;&#1575;&#1580;',
update : '&#1573;&#1583;&#1585;&#1575;&#1580;',
cancel : '&#1571;&#1604;&#1594;&#1610;',
insert_link_url : '&#1585;&#1575;&#1576;&#1591; URL',
insert_link_target : '&#1575;&#1604;&#1607;&#1583;&#1601;',
insert_link_target_same : '&#1606;&#1601;&#1587; &#1575;&#1604;&#1573;&#1591;&#1575;&#1585;',
insert_link_target_blank : '&#1573;&#1591;&#1575;&#1585; &#1580;&#1583;&#1610;&#1583; (_blank)',
insert_image_title : '&#1573;&#1583;&#1585;&#1575;&#1580;/&#1578;&#1581;&#1585;&#1610;&#1585; &#1589;&#1608;&#1585;&#1577;',
insert_image_src : '&#1589;&#1608;&#1585;&#1577; URL',
insert_image_alt : '&#1575;&#1604;&#1608;&#1589;&#1601;',
help_desc : '&#1575;&#1604;&#1605;&#1587;&#1575;&#1593;&#1583;&#1577;',
bold_img : 'bold.gif',
italic_img : 'italic.gif',
underline_img : "underline.gif",
clipboard_msg : 'Copy/Cut/Paste is not available in Mozilla and Firefox.\nDo you want more information about this issue?',
popup_blocked : 'Sorry, but we have noticed that your popup-blocker has disabled a window that provides application functionality. You will need to disable popup blocking on this site in order to fully utilize this tool.'
});
+41
View File
@@ -0,0 +1,41 @@
// CA lang variables by Marc Bria
tinyMCE.addToLang('',{
bold_desc : 'Negreta',
italic_desc : 'Cursiva',
underline_desc : 'Subratllat',
striketrough_desc : 'Tatxat',
justifyleft_desc : 'Alinear a l´esquerra',
justifycenter_desc : 'Alinear al centre',
justifyright_desc : 'Alinear a la dreta',
justifyfull_desc : 'Alinear justificat',
bullist_desc : 'Llista sense ordenar',
numlist_desc : 'Llista ordenada',
outdent_desc : 'Disminueix sangria',
indent_desc : 'Augmentar sangria',
undo_desc : 'Desfer',
redo_desc : 'Refer',
link_desc : 'Insertar enllaç',
unlink_desc : 'Treure enllaç',
image_desc : 'Insertar imatge',
cleanup_desc : 'Netejar codi',
focus_alert : 'L´àrea de l´editor ha de ser enfocada abans d´executar aquesta comanda.',
edit_confirm : 'Vols utilitzar el modus WYSIWYG per a aquesta àrea de text?',
insert_link_title : 'Insertar/editar enllaç',
insert : 'Insertar',
update : 'Insertar',
cancel : 'Cancel·lar',
insert_link_url : 'Adreça de l´enllaç',
insert_link_target : 'Destí',
insert_link_target_same : 'Obrir enllaç a la mateixa finestra',
insert_link_target_blank : 'Obrir enllaç en una finestra nova',
insert_image_title : 'Insertar/editar imatge',
insert_image_src : 'URL de l´imatge',
insert_image_alt : 'Descripció de la imatge',
help_desc : 'Ajut',
bold_img : "bold.gif",
italic_img : "italic.gif",
underline_img : "underline.gif",
clipboard_msg : 'Copiar/Tallar/Enganxar no és possible amb Mozilla i Firefox.\nVols més informació sobre aquest problema de seguretat?',
popup_blocked : 'Sorry, but we have noticed that your popup-blocker has disabled a window that provides application functionality. You will need to disable popup blocking on this site in order to fully utilize this tool.'
});
+52
View File
@@ -0,0 +1,52 @@
/**
* Czech lang variables
* encoding: utf-8
*
* @author Michi
* @author Pavel Novák
* @author Josef Klimosz
*
* $Id: cs.js,v 1.6 2005/10/18 13:59:21 spocke Exp $
*/
tinyMCE.addToLang('',{
bold_desc : 'Tučně',
italic_desc : 'Kurzíva',
underline_desc : 'Podtržení',
striketrough_desc : 'Přeškrtnutí',
justifyleft_desc : 'Zarovnání vlevo',
justifycenter_desc : 'Zarovnání na střed',
justifyright_desc : 'Zarovnání vpravo',
justifyfull_desc : 'Zarovnání do bloku',
bullist_desc : 'Seznam s odrážkami',
numlist_desc : 'Číslovaný seznam',
outdent_desc : 'Snížit odsazení',
indent_desc : 'Zvýšit odsazení',
undo_desc : 'Zpět',
redo_desc : 'Znovu',
link_desc : 'Vložit odkaz',
unlink_desc : 'Zrušit odkaz',
image_desc : 'Vložit obrázek',
cleanup_desc : 'Vyčistit kód',
focus_alert : 'Před použitím tohoto příkazu musí být kurzor v okně editoru.',
edit_confirm : 'Chcete použít WYSIWYG editaci pro tento text?',
insert_link_title : 'Vložit/upravit odkaz',
insert : 'Vložit',
update : 'Změnit',
cancel : 'Zrušit',
insert_link_url : 'URL odkazu',
insert_link_target : 'Cíl',
insert_link_target_same : 'Otevřít odkaz ve stejném okně',
insert_link_target_blank : 'Otevřít odkaz v novém okně',
insert_image_title : 'Vložit/upravit obrázek',
insert_image_src : 'URL obrázku',
insert_image_alt : 'Popis obrázku',
help_desc : 'Nápověda',
bold_img : 'bold.gif',
italic_img : 'italic.gif',
underline_img : "underline.gif",
clipboard_msg : 'Funkce Kopírovat/vyjmout/vložit nejsou použitelné v Mozille a Firefoxu.\nChcete více informací o tomto problému?',
popup_blocked : 'Omlouváme se, ale blokovač vyskakovacích oken neumožnil otevřít okno, které zprostředkovává funkčnost aplikace. Musíte vypnout blokování vyskakovacích oken na tomto webu, abyste využili plné funkčnosti.'
});
+41
View File
@@ -0,0 +1,41 @@
// UK lang variables
tinyMCE.addToLang('',{
bold_desc : 'Bold (Ctrl+B)',
italic_desc : 'Italig (Ctrl+I)',
underline_desc : 'Tanlinellu (Ctrl+U)',
striketrough_desc : 'Llinell drwodd',
justifyleft_desc : 'Unioni i\'r chwith',
justifycenter_desc : 'Unioni i\'r canol',
justifyright_desc : 'Unioni i\'r dde',
justifyfull_desc : 'Unioni llawn',
bullist_desc : 'Rhestr heb drefn',
numlist_desc : 'Rhestr mewn trefn',
outdent_desc : 'Lleihau mewnoliad',
indent_desc : 'Cynyddu mewnoliad',
undo_desc : 'Dadwneud (Ctrl+Z)',
redo_desc : 'Ailwneud (Ctrl+Y)',
link_desc : 'Mewnosod/golygu dolen',
unlink_desc : 'Dadgysylltu',
image_desc : 'Mewnosod/golygu delwedd',
cleanup_desc : 'Tacluso c&ocirc;d',
focus_alert : 'Rhaid rhoi ffocws i\'r golygydd cyn defnyddio\'r gorchymyn hwn.',
edit_confirm : 'Wyt ti eisiau defnyddio\'r dull WYSIWYG ar gyfer yr ardal destun hon?',
insert_link_title : 'Mewnosod/golygu dolen',
insert : 'Mewnosod',
update : 'Diweddaru',
cancel : 'Diddymu',
insert_link_url : 'URL dolen',
insert_link_target : 'Targed',
insert_link_target_same : 'Agor dolen yn yr un ffenest',
insert_link_target_blank : 'Agor dolen mewn ffenest newydd',
insert_image_title : 'Mewnosod/golygu delwedd',
insert_image_src : 'URL delwedd',
insert_image_alt : 'Disgrifiad delwedd',
help_desc : 'Cymorth',
bold_img : "bold.gif",
italic_img : "italic.gif",
underline_img : "underline.gif",
clipboard_msg : 'Dyw Cop&iuml;o/Torri/Gludo ddim ar gael ym Mozilla na Firefox.\nHoffet ti ragor o wybodaeth ynghylch hyn?',
popup_blocked : 'Mae\'n ddrwg gennym, ond mae dy declyn atal ffenestri naid wedi analluogi ffenest sy\'n cynnig nodweddion i\'r rhaglen. Bydd rhaid i ti analluogi atal ffenestri naid ar gyfer y safle hon er mwyn cael y defnydd gorau o\'r rhaglen hwn.'
});
+41
View File
@@ -0,0 +1,41 @@
// DK lang variables contributed by Jan Moelgaard
tinyMCE.addToLang('',{
bold_desc : 'Fed',
italic_desc : 'Kursiv',
underline_desc : 'Understreg',
striketrough_desc : 'Gennemstreg',
justifyleft_desc : 'Venstrestil',
justifycenter_desc : 'Centrer',
justifyright_desc : 'H&#248;jrestil',
justifyfull_desc : 'Lige margin',
bullist_desc : 'Liste med bullets',
numlist_desc : 'Liste med tal',
outdent_desc : 'Ryk til venstre',
indent_desc : 'Ryk til h&#248;jre',
undo_desc : 'Fortryd',
redo_desc : 'G&#248;r igen',
link_desc : 'Inds&#230;t link',
unlink_desc : 'Fjern link',
image_desc : 'Inds&#230;t billede',
cleanup_desc : 'Ryd op i koden',
focus_alert : 'Der skal s&#230;ttes fokus p&#229; sessionen, f&#248;r man kan bruge denne kommando',
edit_confirm : 'Vil du bruge WYSIWYG mode til dette textomr&#229;de?',
insert_link_title : 'Inds&#230;t eller rediger link',
insert : 'Inds&#230;t',
update : 'Opdater',
cancel : 'Fortryd',
insert_link_url : 'Linkadresse',
insert_link_target : 'Destination',
insert_link_target_same : 'Luk linket op i samme vindue',
insert_link_target_blank : 'Luk linket op i et nyt vindue',
insert_image_title : 'Inds&#230;t / rediger billede',
insert_image_src : 'Billedets adresse',
insert_image_alt : 'Alternativ tekst',
help_desc : 'Hj&#230;lp',
bold_img : "bold.gif",
italic_img : "italic.gif",
underline_img : "underline.gif",
clipboard_msg : 'Kopier/Klip/Inds&#230;t virker ikke i Mozilla og Firefox.\nVil du vide mere om dette?',
popup_blocked : 'Beklager, men din browser blokerer for pop-up-vinduer. Skal du bruge denne editor fuldt ud, skal pop-up-vinduer v&#230;re tilladt.'
});
+41
View File
@@ -0,0 +1,41 @@
// DE lang variables
tinyMCE.addToLang('',{
bold_desc : 'Fett',
italic_desc : 'Kursiv',
underline_desc : 'Unterstrichen',
striketrough_desc : 'Durchgestrichen',
justifyleft_desc : 'Linksb&uuml;ndig',
justifycenter_desc : 'Zentriert',
justifyright_desc : 'Rechtsb&uuml;ndig',
justifyfull_desc : 'Blocksatz',
bullist_desc : 'Aufz&auml;hlungszeichen',
numlist_desc : 'Nummerierung',
outdent_desc : 'Einzug verkleinern',
indent_desc : 'Einzug vergr&ouml;&szlig;ern',
undo_desc : 'R&uuml;ckg&auml;ngig',
redo_desc : 'Wiederholen',
link_desc : 'Link einf&uuml;gen/bearbeiten',
unlink_desc : 'Link entfernen',
image_desc : 'Bild einf&uuml;gen/bearbeiten',
cleanup_desc : 'Unsauberen Code aufr&auml;umen',
focus_alert : 'Klicken Sie bitte vor Benutzung dieses Befehls auf das Editorfenster.',
edit_confirm : 'Wollen Sie den WYSIWYG-Modus f&uuml;r dieses Textfeld benutzen?',
insert_link_title : 'Link einf&uuml;gen/bearbeiten',
insert : 'Einf&uuml;gen',
update : 'Aktualisieren',
cancel : 'Abbrechen',
insert_link_url : 'Link-URL',
insert_link_target : 'Ziel',
insert_link_target_same : 'Link in gleichen Fester &ouml;ffnen',
insert_link_target_blank : 'Link in neuen Fenster &ouml;ffnen',
insert_image_title : 'Bild einf&uuml;gen/bearbeiten',
insert_image_src : 'Bild-URL',
insert_image_alt : 'Bild-Beschreibung',
help_desc : 'Hilfe',
bold_img : "bold_de_se.gif",
italic_img : "italic_de_se.gif",
underline_img : "underline.gif",
clipboard_msg : 'Kopieren/Ausschneiden/Einf&uuml;gen ist in Mozilla und Firefox nicht verf&uuml;gbar.\nWollen Sie mehr Informationen dar&uuml;ber erhalten?',
popup_blocked : 'Ihr Popup-Blocker hat verhindert, dass das Bearbeitungsfenster des Editors ge&ouml;ffnet werden konnte. Bitte deaktivieren Sie den Popup-Schutz f&uuml;r diese Seite.'
});
+41
View File
@@ -0,0 +1,41 @@
// Greek lang variables by Jacaranda Bill
tinyMCE.addToLang('',{
bold_desc : '¸íôïíç ãñá&ouml;Þ',
italic_desc : 'ÐëÜãéá ãñá&ouml;Þ',
underline_desc : 'ÕðïãñÜììéóç',
striketrough_desc : '&Auml;éáêñéôÞ &auml;éáãñá&ouml;Þ',
justifyleft_desc : 'Óôïß÷éóç áñéóô&aring;ñÜ',
justifycenter_desc : 'Óôïß÷éóç óôï êÝíôñï',
justifyright_desc : 'Óôïß÷éóç &auml;&aring;îéÜ',
justifyfull_desc : 'ÐëÞñçò óôïß÷éóç',
bullist_desc : 'Êïõêêß&auml;&aring;ò',
numlist_desc : 'Áñßèìçóç',
outdent_desc : 'Ì&aring;ßùóç &aring;óï÷Þò',
indent_desc : 'Áýîçóç &aring;óï÷Þò',
undo_desc : 'Áíáßñ&aring;óç',
redo_desc : 'Áêýñùóç áíáßñ&aring;óçò',
link_desc : '&Auml;çìéïõñãßá/&Auml;éüñèùóç õð&aring;ñ-óýí&auml;&aring;óçò',
unlink_desc : '&Auml;éáãñá&ouml;Þ õð&aring;ñ-óýí&auml;&aring;óçò',
image_desc : '&Aring;éóáãùãÞ/&Auml;éüñèùóç &aring;éêüíáò',
cleanup_desc : 'ÊáèÜñéóìá êþ&auml;éêá',
focus_alert : 'ÐñÝð&aring;é íá õðÜñ÷&aring;é &aring;í&aring;ñãüò êÜðïéïò &aring;ð&aring;î&aring;ñãáóôÞò ê&aring;éìÝíïõ ðñéí íá ÷ñçóéìïðïéÞó&aring;ô&aring; áõôÞ ôçí &aring;íôïëÞ.',
edit_confirm : 'ÈÝë&aring;ô&aring; íá ÷ñçóéìïðïéÞó&aring;ô&aring; ôçí êáôÜóôáóç WYSIWYG ãéá ôï óõãê&aring;êñéìÝíï ðëáßóéï ê&aring;éìÝíïõ;',
insert_link_title : '&Auml;çìéïõñãßá/&Auml;éüñèùóç õð&aring;ñ-óýí&auml;&aring;óçò',
insert : '&Aring;éóáãùãÞ',
update : '&Aring;éóáãùãÞ',
cancel : 'Áêýñùóç',
insert_link_url : '&Auml;é&aring;ýèõíóç',
insert_link_target : 'Óôü÷ïò',
insert_link_target_same : '¢íïéãìá ôçò &auml;é&aring;ýèõíóçò óôï ß&auml;éï ðáñÜèõñï',
insert_link_target_blank : '¢íïéãìá ôçò &auml;é&aring;ýèõíóçò ó&aring; íÝï ðáñÜèõñï',
insert_image_title : '&Aring;éóáãùãÞ/&Auml;éüñèùóç &aring;éêüíáò',
insert_image_src : '&Auml;é&aring;ýèõíóç',
insert_image_alt : 'Ð&aring;ñéãñá&ouml;Þ',
help_desc : 'ÂïÞè&aring;éá',
bold_img : "bold.gif",
italic_img : "italic.gif",
underline_img : "underline.gif",
clipboard_msg : 'Copy/Cut/Paste is not available in Mozilla and Firefox.\nDo you want more information about this issue?',
popup_blocked : 'Sorry, but we have noticed that your popup-blocker has disabled a window that provides application functionality. You will need to disable popup blocking on this site in order to fully utilize this tool.'
});
+41
View File
@@ -0,0 +1,41 @@
// UK lang variables
tinyMCE.addToLang('',{
bold_desc : 'Bold (Ctrl+B)',
italic_desc : 'Italic (Ctrl+I)',
underline_desc : 'Underline (Ctrl+U)',
striketrough_desc : 'Strikethrough',
justifyleft_desc : 'Align left',
justifycenter_desc : 'Align center',
justifyright_desc : 'Align right',
justifyfull_desc : 'Align full',
bullist_desc : 'Unordered list',
numlist_desc : 'Ordered list',
outdent_desc : 'Outdent',
indent_desc : 'Indent',
undo_desc : 'Undo (Ctrl+Z)',
redo_desc : 'Redo (Ctrl+Y)',
link_desc : 'Insert/edit link',
unlink_desc : 'Unlink',
image_desc : 'Insert/edit image',
cleanup_desc : 'Cleanup messy code',
focus_alert : 'A editor instance must be focused before using this command.',
edit_confirm : 'Do you want to use the WYSIWYG mode for this textarea?',
insert_link_title : 'Insert/edit link',
insert : 'Insert',
update : 'Update',
cancel : 'Cancel',
insert_link_url : 'Link URL',
insert_link_target : 'Target',
insert_link_target_same : 'Open link in the same window',
insert_link_target_blank : 'Open link in a new window',
insert_image_title : 'Insert/edit image',
insert_image_src : 'Image URL',
insert_image_alt : 'Image description',
help_desc : 'Help',
bold_img : "bold.gif",
italic_img : "italic.gif",
underline_img : "underline.gif",
clipboard_msg : 'Copy/Cut/Paste is not available in Mozilla and Firefox.\nDo you want more information about this issue?',
popup_blocked : 'Sorry, but we have noticed that your popup-blocker has disabled a window that provides application functionality. You will need to disable popup blocking on this site in order to fully utilize this tool.'
});
+50
View File
@@ -0,0 +1,50 @@
/**
* ES lang variables
*
* Authors : Alvaro Velasco,
* Adolfo Sanz De Diego (asanzdiego) <asanzdiego@yahoo.es>,
* Carlos C Soto (eclipxe) <csoto@sia-solutions.com>
* Last Updated : October 17, 2005
* TinyMCE Version : 2.0RC3
*/
tinyMCE.addToLang('',{
bold_desc : 'Negrita (Ctrl+B)',
italic_desc : 'Cursiva (Ctrl+I)',
underline_desc : 'Subrayado (Ctrl+U)',
striketrough_desc : 'Tachado',
justifyleft_desc : 'Alinear a la izquierda',
justifycenter_desc : 'Alinear al centro',
justifyright_desc : 'Alinear a la derecha',
justifyfull_desc : 'Alinear justificado',
bullist_desc : 'Lista sin ordenar',
numlist_desc : 'Lista ordenada',
outdent_desc : 'Disminuir sangría',
indent_desc : 'Aumentar sangría',
undo_desc : 'Deshacer',
redo_desc : 'Rehacer',
link_desc : 'Insertar enlace',
unlink_desc : 'Quitar enlace',
image_desc : 'Insertar imagen',
cleanup_desc : 'Limpiar codigo',
focus_alert : 'Una instanacia del editor debe ser enfocada antes de usar este comando.',
edit_confirm : '¿Quieres usar el modo WYSIWYG (What You See Is What You Get - "lo que ves es lo que obtienes") para esta area de texto?',
insert_link_title : 'Insertar/editar enlace',
insert : 'Insertar',
update : 'Actualizar',
cancel : 'Cancelar',
insert_link_url : 'Dirección del enlace',
insert_link_target : 'Destino',
insert_link_target_same : 'Abrir enlace en la misma ventana',
insert_link_target_blank : 'Abrir enlace en una ventana nueva',
insert_image_title : 'Insertar/editar imagen',
insert_image_src : 'Dirección de la imagen',
insert_image_alt : 'Descripción de la imagen',
help_desc : 'Ayuda',
bold_img : "bold_es.gif",
italic_img : "italic_es.gif",
underline_img : "underline_es.gif",
clipboard_msg : 'No se pueden utilizar los comandos Copiar / Cortar / Pegar en Mozilla y en Firefox.\r\nUse el teclado Copiar (Ctrl+C) / Cortar (Ctrl+X) / Pegar (Ctrl+V)\r\n¿Quieres obtener más información?',
popup_blocked : 'Lo siento, pero tu bloqueador de popups ha desactivado una ventana que ha lanzado la aplicación. Debes desactivar tu bloqueador de popups para tener toda la funcionalad de la aplicación.'
});
+46
View File
@@ -0,0 +1,46 @@
// IR lang variables
// Persian (Farsi) language pack (for IRAN)
// By: Morteza Zafari
// Lost@LostLord.com
// http://www.LostLord.com
tinyMCE.addToLang('',{
dir : 'rtl',
bold_desc : '????',
italic_desc : '????',
underline_desc : '??? ?? ???',
striketrough_desc : '?? ?????',
justifyleft_desc : '?? ???',
justifycenter_desc : '??? ???',
justifyright_desc : '???? ???',
justifyfull_desc : '????? ???',
bullist_desc : '????',
numlist_desc : '???? ????',
outdent_desc : '???? ?????',
indent_desc : '?????? ?????',
undo_desc : '????????',
redo_desc : '????????',
link_desc : '??? ? ?????? ????',
unlink_desc : '??? ????',
image_desc : '??? ? ?????? ???',
cleanup_desc : '??????? ??',
focus_alert : 'A editor instance must be focused before using this command.',
edit_confirm : 'Do you want to use the WYSIWYG mode for this textarea?',
insert_link_title : '??? ? ?????? ????',
insert : ' ????? ',
update : ' ????? ',
cancel : ' ?????? ',
insert_link_url : 'URL ????',
insert_link_target : '????',
insert_link_target_same : '???? ?? ?? ???? ???? ??? ??',
insert_link_target_blank : '???? ?? ?? ???? ???? ??? ??',
insert_image_title : '??? ? ?????? ???',
insert_image_src : 'URL ???',
insert_image_alt : '?????',
help_desc : '??????',
bold_img : "bold.gif",
italic_img : "italic.gif",
underline_img : "underline.gif",
clipboard_msg : 'Copy/Cut/Paste is not available in Mozilla and Firefox.\nDo you want more information about this issue?',
popup_blocked : 'Sorry, but we have noticed that your popup-blocker has disabled a window that provides application functionality. You will need to disable popup blocking on this site in order to fully utilize this tool.'
});
+42
View File
@@ -0,0 +1,42 @@
// FI lang variables by Urho Konttori from Absolutions
// Updated by Tuomo Aura, Ateco.fi
tinyMCE.addToLang('',{
bold_desc : 'Lihavoi (Ctrl+B)',
italic_desc : 'Kursivoi (Ctrl+I)',
underline_desc : 'Alleviivaa (Ctrl+U)',
striketrough_desc : 'Yliviivaa',
justifyleft_desc : 'Vasen tasaus',
justifycenter_desc : 'Keskitys',
justifyright_desc : 'Oikea tasaus',
justifyfull_desc : 'Pakotettu tasaus',
bullist_desc : 'Luettelo',
numlist_desc : 'Numeroitu lista',
outdent_desc : 'Poista sisennyt',
indent_desc : 'Sisennys',
undo_desc : 'Peruuta (Ctrl+Z)',
redo_desc : 'Tee uudelleen (Ctrl+Y)',
link_desc : 'Lis&auml;&auml; linkki',
unlink_desc : 'Poista linkki',
image_desc : 'Lis&auml;&auml; kuva',
cleanup_desc : 'Siisti koodi',
focus_alert : 'Teksink&auml;sittelyalue t&auml;ytyy olla valittuna ennen t&auml;m&auml;n komennon suorittamista.',
edit_confirm : 'Haluatko k&auml;ytt&auml;&auml; WYSIWYG-tilaa t&auml;h&auml;n tekstialueeseen?',
insert_link_title : 'Lis&auml;&auml;/muokkaa linkki&auml;',
insert : 'Lisää',
update : 'Päivitä',
cancel : 'Peruuta',
insert_link_url : 'Linkin URL',
insert_link_target : 'Kohde',
insert_link_target_same : 'Avaa linkki samassa ikkunassa',
insert_link_target_blank : 'Avaa linkki uudessa ikkunassa',
insert_image_title : 'Lis&auml;&auml;/muokkaa kuvaa',
insert_image_src : 'Kuvan URL',
insert_image_alt : 'Kuvan selite',
help_desc : 'Apua',
bold_img : "bold.gif",
italic_img : "italic.gif",
underline_img : "underline.gif",
clipboard_msg : 'Leikkaus/Kopiointi/Liit&auml;minen ei onnistu Mozilla eik&auml; Firefox -selaimilla tietoturvasta johtuen. \n Haluatko lis&auml;tietoa aiheesta?',
popup_blocked : 'Koneellasi oleva popup-ikkunoiden esto-ohjelma est&auml;&auml; tarvittavan ikkunan avaamisen. Sinun pit&auml;&auml; sallia popup-ikkunoiden n&auml;ytt&auml;minen t&auml;ll&auml; sivustolla ohjelman asetuksista.'
});
+43
View File
@@ -0,0 +1,43 @@
// FR lang variables by Pat Boens
// Modify by Laurent Dran
// Modifié par Normand Lamoureux le 2005-11-12
tinyMCE.addToLang('',{
bold_desc : 'Gras',
italic_desc : 'Italique',
underline_desc : 'Souligné',
striketrough_desc : 'Barré',
justifyleft_desc : 'Aligner à gauche',
justifycenter_desc : 'Centrer',
justifyright_desc : 'Aligner à droite',
justifyfull_desc : 'Justifier',
bullist_desc : 'Liste à puces',
numlist_desc : 'Liste numérotée',
outdent_desc : 'Diminuer le retrait',
indent_desc : 'Augmenter le retrait',
undo_desc : 'Annuler',
redo_desc : 'Restaurer',
link_desc : 'Insérer/Modifier un lien',
unlink_desc : 'Supprimer le lien',
image_desc : 'Insérer/Modifier une image',
cleanup_desc : 'Nettoyer le code',
focus_alert : 'Une instance de l\éditeur doit avoir le focus avant d\'utiliser cette commande.',
edit_confirm : 'Voulez-vous utiliser le mode WYSIWYG pour cette zone d\'édition de texte ?',
insert_link_title : 'Gestionnaire d\'hyperlien',
insert : 'Insérer',
update : 'Appliquer',
cancel : 'Annuler',
insert_link_url : 'Lien URL',
insert_link_target : 'Cible',
insert_link_target_same : 'Ouvrir dans la même fenêtre',
insert_link_target_blank : 'Ouvrir dans une nouvelle fenêtre',
insert_image_title : 'Gestionnaire d\'image',
insert_image_src : 'URL de l\'image',
insert_image_alt : 'Équivalent textuel',
help_desc : 'Aide',
bold_img : "bold_fr.gif",
italic_img : "italic.gif",
underline_img : "underline_fr.gif",
clipboard_msg : 'Pour des raisons de sécurité, les fonctions « Copier », « Couper » et « Coller »\nne sont pas disponibles dans Mozilla et Firefox.\n\n\nVoulez-vous plus d\'information à ce sujet?\n',
popup_blocked : 'Désolé, mais votre bloqueur de pop-up empêche le fonctionnement normal de l\'application.\n\n\nPour utiliser cet outil, veuillez régler votre navigateur pour qu\'il accepte les pop-up de ce site.'
});
+40
View File
@@ -0,0 +1,40 @@
// Canadian French lang variables by Virtuelcom
tinyMCE.addToLang('',{
bold_desc : 'Gras',
italic_desc : 'Italique',
underline_desc : 'Souligner',
striketrough_desc : 'Barrer',
justifyleft_desc : 'Aligner à gauche',
justifycenter_desc : 'Aligner au centre',
justifyright_desc : 'Aligner à droite',
justifyfull_desc : 'Justifier',
bullist_desc : 'Puces',
numlist_desc : 'Numérotation',
outdent_desc : 'Réduire le retrait',
indent_desc : 'Augmenter le retrait',
undo_desc : 'Annuler la dernière action',
redo_desc : 'Refaire la dernière action annulée',
link_desc : 'Insérer un hyperlien',
unlink_desc : 'Supprimer un hyperlien',
image_desc : 'Insérer une image',
cleanup_desc : 'Nettoyer le code',
focus_alert : 'Un éditeur doit être sélectionné pour utiliser cette fonction.',
edit_confirm : 'Désirez-vous utiliser l\'éditeur pour modifier cette zone?',
insert_link_title : 'Insérer / Modifier un hyperlien',
insert : 'Insérer',
update : 'Insérer',
cancel : 'Annuler',
insert_link_url : 'Adresse URL',
insert_link_target : 'Destination',
insert_link_target_same : 'Ouvrir dans la même fenêtre',
insert_link_target_blank : 'Ouvrir dans une nouvelle fenêtre',
insert_image_title : 'Insérer / Modifier une image',
insert_image_src : 'Adresse de l\'image',
insert_image_alt : 'Description de l\'image',
help_desc : 'Aide',
bold_img : "bold_fr.gif",
italic_img : "italic.gif",
underline_img : "underline_fr.gif",
clipboard_msg : 'Copier/Couper/Coller ne sont pas disponibles dans Mozilla et FireFox.\nDésirez-vous consulter de plus amples informations à ce sujet?'
});
+41
View File
@@ -0,0 +1,41 @@
// HE lang variables by Liron Newman, http://eesh.net
tinyMCE.addToLang('',{
bold_desc : 'îåãâù (Ctrl+B)',
italic_desc : 'ðèåé (Ctrl+I)',
underline_desc : '÷å úçúé (Ctrl+U)',
striketrough_desc : '÷å çåöä',
justifyleft_desc : 'éùø ìùîàì',
justifycenter_desc : 'éùø ìîøëæ',
justifyright_desc : 'éùø ìéîéï',
justifyfull_desc : 'éùø ìùðé äöããéí',
bullist_desc : 'øùéîä çñøú ñãø',
numlist_desc : 'øùéîä îñåãøú',
outdent_desc : 'ä÷èï ëðéñä',
indent_desc : 'äâãì ëðéñä',
undo_desc : 'áèì (Ctrl+Z)',
redo_desc : 'áöò ùåá (Ctrl+Y)',
link_desc : 'äëðñ/òøåê ÷éùåø',
unlink_desc : 'áèì ÷éùåø',
image_desc : 'äëðñ/òøåê úîåðä',
cleanup_desc : 'ð÷ä ÷åã îáåìâï',
focus_alert : 'éù ìáçåø áùãä òøéëä ìôðé ùðéúï ìäùúîù áô÷åãä æå.',
edit_confirm : 'äàí áøöåðê ìäùúîù áîöá òøéëä òùéøä (WYSIWYG) òáåø ùãä è÷ñè æä?',
insert_link_title : 'äëðñ/òøåê ÷éùåø',
insert : 'äëðñ',
update : 'òãëï',
cancel : 'áèì',
insert_link_url : 'ëúåáú (URL) ä÷éùåø',
insert_link_target : 'éòã',
insert_link_target_same : 'ôúç àú ä÷éùåø áàåúå çìåï',
insert_link_target_blank : 'ôúç àú ä÷éùåø áçìåï çãù',
insert_image_title : 'äëðñ/òøåê úîåðä',
insert_image_src : 'ëúåáú (URL) äúîåðä',
insert_image_alt : 'úéàåø äúîåðä',
help_desc : 'òæøä',
bold_img : "bold.gif",
italic_img : "italic.gif",
underline_img : "underline.gif",
clipboard_msg : 'ôòåìåú äòú÷ä/âæéøä/äãá÷ä àéðï ðúîëåú úçú Mozilla å-Firefox.\näàí áøöåðê ì÷áì îéãò ðåñó àåãåú ðåùà æä?',
popup_blocked : 'ñìéçä, àê ùîðå ìá ëé çåñí äçìåðåú ä÷åôöéí ùìê çñí çìåï ùîäååä çì÷ îäééùåí. úöèøê ìáèì àú çñéîú äçìåðåú ä÷åôöéí áàúø æä ëãé ìðöì ëìé æä áîìåàå.'
});
+41
View File
@@ -0,0 +1,41 @@
// HU lang variables
tinyMCE.addToLang('',{
bold_desc : 'Félkövér',
italic_desc : 'Dölt',
underline_desc : 'Aláhúzott',
striketrough_desc : 'Áthúzott',
justifyleft_desc : 'Balra igazított',
justifycenter_desc : 'Középre igazított',
justifyright_desc : 'Jobbra igazított',
justifyfull_desc : 'Telejesen igazított',
bullist_desc : 'Rendezetlen lista',
numlist_desc : 'Rendezett lista',
outdent_desc : 'Kihúzás',
indent_desc : 'Behúzás',
undo_desc : 'visszavonás',
redo_desc : 'Ismét',
link_desc : 'Link hozzáadása/szerkesztése',
unlink_desc : 'Link megszüntetése',
image_desc : 'Kép beillesztése/szerkesztése',
cleanup_desc : 'Rendetlen kód tisztítása',
focus_alert : 'Egy szerkesztőablakra muszáj fókuszálni ennek a parancsnak a használata előtt.',
edit_confirm : 'Szeretnéd használni ezt a WYSIWYG módot ehhez a szövegmezőhöz?',
insert_link_title : 'Link beillesztése/szerkesztése',
insert : 'Beillesztés',
update : 'Frissítés',
cancel : 'Mégse',
insert_link_url : 'Link URL',
insert_link_target : 'Cél',
insert_link_target_same : 'Link megnyitása ugyanabban az ablakban',
insert_link_target_blank : 'Link megnyitása új ablakban',
insert_image_title : 'Kép beillesztése/szerkesztése',
insert_image_src : 'Kép URL',
insert_image_alt : 'Kép leírása',
help_desc : 'Súgó',
bold_img : "bold.gif",
italic_img : "italic.gif",
underline_img : "underline.gif",
clipboard_msg : 'A Másolás/Kivágás/Beillesztés nem elérhető Mozillában and Firefox-ban.\nSzeretnél több információt erről a problémáról?',
popup_blocked : 'Sajnálom, de észrevettem, hogy a popup-blokkolód letiltotta az ablakot, ami biztosítja ennek az alkalmazásnak a működését. Meg kell szüntetned a popup-blokkolást ennek a segédeszköznek a teljes használatához.'
});
+41
View File
@@ -0,0 +1,41 @@
// Iceland lang variables by Johannes Birgir Jensson
tinyMCE.addToLang('',{
bold_desc : 'Feitletrun (Ctrl+B)',
italic_desc : 'Sk&aacute;letrun (Ctrl+I)',
underline_desc : 'Undirstrikun (Ctrl+U)',
striketrough_desc : 'Strik &iacute; gegn',
justifyleft_desc : 'Vinstri j&ouml;fnun',
justifycenter_desc : 'Mi&eth;ju j&ouml;fnun',
justifyright_desc : 'H&aelig;gri j&ouml;fnun',
justifyfull_desc : 'Samfelld j&ouml;fnun',
bullist_desc : 'Óra&eth;a&eth;ur listi',
numlist_desc : 'Ra&eth;a&eth;ur listi',
outdent_desc : 'Útdr&aacute;ttur',
indent_desc : 'Inndr&aacute;ttur',
undo_desc : 'Afturkalla (Ctrl+Z)',
redo_desc : 'Endurkalla (Ctrl+Y)',
link_desc : 'Setja inn/breyta hlekk',
unlink_desc : 'Fjarl&aelig;gja hlekk',
image_desc : 'Setja inn/breyta mynd',
cleanup_desc : 'Hreinsa ruslk&oacute;&eth;a',
focus_alert : 'Setja &thorn;arf bendil &iacute; ritsv&aelig;&eth;i &aacute;&eth;ur en &thorn;essi skipun er notu&eth;.',
edit_confirm : 'Viltu nota WYSIWYG &aacute; &thorn;essum reit?',
insert_link_title : 'N&yacute;r/breyttur hlekkur',
insert : 'Setja inn',
update : 'Uppf&aelig;ra',
cancel : 'H&aelig;tta vi&eth;',
insert_link_url : 'Sl&oacute;&eth; hlekks',
insert_link_target : 'Gluggi',
insert_link_target_same : 'Opna tengil &iacute; sama glugga',
insert_link_target_blank : 'Opna tengil &iacute; n&yacute;jum glugga',
insert_image_title : 'N&yacute;/breytt mynd',
insert_image_src : 'Sl&oacute;&eth; myndar',
insert_image_alt : 'L&yacute;sing myndar',
help_desc : 'Hj&aacute;lp',
bold_img : "bold.gif",
italic_img : "italic.gif",
underline_img : "underline.gif",
clipboard_msg : 'Afrita/skeyta/líma er ekki leyft í vafranum.\nViltu fá frekari upplýsingar um hvernig á að stilla það?',
popup_blocked : 'Afsakið, gluggavörn vafrans hefur meinað glugga, sem umsjónarkerfið notar, leyfi til þess að opnast. Þú verður að leyfa þessum vef að opna sprettiglugga (popup) til að geta nýtt þennan möguleika.'
});
+41
View File
@@ -0,0 +1,41 @@
// Variabili lingua IT - fabrix.xm@lombardiacom.it
tinyMCE.addToLang('',{
bold_desc : 'Grassetto',
italic_desc : 'Corsivo',
underline_desc : 'Sottolineato',
striketrough_desc : 'Barrato',
justifyleft_desc : 'Allinea a sinistra',
justifycenter_desc : 'Allinea centrato',
justifyright_desc : 'Allinea a destra',
justifyfull_desc : 'Giustifica',
bullist_desc : 'Lista non ordinata',
numlist_desc : 'Lista ordinata',
outdent_desc : 'Rientra',
indent_desc : 'Indenta',
undo_desc : 'Annulla',
redo_desc : 'Ripeti',
link_desc : 'Inserisci link',
unlink_desc : 'Elimina link',
image_desc : 'Inserisci immagine',
cleanup_desc : 'Pulisci il codice',
focus_alert : 'Una istanza dell\' editor deve essere selezionata prima di usare questo comando.',
edit_confirm : 'Vuoi usare la modalit\u00E0 WYSIWYG per questa textarea?',
insert_link_title : 'Inserisci/modifica link',
insert : 'Inserisci',
update : 'Inserisci',
cancel : 'Cancella',
insert_link_url : 'Link URL',
insert_link_target : 'Target',
insert_link_target_same : 'Apri il link nella stessa finestra',
insert_link_target_blank : 'Apri il link in una nuova finestra',
insert_image_title : 'Inserisci/modifica immagine',
insert_image_src : 'URL immagine',
insert_image_alt : 'Descrizione dell\'immagine',
help_desc : 'Guida',
bold_img : "bold.gif",
italic_img : "italic.gif",
underline_img : "underline.gif",
clipboard_msg : 'Copia, Taglia e Incolla non sono disponibili in Mozilla e Firefox.\nVuoi maggiori dettegli su questo problema?',
popup_blocked : 'Spiacenti, un sistema di blocco popup ha impedito l\'apertura di una finestra necessaria per il funzionamento dell\'editor. Disabilita il blocco popup per questo sito se vuoi utilizzare tutte le funzionalità.'
});
+41
View File
@@ -0,0 +1,41 @@
// JP lang variables
tinyMCE.addToLang('',{
bold_desc : '$BB@;z(B',
italic_desc : '$B<PBN(B',
underline_desc : '$B2<@~(B',
striketrough_desc : '$BKu>C@~(B',
justifyleft_desc : '$B:85M$a(B',
justifycenter_desc : '$BCf1{9g$o$;(B',
justifyright_desc : '$B1&5M$a(B',
justifyfull_desc : '$B9TB7$((B',
bullist_desc : '$B2U>r=q(B',
numlist_desc : '$BHV9fIU$-2U>r=q(B',
outdent_desc : '$B;z>e$2(B',
indent_desc : '$B;z2<$2(B',
undo_desc : '$B$d$j$J$*$7(B',
redo_desc : '$B:F<B9T(B',
link_desc : '$B%j%s%/$NA^F~(B/$BJT=8(B',
unlink_desc : '$B%j%s%/$N:o=|(B',
image_desc : '$B2hA|$NA^F~(B/$BJT=8(B',
cleanup_desc : '$B%3!<%I@0M}(B',
focus_alert : '$B$3$N%3%^%s%I$r;H$&A0$K%(%G%#%?>e$N$I$3$+$rA*Br$9$kI,MW$,$"$j$^$9!#(B',
edit_confirm : 'WYSIWYG$B%b!<%I$G$3$N%F%-%9%H%(%j%"$rJT=8$7$^$9$+!)(B',
insert_link_title : '$B%j%s%/$NA^F~(B/$BJT=8(B',
insert : '$BA^F~(B',
update : '$BA^F~(B',
cancel : '$B<h$j>C$7(B',
insert_link_url : '$B%j%s%/@h(BURL',
insert_link_target : '$B%?!<%2%C%H(B',
insert_link_target_same : '$BF1$8Ak$G%j%s%/$r3+$/(B',
insert_link_target_blank : '$B?7$7$$Ak$G%j%s%/$r3+$/(B',
insert_image_title : '$B2hA|$NA^F~(B/$BJT=8(B',
insert_image_src : '$B2hA|$N(BURL',
insert_image_alt : '$B2hA|$N@bL@(B',
help_desc : '$B%X%k%W(B',
bold_img : "bold.gif",
italic_img : "italic.gif",
underline_img : "underline.gif",
clipboard_msg : 'Copy/Cut/Paste is not available in Mozilla and Firefox.\nDo you want more information about this issue?',
popup_blocked : 'Sorry, but we have noticed that your popup-blocker has disabled a window that provides application functionality. You will need to disable popup blocking on this site in order to fully utilize this tool.'
});
+40
View File
@@ -0,0 +1,40 @@
// KO lang variables by Setzer Gabbiani
tinyMCE.addToLang('',{
bold_desc : 'ÁøÇϰÔ',
italic_desc : '±â¿ïÀÓ',
underline_desc : '¹ØÁÙ',
striketrough_desc : '°¡·ÎÁÙ',
justifyleft_desc : '¿ÞÂÊ Á¤·&Auml;',
justifycenter_desc : '°¡¿îµ¥ Á¤·&Auml;',
justifyright_desc : '¿À¸¥ÂÊ Á¤·&Auml;',
justifyfull_desc : '¾çÂÊ Á¤·&Auml;',
bullist_desc : '¸ñÂ÷ ¸&Aring;±â±â',
numlist_desc : '¹øÈ£ ¸&Aring;±â±â',
outdent_desc : '³»¾î¾²±â',
indent_desc : 'µé¿©¾²±â',
undo_desc : '½ÇÇàÃë¼Ò',
redo_desc : 'Àç½ÇÇà',
link_desc : '¸µ&Aring;© ³&Ouml;±â/°í&Auml;¡±â',
unlink_desc : '¸µ&Aring;© ÇØÁ¦',
image_desc : '±×¸² ³&Ouml;±â/°í&Auml;¡±â',
cleanup_desc : '&Auml;Úµ&aring;¸¦ ±ò²ûÇϰÔ',
focus_alert : 'ÀÌ ¸í·ÉÀ» ½ÇÇàÇϱâ Àü¿¡ ¹Ýµ&aring;½Ã ¿¡µð&Aring;Í ³»ÀÇ ¾îµò°¡¿¡ &Auml;¿¼­°¡ À&Ouml;¾î¾ß ÇÕ´Ï´Ù.',
edit_confirm : 'ÀÌ &Aring;ؽºÆ® ¹Ú½º¿¡¼­ HTML ¿¡µð&Aring;͸¦ »ç¿ëÇÏ±æ ¿øÇϽʴϱî?',
insert_link_title : '¸µ&Aring;© ³&Ouml;±â/°í&Auml;¡±â',
insert : '»ðÀÔ',
update : '»ðÀÔ',
cancel : 'Ãë¼Ò',
insert_link_url : 'URL ¸µ&Aring;©',
insert_link_target : '&Aring;¸°Ù',
insert_link_target_same : '°°Àº â¿¡¼­ ¸µ&Aring;© ¿­±â',
insert_link_target_blank : '»õ â¿¡¼­ ¸µ&Aring;© ¿­±â',
insert_image_title : '±×¸² ³&Ouml;±â/°í&Auml;¡±â',
insert_image_src : '±×¸² URL',
insert_image_alt : '±×¸² ¼³¸í',
help_desc : 'µµ¿ò¸»',
bold_img : "bold.gif",
italic_img : "italic.gif",
underline_img : "underline.gif",
popup_blocked : 'Sorry, but we have noticed that your popup-blocker has disabled a window that provides application functionality. You will need to disable popup blocking on this site in order to fully utilize this tool.'
});
+41
View File
@@ -0,0 +1,41 @@
// nb = Norwegian (bokm&aring;l) lang variables by Knut B. Jacobsen
tinyMCE.addToLang('',{
bold_desc : 'Fet',
italic_desc : 'Kursiv',
underline_desc : 'Understreking',
striketrough_desc : 'Gjennomstreking',
justifyleft_desc : 'Venstrestill',
justifycenter_desc : 'Sentrer',
justifyright_desc : 'H&oslash;yrestill',
justifyfull_desc : 'Blokkjustering',
bullist_desc : 'Punktliste',
numlist_desc : 'Nummerliste',
outdent_desc : 'Reduser innrykk',
indent_desc : '&Oslash;k innrykk',
undo_desc : 'Angre',
redo_desc : 'Gj&oslash;r om',
link_desc : 'Opprett/endre lenke',
unlink_desc : 'Fjern lenke',
image_desc : 'Sett inn/endre bilde',
cleanup_desc : 'Rens grisete kode',
focus_alert : 'Editoren m&aring; v&aelig;re i fokus f&oslash;r du benytter denne kommando.',
edit_confirm : 'Vil du benytte WYSIWYG editoren for dette tekstfelt?',
insert_link_title : 'Opprett/endre lenke',
insert : 'Sett inn',
update : 'Oppdater',
cancel : 'Avbryt',
insert_link_url : 'Lenkens URL',
insert_link_target : 'Vindu',
insert_link_target_same : '&Aring;pne i samme vindu',
insert_link_target_blank : '&Aring;pne i nytt vindu',
insert_image_title : 'Opprett/endre bilde',
insert_image_src : 'Bildets URL',
insert_image_alt : 'Bildets beskrivelse',
help_desc : 'Hjelp',
bold_img : 'bold_de_se.gif',
italic_img : 'italic_de_se.gif',
underline_img : 'underline.gif',
clipboard_msg : 'Klipp ut/Kopier/Lim inn fungerer ikke i Mozilla og Firefox. Vil du vite mer om dette?',
popup_blocked : 'Sorry, but we have noticed that your popup-blocker has disabled a window that provides application functionality. You will need to disable popup blocking on this site in order to fully utilize this tool.'
});
+42
View File
@@ -0,0 +1,42 @@
// NL lang variables thanks to "Meint Post"
// Updates by (2.0) Mark van der Sanden
tinyMCE.addToLang('',{
bold_desc : 'Vet (Ctrl+B)',
italic_desc : 'Cursief (Ctrl+I)',
underline_desc : 'Onderstrepen (Ctrl+U)',
striketrough_desc : 'Doorhalen',
justifyleft_desc : 'Links uitlijnen',
justifycenter_desc : 'Centreren',
justifyright_desc : 'Rechts uitlijnen',
justifyfull_desc : 'Volledig uitlijnen',
bullist_desc : 'Opsommingstekens',
numlist_desc : 'Genummerde lijst',
outdent_desc : 'Inspringen verkleinen',
indent_desc : 'Inspringen vergroten',
undo_desc : 'Ongedaan maken (Ctrl+Z)',
redo_desc : 'Opnieuw (Ctrl+Y)',
link_desc : 'Hyperlink invoegen/bewerken',
unlink_desc : 'Hyperlink verwijderen',
image_desc : 'Afbeelding invoegen',
cleanup_desc : 'Code opschonen',
focus_alert : 'Klik op de tekst in de editor voor het uitvoeren van dit commando.',
edit_confirm : 'Wilt u de WYSIWYG modus voor deze textarea gebruiken?',
insert_link_title : 'Hyperlink invoegen/bewerken',
insert : 'OK',
update : 'Toepassen',
cancel : 'Annuleren',
insert_link_url : 'URL link',
insert_link_target : 'Bestemming',
insert_link_target_same : 'Open link in hetzelfde venster',
insert_link_target_blank : 'Open link in een nieuw venster',
insert_image_title : 'Afbeelding invoegen/bewerken',
insert_image_src : 'Afbeelding',
insert_image_alt : 'Beschrijving',
help_desc : 'Help',
bold_img : "bold.gif",
italic_img : "italic.gif",
underline_img : "underline.gif",
clipboard_msg : 'Kopiëren/knippen/plakken is niet beschikbaar in Mozilla en Firefox.\nWilt u meer informatie over deze kwestie?',
popup_blocked : 'Uw browser heeft zojuist geweigerd een popup-venster te tonen. Waarschijnlijk gebruikt u een poup-blocker die voor deze editor te streng omgaat met popups. Om het venster toch te tonen, zult u uw popup-blocker zo in moeten stellen dat het popups van deze website toestaat.'
});
+41
View File
@@ -0,0 +1,41 @@
// nn = Norwegian (nynorsk) lang variables by Knut B. Jacobsen
tinyMCE.addToLang('',{
bold_desc : 'Feit',
italic_desc : 'Kursiv',
underline_desc : 'Understreking',
striketrough_desc : 'Gjennomstreking',
justifyleft_desc : 'Venstrestill',
justifycenter_desc : 'Sentrer',
justifyright_desc : 'H&oslash;grestill',
justifyfull_desc : 'Blokkjustering',
bullist_desc : 'Punktliste',
numlist_desc : 'Nummerliste',
outdent_desc : 'Reduser innrykk',
indent_desc : 'Auk innrykk',
undo_desc : 'Angre',
redo_desc : 'Gjer om',
link_desc : 'Opprett/endre lenke',
unlink_desc : 'Fjern lenke',
image_desc : 'Sett inn/endre bilde',
cleanup_desc : 'Rens grisete kode',
focus_alert : 'Editoren m&aring; v&aelig;re i fokus f&oslash;r du benytter denne kommando.',
edit_confirm : 'Vil du benytte WYSIWYG editoren for dette tekstfelt?',
insert_link_title : 'Opprett/endre lenke',
insert : 'Sett inn',
update : 'Oppdater',
cancel : 'Avbryt',
insert_link_url : 'Lenkens URL',
insert_link_target : 'Vindu',
insert_link_target_same : '&Aring;pne i samme vindauge',
insert_link_target_blank : '&Aring;pne i nytt vindauge',
insert_image_title : 'Opprett/endre bilde',
insert_image_src : 'Bildets URL',
insert_image_alt : 'Bildets beskrivelse',
help_desc : 'Hjelp',
bold_img : 'bold_de_se.gif',
italic_img : 'italic_de_se.gif',
underline_img : 'underline.gif',
clipboard_msg : 'Klipp ut/Kopier/Lim inn fungerer ikkje i Mozilla og Firefox. Vil du vite meir om dette?',
popup_blocked : 'Sorry, but we have noticed that your popup-blocker has disabled a window that provides application functionality. You will need to disable popup blocking on this site in order to fully utilize this tool.'
});
+44
View File
@@ -0,0 +1,44 @@
// PL lang variables
// fixed by Wooya
// http://www.mfusion.prv.pl
// fixed by lemiel 26.10.2005
tinyMCE.addToLang('',{
bold_desc : 'Pogrubienie (Ctrl+B)',
italic_desc : 'Pochylenie (Ctrl+I)',
underline_desc : 'Podkreślenie (Ctrl+U)',
striketrough_desc : 'Przekreślenie',
justifyleft_desc : 'Wyrównaj do lewej',
justifycenter_desc : 'Wyrównaj do środka',
justifyright_desc : 'Wyrównaj do prawej',
justifyfull_desc : 'Wyrównaj na całości',
bullist_desc : 'Lista nienumerowana',
numlist_desc : 'Lista numerowana',
outdent_desc : 'Zmniejsz wcięcie',
indent_desc : 'Zwiększ wcięcie',
undo_desc : 'Cofnij (Ctrl+Z)',
redo_desc : 'Ponów (Ctrl+Y)',
link_desc : 'Wstaw/edytuj link',
unlink_desc : 'Usuń link',
image_desc : 'Wstaw/edytuj obrazek',
cleanup_desc : 'Usuń zbędny kod',
focus_alert : 'Instancja edytora musi być aktywna przed użyciem tego polecenia.',
edit_confirm : 'Czy chcesz użyć edytora WYSIWYG dla tego pola tekstowego?',
insert_link_title : 'Wstaw/edytuj link',
insert : 'Wstaw',
update : 'Aktualizuj',
cancel : 'Anuluj',
insert_link_url : 'URL linku',
insert_link_target : 'Cel',
insert_link_target_same : 'Otwórz link w tym samym oknie',
insert_link_target_blank : 'Otwórz link w nowym oknie',
insert_image_title : 'Wstaw/edytuj obrazek',
insert_image_src : 'URL obrazka',
insert_image_alt : 'Opis obrazka',
help_desc : 'Pomoc',
bold_img : "bold.gif",
italic_img : "italic.gif",
underline_img : "underline.gif",
clipboard_msg : 'Kopiuj/Wytnij/Wklej nie jest dostępne dla przeglądarek Mozilla i Firefox.\nCzy chcesz uzyskać o tym więcej informacji?',
popup_blocked : 'Niestety, ale odnotowano, że Twoja przeglądarka ma włączoną blokadę okienek popup. Musisz wyłączyć opcję blokowania okienek dla tej strony, aby TinyMCE mógł pracować z pełną funkcjonalnością.'
});
+42
View File
@@ -0,0 +1,42 @@
// PT lang variables
tinyMCE.addToLang('',{
bold_desc : 'Negrito',
italic_desc : 'Itálico',
underline_desc : 'Sublinhar',
striketrough_desc : 'Riscado',
justifyleft_desc : 'Alinhar á esquerda',
justifycenter_desc : 'Alinhar ao centro',
justifyright_desc : 'Alinhar á direita',
justifyfull_desc : 'Justificado',
bullist_desc : 'Lista não ordenada',
numlist_desc : 'Lista ordenada',
outdent_desc : 'Retirar indentação',
indent_desc : 'Indentar',
undo_desc : 'Desfazer',
redo_desc : 'Refazer',
link_desc : 'Inserir Hiperligação',
unlink_desc : 'Remover hiperligação',
image_desc : 'Inserir Referência a imagem externa',
object_desc : 'Inserir Objecto Multimédia da Galeria',
cleanup_desc : 'Limpeza de código',
focus_alert : 'Uma instância do editor deverá estar seleccionada antes de utilizar este comando.',
edit_confirm : 'Deseja utilizar o modo visual de edição para ezta área de texto?',
insert_link_title : 'Inserir/editar hiperligação',
insert : 'Inserir',
update : 'Actualizar',
cancel : 'Cancelar',
insert_link_url : 'URL de hiperligação',
insert_link_target : 'Destino',
insert_link_target_same : 'Abrir endereço na mesma janela',
insert_link_target_blank : 'Abrir endereço numa nova janela',
insert_image_title : 'Inserir/editar imagem',
insert_image_src : 'Endereço da imagem',
insert_image_alt : 'Descrição alt.',
help_desc : 'Ajuda',
bold_img : "bold.gif",
italic_img : "italic.gif",
underline_img : "underline.gif",
clipboard_msg : 'Copiar/Cortar/Colar não está disponível em Mozilla and Firefox.\nPretende obter mais informação acerca desta questão?',
popup_blocked : 'Sorry, but we have noticed that your popup-blocker has disabled a window that provides application functionality. You will need to disable popup blocking on this site in order to fully utilize this tool.'
});
+50
View File
@@ -0,0 +1,50 @@
/**
* pt_br lang variables
* Brazilian Portuguese
*
* Authors : ????
* Revision and modifications:
* Marcio Barbosa (mpg) <mpg@mpg.com.br>
* Last Updated : November 26, 2005
* TinyMCE Version : 2.0RC4
*/
tinyMCE.addToLang('',{
bold_desc : 'Negrito (Ctrl+B)',
italic_desc : 'Itálico (Ctrl+I)',
underline_desc : 'Sublinhar (Ctrl+U)',
striketrough_desc : 'Riscado',
justifyleft_desc : 'Alinhar à esquerda',
justifycenter_desc : 'Centralizado',
justifyright_desc : 'Alinhar à direita',
justifyfull_desc : 'Justificado',
bullist_desc : 'Lista não ordenada',
numlist_desc : 'Lista ordenada',
outdent_desc : 'Retirar indentação',
indent_desc : 'Indentar',
undo_desc : 'Desfazer (Ctrl+Z)',
redo_desc : 'Refazer (Ctrl+Y)',
link_desc : 'Inserir link',
unlink_desc : 'Remover link',
image_desc : 'Inserir Referência a imagem externa',
object_desc : 'Inserir Objeto Multimídia da Galeria',
cleanup_desc : 'Limpeza de código',
focus_alert : 'Uma instância do editor deverá estar selecionada antes de utilizar este comando.',
edit_confirm : 'Deseja utilizar o Modo Visual (WYSIWYG) de edição para esta área de texto?',
insert_link_title : 'Inserir/editar link',
insert : 'Inserir',
update : 'Atualizar',
cancel : 'Cancelar',
insert_link_url : 'URL do link',
insert_link_target : 'Destino',
insert_link_target_same : 'Abrir link na mesma janela',
insert_link_target_blank : 'Abrir link em uma nova janela',
insert_image_title : 'Inserir/editar imagem',
insert_image_src : 'Endereço (URL) da imagem',
insert_image_alt : 'Descrição da imagem',
help_desc : 'Ajuda',
bold_img : "bold.gif",
italic_img : "italic.gif",
underline_img : "underline.gif",
clipboard_msg : 'Copiar/Cortar/Colar não está disponível no Mozilla e Firefox.\nPretende obter mais informação sobre esta questão?',
popup_blocked : 'Desculpe, mas sabemos que seu bloqueador de popup desativou uma que permite a funcionabilidade desta aplicação. Você precisa desativar seu bloqueador de popup neste site para que possa ser utilizado todos os recursos desta ferramenta.'
});
+2
View File
@@ -0,0 +1,2 @@
The language pack codes are based on ISO-639-2
http://www.loc.gov/standards/iso639-2/englangn.html
+43
View File
@@ -0,0 +1,43 @@
// Russian windows-1251 translation by Vladimir Vitkovsky
// admin@transport.su
// www.webgui.uanet.biz
tinyMCE.addToLang('',{
bold_desc : 'Полужирный',
italic_desc : 'Курсив',
underline_desc : 'Подчеркнутый',
striketrough_desc : 'Перечеркнутый',
justifyleft_desc : 'Выравнивание влево',
justifycenter_desc : 'Выравнивание по центру',
justifyright_desc : 'Выравнивание вправо',
justifyfull_desc : 'Равномерное заполнение',
bullist_desc : 'Маркированный список',
numlist_desc : 'Нумерованный список',
outdent_desc : 'Уменьшить отступ',
indent_desc : 'Увеличить отспут',
undo_desc : 'Отменить',
redo_desc : 'Вернуть',
link_desc : 'Вставить/изменить ссылку',
unlink_desc : 'Убрать ссылку',
image_desc : 'Вставить/изменить изображение',
cleanup_desc : 'Подчистить избыточный код',
focus_alert : 'Для использования данной команды Вы должны находится в поле редактора.',
edit_confirm : 'Хотите ли Вы редактировать в визуальном (WYSIWYG) режиме?',
insert_link_title : 'Вставить/изменить ссылку',
insert : 'Вставить',
update : 'Применить',
cancel : 'Отменить',
insert_link_url : 'Адрес ссылки',
insert_link_target : 'Открыть в...:',
insert_link_target_same : 'том же окне',
insert_link_target_blank : 'новом окне',
insert_image_title : 'Вставить/изменить изображение',
insert_image_src : 'Адрес картинки',
insert_image_alt : 'Описание картинки',
help_desc : 'Помощь',
bold_img : "bold_ru.gif",
italic_img : "italic_ru.gif",
underline_img : "underline_ru.gif",
clipboard_msg : 'Копировать/Вырезать/Вставить недоступны для Mozilla и Firefox.\nХотите узнать об этом подробнее?',
popup_blocked : 'Извините, но в Вашем браузере заблокированы всплывающие окна. Для того, чтобы иметь возможность воспользоваться всеми возможностями редактора, необходимо отключить блокировку всплывающих окон для этого сайта.'
});
+43
View File
@@ -0,0 +1,43 @@
// Russian KOI8-R translation by Vladimir Vitkovsky
// admin@transport.su
// www.webgui.uanet.biz
tinyMCE.addToLang('',{
bold_desc : 'Полужирный',
italic_desc : 'Курсив',
underline_desc : 'Подчеркнутый',
striketrough_desc : 'Перечеркнутый',
justifyleft_desc : 'Выравнивание влево',
justifycenter_desc : 'Выравнивание по центру',
justifyright_desc : 'Выравнивание вправо',
justifyfull_desc : 'Равномерное заполнение',
bullist_desc : 'Маркированный список',
numlist_desc : 'Нумерованный список',
outdent_desc : 'Уменьшить отступ',
indent_desc : 'Увеличить отспут',
undo_desc : 'Отменить',
redo_desc : 'Вернуть',
link_desc : 'Вставить/изменить ссылку',
unlink_desc : 'Убрать ссылку',
image_desc : 'Вставить/изменить изображение',
cleanup_desc : 'Подчистить избыточный код',
focus_alert : 'Для использования данной команды Вы должны находится в поле редактора.',
edit_confirm : 'Хотите ли Вы редактировать в визуальном (WYSIWYG) режиме?',
insert_link_title : 'Вставить/изменить ссылку',
insert : 'Вставить',
update : 'Применить',
cancel : 'Отменить',
insert_link_url : 'Адрес ссылки',
insert_link_target : 'Открыть в...:',
insert_link_target_same : 'том же окне',
insert_link_target_blank : 'новом окне',
insert_image_title : 'Вставить/изменить изображение',
insert_image_src : 'Адрес картинки',
insert_image_alt : 'Описание картинки',
help_desc : 'Помощь',
bold_img : "bold_ru.gif",
italic_img : "italic_ru.gif",
underline_img : "underline_ru.gif",
clipboard_msg : 'Копировать/Вырезать/Вставить недоступны для Mozilla и Firefox.\nХотите узнать об этом подробнее?',
popup_blocked : 'Извините, но в Вашем браузере заблокированы всплывающие окна. Для того, чтобы иметь возможность воспользоваться всеми возможностями редактора, необходимо отключить блокировку всплывающих окон для этого сайта.'
});
+43
View File
@@ -0,0 +1,43 @@
// Russian UTF-8 translation by Vladimir Vitkovsky
// admin@transport.su
// www.webgui.uanet.biz
tinyMCE.addToLang('',{
bold_desc : 'Полужирный',
italic_desc : 'Курсив',
underline_desc : 'Подчеркнутый',
striketrough_desc : 'Перечеркнутый',
justifyleft_desc : 'Выравнивание влево',
justifycenter_desc : 'Выравнивание по центру',
justifyright_desc : 'Выравнивание вправо',
justifyfull_desc : 'Равномерное заполнение',
bullist_desc : 'Маркированный список',
numlist_desc : 'Нумерованный список',
outdent_desc : 'Уменьшить отступ',
indent_desc : 'Увеличить отспут',
undo_desc : 'Отменить',
redo_desc : 'Вернуть',
link_desc : 'Вставить/изменить ссылку',
unlink_desc : 'Убрать ссылку',
image_desc : 'Вставить/изменить изображение',
cleanup_desc : 'Подчистить избыточный код',
focus_alert : 'Для использования данной команды Вы должны находится в поле редактора.',
edit_confirm : 'Хотите ли Вы редактировать в визуальном (WYSIWYG) режиме?',
insert_link_title : 'Вставить/изменить ссылку',
insert : 'Вставить',
update : 'Применить',
cancel : 'Отменить',
insert_link_url : 'Адрес ссылки',
insert_link_target : 'Открыть в...:',
insert_link_target_same : 'том же окне',
insert_link_target_blank : 'новом окне',
insert_image_title : 'Вставить/изменить изображение',
insert_image_src : 'Адрес картинки',
insert_image_alt : 'Описание картинки',
help_desc : 'Помощь',
bold_img : "bold_ru.gif",
italic_img : "italic_ru.gif",
underline_img : "underline_ru.gif",
clipboard_msg : 'Копировать/Вырезать/Вставить недоступны для Mozilla и Firefox.\nХотите узнать об этом подробнее?',
popup_blocked : 'Извините, но в Вашем браузере заблокированы всплывающие окна. Для того, чтобы иметь возможность воспользоваться всеми возможностями редактора, необходимо отключить блокировку всплывающих окон для этого сайта.'
});
+50
View File
@@ -0,0 +1,50 @@
/**
* Slovak lang variables
* encoding: utf-8
*
* @author Vladimir VASIL vvasil@post.sk
*
* $Id: sk.js,v 1.1 2005/11/22 20:56:43 spocke Exp $
*/
tinyMCE.addToLang('',{
bold_desc : 'Tučné',
italic_desc : 'Kurzivá',
underline_desc : 'Podčiarknutie',
striketrough_desc : 'Preškrtnutie',
justifyleft_desc : 'Zarovnanie vľavo',
justifycenter_desc : 'Zarovnanie na stred',
justifyright_desc : 'Zarovnanie vpravo',
justifyfull_desc : 'Zarovnanie do bloku',
bullist_desc : 'Zoznam s odrážkami',
numlist_desc : 'Číslovaný zoznam',
outdent_desc : 'Snížiť odsadenie',
indent_desc : 'Zvýšiť odsadenie',
undo_desc : 'Zpäť',
redo_desc : 'Znovu',
link_desc : 'Vložiť odkaz',
unlink_desc : 'Zrušiť odkaz',
image_desc : 'Vložiť obrázok',
cleanup_desc : 'Vyčistiť kód',
focus_alert : 'Pred použitím tohoto príkazu musí byť kurzor v okne editora.',
edit_confirm : 'Chcete použiť WYSIWYG editáciu pre tento text?',
insert_link_title : 'Vložiť/upraviť odkaz',
insert : 'Vložiť',
update : 'Zmeniť',
cancel : 'Zrušiť',
insert_link_url : 'URL odkazu',
insert_link_target : 'Cieľ',
insert_link_target_same : 'Otvoriť odkaz v rovnakom okne',
insert_link_target_blank : 'Otvoriť odkaz v novom okne',
insert_image_title : 'Vložiť/upraviť obrázok',
insert_image_src : 'URL obrázku',
insert_image_alt : 'Popis obrázku',
help_desc : 'Nápoveda',
bold_img : 'bold.gif',
italic_img : 'italic.gif',
underline_img : "underline.gif",
clipboard_msg : 'Funkcia Kopírovať/vysrihnúť/vložiť niesú použiteľné v Mozille a Firefoxe.\nChcete viac informácií o tomto probléme?',
popup_blocked : 'Ospravedlňujeme sa, ale blokovač vyskakovacích okien neumožnil otvoriť okno, ktoré zprostredkovává funkčnosť aplikáce. Musíte vypnuť blokovanie vyskakovacích okien na tomto webe, abyste využili jeho plnú funkčnosť.'
});
+43
View File
@@ -0,0 +1,43 @@
// SE lang variables
tinyMCE.addToLang('',{
bold_desc : 'Fet',
italic_desc : 'Kursiv',
underline_desc : 'Understruken',
striketrough_desc : 'Genomstruken',
justifyleft_desc : 'V&auml;nsterjustera',
justifycenter_desc : 'Centrera',
justifyright_desc : 'H&ouml;gerjustera',
justifyfull_desc : 'Kantjustera',
bullist_desc : 'Punktlista',
numlist_desc : 'Nummerlista',
outdent_desc : 'Utdrag',
indent_desc : 'Indrag',
undo_desc : '&Aring;ngra',
redo_desc : 'G&ouml;r om',
link_desc : 'Skapa l&auml;nk',
unlink_desc : 'Ta bort l&auml;nk',
image_desc : 'Skapa/redigera bild',
cleanup_desc : 'Rensa skr&auml;pkod',
focus_alert : 'Flytta mark&ouml;ren till en textyta innan du anv&auml;nder detta kommando.',
edit_confirm : 'Vill du anv&auml;nda WYSIWYG-editorn f&ouml;r detta textf&auml;lt?',
insert_link_title : 'Skapa/redigera l&auml;nk',
insert : 'Skapa',
update : 'Uppdatera',
cancel : 'Avbryt',
insert_link_url : 'L&auml;nkens URL',
insert_link_target : 'F&ouml;nster',
insert_link_target_same : '&Ouml;ppna l&auml;nken i samma f&ouml;nster',
insert_link_target_blank : '&Ouml;ppna l&auml;nken i ett nytt f&ouml;nster',
insert_link_delta_width : 20,
insert_link_delta_height : 10,
insert_image_title : 'Skapa/redigera bild',
insert_image_src : 'Bildens URL',
insert_image_alt : 'Bildens beskrivning',
bold_img : 'bold_de_se.gif',
italic_img : 'italic_de_se.gif',
underline_img : "underline.gif",
clipboard_msg : 'Klipput/Kopiera/Klistra fungerar inte Mozilla och Firefox. Vill du veta mer om detta?',
help_desc : "Hj&auml;lp",
popup_blocked : 'Sorry, but we have noticed that your popup-blocker has disabled a window that provides application functionality. You will need to disable popup blocking on this site in order to fully utilize this tool.'
});
+40
View File
@@ -0,0 +1,40 @@
// TH lang variables Thai contributed by Innozent
tinyMCE.addToLang('',{
bold_desc : 'µÑÇ˹Ò',
italic_desc : 'µÑÇéàÍÕ§',
underline_desc : '¢Õ´àÊé¹ãµé',
striketrough_desc : '¢Õ´¤&Aring;èÍÁ',
justifyleft_desc : 'ªÔ´¢Íº«éÒÂ',
justifycenter_desc : '¡&Ouml;è§¡&Aring;Ò§',
justifyright_desc : 'ªÔ´¢Íº¢ÇÒ',
justifyfull_desc : '¨Ñ´ªÔ´¢Íº',
bullist_desc : 'ÊÑ­&Aring;ѡɳìáÊ´§ËÑÇ¢éÍÂèÍÂ',
numlist_desc : '&Aring;ӴѺà&Aring;¢',
outdent_desc : '&Aring;´¡ÒÃàÂ×éͧ',
indent_desc : 'à¾ÔèÁ¡ÒÃàÂ×éͧ',
undo_desc : 'à&Aring;Ô¡·Ó',
redo_desc : '·ÓãËÁè',
link_desc : 'à¾ÔèÁ&Aring;Ô§¤ì',
unlink_desc : '&Aring;º&Aring;Ô§¤ì',
image_desc : 'ãÊèÃÙ»',
cleanup_desc : '·Ó¤ÇÒÁÊÐÍÒ´¢éͤÇÒÁ',
focus_alert : 'µéͧà&Aring;×Í¡¡&Aring;èͧ¢éͤÇÒÁ¡è͹·Õè¨Ðãªé¤ÓÊÑè§¹Õé',
edit_confirm : '¤Ø³µéͧ¡Ò÷Õè¨Ðãªé WYSIWYG mode ÊÓËÃѺ¡&Aring;èͧ¢éͤÇÒÁ¹ÕéËÃ×Í&auml;Áè?',
insert_link_title : 'à¾ÔèÁ/á¡é&auml;¢ &Aring;Ô§¤ì',
insert : 'à¾ÔèÁ',
cancel : '¡à&Aring;Ô¡',
insert_link_url : 'Link URL',
insert_link_target : 'à»Ô´&Aring;Ô§¤ìã¹',
insert_link_target_same : '˹éÒµèÒ§à´ÕÂǡѹ',
insert_link_target_blank : '˹éÒµèÒ§ãËÁè',
insert_image_title : 'à¾ÔèÁ/á¡é&auml;¢ ÃÙ»',
insert_image_src : 'URL ¢Í§ÃÙ»',
insert_image_alt : '¤Ó͸ԺÒÂÃÙ»',
help_desc : 'ªèÇÂàË&Aring;×Í',
bold_img : "bold.gif",
italic_img : "italic.gif",
underline_img : "underline.gif",
clipboard_msg : 'Copy/Cut/Paste is not available in Mozilla and Firefox.\nDo you want more information about this issue?',
popup_blocked : 'Sorry, but we have noticed that your popup-blocker has disabled a window that provides application functionality. You will need to disable popup blocking on this site in order to fully utilize this tool.'
});
+41
View File
@@ -0,0 +1,41 @@
// Simplified Chinese lang variables contributed by tom_cat (thomaswangyang@gmail.com)
tinyMCE.addToLang('',{
bold_desc : '黑体 (Ctrl+B)',
italic_desc : '斜体 (Ctrl+I)',
underline_desc : '下划线 (Ctrl+U)',
striketrough_desc : '删除线',
justifyleft_desc : '左对齐',
justifycenter_desc : '居中对齐',
justifyright_desc : '右对齐',
justifyfull_desc : '两端对齐',
bullist_desc : '无序列表',
numlist_desc : '有序列表',
outdent_desc : '减少缩进',
indent_desc : '增加缩进',
undo_desc : '撤消 (Ctrl+Z)',
redo_desc : '重做 (Ctrl+Y)',
link_desc : '插入/编辑 链接',
unlink_desc : '删除链接',
image_desc : '插入/编辑 图像',
cleanup_desc : '删除冗余代码',
focus_alert : '请先选择编辑区',
edit_confirm : '您想在编辑区域上使用所见即所得编辑器么?',
insert_link_title : '插入/编辑 链接',
insert : '插入',
update : '更新',
cancel : '取消',
insert_link_url : '链接地址',
insert_link_target : '链接目标',
insert_link_target_same : '在同一窗口中打开链接',
insert_link_target_blank : '在新窗口中打开链接',
insert_image_title : '插入/编辑 图像',
insert_image_src : '图像地址',
insert_image_alt : '图像描述',
help_desc : '帮助',
bold_img : "bold.gif",
italic_img : "italic.gif",
underline_img : "underline.gif",
clipboard_msg : '剪切/复制/粘贴功能在 Mozilla 和 Firefox 浏览器中不支持。您希望获得更多的信息吗?',
popup_blocked : '对不起, 您的浏览器禁止了弹出式窗口。为了让您使用到最完善的功能,请对本网站的弹出式窗口解除禁止。'
});
+42
View File
@@ -0,0 +1,42 @@
// Traditional Chinese BIG-5; Twapweb Site translated; twapweb_AT_gmail_DOT_com
// 繁體中文 BIG-5 ;數位應用坊製作; twapweb_AT_gmail_DOT_com
tinyMCE.addToLang('',{
bold_desc : '粗體(Ctrl+B)',
italic_desc : '斜體(Ctrl+I)',
underline_desc : '加底線(Ctrl+U)',
striketrough_desc : '刪除線',
justifyleft_desc : '靠左',
justifycenter_desc : '置中',
justifyright_desc : '靠右',
justifyfull_desc : '整篇對齊',
bullist_desc : '項目方式條列',
numlist_desc : '編號方式條列',
outdent_desc : '擴大縮排',
indent_desc : '減小縮排',
undo_desc : '復原(Ctrl+Z)',
redo_desc : '重複(Ctrl+Y)',
link_desc : '插入或編輯連結',
unlink_desc : '刪除連結',
image_desc : '插入或編輯圖檔',
cleanup_desc : '清除冗碼',
focus_alert : '使用此指令前須先指定編輯器',
edit_confirm : '要於此文字輸入區中採用所視即得模式嗎?',
insert_link_title : '插入或編輯連結',
insert : '插入',
update : '更新',
cancel : '取消',
insert_link_url : '連結網址',
insert_link_target : '對象',
insert_link_target_same : '於同視窗中開啟連結',
insert_link_target_blank : '以新視窗中開啟連結',
insert_image_title : '插入或編輯圖檔',
insert_image_src : '圖檔網址',
insert_image_alt : '圖檔說明',
help_desc : '協助',
bold_img : "bold_tw.gif",
italic_img : "italic_tw.gif",
underline_img : "underline_tw.gif",
clipboard_msg : '在 Mozilla 和 Firefox 中無法使用複製或剪下或貼上功能。\n需要更多關於此的訊息嗎?',
popup_blocked : '喔!您有設置跳現視窗隔絕機制,已將功能跳現視窗給隔絕了。\n請調整跳現視窗隔絕機制的設定,才能正常使用此功能。'
});
+42
View File
@@ -0,0 +1,42 @@
// Traditional Chinese UTF-8; Twapweb Site translated; twapweb_AT_gmail_DOT_com
// 繁體中文 UTF-8 ;數位應用坊製作; twapweb_AT_gmail_DOT_com
tinyMCE.addToLang('',{
bold_desc : '粗體(Ctrl+B)',
italic_desc : '斜體(Ctrl+I)',
underline_desc : '加底線(Ctrl+U)',
striketrough_desc : '刪除線',
justifyleft_desc : '靠左',
justifycenter_desc : '置中',
justifyright_desc : '靠右',
justifyfull_desc : '整篇對齊',
bullist_desc : '項目方式條列',
numlist_desc : '編號方式條列',
outdent_desc : '擴大縮排',
indent_desc : '減小縮排',
undo_desc : '復原(Ctrl+Z)',
redo_desc : '重複(Ctrl+Y)',
link_desc : '插入或編輯連結',
unlink_desc : '刪除連結',
image_desc : '插入或編輯圖檔',
cleanup_desc : '清除冗碼',
focus_alert : '使用此指令前須先指定編輯器',
edit_confirm : '要於此文字輸入區中採用所視即得模式嗎?',
insert_link_title : '插入或編輯連結',
insert : '插入',
update : '更新',
cancel : '取消',
insert_link_url : '連結網址',
insert_link_target : '對象',
insert_link_target_same : '於同視窗中開啟連結',
insert_link_target_blank : '以新視窗中開啟連結',
insert_image_title : '插入或編輯圖檔',
insert_image_src : '圖檔網址',
insert_image_alt : '圖檔說明',
help_desc : '協助',
bold_img : "bold_tw.gif",
italic_img : "italic_tw.gif",
underline_img : "underline_tw.gif",
clipboard_msg : '在 Mozilla 和 Firefox 中無法使用複製或剪下或貼上功能。\n需要更多關於此的訊息嗎?',
popup_blocked : '喔!您有設置跳現視窗隔絕機制,已將功能跳現視窗給隔絕了。\n請調整跳現視窗隔絕機制的設定,才能正常使用此功能。'
});
+437
View File
@@ -0,0 +1,437 @@
GNU LIBRARY GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the library GPL. It is
numbered 2 because it goes with version 2 of the ordinary GPL.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Library General Public License, applies to some
specially designated Free Software Foundation software, and to any
other libraries whose authors decide to use it. You can use it for
your libraries, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if
you distribute copies of the library, or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link a program with the library, you must provide
complete object files to the recipients so that they can relink them
with the library, after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
Our method of protecting your rights has two steps: (1) copyright
the library, and (2) offer you this license which gives you legal
permission to copy, distribute and/or modify the library.
Also, for each distributor's protection, we want to make certain
that everyone understands that there is no warranty for this free
library. If the library is modified by someone else and passed on, we
want its recipients to know that what they have is not the original
version, so that any problems introduced by others will not reflect on
the original authors' reputations.
.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that companies distributing free
software will individually obtain patent licenses, thus in effect
transforming the program into proprietary software. To prevent this,
we have made it clear that any patent must be licensed for everyone's
free use or not licensed at all.
Most GNU software, including some libraries, is covered by the ordinary
GNU General Public License, which was designed for utility programs. This
license, the GNU Library General Public License, applies to certain
designated libraries. This license is quite different from the ordinary
one; be sure to read it in full, and don't assume that anything in it is
the same as in the ordinary license.
The reason we have a separate public license for some libraries is that
they blur the distinction we usually make between modifying or adding to a
program and simply using it. Linking a program with a library, without
changing the library, is in some sense simply using the library, and is
analogous to running a utility program or application program. However, in
a textual and legal sense, the linked executable is a combined work, a
derivative of the original library, and the ordinary General Public License
treats it as such.
Because of this blurred distinction, using the ordinary General
Public License for libraries did not effectively promote software
sharing, because most developers did not use the libraries. We
concluded that weaker conditions might promote sharing better.
However, unrestricted linking of non-free programs would deprive the
users of those programs of all benefit from the free status of the
libraries themselves. This Library General Public License is intended to
permit developers of non-free programs to use free libraries, while
preserving your freedom as a user of such programs to change the free
libraries that are incorporated in them. (We have not seen how to achieve
this as regards changes in header files, but we have achieved it as regards
changes in the actual functions of the Library.) The hope is that this
will lead to faster development of free libraries.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, while the latter only
works together with the library.
Note that it is possible for a library to be covered by the ordinary
General Public License rather than by this special one.
.
GNU LIBRARY GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library which
contains a notice placed by the copyright holder or other authorized
party saying it may be distributed under the terms of this Library
General Public License (also called "this License"). Each licensee is
addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
.
6. As an exception to the Sections above, you may also compile or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
c) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
d) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the source code distributed need not include anything that is normally
distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Library General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
+118
View File
@@ -0,0 +1,118 @@
/* Import plugin specific language pack */
tinyMCE.importPluginLanguagePack('template', 'en'); // <- Add a comma separated list of all supported languages
/****
* Steps for creating a plugin from this template:
*
* 1. Change all "template" to the name of your plugin.
* 2. Remove all the callbacks in this file that you don't need.
* 3. Remove the popup.htm file if you don't need any popups.
* 4. Add your custom logic to the callbacks you needed.
* 5. Write documentation in a readme.txt file on how to use the plugin.
* 6. Upload it under the "Plugins" section at sourceforge.
*
****/
/**
* Gets executed when a editor instance is initialized
*/
function TinyMCE_template_initInstance(inst) {
// You can take out plugin specific parameters
alert("Initialization parameter:" + tinyMCE.getParam("template_someparam", false));
}
/**
* Gets executed when a editor needs to generate a button.
*/
function TinyMCE_template_getControlHTML(control_name) {
switch (control_name) {
case "template":
return '<img id="{$editor_id}_template" src="{$pluginurl}/images/template.gif" title="{$lang_template_desc}" width="20" height="20" class="mceButtonNormal" onmouseover="tinyMCE.switchClass(this,\'mceButtonOver\');" onmouseout="tinyMCE.restoreClass(this);" onmousedown="tinyMCE.restoreAndSwitchClass(this,\'mceButtonDown\');tinyMCE.execInstanceCommand(\'{$editor_id}\',\'mceTemplate\', true);" />';
}
return "";
}
/**
* Gets executed when a command is called.
*/
function TinyMCE_template_execCommand(editor_id, element, command, user_interface, value) {
// Handle commands
switch (command) {
// Remember to have the "mce" prefix for commands so they don't intersect with built in ones in the browser.
case "mceTemplate":
// Show UI/Popup
if (user_interface) {
// Open a popup window and send in some custom data in a window argument
var template = new Array();
template['file'] = '../../plugins/template/popup.htm'; // Relative to theme
template['width'] = 300;
template['height'] = 200;
tinyMCE.openWindow(template, {editor_id : editor_id, some_custom_arg : "somecustomdata"});
// Let TinyMCE know that something was modified
tinyMCE.triggerNodeChange(false);
} else {
// Do a command this gets called from the template popup
alert("execCommand: mceTemplate gets called from popup.");
}
return true;
}
// Pass to next handler in chain
return false;
}
/**
* Gets executed when the selection/cursor position was changed.
*/
function TinyMCE_template_handleNodeChange(editor_id, node, undo_index, undo_levels, visual_aid, any_selection) {
// Deselect template button
tinyMCE.switchClassSticky(editor_id + '_template', 'mceButtonNormal');
// Select template button if parent node is a strong or b
if (node.parentNode.nodeName == "STRONG" || node.parentNode.nodeName == "B")
tinyMCE.switchClassSticky(editor_id + '_template', 'mceButtonSelected');
return true;
}
/**
* Gets executed when contents is inserted / retrived.
*/
function TinyMCE_template_cleanup(type, content) {
switch (type) {
case "get_from_editor":
alert("[FROM] Value HTML string: " + content);
// Do custom cleanup code here
break;
case "insert_to_editor":
alert("[TO] Value HTML string: " + content);
// Do custom cleanup code here
break;
case "get_from_editor_dom":
alert("[FROM] Value DOM Element " + content.innerHTML);
// Do custom cleanup code here
break;
case "insert_to_editor_dom":
alert("[TO] Value DOM Element: " + content.innerHTML);
// Do custom cleanup code here
break;
}
return content;
}
+132
View File
@@ -0,0 +1,132 @@
/* Import plugin specific language pack */
tinyMCE.importPluginLanguagePack('template', 'en,he,nb,ru,ru_KOI8-R,ru_UTF-8,nn,fi,cy,es,is,pl'); // <- Add a comma separated list of all supported languages
/****
* Steps for creating a plugin from this template:
*
* 1. Change all "template" to the name of your plugin.
* 2. Remove all the callbacks in this file that you don't need.
* 3. Remove the popup.htm file if you don't need any popups.
* 4. Add your custom logic to the callbacks you needed.
* 5. Write documentation in a readme.txt file on how to use the plugin.
* 6. Upload it under the "Plugins" section at sourceforge.
*
****/
/**
* Information about the plugin.
*/
function TinyMCE_template_getInfo() {
return {
longname : 'Template plugin',
author : 'Your name',
authorurl : 'http://www.yoursite.com',
infourl : 'http://www.yoursite.com/docs/template.html',
version : "1.0"
};
};
/**
* Gets executed when a editor instance is initialized
*/
function TinyMCE_template_initInstance(inst) {
// You can take out plugin specific parameters
alert("Initialization parameter:" + tinyMCE.getParam("template_someparam", false));
}
/**
* Gets executed when a editor needs to generate a button.
*/
function TinyMCE_template_getControlHTML(control_name) {
switch (control_name) {
case "template":
var cmd = 'tinyMCE.execInstanceCommand(\'{$editor_id}\',\'mceTemplate\', true);return false;';
return '<a href="javascript:' + cmd + '" onclick="' + cmd + '" target="_self" onmousedown="return false;"><img id="{$editor_id}_template" src="{$pluginurl}/images/template.gif" title="{$lang_template_desc}" width="20" height="20" class="mceButtonNormal" onmouseover="tinyMCE.switchClass(this,\'mceButtonOver\');" onmouseout="tinyMCE.restoreClass(this);" onmousedown="tinyMCE.restoreAndSwitchClass(this,\'mceButtonDown\');" /></a>';
}
return "";
}
/**
* Gets executed when a command is called.
*/
function TinyMCE_template_execCommand(editor_id, element, command, user_interface, value) {
// Handle commands
switch (command) {
// Remember to have the "mce" prefix for commands so they don't intersect with built in ones in the browser.
case "mceTemplate":
// Show UI/Popup
if (user_interface) {
// Open a popup window and send in some custom data in a window argument
var template = new Array();
template['file'] = '../../plugins/template/popup.htm'; // Relative to theme
template['width'] = 300;
template['height'] = 200;
tinyMCE.openWindow(template, {editor_id : editor_id, some_custom_arg : "somecustomdata"});
// Let TinyMCE know that something was modified
tinyMCE.triggerNodeChange(false);
} else {
// Do a command this gets called from the template popup
alert("execCommand: mceTemplate gets called from popup.");
}
return true;
}
// Pass to next handler in chain
return false;
}
/**
* Gets executed when the selection/cursor position was changed.
*/
function TinyMCE_template_handleNodeChange(editor_id, node, undo_index, undo_levels, visual_aid, any_selection) {
// Deselect template button
tinyMCE.switchClassSticky(editor_id + '_template', 'mceButtonNormal');
// Select template button if parent node is a strong or b
if (node.parentNode.nodeName == "STRONG" || node.parentNode.nodeName == "B")
tinyMCE.switchClassSticky(editor_id + '_template', 'mceButtonSelected');
return true;
}
/**
* Gets executed when contents is inserted / retrived.
*/
function TinyMCE_template_cleanup(type, content) {
switch (type) {
case "get_from_editor":
alert("[FROM] Value HTML string: " + content);
// Do custom cleanup code here
break;
case "insert_to_editor":
alert("[TO] Value HTML string: " + content);
// Do custom cleanup code here
break;
case "get_from_editor_dom":
alert("[FROM] Value DOM Element " + content.innerHTML);
// Do custom cleanup code here
break;
case "insert_to_editor_dom":
alert("[TO] Value DOM Element: " + content.innerHTML);
// Do custom cleanup code here
break;
}
return content;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 87 B

+8
View File
@@ -0,0 +1,8 @@
// DK lang variables contributed by Jan Moelgaard
/* Remember to namespace the language parameters lang_<your plugin>_<some name> */
tinyMCE.addToLang('',{
template_title : 'Dette er bare en pop-up-skabelon',
template_desc : 'Dette er bare en testknap'
});
+9
View File
@@ -0,0 +1,9 @@
// DE lang variables
/* Remember to namespace the language parameters lang_<your plugin>_<some name> */
/* Sprachparameter müssen als lang_<Eigenes Plugin>_<Eigener Name> definiert werden */
tinyMCE.addToLang('',{
template_title : 'Dies ist nur ein Beispiel-Popup',
template_desc : 'Dies ist nur ein Beispiel-Button'
});
+8
View File
@@ -0,0 +1,8 @@
// UK lang variables
/* Remember to namespace the language parameters lang_<your plugin>_<some name> */
tinyMCE.addToLang('',{
template_title : 'This is just a template popup',
template_desc : 'This is just a template button'
});
+14
View File
@@ -0,0 +1,14 @@
/**
* ES lang variables
*
* Authors : Alvaro Velasco,
* Adolfo Sanz De Diego (asanzdiego) <asanzdiego@yahoo.es>,
* Carlos C Soto (eclipxe) <csoto@sia-solutions.com>
* Last Updated : October 17, 2005
* TinyMCE Version : 2.0RC3
*/
tinyMCE.addToLang('',{
template_title : 'Esto es solo la plantilla de un popup',
template_desc : 'Esto es solo la plantilla de un botón'
});
+9
View File
@@ -0,0 +1,9 @@
// Canadian French lang variables by Virtuelcom last modification: 2005-06-15
// Modifié par Normand Lamoureux le 2005-11-12
/* N'oubliez pas d'identifer les paramètres de langue ainsi: <votre plugin>_<un nom> */
tinyMCE.addToLang('',{
template_title : 'Texte qui apparaîtra sous forme de titre dans la fenêtre pop-up de votre plugin',
template_desc : 'Texte qui apparaîtra sous forme d\'info-bulle au survol du bouton de votre plugin'
});
+8
View File
@@ -0,0 +1,8 @@
// Canadian French lang variables by Virtuelcom last modification: 2005-06-15
/* Remember to namespace the language parameters <your plugin>_<some name> */
tinyMCE.addToLang('',{
template_title : 'Ceci est un exmple pour le gabarit de popup',
template_desc : 'Ceci est un exmple pour le gabarit d\'un bouton'
});
+8
View File
@@ -0,0 +1,8 @@
// HE lang variables
/* Remember to namespace the language parameters lang_<your plugin>_<some name> */
tinyMCE.addToLang('',{
template_title : 'æä ñúí çìåï ÷åôõ ùì äúáðéú',
template_desc : 'æä ñúí ëôúåø ùì äúáðéú'
});
+8
View File
@@ -0,0 +1,8 @@
// HU lang variables
/* Remember to namespace the language parameters lang_<your plugin>_<some name> */
tinyMCE.addToLang('',{
template_title : 'Ez csak egy példa popup',
template_desc : 'Ez csak egy példa gomb'
});
+8
View File
@@ -0,0 +1,8 @@
// Iceland lang variables by Johannes Birgir Jensson
/* Remember to namespace the language parameters lang_<your plugin>_<some name> */
tinyMCE.addToLang('',{
template_title : '&THORN;etta er sni&eth;m&aacute;tsgluggi',
template_desc : '&THORN;etta er sni&eth;m&aacute;tstakki'
});
+8
View File
@@ -0,0 +1,8 @@
// nb = Norwegian (bokm&aring;l) lang variables by Knut B. Jacobsen
/* Remember to namespace the language parameters lang_<your plugin>_<some name> */
tinyMCE.addToLang('',{
template_title : 'Dette er bare en template popup',
template_desc : 'Dette er bare en template knapp'
});
+8
View File
@@ -0,0 +1,8 @@
// NL lang variables
/* Remember to namespace the language parameters lang_<your plugin>_<some name> */
tinyMCE.addToLang('',{
template_title : 'Dit is slechts een voorbeeldpopup',
template_desc : 'Dit is slechts een voorbeeldknop'
});
+8
View File
@@ -0,0 +1,8 @@
// nn = Norwegian (nynorsk) lang variables by Knut B. Jacobsen
/* Remember to namespace the language parameters lang_<your plugin>_<some name> */
tinyMCE.addToLang('',{
template_title : 'Dette er berre ein template popup',
template_desc : 'Dette er berre ein template knapp'
});
+8
View File
@@ -0,0 +1,8 @@
// PL lang variables
/* Remember to namespace the language parameters lang_<your plugin>_<some name> */
tinyMCE.addToLang('',{
template_title : 'To jest szablon okna popup',
template_desc : 'To jest szablon przycisku'
});
+13
View File
@@ -0,0 +1,13 @@
/**
* pt_br lang variables
* Brazilian Portuguese
*
* Authors :
* Marcio Barbosa (mpg) <mpg@mpg.com.br>
* Last Updated : November 26, 2005
* TinyMCE Version : 2.0RC4
*/
tinyMCE.addToLang('',{
template_title : 'Este é só um modêlo de popup',
template_desc : 'Este é só um modêlo de botão'
});
+8
View File
@@ -0,0 +1,8 @@
// RU cp1251 lang variables
/* Remember to namespace the language parameters lang_<your plugin>_<some name> */
tinyMCE.addToLang('',{
template_title : 'Ýòî øàáëîí äëÿ popup',
template_desc : 'Ýòî øàáëîí äëÿ êíîïêè'
});
@@ -0,0 +1,8 @@
// RU KOI8-R lang variables
/* Remember to namespace the language parameters lang_<your plugin>_<some name> */
tinyMCE.addToLang('',{
template_title : 'üÔÏ ÛÁÂÌÏÎ ÄÌÑ popup',
template_desc : 'üÔÏ ÛÁÂÌÏÎ ÄÌÑ ËÎÏÐËÉ'
});
+8
View File
@@ -0,0 +1,8 @@
// RU UTF-8 lang variables
/* Remember to namespace the language parameters lang_<your plugin>_<some name> */
tinyMCE.addToLang('',{
template_title : 'Это шаблон для popup',
template_desc : 'Это шаблон для кнопки'
});
+8
View File
@@ -0,0 +1,8 @@
// Simplified Chinese lang variables contributed by tom_cat (thomaswangyang@gmail.com)
/* Remember to namespace the language parameters <your plugin>_<some name> */
tinyMCE.addToLang('',{
template_title : '这是一个模板弹出窗口',
template_desc : '这是一个模板按钮'
});
Loaded 100 of 1198 files, more files were not shown because too many files have changed in this diff. Show more