File manager - Edit - /home/opticamezl/www/newok/sources.zip
Back
PK 唘\�Y� � k2/k2.phpnu &1i� <?php /** * @package ThemeXpert Extension Framework (XEF) * @copyright Copyright (c)2010-2012 ThemeXpert.com * @license GNU General Public License version 3, or later **/ // Protect from unauthorized access defined('_JEXEC') or die(); // Require XEF helper class require_once JPATH_LIBRARIES . '/xef/xef.php'; require_once(JPATH_SITE . '/components/com_k2/helpers/route.php'); require_once(JPATH_SITE . '/components/com_k2/helpers/utilities.php'); class XEFSourceK2 extends XEFHelper { public function getItems() { jimport('joomla.filesystem.file'); $app = JFactory::getApplication('site', array(), 'J'); $cid = $this->get('k2_catid', NULL); $ordering = $this->get('k2_items_ordering',''); $user = JFactory::getUser(); $aid = $user->get('aid'); $db = JFactory::getDBO(); $jnow = JFactory::getDate(); $now = $jnow->toSQL(); $nullDate = $db->getNullDate(); $query = "SELECT i.*, CASE WHEN i.modified = 0 THEN i.created ELSE i.modified END as lastChanged, c.name AS categoryname,c.id AS categoryid, c.alias AS categoryalias, c.params AS categoryparams"; if ($ordering == 'best') $query .= ", (r.rating_sum/r.rating_count) AS rating"; if ($ordering == 'comments') $query .= ", COUNT(comments.id) AS numOfComments"; $query .= " FROM #__k2_items as i LEFT JOIN #__k2_categories c ON c.id = i.catid"; if ($ordering == 'best') $query .= " LEFT JOIN #__k2_rating r ON r.itemID = i.id"; if ($ordering == 'comments') $query .= " LEFT JOIN #__k2_comments comments ON comments.itemID = i.id"; $query .= " WHERE i.published = 1 AND i.access IN(".implode(',', $user->getAuthorisedViewLevels()).") AND i.trash = 0 AND c.published = 1 AND c.access IN(".implode(',', $user->getAuthorisedViewLevels()).") AND c.trash = 0"; $query .= " AND ( i.publish_up = ".$db->Quote($nullDate)." OR i.publish_up <= ".$db->Quote($now)." )"; $query .= " AND ( i.publish_down = ".$db->Quote($nullDate)." OR i.publish_down >= ".$db->Quote($now)." )"; if ($this->get('k2_catfilter')) { if (!is_null($cid)) { if (is_array($cid)) { if ($this->get('k2_get_children')) { $itemListModel = K2Model::getInstance('Itemlist', 'K2Model'); $categories = $itemListModel->getCategoryTree($cid); $sql = @implode(',', $categories); $query .= " AND i.catid IN ({$sql})"; } else { JArrayHelper::toInteger($cid); $query .= " AND i.catid IN(".implode(',', $cid).")"; } } else { if ($this->get('k2_get_children')) { $itemListModel = K2Model::getInstance('Itemlist', 'K2Model'); $categories = $itemListModel->getCategoryTree($cid); $sql = @implode(',', $categories); $query .= " AND i.catid IN ({$sql})"; } else { $query .= " AND i.catid=".(int)$cid; } } } } if ($this->get('k2_featured_items') == '0') $query .= " AND i.featured != 1"; if ($this->get('k2_featured_items') == '2') $query .= " AND i.featured = 1"; if ($ordering == 'comments') $query .= " AND comments.published = 1"; if ($app->getLanguageFilter()) { $languageTag = JFactory::getLanguage()->getTag(); $query .= " AND c.language IN (".$db->Quote($languageTag).", ".$db->Quote('*').") AND i.language IN (".$db->Quote($languageTag).", ".$db->Quote('*').")"; } switch ($ordering) { case 'date' : $orderby = 'i.created ASC'; break; case 'rdate' : $orderby = 'i.created DESC'; break; case 'alpha' : $orderby = 'i.title'; break; case 'ralpha' : $orderby = 'i.title DESC'; break; case 'order' : if ($this->get('FeaturedItems') == '2') $orderby = 'i.featured_ordering'; else $orderby = 'i.ordering'; break; case 'rorder' : if ($this->get('FeaturedItems') == '2') $orderby = 'i.featured_ordering DESC'; else $orderby = 'i.ordering DESC'; break; case 'hits' : if ($this->get('popularityRange')) { $datenow = &JFactory::getDate(); $date = $datenow->toSQL(); $query .= " AND i.created > DATE_SUB('{$date}',INTERVAL ".$this->get('popularityRange')." DAY) "; } $orderby = 'i.hits DESC'; break; case 'rand' : $orderby = 'RAND()'; break; case 'best' : $orderby = 'rating DESC'; break; case 'comments' : if ($this->get('popularityRange')) { $datenow = &JFactory::getDate(); $date = $datenow->toSQL(); $query .= " AND i.created > DATE_SUB('{$date}',INTERVAL ".$this->get('popularityRange')." DAY) "; } $query .= " GROUP BY i.id "; $orderby = 'numOfComments DESC'; break; case 'modified' : $orderby = 'lastChanged DESC'; break; case 'publishUp' : $orderby = 'i.publish_up DESC'; break; default : $orderby = 'i.id DESC'; break; } $query .= " ORDER BY ".$orderby; $db->setQuery($query, 0, $this->get('count')); $items = $db->loadObjectList(); //XEFUtility::debug($items); $items = $this->prepareItems($items); return $items; } public function getLink($item) { return urldecode(JRoute::_( K2HelperRoute::getItemRoute($item->id.':'.urlencode($item->alias), $item->catid.':'.urlencode($item->categoryalias)) . $this->getMenuItemId())); } public function getCategory($item) { return $item->categoryname; } public function getCategoryLink($item) { return urldecode(JRoute::_(K2HelperRoute::getCategoryRoute($item->catid.':'.urlencode($item->categoryalias))) . $this->getMenuItemId()); } public function getImage($item) { return XEFUtility::getK2Images($item->id, $item->title, $item->introtext); } public function getDate($item) { return JHTML::_('date',$item->created, JText::_('DATE_FORMAT_LC3')); } }PK 唘\�V� k2/index.htmlnu &1i� <!DOCTYPE html><title></title> PK 唘\�V� module/index.htmlnu &1i� <!DOCTYPE html><title></title> PK 唘\9ǩ=8 8 module/module.phpnu &1i� <?php /** * @package ThemeXpert Extension Framework (XEF) * @copyright Copyright (c)2010-2012 ThemeXpert.com * @license GNU General Public License version 3, or later **/ // Protect from unauthorized access defined('_JEXEC') or die(); // Require XEF helper class require_once JPATH_LIBRARIES . '/xef/xef.php'; class XEFSourceModule extends XEFHelper { public function getItems() { //module specific $mods = $this->get('modules'); $options = array('style' => 'none'); $items = array(); for ($i=0;$i<count($mods);$i++) { if( $this->getModule($mods[$i]) !== NULL ) { $items[$i] = new stdClass(); $items[$i]->order = $this->getModule($mods[$i])->ordering; $items[$i]->title = $this->getModule($mods[$i])->title; $items[$i]->content = $items[$i]->introtext = JModuleHelper::renderModule( $this->getModule($mods[$i]), $options); } } return $items; } //fetch module by id public function getModule( $id ){ $db = JFactory::getDBO(); $where = ' AND ( m.id='.$id.' ) '; $query = 'SELECT *'. ' FROM #__modules AS m'. ' WHERE m.client_id = 0'. $where. ' ORDER BY ordering'. ' LIMIT 1'; $db->setQuery( $query ); $module = $db->loadObject(); if (!$module) return NULL; $file = $module->module; $custom = substr($file, 0, 4) == 'mod_' ? 0 : 1; $module->user = $custom; $module->name = $custom ? $module->title : substr($file, 4); $module->style = null; $module->position = strtolower($module->position); $clean[$module->id] = $module; return $module; } }PK 唘\�V� instagram/index.htmlnu &1i� <!DOCTYPE html><title></title> PK 唘\ox� flickr/flickr.phpnu &1i� <?php /** * @package ThemeXpert Extension Framework (XEF) * @copyright Copyright (c)2010-2012 ThemeXpert.com * @license GNU General Public License version 3, or later **/ // Protect from unauthorized access defined('_JEXEC') or die(); // Require XEF helper class require_once JPATH_LIBRARIES . '/xef/xef.php'; class XEFSourceFlickr extends XEFHelper { public function getItems() { jimport('joomla.filesystem.folder'); $api_key = '2a4dbf07ad5341b2b06d60c91d44e918'; $cache_path = JPATH_ROOT. '/cache/test/flickr'; $nsid = ''; $photos = array(); // create cache folder if not exist JFolder::create($cache_path, 0755); if( !class_exists('phpFlickr')) { require_once 'api/phpFlickr.php'; } $f = new phpFlickr($api_key); $f->enableCache('fs',$cache_path, $this->get('cache_time')); //enable caching if($this->get('flickr_search_from') == 'user') { $username = $this->get('flickr_search_from'); if($username != NULL) { $person = $f->people_findByUsername($username); $nsid = $person['id']; }else{ return ''; } $photos = $f->people_getPublicPhotos($nsid, NULL, NULL, $this->get('item_count')); $source = $photos['photos']['photo']; } if( $this->get('flickr_search_from') == 'tags' OR $this->get('flickr_search_from') == 'text') { $tags = $this->get('flickr_attrs'); if(!empty($tags)) { $attrs = ''; if($this->get('flickr_search_from') == 'tags') $attrs = 'tags'; if($this->get('flickr_search_from') == 'text') $attrs = 'text'; $photos = $f->photos_search(array($attrs=>$tags,'per_page'=>$this->get('item_count'))); $source = $photos['photo']; }else{ return ''; } } if($this->get('flickr_search_from') == 'recent'){ $photos = $f->photos_getRecent( NULL, $this->get('item_count') ); $source = $photos['photo']; } //$extras = 'description,date_upload,owner_name,tags'; $items = array(); $i = 0; if(count($source)>0){ foreach ($source as $photo) { $id = $photo['id']; $obj = new stdClass(); $info = $f->photos_getInfo($id); $nsid = $info['owner']['username']; $obj->title = $info['title']; $obj->image = $f->buildPhotoURL($photo,'_b'); $obj->link = $info['urls']['url'][0]['_content']; $obj->introtext = $info['description']; $obj->date = date('Y.M.d : H:i:s A', $info['dateuploaded']); $items[$i] = $obj; $i++; } } //return $items; var_dump($f); } public function getLink($item) { return $item->link; } public function getImage($item) { return $item->image; } public function getDate($item) { return $item->date; } public function getCategory($item) { return ; } public function getCategoryLink($item) { return; } } PK 唘\����� �� flickr/api/PEAR/DB/pgsql.phpnu &1i� <?php /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ /** * The PEAR DB driver for PHP's pgsql extension * for interacting with PostgreSQL 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 Rui Hirokawa <hirokawa@php.net> * @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: pgsql.php 32 2005-08-01 06:21:02Z dancoulter $ * @link http://pear.php.net/package/DB */ // no direct access defined('_JEXEC') or die('Restricted accessd'); /** * 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 pgsql extension * for interacting with PostgreSQL databases * * These methods overload the ones declared in DB_common. * * @category Database * @package DB * @author Rui Hirokawa <hirokawa@php.net> * @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: @package_version@ * @link http://pear.php.net/package/DB */ class DB_pgsql extends DB_common { // {{{ properties /** * The DB driver type (mysql, oci8, odbc, etc.) * @var string */ var $phptype = 'pgsql'; /** * The database syntax variant to be used (db2, access, etc.), if any * @var string */ var $dbsyntax = 'pgsql'; /** * 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' => '4.3.0', 'numrows' => true, 'pconnect' => true, 'prepare' => false, 'ssl' => true, '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 number of rows affected by a data manipulation query * @var integer */ var $affected = 0; /** * The current row being looked at in fetchInto() * @var array * @access private */ var $row = array(); /** * The number of rows in a given result set * @var array * @access private */ var $_num_rows = array(); // }}} // {{{ constructor /** * This constructor calls <kbd>$this->DB_common()</kbd> * * @return void */ function DB_pgsql() { $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 pgsql driver supports the following extra DSN options: * + connect_timeout How many seconds to wait for a connection to * be established. Available since PEAR DB 1.7.0. * + new_link If set to true, causes subsequent calls to * connect() to return a new connection link * instead of the existing one. WARNING: this is * not portable to other DBMS's. Available only * if PHP is >= 4.3.0 and PEAR DB is >= 1.7.0. * + options Command line options to be sent to the server. * Available since PEAR DB 1.6.4. * + service Specifies a service name in pg_service.conf that * holds additional connection parameters. * Available since PEAR DB 1.7.0. * + sslmode How should SSL be used when connecting? Values: * disable, allow, prefer or require. * Available since PEAR DB 1.7.0. * + tty This was used to specify where to send server * debug output. Available since PEAR DB 1.6.4. * * Example of connecting to a new link via a socket: * <code> * require_once 'DB.php'; * * $dsn = 'pgsql://user:pass@unix(/tmp)/dbname?new_link=true'; * $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. * * @link http://www.postgresql.org/docs/current/static/libpq.html#LIBPQ-CONNECT */ function connect($dsn, $persistent = false) { if (!PEAR::loadExtension('pgsql')) { return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); } $this->dsn = $dsn; if ($dsn['dbsyntax']) { $this->dbsyntax = $dsn['dbsyntax']; } $protocol = $dsn['protocol'] ? $dsn['protocol'] : 'tcp'; $params = array(''); if ($protocol == 'tcp') { if ($dsn['hostspec']) { $params[0] .= 'host=' . $dsn['hostspec']; } if ($dsn['port']) { $params[0] .= ' port=' . $dsn['port']; } } elseif ($protocol == 'unix') { // Allow for pg socket in non-standard locations. if ($dsn['socket']) { $params[0] .= 'host=' . $dsn['socket']; } if ($dsn['port']) { $params[0] .= ' port=' . $dsn['port']; } } if ($dsn['database']) { $params[0] .= ' dbname=\'' . addslashes($dsn['database']) . '\''; } if ($dsn['username']) { $params[0] .= ' user=\'' . addslashes($dsn['username']) . '\''; } if ($dsn['password']) { $params[0] .= ' password=\'' . addslashes($dsn['password']) . '\''; } if (!empty($dsn['options'])) { $params[0] .= ' options=' . $dsn['options']; } if (!empty($dsn['tty'])) { $params[0] .= ' tty=' . $dsn['tty']; } if (!empty($dsn['connect_timeout'])) { $params[0] .= ' connect_timeout=' . $dsn['connect_timeout']; } if (!empty($dsn['sslmode'])) { $params[0] .= ' sslmode=' . $dsn['sslmode']; } if (!empty($dsn['service'])) { $params[0] .= ' service=' . $dsn['service']; } if (isset($dsn['new_link']) && ($dsn['new_link'] == 'true' || $dsn['new_link'] === true)) { if (version_compare(phpversion(), '4.3.0', '>=')) { $params[] = PGSQL_CONNECT_FORCE_NEW; } } $connect_function = $persistent ? 'pg_pconnect' : 'pg_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); } return DB_OK; } // }}} // {{{ disconnect() /** * Disconnects from the database server * * @return bool TRUE on success, FALSE on failure */ function disconnect() { $ret = @pg_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; $query = $this->modifyQuery($query); if (!$this->autocommit && $ismanip) { if ($this->transaction_opcount == 0) { $result = @pg_exec($this->connection, 'begin;'); if (!$result) { return $this->pgsqlRaiseError(); } } $this->transaction_opcount++; } $result = @pg_exec($this->connection, $query); if (!$result) { return $this->pgsqlRaiseError(); } // Determine which queries that should return data, and which // should return an error code only. if ($ismanip) { $this->affected = @pg_affected_rows($result); return DB_OK; } elseif (preg_match('/^\s*\(*\s*(SELECT|EXPLAIN|SHOW)\s/si', $query)) { /* PostgreSQL commands: ABORT, ALTER, BEGIN, CLOSE, CLUSTER, COMMIT, COPY, CREATE, DECLARE, DELETE, DROP TABLE, EXPLAIN, FETCH, GRANT, INSERT, LISTEN, LOAD, LOCK, MOVE, NOTIFY, RESET, REVOKE, ROLLBACK, SELECT, SELECT INTO, SET, SHOW, UNLISTEN, UPDATE, VACUUM */ $this->row[(int)$result] = 0; // reset the row counter. $numrows = $this->numRows($result); if (is_object($numrows)) { return $numrows; } $this->_num_rows[(int)$result] = $numrows; $this->affected = 0; return $result; } else { $this->affected = 0; return DB_OK; } } // }}} // {{{ nextResult() /** * Move the internal pgsql result pointer to the next available result * * @param a valid fbsql result resource * * @access public * * @return true if a result is available otherwise return false */ function nextResult($result) { return false; } // }}} // {{{ 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) { $result_int = (int)$result; $rownum = ($rownum !== null) ? $rownum : $this->row[$result_int]; if ($rownum >= $this->_num_rows[$result_int]) { return null; } if ($fetchmode & DB_FETCHMODE_ASSOC) { $arr = @pg_fetch_array($result, $rownum, PGSQL_ASSOC); if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) { $arr = array_change_key_case($arr, CASE_LOWER); } } else { $arr = @pg_fetch_row($result, $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); } $this->row[$result_int] = ++$rownum; 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) { if (is_resource($result)) { unset($this->row[(int)$result]); unset($this->_num_rows[(int)$result]); $this->affected = 0; return @pg_freeresult($result); } return false; } // }}} // {{{ quote() /** * @deprecated Deprecated in release 1.6.0 * @internal */ function quote($str) { return $this->quoteSmart($str); } // }}} // {{{ 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 MySQL'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) . "'"; } } // }}} // {{{ escapeSimple() /** * Escapes a string according to the current DBMS's standards * * {@internal PostgreSQL treats a backslash as an escape character, * so they are escaped as well. * * Not using pg_escape_string() yet because it requires PostgreSQL * to be at version 7.2 or greater.}} * * @param string $str the string to be escaped * * @return string the escaped string * * @see DB_common::quoteSmart() * @since Method available since Release 1.6.0 */ function escapeSimple($str) { return str_replace("'", "''", str_replace('\\', '\\\\', $str)); } // }}} // {{{ 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 = @pg_numfields($result); if (!$cols) { return $this->pgsqlRaiseError(); } 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 = @pg_numrows($result); if ($rows === null) { return $this->pgsqlRaiseError(); } 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) { // (disabled) hack to shut up error messages from libpq.a //@fclose(@fopen("php://stderr", "w")); $result = @pg_exec($this->connection, 'end;'); $this->transaction_opcount = 0; if (!$result) { return $this->pgsqlRaiseError(); } } return DB_OK; } // }}} // {{{ rollback() /** * Reverts the current transaction * * @return int DB_OK on success. A DB_Error object on failure. */ function rollback() { if ($this->transaction_opcount > 0) { $result = @pg_exec($this->connection, 'abort;'); $this->transaction_opcount = 0; if (!$result) { return $this->pgsqlRaiseError(); } } return DB_OK; } // }}} // {{{ affectedRows() /** * 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 $this->affected; } // }}} // {{{ 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_pgsql::createSequence(), DB_pgsql::dropSequence() */ function nextId($seq_name, $ondemand = true) { $seqname = $this->getSequenceName($seq_name); $repeat = false; do { $this->pushErrorHandling(PEAR_ERROR_RETURN); $result =& $this->query("SELECT NEXTVAL('${seqname}')"); $this->popErrorHandling(); if ($ondemand && DB::isError($result) && $result->getCode() == DB_ERROR_NOSUCHTABLE) { $repeat = 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 * * @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_pgsql::nextID(), DB_pgsql::dropSequence() */ function createSequence($seq_name) { $seqname = $this->getSequenceName($seq_name); $result = $this->query("CREATE SEQUENCE ${seqname}"); return $result; } // }}} // {{{ 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_pgsql::nextID(), DB_pgsql::createSequence() */ function dropSequence($seq_name) { return $this->query('DROP SEQUENCE ' . $this->getSequenceName($seq_name)); } // }}} // {{{ 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"; } // }}} // {{{ pgsqlRaiseError() /** * 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_pgsql::errorNative(), DB_pgsql::errorCode() */ function pgsqlRaiseError($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 * * {@internal Error messages are used instead of error codes * in order to support older versions of PostgreSQL.}} * * @return string the DBMS' error message */ function errorNative() { return @pg_errormessage($this->connection); } // }}} // {{{ 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( '/(relation|sequence|table).*does not exist|class .* not found/i' => DB_ERROR_NOSUCHTABLE, '/index .* does not exist/' => DB_ERROR_NOT_FOUND, '/column .* does not exist/i' => DB_ERROR_NOSUCHFIELD, '/relation .* already exists/i' => DB_ERROR_ALREADY_EXISTS, '/(divide|division) by zero$/i' => DB_ERROR_DIVZERO, '/pg_atoi: error in .*: can\'t parse /i' => DB_ERROR_INVALID_NUMBER, '/invalid input syntax for( type)? (integer|numeric)/i' => DB_ERROR_INVALID_NUMBER, '/value .* is out of range for type \w*int/i' => DB_ERROR_INVALID_NUMBER, '/integer out of range/i' => DB_ERROR_INVALID_NUMBER, '/value too long for type character/i' => DB_ERROR_INVALID, '/attribute .* not found|relation .* does not have attribute/i' => DB_ERROR_NOSUCHFIELD, '/column .* specified in USING clause does not exist in (left|right) table/i' => DB_ERROR_NOSUCHFIELD, '/parser: parse error at or near/i' => DB_ERROR_SYNTAX, '/syntax error at/' => DB_ERROR_SYNTAX, '/column reference .* is ambiguous/i' => DB_ERROR_SYNTAX, '/permission denied/' => DB_ERROR_ACCESS_VIOLATION, '/violates not-null constraint/' => DB_ERROR_CONSTRAINT_NOT_NULL, '/violates [\w ]+ constraint/' => DB_ERROR_CONSTRAINT, '/referential integrity violation/' => DB_ERROR_CONSTRAINT, '/more expressions than target 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 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. */ $id = @pg_exec($this->connection, "SELECT * FROM $result LIMIT 0"); $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->pgsqlRaiseError(DB_ERROR_NEED_MORE_DATA); } if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { $case_func = 'strtolower'; } else { $case_func = 'strval'; } $count = @pg_numfields($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(@pg_fieldname($id, $i)), 'type' => @pg_fieldtype($id, $i), 'len' => @pg_fieldsize($id, $i), 'flags' => $got_string ? $this->_pgFieldFlags($id, $i, $result) : '', ); if ($mode & DB_TABLEINFO_ORDER) { $res['order'][$res[$i]['name']] = $i; } if ($mode & DB_TABLEINFO_ORDERTABLE) { $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; } } // free the result only if we were called on a table if ($got_string) { @pg_freeresult($id); } return $res; } // }}} // {{{ _pgFieldFlags() /** * Get a column's flags * * Supports "not_null", "default_value", "primary_key", "unique_key" * and "multiple_key". The default value is passed through * rawurlencode() in case there are spaces in it. * * @param int $resource the PostgreSQL result identifier * @param int $num_field the field number * * @return string the flags * * @access private */ function _pgFieldFlags($resource, $num_field, $table_name) { $field_name = @pg_fieldname($resource, $num_field); $result = @pg_exec($this->connection, "SELECT f.attnotnull, f.atthasdef FROM pg_attribute f, pg_class tab, pg_type typ WHERE tab.relname = typ.typname AND typ.typrelid = f.attrelid AND f.attname = '$field_name' AND tab.relname = '$table_name'"); if (@pg_numrows($result) > 0) { $row = @pg_fetch_row($result, 0); $flags = ($row[0] == 't') ? 'not_null ' : ''; if ($row[1] == 't') { $result = @pg_exec($this->connection, "SELECT a.adsrc FROM pg_attribute f, pg_class tab, pg_type typ, pg_attrdef a WHERE tab.relname = typ.typname AND typ.typrelid = f.attrelid AND f.attrelid = a.adrelid AND f.attname = '$field_name' AND tab.relname = '$table_name' AND f.attnum = a.adnum"); $row = @pg_fetch_row($result, 0); $num = preg_replace("/'(.*)'::\w+/", "\\1", $row[0]); $flags .= 'default_' . rawurlencode($num) . ' '; } } else { $flags = ''; } $result = @pg_exec($this->connection, "SELECT i.indisunique, i.indisprimary, i.indkey FROM pg_attribute f, pg_class tab, pg_type typ, pg_index i WHERE tab.relname = typ.typname AND typ.typrelid = f.attrelid AND f.attrelid = i.indrelid AND f.attname = '$field_name' AND tab.relname = '$table_name'"); $count = @pg_numrows($result); for ($i = 0; $i < $count ; $i++) { $row = @pg_fetch_row($result, $i); $keys = explode(' ', $row[2]); if (in_array($num_field + 1, $keys)) { $flags .= ($row[0] == 't' && $row[1] == 'f') ? 'unique_key ' : ''; $flags .= ($row[1] == 't') ? 'primary_key ' : ''; if (count($keys) > 1) $flags .= 'multiple_key '; } } return trim($flags); } // }}} // {{{ 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 c.relname AS "Name"' . ' FROM pg_class c, pg_user u' . ' WHERE c.relowner = u.usesysid' . " AND c.relkind = 'r'" . ' AND NOT EXISTS' . ' (SELECT 1 FROM pg_views' . ' WHERE viewname = c.relname)' . " AND c.relname !~ '^(pg_|sql_)'" . ' UNION' . ' SELECT c.relname AS "Name"' . ' FROM pg_class c' . " WHERE c.relkind = 'r'" . ' AND NOT EXISTS' . ' (SELECT 1 FROM pg_views' . ' WHERE viewname = c.relname)' . ' AND NOT EXISTS' . ' (SELECT 1 FROM pg_user' . ' WHERE usesysid = c.relowner)' . " AND c.relname !~ '^pg_'"; case 'schema.tables': return "SELECT schemaname || '.' || tablename" . ' AS "Name"' . ' FROM pg_catalog.pg_tables' . ' WHERE schemaname NOT IN' . " ('pg_catalog', 'information_schema', 'pg_toast')"; case 'views': // Table cols: viewname | viewowner | definition return 'SELECT viewname from pg_views WHERE schemaname' . " NOT IN ('information_schema', 'pg_catalog')"; case 'users': // cols: usename |usesysid|usecreatedb|usetrace|usesuper|usecatupd|passwd |valuntil return 'SELECT usename FROM pg_user'; case 'databases': return 'SELECT datname FROM pg_database'; case 'functions': case 'procedures': return 'SELECT proname FROM pg_proc WHERE proowner <> 1'; default: return null; } } // }}} } /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: */ ?> PK 唘\�#o, , flickr/api/PEAR/DB/index.htmlnu &1i� <html><body bgcolor="#FFFFFF"></body></html>PK 唘\�Y(�s~ s~ flickr/api/PEAR/DB/mysql.phpnu &1i� <?php /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ /** * The PEAR DB driver for PHP's mysql extension * for interacting with MySQL 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 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: mysql.php 32 2005-08-01 06:21:02Z dancoulter $ * @link http://pear.php.net/package/DB */ // no direct access defined('_JEXEC') or die('Restricted accessd'); /** * 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 mysql extension * for interacting with MySQL databases * * These methods overload the ones declared in DB_common. * * @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: @package_version@ * @link http://pear.php.net/package/DB */ class DB_mysql extends DB_common { // {{{ properties /** * The DB driver type (mysql, oci8, odbc, etc.) * @var string */ var $phptype = 'mysql'; /** * The database syntax variant to be used (db2, access, etc.), if any * @var string */ var $dbsyntax = 'mysql'; /** * 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' => '4.2.0', '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( 1004 => DB_ERROR_CANNOT_CREATE, 1005 => DB_ERROR_CANNOT_CREATE, 1006 => DB_ERROR_CANNOT_CREATE, 1007 => DB_ERROR_ALREADY_EXISTS, 1008 => DB_ERROR_CANNOT_DROP, 1022 => DB_ERROR_ALREADY_EXISTS, 1044 => DB_ERROR_ACCESS_VIOLATION, 1046 => DB_ERROR_NODBSELECTED, 1048 => DB_ERROR_CONSTRAINT, 1049 => DB_ERROR_NOSUCHDB, 1050 => DB_ERROR_ALREADY_EXISTS, 1051 => DB_ERROR_NOSUCHTABLE, 1054 => DB_ERROR_NOSUCHFIELD, 1061 => DB_ERROR_ALREADY_EXISTS, 1062 => DB_ERROR_ALREADY_EXISTS, 1064 => DB_ERROR_SYNTAX, 1091 => DB_ERROR_NOT_FOUND, 1100 => DB_ERROR_NOT_LOCKED, 1136 => DB_ERROR_VALUE_COUNT_ON_ROW, 1142 => DB_ERROR_ACCESS_VIOLATION, 1146 => DB_ERROR_NOSUCHTABLE, 1216 => DB_ERROR_CONSTRAINT, 1217 => 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(); /** * 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_mysql() { $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 mysql driver supports the following extra DSN options: * + new_link If set to true, causes subsequent calls to connect() * to return a new connection link instead of the * existing one. WARNING: this is not portable to * other DBMS's. Available since PEAR DB 1.7.0. * + client_flags Any combination of MYSQL_CLIENT_* constants. * Only used if PHP is at version 4.3.0 or greater. * 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('mysql')) { return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); } $this->dsn = $dsn; if ($dsn['dbsyntax']) { $this->dbsyntax = $dsn['dbsyntax']; } $params = array(); if ($dsn['protocol'] && $dsn['protocol'] == 'unix') { $params[0] = ':' . $dsn['socket']; } else { $params[0] = $dsn['hostspec'] ? $dsn['hostspec'] : 'localhost'; if ($dsn['port']) { $params[0] .= ':' . $dsn['port']; } } $params[] = $dsn['username'] ? $dsn['username'] : null; $params[] = $dsn['password'] ? $dsn['password'] : null; if (!$persistent) { if (isset($dsn['new_link']) && ($dsn['new_link'] == 'true' || $dsn['new_link'] === true)) { $params[] = true; } else { $params[] = false; } } if (version_compare(phpversion(), '4.3.0', '>=')) { $params[] = isset($dsn['client_flags']) ? $dsn['client_flags'] : null; } $connect_function = $persistent ? 'mysql_pconnect' : 'mysql_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 = @mysql_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 ($dsn['database']) { if (!@mysql_select_db($dsn['database'], $this->connection)) { return $this->mysqlRaiseError(); } $this->_db = $dsn['database']; } return DB_OK; } // }}} // {{{ disconnect() /** * Disconnects from the database server * * @return bool TRUE on success, FALSE on failure */ function disconnect() { $ret = @mysql_close($this->connection); $this->connection = null; return $ret; } // }}} // {{{ simpleQuery() /** * Sends a query to the database server * * Generally uses mysql_query(). If you want to use * mysql_unbuffered_query() set the "result_buffering" option to 0 using * setOptions(). This option was added in Release 1.7.0. * * @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); if ($this->_db) { if (!@mysql_select_db($this->_db, $this->connection)) { return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED); } } if (!$this->autocommit && $ismanip) { if ($this->transaction_opcount == 0) { $result = @mysql_query('SET AUTOCOMMIT=0', $this->connection); $result = @mysql_query('BEGIN', $this->connection); if (!$result) { return $this->mysqlRaiseError(); } } $this->transaction_opcount++; } if (!$this->options['result_buffering']) { $result = @mysql_unbuffered_query($query, $this->connection); } else { $result = @mysql_query($query, $this->connection); } if (!$result) { return $this->mysqlRaiseError(); } if (is_resource($result)) { return $result; } return DB_OK; } // }}} // {{{ nextResult() /** * Move the internal mysql result pointer to the next available result * * This method has not been implemented yet. * * @param a valid sql result resource * * @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 (!@mysql_data_seek($result, $rownum)) { return null; } } if ($fetchmode & DB_FETCHMODE_ASSOC) { $arr = @mysql_fetch_array($result, MYSQL_ASSOC); if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) { $arr = array_change_key_case($arr, CASE_LOWER); } } else { $arr = @mysql_fetch_row($result); } 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) { return @mysql_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 = @mysql_num_fields($result); if (!$cols) { return $this->mysqlRaiseError(); } 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 = @mysql_num_rows($result); if ($rows === null) { return $this->mysqlRaiseError(); } 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 ($this->_db) { if (!@mysql_select_db($this->_db, $this->connection)) { return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED); } } $result = @mysql_query('COMMIT', $this->connection); $result = @mysql_query('SET AUTOCOMMIT=1', $this->connection); $this->transaction_opcount = 0; if (!$result) { return $this->mysqlRaiseError(); } } return DB_OK; } // }}} // {{{ rollback() /** * Reverts the current transaction * * @return int DB_OK on success. A DB_Error object on failure. */ function rollback() { if ($this->transaction_opcount > 0) { if ($this->_db) { if (!@mysql_select_db($this->_db, $this->connection)) { return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED); } } $result = @mysql_query('ROLLBACK', $this->connection); $result = @mysql_query('SET AUTOCOMMIT=1', $this->connection); $this->transaction_opcount = 0; if (!$result) { return $this->mysqlRaiseError(); } } return DB_OK; } // }}} // {{{ affectedRows() /** * 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 @mysql_affected_rows($this->connection); } else { return 0; } } // }}} // {{{ 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_mysql::createSequence(), DB_mysql::dropSequence() */ function nextId($seq_name, $ondemand = true) { $seqname = $this->getSequenceName($seq_name); do { $repeat = 0; $this->pushErrorHandling(PEAR_ERROR_RETURN); $result = $this->query("UPDATE ${seqname} ". 'SET id=LAST_INSERT_ID(id+1)'); $this->popErrorHandling(); if ($result === DB_OK) { // COMMON CASE $id = @mysql_insert_id($this->connection); if ($id != 0) { return $id; } // EMPTY SEQ TABLE // Sequence table must be empty for some reason, so fill // it and return 1 and obtain a user-level lock $result = $this->getOne("SELECT GET_LOCK('${seqname}_lock',10)"); if (DB::isError($result)) { return $this->raiseError($result); } if ($result == 0) { // Failed to get the lock return $this->mysqlRaiseError(DB_ERROR_NOT_LOCKED); } // add the default value $result = $this->query("REPLACE INTO ${seqname} (id) VALUES (0)"); if (DB::isError($result)) { return $this->raiseError($result); } // Release the lock $result = $this->getOne('SELECT RELEASE_LOCK(' . "'${seqname}_lock')"); if (DB::isError($result)) { return $this->raiseError($result); } // We know what the result will be, so no need to try again return 1; } elseif ($ondemand && DB::isError($result) && $result->getCode() == DB_ERROR_NOSUCHTABLE) { // ONDEMAND TABLE CREATION $result = $this->createSequence($seq_name); if (DB::isError($result)) { return $this->raiseError($result); } else { $repeat = 1; } } elseif (DB::isError($result) && $result->getCode() == DB_ERROR_ALREADY_EXISTS) { // BACKWARDS COMPAT // see _BCsequence() comment $result = $this->_BCsequence($seqname); if (DB::isError($result)) { return $this->raiseError($result); } $repeat = 1; } } while ($repeat); return $this->raiseError($result); } // }}} // {{{ createSequence() /** * 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_mysql::nextID(), DB_mysql::dropSequence() */ function createSequence($seq_name) { $seqname = $this->getSequenceName($seq_name); $res = $this->query('CREATE TABLE ' . $seqname . ' (id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL,' . ' PRIMARY KEY(id))'); if (DB::isError($res)) { return $res; } // insert yields value 1, nextId call will generate ID 2 $res = $this->query("INSERT INTO ${seqname} (id) VALUES (0)"); if (DB::isError($res)) { return $res; } // so reset to zero return $this->query("UPDATE ${seqname} SET id = 0"); } // }}} // {{{ 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_mysql::nextID(), DB_mysql::createSequence() */ function dropSequence($seq_name) { return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name)); } // }}} // {{{ _BCsequence() /** * Backwards compatibility with old sequence emulation implementation * (clean up the dupes) * * @param string $seqname the sequence name to clean up * * @return bool true on success. A DB_Error object on failure. * * @access private */ function _BCsequence($seqname) { // Obtain a user-level lock... this will release any previous // application locks, but unlike LOCK TABLES, it does not abort // the current transaction and is much less frequently used. $result = $this->getOne("SELECT GET_LOCK('${seqname}_lock',10)"); if (DB::isError($result)) { return $result; } if ($result == 0) { // Failed to get the lock, can't do the conversion, bail // with a DB_ERROR_NOT_LOCKED error return $this->mysqlRaiseError(DB_ERROR_NOT_LOCKED); } $highest_id = $this->getOne("SELECT MAX(id) FROM ${seqname}"); if (DB::isError($highest_id)) { return $highest_id; } // This should kill all rows except the highest // We should probably do something if $highest_id isn't // numeric, but I'm at a loss as how to handle that... $result = $this->query('DELETE FROM ' . $seqname . " WHERE id <> $highest_id"); if (DB::isError($result)) { return $result; } // If another thread has been waiting for this lock, // it will go thru the above procedure, but will have no // real effect $result = $this->getOne("SELECT RELEASE_LOCK('${seqname}_lock')"); if (DB::isError($result)) { return $result; } return true; } // }}} // {{{ quoteIdentifier() /** * Quotes a string so it can be safely used as a table or column name * * MySQL can't handle the backtick character (<kbd>`</kbd>) in * table or column names. * * @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 . '`'; } // }}} // {{{ quote() /** * @deprecated Deprecated in release 1.6.0 */ function quote($str) { return $this->quoteSmart($str); } // }}} // {{{ 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.6.0 */ function escapeSimple($str) { if (function_exists('mysql_real_escape_string')) { return @mysql_real_escape_string($str, $this->connection); } else { return @mysql_escape_string($str); } } // }}} // {{{ 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) { // "DELETE FROM table" gives 0 affected rows in MySQL. // This little hack lets you know how many rows were deleted. if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $query)) { $query = preg_replace('/^\s*DELETE\s+FROM\s+(\S+)\s*$/', 'DELETE FROM \1 WHERE 1=1', $query); } } return $query; } // }}} // {{{ modifyLimitQuery() /** * 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 $query . " LIMIT $count"; } else { return $query . " LIMIT $from, $count"; } } // }}} // {{{ mysqlRaiseError() /** * 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_mysql::errorNative(), DB_common::errorCode() */ function mysqlRaiseError($errno = null) { if ($errno === null) { if ($this->options['portability'] & DB_PORTABILITY_ERRORS) { $this->errorcode_map[1022] = DB_ERROR_CONSTRAINT; $this->errorcode_map[1048] = DB_ERROR_CONSTRAINT_NOT_NULL; $this->errorcode_map[1062] = DB_ERROR_CONSTRAINT; } else { // Doing this in case mode changes during runtime. $this->errorcode_map[1022] = DB_ERROR_ALREADY_EXISTS; $this->errorcode_map[1048] = DB_ERROR_CONSTRAINT; $this->errorcode_map[1062] = DB_ERROR_ALREADY_EXISTS; } $errno = $this->errorCode(mysql_errno($this->connection)); } return $this->raiseError($errno, null, null, null, @mysql_errno($this->connection) . ' ** ' . @mysql_error($this->connection)); } // }}} // {{{ errorNative() /** * Gets the DBMS' native error code produced by the last query * * @return int the DBMS' error code */ function errorNative() { return @mysql_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 = @mysql_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->mysqlRaiseError(DB_ERROR_NEED_MORE_DATA); } if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { $case_func = 'strtolower'; } else { $case_func = 'strval'; } $count = @mysql_num_fields($id); $res = array(); if ($mode) { $res['num_fields'] = $count; } for ($i = 0; $i < $count; $i++) { $res[$i] = array( 'table' => $case_func(@mysql_field_table($id, $i)), 'name' => $case_func(@mysql_field_name($id, $i)), 'type' => @mysql_field_type($id, $i), 'len' => @mysql_field_len($id, $i), 'flags' => @mysql_field_flags($id, $i), ); if ($mode & DB_TABLEINFO_ORDER) { $res['order'][$res[$i]['name']] = $i; } if ($mode & DB_TABLEINFO_ORDERTABLE) { $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; } } // free the result only if we were called on a table if ($got_string) { @mysql_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 'SHOW TABLES'; case 'users': return 'SELECT DISTINCT User FROM mysql.user'; case 'databases': return 'SHOW DATABASES'; default: return null; } } // }}} } /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: */ ?> PK 唘\���=Q: Q: flickr/api/PEAR/DB/storage.phpnu &1i� <?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 32 2005-08-01 06:21:02Z dancoulter $ * @link http://pear.php.net/package/DB */ // no direct access defined('_JEXEC') or die('Restricted accessd'); /** * 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: @package_version@ * @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: */ ?> PK 唘\ZO� � flickr/api/PEAR/DB/common.phpnu &1i� <?php /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ /** * Contains the DB_common base class * * 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 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: common.php 32 2005-08-01 06:21:02Z dancoulter $ * @link http://pear.php.net/package/DB */ // no direct access defined('_JEXEC') or die('Restricted accessd'); /** * Obtain the PEAR class so it can be extended from */ require_once 'PEAR.php'; /** * DB_common is the base class from which each database driver class extends * * All common methods are declared here. If a given DBMS driver contains * a particular method, that method will overload the one here. * * @category Database * @package DB * @author Stig Bakken <ssb@php.net> * @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: @package_version@ * @link http://pear.php.net/package/DB */ class DB_common extends PEAR { // {{{ properties /** * The current default fetch mode * @var integer */ var $fetchmode = DB_FETCHMODE_ORDERED; /** * The name of the class into which results should be fetched when * DB_FETCHMODE_OBJECT is in effect * * @var string */ var $fetchmode_object_class = 'stdClass'; /** * Was a connection present when the object was serialized()? * @var bool * @see DB_common::__sleep(), DB_common::__wake() */ var $was_connected = null; /** * The most recently executed query * @var string */ var $last_query = ''; /** * Run-time configuration options * * The 'optimize' option has been deprecated. Use the 'portability' * option instead. * * @var array * @see DB_common::setOption() */ var $options = array( 'result_buffering' => 500, 'persistent' => false, 'ssl' => false, 'debug' => 0, 'seqname_format' => '%s_seq', 'autofree' => false, 'portability' => DB_PORTABILITY_NONE, 'optimize' => 'performance', // Deprecated. Use 'portability'. ); /** * The parameters from the most recently executed query * @var array * @since Property available since Release 1.7.0 */ var $last_parameters = array(); /** * The elements from each prepared statement * @var array */ var $prepare_tokens = array(); /** * The data types of the various elements in each prepared statement * @var array */ var $prepare_types = array(); /** * The prepared queries * @var array */ var $prepared_queries = array(); // }}} // {{{ DB_common /** * This constructor calls <kbd>$this->PEAR('DB_Error')</kbd> * * @return void */ function DB_common() { $this->PEAR('DB_Error'); } // }}} // {{{ __sleep() /** * Automatically indicates which properties should be saved * when PHP's serialize() function is called * * @return array the array of properties names that should be saved */ function __sleep() { if ($this->connection) { // Don't disconnect(), people use serialize() for many reasons $this->was_connected = true; } else { $this->was_connected = false; } if (isset($this->autocommit)) { return array('autocommit', 'dbsyntax', 'dsn', 'features', 'fetchmode', 'fetchmode_object_class', 'options', 'was_connected', ); } else { return array('dbsyntax', 'dsn', 'features', 'fetchmode', 'fetchmode_object_class', 'options', 'was_connected', ); } } // }}} // {{{ __wakeup() /** * Automatically reconnects to the database when PHP's unserialize() * function is called * * The reconnection attempt is only performed if the object was connected * at the time PHP's serialize() function was run. * * @return void */ function __wakeup() { if ($this->was_connected) { $this->connect($this->dsn, $this->options); } } // }}} // {{{ __toString() /** * Automatic string conversion for PHP 5 * * @return string a string describing the current PEAR DB object * * @since Method available since Release 1.7.0 */ function __toString() { $info = strtolower(get_class($this)); $info .= ': (phptype=' . $this->phptype . ', dbsyntax=' . $this->dbsyntax . ')'; if ($this->connection) { $info .= ' [connected]'; } return $info; } // }}} // {{{ toString() /** * DEPRECATED: String conversion method * * @return string a string describing the current PEAR DB object * * @deprecated Method deprecated in Release 1.7.0 */ function toString() { return $this->__toString(); } // }}} // {{{ quoteString() /** * DEPRECATED: Quotes a string so it can be safely used within string * delimiters in a query * * @param string $string the string to be quoted * * @return string the quoted string * * @see DB_common::quoteSmart(), DB_common::escapeSimple() * @deprecated Method deprecated some time before Release 1.2 */ function quoteString($string) { $string = $this->quote($string); if ($string{0} == "'") { return substr($string, 1, -1); } return $string; } // }}} // {{{ quote() /** * DEPRECATED: Quotes a string so it can be safely used in a query * * @param string $string the string to quote * * @return string the quoted string or the string <samp>NULL</samp> * if the value submitted is <kbd>null</kbd>. * * @see DB_common::quoteSmart(), DB_common::escapeSimple() * @deprecated Deprecated in release 1.6.0 */ function quote($string = null) { return ($string === null) ? 'NULL' : "'" . str_replace("'", "''", $string) . "'"; } // }}} // {{{ quoteIdentifier() /** * Quotes a string so it can be safely used as a table or column name * * Delimiting style depends on which database driver is being used. * * NOTE: just because you CAN use delimited identifiers doesn't mean * you SHOULD use them. In general, they end up causing way more * problems than they solve. * * Portability is broken by using the following characters inside * delimited identifiers: * + backtick (<kbd>`</kbd>) -- due to MySQL * + double quote (<kbd>"</kbd>) -- due to Oracle * + brackets (<kbd>[</kbd> or <kbd>]</kbd>) -- due to Access * * Delimited identifiers are known to generally work correctly under * the following drivers: * + mssql * + mysql * + mysqli * + oci8 * + odbc(access) * + odbc(db2) * + pgsql * + sqlite * + sybase (must execute <kbd>set quoted_identifier on</kbd> sometime * prior to use) * * InterBase doesn't seem to be able to use delimited identifiers * via PHP 4. They work fine under PHP 5. * * @param string $str the identifier name to be quoted * * @return string the quoted identifier * * @since Method available since Release 1.6.0 */ function quoteIdentifier($str) { return '"' . str_replace('"', '""', $str) . '"'; } // }}} // {{{ quoteSmart() /** * Formats input so it can be safely used in a query * * The output depends on the PHP data type of input and the database * type being used. * * @param mixed $in the data to be formatted * * @return mixed the formatted data. The format depends on the input's * PHP type: * <ul> * <li> * <kbd>input</kbd> -> <samp>returns</samp> * </li> * <li> * <kbd>null</kbd> -> the string <samp>NULL</samp> * </li> * <li> * <kbd>integer</kbd> or <kbd>double</kbd> -> the unquoted number * </li> * <li> * <kbd>bool</kbd> -> output depends on the driver in use * Most drivers return integers: <samp>1</samp> if * <kbd>true</kbd> or <samp>0</samp> if * <kbd>false</kbd>. * Some return strings: <samp>TRUE</samp> if * <kbd>true</kbd> or <samp>FALSE</samp> if * <kbd>false</kbd>. * Finally one returns strings: <samp>T</samp> if * <kbd>true</kbd> or <samp>F</samp> if * <kbd>false</kbd>. Here is a list of each DBMS, * the values returned and the suggested column type: * <ul> * <li> * <kbd>dbase</kbd> -> <samp>T/F</samp> * (<kbd>Logical</kbd>) * </li> * <li> * <kbd>fbase</kbd> -> <samp>TRUE/FALSE</samp> * (<kbd>BOOLEAN</kbd>) * </li> * <li> * <kbd>ibase</kbd> -> <samp>1/0</samp> * (<kbd>SMALLINT</kbd>) [1] * </li> * <li> * <kbd>ifx</kbd> -> <samp>1/0</samp> * (<kbd>SMALLINT</kbd>) [1] * </li> * <li> * <kbd>msql</kbd> -> <samp>1/0</samp> * (<kbd>INTEGER</kbd>) * </li> * <li> * <kbd>mssql</kbd> -> <samp>1/0</samp> * (<kbd>BIT</kbd>) * </li> * <li> * <kbd>mysql</kbd> -> <samp>1/0</samp> * (<kbd>TINYINT(1)</kbd>) * </li> * <li> * <kbd>mysqli</kbd> -> <samp>1/0</samp> * (<kbd>TINYINT(1)</kbd>) * </li> * <li> * <kbd>oci8</kbd> -> <samp>1/0</samp> * (<kbd>NUMBER(1)</kbd>) * </li> * <li> * <kbd>odbc</kbd> -> <samp>1/0</samp> * (<kbd>SMALLINT</kbd>) [1] * </li> * <li> * <kbd>pgsql</kbd> -> <samp>TRUE/FALSE</samp> * (<kbd>BOOLEAN</kbd>) * </li> * <li> * <kbd>sqlite</kbd> -> <samp>1/0</samp> * (<kbd>INTEGER</kbd>) * </li> * <li> * <kbd>sybase</kbd> -> <samp>1/0</samp> * (<kbd>TINYINT(1)</kbd>) * </li> * </ul> * [1] Accommodate the lowest common denominator because not all * versions of have <kbd>BOOLEAN</kbd>. * </li> * <li> * other (including strings and numeric strings) -> * the data with single quotes escaped by preceeding * single quotes, backslashes are escaped by preceeding * backslashes, then the whole string is encapsulated * between single quotes * </li> * </ul> * * @see DB_common::escapeSimple() * @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 ? 1 : 0; } elseif (is_null($in)) { return 'NULL'; } else { return "'" . $this->escapeSimple($in) . "'"; } } // }}} // {{{ 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 * * @see DB_common::quoteSmart() * @since Method available since Release 1.6.0 */ function escapeSimple($str) { return str_replace("'", "''", $str); } // }}} // {{{ provides() /** * Tells whether the present driver supports a given feature * * @param string $feature the feature you're curious about * * @return bool whether this driver supports $feature */ function provides($feature) { return $this->features[$feature]; } // }}} // {{{ setFetchMode() /** * Sets the fetch mode that should be used by default for query results * * @param integer $fetchmode DB_FETCHMODE_ORDERED, DB_FETCHMODE_ASSOC * or DB_FETCHMODE_OBJECT * @param string $object_class the class name of the object to be returned * by the fetch methods when the * DB_FETCHMODE_OBJECT mode is selected. * If no class is specified by default a cast * to object from the assoc array row will be * done. There is also the posibility to use * and extend the 'DB_row' class. * * @see DB_FETCHMODE_ORDERED, DB_FETCHMODE_ASSOC, DB_FETCHMODE_OBJECT */ function setFetchMode($fetchmode, $object_class = 'stdClass') { switch ($fetchmode) { case DB_FETCHMODE_OBJECT: $this->fetchmode_object_class = $object_class; case DB_FETCHMODE_ORDERED: case DB_FETCHMODE_ASSOC: $this->fetchmode = $fetchmode; break; default: return $this->raiseError('invalid fetchmode mode'); } } // }}} // {{{ setOption() /** * Sets run-time configuration options for PEAR DB * * Options, their data types, default values and description: * <ul> * <li> * <var>autofree</var> <kbd>boolean</kbd> = <samp>false</samp> * <br />should results be freed automatically when there are no * more rows? * </li><li> * <var>result_buffering</var> <kbd>integer</kbd> = <samp>500</samp> * <br />how many rows of the result set should be buffered? * <br />In mysql: mysql_unbuffered_query() is used instead of * mysql_query() if this value is 0. (Release 1.7.0) * <br />In oci8: this value is passed to ocisetprefetch(). * (Release 1.7.0) * </li><li> * <var>debug</var> <kbd>integer</kbd> = <samp>0</samp> * <br />debug level * </li><li> * <var>persistent</var> <kbd>boolean</kbd> = <samp>false</samp> * <br />should the connection be persistent? * </li><li> * <var>portability</var> <kbd>integer</kbd> = <samp>DB_PORTABILITY_NONE</samp> * <br />portability mode constant (see below) * </li><li> * <var>seqname_format</var> <kbd>string</kbd> = <samp>%s_seq</samp> * <br />the sprintf() format string used on sequence names. This * format is applied to sequence names passed to * createSequence(), nextID() and dropSequence(). * </li><li> * <var>ssl</var> <kbd>boolean</kbd> = <samp>false</samp> * <br />use ssl to connect? * </li> * </ul> * * ----------------------------------------- * * PORTABILITY MODES * * These modes are bitwised, so they can be combined using <kbd>|</kbd> * and removed using <kbd>^</kbd>. See the examples section below on how * to do this. * * <samp>DB_PORTABILITY_NONE</samp> * turn off all portability features * * This mode gets automatically turned on if the deprecated * <var>optimize</var> option gets set to <samp>performance</samp>. * * * <samp>DB_PORTABILITY_LOWERCASE</samp> * convert names of tables and fields to lower case when using * <kbd>get*()</kbd>, <kbd>fetch*()</kbd> and <kbd>tableInfo()</kbd> * * This mode gets automatically turned on in the following databases * if the deprecated option <var>optimize</var> gets set to * <samp>portability</samp>: * + oci8 * * * <samp>DB_PORTABILITY_RTRIM</samp> * right trim the data output by <kbd>get*()</kbd> <kbd>fetch*()</kbd> * * * <samp>DB_PORTABILITY_DELETE_COUNT</samp> * force reporting the number of rows deleted * * Some DBMS's don't count the number of rows deleted when performing * simple <kbd>DELETE FROM tablename</kbd> queries. This portability * mode tricks such DBMS's into telling the count by adding * <samp>WHERE 1=1</samp> to the end of <kbd>DELETE</kbd> queries. * * This mode gets automatically turned on in the following databases * if the deprecated option <var>optimize</var> gets set to * <samp>portability</samp>: * + fbsql * + mysql * + mysqli * + sqlite * * * <samp>DB_PORTABILITY_NUMROWS</samp> * enable hack that makes <kbd>numRows()</kbd> work in Oracle * * This mode gets automatically turned on in the following databases * if the deprecated option <var>optimize</var> gets set to * <samp>portability</samp>: * + oci8 * * * <samp>DB_PORTABILITY_ERRORS</samp> * makes certain error messages in certain drivers compatible * with those from other DBMS's * * + mysql, mysqli: change unique/primary key constraints * DB_ERROR_ALREADY_EXISTS -> DB_ERROR_CONSTRAINT * * + odbc(access): MS's ODBC driver reports 'no such field' as code * 07001, which means 'too few parameters.' When this option is on * that code gets mapped to DB_ERROR_NOSUCHFIELD. * DB_ERROR_MISMATCH -> DB_ERROR_NOSUCHFIELD * * <samp>DB_PORTABILITY_NULL_TO_EMPTY</samp> * convert null values to empty strings in data output by get*() and * fetch*(). Needed because Oracle considers empty strings to be null, * while most other DBMS's know the difference between empty and null. * * * <samp>DB_PORTABILITY_ALL</samp> * turn on all portability features * * ----------------------------------------- * * Example 1. Simple setOption() example * <code> * $db->setOption('autofree', true); * </code> * * Example 2. Portability for lowercasing and trimming * <code> * $db->setOption('portability', * DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_RTRIM); * </code> * * Example 3. All portability options except trimming * <code> * $db->setOption('portability', * DB_PORTABILITY_ALL ^ DB_PORTABILITY_RTRIM); * </code> * * @param string $option option name * @param mixed $value value for the option * * @return int DB_OK on success. A DB_Error object on failure. * * @see DB_common::$options */ function setOption($option, $value) { if (isset($this->options[$option])) { $this->options[$option] = $value; /* * Backwards compatibility check for the deprecated 'optimize' * option. Done here in case settings change after connecting. */ if ($option == 'optimize') { if ($value == 'portability') { switch ($this->phptype) { case 'oci8': $this->options['portability'] = DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_NUMROWS; break; case 'fbsql': case 'mysql': case 'mysqli': case 'sqlite': $this->options['portability'] = DB_PORTABILITY_DELETE_COUNT; break; } } else { $this->options['portability'] = DB_PORTABILITY_NONE; } } return DB_OK; } return $this->raiseError("unknown option $option"); } // }}} // {{{ getOption() /** * Returns the value of an option * * @param string $option the option name you're curious about * * @return mixed the option's value */ function getOption($option) { if (isset($this->options[$option])) { return $this->options[$option]; } return $this->raiseError("unknown option $option"); } // }}} // {{{ prepare() /** * Prepares a query for multiple execution with execute() * * Creates a query that can be run multiple times. Each time it is run, * the placeholders, if any, will be replaced by the contents of * execute()'s $data argument. * * Three types of placeholders can be used: * + <kbd>?</kbd> scalar value (i.e. strings, integers). The system * will automatically quote and escape the data. * + <kbd>!</kbd> value is inserted 'as is' * + <kbd>&</kbd> requires a file name. The file's contents get * inserted into the query (i.e. saving binary * data in a db) * * Example 1. * <code> * $sth = $db->prepare('INSERT INTO tbl (a, b, c) VALUES (?, !, &)'); * $data = array( * "John's text", * "'it''s good'", * 'filename.txt' * ); * $res = $db->execute($sth, $data); * </code> * * Use backslashes to escape placeholder characters if you don't want * them to be interpreted as placeholders: * <pre> * "UPDATE foo SET col=? WHERE col='over \& under'" * </pre> * * With some database backends, this is emulated. * * {@internal ibase and oci8 have their own prepare() methods.}} * * @param string $query the query to be prepared * * @return mixed DB statement resource on success. A DB_Error object * on failure. * * @see DB_common::execute() */ function prepare($query) { $tokens = preg_split('/((?<!\\\)[&?!])/', $query, -1, PREG_SPLIT_DELIM_CAPTURE); $token = 0; $types = array(); $newtokens = array(); foreach ($tokens as $val) { switch ($val) { case '?': $types[$token++] = DB_PARAM_SCALAR; break; case '&': $types[$token++] = DB_PARAM_OPAQUE; break; case '!': $types[$token++] = DB_PARAM_MISC; break; default: $newtokens[] = preg_replace('/\\\([&?!])/', "\\1", $val); } } $this->prepare_tokens[] = &$newtokens; end($this->prepare_tokens); $k = key($this->prepare_tokens); $this->prepare_types[$k] = $types; $this->prepared_queries[$k] = implode(' ', $newtokens); return $k; } // }}} // {{{ autoPrepare() /** * Automaticaly generates an insert or update query and pass it to prepare() * * @param string $table the table name * @param array $table_fields the array of field names * @param int $mode a type of query to make: * DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE * @param string $where for update queries: the WHERE clause to * append to the SQL statement. Don't * include the "WHERE" keyword. * * @return resource the query handle * * @uses DB_common::prepare(), DB_common::buildManipSQL() */ function autoPrepare($table, $table_fields, $mode = DB_AUTOQUERY_INSERT, $where = false) { $query = $this->buildManipSQL($table, $table_fields, $mode, $where); if (DB::isError($query)) { return $query; } return $this->prepare($query); } // }}} // {{{ autoExecute() /** * Automaticaly generates an insert or update query and call prepare() * and execute() with it * * @param string $table the table name * @param array $fields_values the associative array where $key is a * field name and $value its value * @param int $mode a type of query to make: * DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE * @param string $where for update queries: the WHERE clause to * append to the SQL statement. Don't * include the "WHERE" keyword. * * @return mixed a new DB_result object for successful SELECT queries * or DB_OK for successul data manipulation queries. * A DB_Error object on failure. * * @uses DB_common::autoPrepare(), DB_common::execute() */ function autoExecute($table, $fields_values, $mode = DB_AUTOQUERY_INSERT, $where = false) { $sth = $this->autoPrepare($table, array_keys($fields_values), $mode, $where); if (DB::isError($sth)) { return $sth; } $ret =& $this->execute($sth, array_values($fields_values)); $this->freePrepared($sth); return $ret; } // }}} // {{{ buildManipSQL() /** * Produces an SQL query string for autoPrepare() * * Example: * <pre> * buildManipSQL('table_sql', array('field1', 'field2', 'field3'), * DB_AUTOQUERY_INSERT); * </pre> * * That returns * <samp> * INSERT INTO table_sql (field1,field2,field3) VALUES (?,?,?) * </samp> * * NOTES: * - This belongs more to a SQL Builder class, but this is a simple * facility. * - Be carefull! If you don't give a $where param with an UPDATE * query, all the records of the table will be updated! * * @param string $table the table name * @param array $table_fields the array of field names * @param int $mode a type of query to make: * DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE * @param string $where for update queries: the WHERE clause to * append to the SQL statement. Don't * include the "WHERE" keyword. * * @return string the sql query for autoPrepare() */ function buildManipSQL($table, $table_fields, $mode, $where = false) { if (count($table_fields) == 0) { return $this->raiseError(DB_ERROR_NEED_MORE_DATA); } $first = true; switch ($mode) { case DB_AUTOQUERY_INSERT: $values = ''; $names = ''; foreach ($table_fields as $value) { if ($first) { $first = false; } else { $names .= ','; $values .= ','; } $names .= $value; $values .= '?'; } return "INSERT INTO $table ($names) VALUES ($values)"; case DB_AUTOQUERY_UPDATE: $set = ''; foreach ($table_fields as $value) { if ($first) { $first = false; } else { $set .= ','; } $set .= "$value = ?"; } $sql = "UPDATE $table SET $set"; if ($where) { $sql .= " WHERE $where"; } return $sql; default: return $this->raiseError(DB_ERROR_SYNTAX); } } // }}} // {{{ execute() /** * Executes a DB statement prepared with prepare() * * Example 1. * <code> * $sth = $db->prepare('INSERT INTO tbl (a, b, c) VALUES (?, !, &)'); * $data = array( * "John's text", * "'it''s good'", * 'filename.txt' * ); * $res =& $db->execute($sth, $data); * </code> * * @param resource $stmt a DB statement resource returned from prepare() * @param mixed $data 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 mixed a new DB_result object for successful SELECT queries * or DB_OK for successul data manipulation queries. * A DB_Error object on failure. * * {@internal ibase and oci8 have their own execute() methods.}} * * @see DB_common::prepare() */ function &execute($stmt, $data = array()) { $realquery = $this->executeEmulateQuery($stmt, $data); if (DB::isError($realquery)) { return $realquery; } $result = $this->simpleQuery($realquery); if ($result === DB_OK || DB::isError($result)) { return $result; } else { $tmp =& new DB_result($this, $result); return $tmp; } } // }}} // {{{ executeEmulateQuery() /** * Emulates executing prepared statements if the DBMS not support them * * @param resource $stmt a DB statement resource returned from execute() * @param mixed $data 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 mixed a string containing the real query run when emulating * prepare/execute. A DB_Error object on failure. * * @access protected * @see DB_common::execute() */ function executeEmulateQuery($stmt, $data = array()) { $stmt = (int)$stmt; $data = (array)$data; $this->last_parameters = $data; if (count($this->prepare_types[$stmt]) != count($data)) { $this->last_query = $this->prepared_queries[$stmt]; return $this->raiseError(DB_ERROR_MISMATCH); } $realquery = $this->prepare_tokens[$stmt][0]; $i = 0; foreach ($data as $value) { if ($this->prepare_types[$stmt][$i] == DB_PARAM_SCALAR) { $realquery .= $this->quoteSmart($value); } elseif ($this->prepare_types[$stmt][$i] == DB_PARAM_OPAQUE) { $fp = @fopen($value, 'rb'); if (!$fp) { return $this->raiseError(DB_ERROR_ACCESS_VIOLATION); } $realquery .= $this->quoteSmart(fread($fp, filesize($value))); fclose($fp); } else { $realquery .= $value; } $realquery .= $this->prepare_tokens[$stmt][++$i]; } return $realquery; } // }}} // {{{ executeMultiple() /** * Performs several execute() calls on the same statement handle * * $data must be an array indexed numerically * from 0, one execute call is done for every "row" in the array. * * If an error occurs during execute(), executeMultiple() does not * execute the unfinished rows, but rather returns that error. * * @param resource $stmt query handle from prepare() * @param array $data numeric array containing the * data to insert into the query * * @return int DB_OK on success. A DB_Error object on failure. * * @see DB_common::prepare(), DB_common::execute() */ function executeMultiple($stmt, $data) { foreach ($data as $value) { $res =& $this->execute($stmt, $value); if (DB::isError($res)) { return $res; } } return DB_OK; } // }}} // {{{ freePrepared() /** * Frees the internal resources associated with a prepared query * * @param resource $stmt the prepared statement's PHP resource * @param bool $free_resource should the PHP resource be freed too? * Use false if you need to get data * from the result set later. * * @return bool TRUE on success, FALSE if $result is invalid * * @see DB_common::prepare() */ function freePrepared($stmt, $free_resource = true) { $stmt = (int)$stmt; if (isset($this->prepare_tokens[$stmt])) { unset($this->prepare_tokens[$stmt]); unset($this->prepare_types[$stmt]); unset($this->prepared_queries[$stmt]); return true; } return false; } // }}} // {{{ modifyQuery() /** * Changes a query string for various DBMS specific reasons * * It is defined here to ensure all drivers have this method available. * * @param string $query the query string to modify * * @return string the modified query string * * @access protected * @see DB_mysql::modifyQuery(), DB_oci8::modifyQuery(), * DB_sqlite::modifyQuery() */ function modifyQuery($query) { return $query; } // }}} // {{{ modifyLimitQuery() /** * Adds LIMIT clauses to a query string according to current DBMS standards * * It is defined here to assure that all implementations * have this method defined. * * @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; } // }}} // {{{ query() /** * Sends a query to the database server * * The query string can be either a normal statement to be sent directly * to the server OR if <var>$params</var> are passed the query can have * placeholders and it will be passed through prepare() and execute(). * * @param string $query the SQL query or the statement to prepare * @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 mixed a new DB_result object for successful SELECT queries * or DB_OK for successul data manipulation queries. * A DB_Error object on failure. * * @see DB_result, DB_common::prepare(), DB_common::execute() */ function &query($query, $params = array()) { if (sizeof($params) > 0) { $sth = $this->prepare($query); if (DB::isError($sth)) { return $sth; } $ret =& $this->execute($sth, $params); $this->freePrepared($sth, false); return $ret; } else { $this->last_parameters = array(); $result = $this->simpleQuery($query); if ($result === DB_OK || DB::isError($result)) { return $result; } else { $tmp =& new DB_result($this, $result); return $tmp; } } } // }}} // {{{ limitQuery() /** * Generates and executes a LIMIT query * * @param string $query the query * @param intr $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 mixed a new DB_result object for successful SELECT queries * or DB_OK for successul data manipulation queries. * A DB_Error object on failure. */ function &limitQuery($query, $from, $count, $params = array()) { $query = $this->modifyLimitQuery($query, $from, $count, $params); if (DB::isError($query)){ return $query; } $result =& $this->query($query, $params); if (is_a($result, 'DB_result')) { $result->setOption('limit_from', $from); $result->setOption('limit_count', $count); } return $result; } // }}} // {{{ getOne() /** * Fetches the first column of the first row from a query result * * Takes care of doing the query and freeing the results when finished. * * @param string $query the SQL query * @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 mixed the returned value of the query. * A DB_Error object on failure. */ function &getOne($query, $params = array()) { $params = (array)$params; // modifyLimitQuery() would be nice here, but it causes BC issues if (sizeof($params) > 0) { $sth = $this->prepare($query); if (DB::isError($sth)) { return $sth; } $res =& $this->execute($sth, $params); $this->freePrepared($sth); } else { $res =& $this->query($query); } if (DB::isError($res)) { return $res; } $err = $res->fetchInto($row, DB_FETCHMODE_ORDERED); $res->free(); if ($err !== DB_OK) { return $err; } return $row[0]; } // }}} // {{{ getRow() /** * Fetches the first row of data returned from a query result * * Takes care of doing the query and freeing the results when finished. * * @param string $query the SQL query * @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. * @param int $fetchmode the fetch mode to use * * @return array the first row of results as an array. * A DB_Error object on failure. */ function &getRow($query, $params = array(), $fetchmode = DB_FETCHMODE_DEFAULT) { // compat check, the params and fetchmode parameters used to // have the opposite order if (!is_array($params)) { if (is_array($fetchmode)) { if ($params === null) { $tmp = DB_FETCHMODE_DEFAULT; } else { $tmp = $params; } $params = $fetchmode; $fetchmode = $tmp; } elseif ($params !== null) { $fetchmode = $params; $params = array(); } } // modifyLimitQuery() would be nice here, but it causes BC issues if (sizeof($params) > 0) { $sth = $this->prepare($query); if (DB::isError($sth)) { return $sth; } $res =& $this->execute($sth, $params); $this->freePrepared($sth); } else { $res =& $this->query($query); } if (DB::isError($res)) { return $res; } $err = $res->fetchInto($row, $fetchmode); $res->free(); if ($err !== DB_OK) { return $err; } return $row; } // }}} // {{{ getCol() /** * Fetches a single column from a query result and returns it as an * indexed array * * @param string $query the SQL query * @param mixed $col which column to return (integer [column number, * starting at 0] or string [column name]) * @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 array the results as an array. A DB_Error object on failure. * * @see DB_common::query() */ function &getCol($query, $col = 0, $params = array()) { $params = (array)$params; if (sizeof($params) > 0) { $sth = $this->prepare($query); if (DB::isError($sth)) { return $sth; } $res =& $this->execute($sth, $params); $this->freePrepared($sth); } else { $res =& $this->query($query); } if (DB::isError($res)) { return $res; } $fetchmode = is_int($col) ? DB_FETCHMODE_ORDERED : DB_FETCHMODE_ASSOC; if (!is_array($row = $res->fetchRow($fetchmode))) { $ret = array(); } else { if (!array_key_exists($col, $row)) { $ret =& $this->raiseError(DB_ERROR_NOSUCHFIELD); } else { $ret = array($row[$col]); while (is_array($row = $res->fetchRow($fetchmode))) { $ret[] = $row[$col]; } } } $res->free(); if (DB::isError($row)) { $ret = $row; } return $ret; } // }}} // {{{ getAssoc() /** * Fetches an entire query result and returns it as an * associative array using the first column as the key * * If the result set contains more than two columns, the value * will be an array of the values from column 2-n. If the result * set contains only two columns, the returned value will be a * scalar with the value of the second column (unless forced to an * array with the $force_array parameter). A DB error code is * returned on errors. If the result set contains fewer than two * columns, a DB_ERROR_TRUNCATED error is returned. * * For example, if the table "mytable" contains: * * <pre> * ID TEXT DATE * -------------------------------- * 1 'one' 944679408 * 2 'two' 944679408 * 3 'three' 944679408 * </pre> * * Then the call getAssoc('SELECT id,text FROM mytable') returns: * <pre> * array( * '1' => 'one', * '2' => 'two', * '3' => 'three', * ) * </pre> * * ...while the call getAssoc('SELECT id,text,date FROM mytable') returns: * <pre> * array( * '1' => array('one', '944679408'), * '2' => array('two', '944679408'), * '3' => array('three', '944679408') * ) * </pre> * * If the more than one row occurs with the same value in the * first column, the last row overwrites all previous ones by * default. Use the $group parameter if you don't want to * overwrite like this. Example: * * <pre> * getAssoc('SELECT category,id,name FROM mytable', false, null, * DB_FETCHMODE_ASSOC, true) returns: * * array( * '1' => array(array('id' => '4', 'name' => 'number four'), * array('id' => '6', 'name' => 'number six') * ), * '9' => array(array('id' => '4', 'name' => 'number four'), * array('id' => '6', 'name' => 'number six') * ) * ) * </pre> * * Keep in mind that database functions in PHP usually return string * values for results regardless of the database's internal type. * * @param string $query the SQL query * @param bool $force_array used only when the query returns * exactly two columns. If true, the values * of the returned array will be one-element * arrays instead of scalars. * @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. * @param int $fetchmode the fetch mode to use * @param bool $group if true, the values of the returned array * is wrapped in another array. If the same * key value (in the first column) repeats * itself, the values will be appended to * this array instead of overwriting the * existing values. * * @return array the associative array containing the query results. * A DB_Error object on failure. */ function &getAssoc($query, $force_array = false, $params = array(), $fetchmode = DB_FETCHMODE_DEFAULT, $group = false) { $params = (array)$params; if (sizeof($params) > 0) { $sth = $this->prepare($query); if (DB::isError($sth)) { return $sth; } $res =& $this->execute($sth, $params); $this->freePrepared($sth); } else { $res =& $this->query($query); } if (DB::isError($res)) { return $res; } if ($fetchmode == DB_FETCHMODE_DEFAULT) { $fetchmode = $this->fetchmode; } $cols = $res->numCols(); if ($cols < 2) { $tmp =& $this->raiseError(DB_ERROR_TRUNCATED); return $tmp; } $results = array(); if ($cols > 2 || $force_array) { // return array values // XXX this part can be optimized if ($fetchmode == DB_FETCHMODE_ASSOC) { while (is_array($row = $res->fetchRow(DB_FETCHMODE_ASSOC))) { reset($row); $key = current($row); unset($row[key($row)]); if ($group) { $results[$key][] = $row; } else { $results[$key] = $row; } } } elseif ($fetchmode == DB_FETCHMODE_OBJECT) { while ($row = $res->fetchRow(DB_FETCHMODE_OBJECT)) { $arr = get_object_vars($row); $key = current($arr); if ($group) { $results[$key][] = $row; } else { $results[$key] = $row; } } } else { while (is_array($row = $res->fetchRow(DB_FETCHMODE_ORDERED))) { // we shift away the first element to get // indices running from 0 again $key = array_shift($row); if ($group) { $results[$key][] = $row; } else { $results[$key] = $row; } } } if (DB::isError($row)) { $results = $row; } } else { // return scalar values while (is_array($row = $res->fetchRow(DB_FETCHMODE_ORDERED))) { if ($group) { $results[$row[0]][] = $row[1]; } else { $results[$row[0]] = $row[1]; } } if (DB::isError($row)) { $results = $row; } } $res->free(); return $results; } // }}} // {{{ getAll() /** * Fetches all of the rows from a query result * * @param string $query the SQL query * @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. * @param int $fetchmode the fetch mode to use: * + DB_FETCHMODE_ORDERED * + DB_FETCHMODE_ASSOC * + DB_FETCHMODE_ORDERED | DB_FETCHMODE_FLIPPED * + DB_FETCHMODE_ASSOC | DB_FETCHMODE_FLIPPED * * @return array the nested array. A DB_Error object on failure. */ function &getAll($query, $params = array(), $fetchmode = DB_FETCHMODE_DEFAULT) { // compat check, the params and fetchmode parameters used to // have the opposite order if (!is_array($params)) { if (is_array($fetchmode)) { if ($params === null) { $tmp = DB_FETCHMODE_DEFAULT; } else { $tmp = $params; } $params = $fetchmode; $fetchmode = $tmp; } elseif ($params !== null) { $fetchmode = $params; $params = array(); } } if (sizeof($params) > 0) { $sth = $this->prepare($query); if (DB::isError($sth)) { return $sth; } $res =& $this->execute($sth, $params); $this->freePrepared($sth); } else { $res =& $this->query($query); } if ($res === DB_OK || DB::isError($res)) { return $res; } $results = array(); while (DB_OK === $res->fetchInto($row, $fetchmode)) { if ($fetchmode & DB_FETCHMODE_FLIPPED) { foreach ($row as $key => $val) { $results[$key][] = $val; } } else { $results[] = $row; } } $res->free(); if (DB::isError($row)) { $tmp =& $this->raiseError($row); return $tmp; } return $results; } // }}} // {{{ 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) { return $this->raiseError(DB_ERROR_NOT_CAPABLE); } // }}} // {{{ commit() /** * Commits the current transaction * * @return int DB_OK on success. A DB_Error object on failure. */ function commit() { return $this->raiseError(DB_ERROR_NOT_CAPABLE); } // }}} // {{{ rollback() /** * Reverts the current transaction * * @return int DB_OK on success. A DB_Error object on failure. */ function rollback() { return $this->raiseError(DB_ERROR_NOT_CAPABLE); } // }}} // {{{ numRows() /** * Determines the number of rows in a query result * * @param resource $result the query result idenifier produced by PHP * * @return int the number of rows. A DB_Error object on failure. */ function numRows($result) { return $this->raiseError(DB_ERROR_NOT_CAPABLE); } // }}} // {{{ 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() { return $this->raiseError(DB_ERROR_NOT_CAPABLE); } // }}} // {{{ getSequenceName() /** * Generates the name used inside the database for a sequence * * The createSequence() docblock contains notes about storing sequence * names. * * @param string $sqn the sequence's public name * * @return string the sequence's name in the backend * * @access protected * @see DB_common::createSequence(), DB_common::dropSequence(), * DB_common::nextID(), DB_common::setOption() */ function getSequenceName($sqn) { return sprintf($this->getOption('seqname_format'), preg_replace('/[^a-z0-9_.]/i', '_', $sqn)); } // }}} // {{{ 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::createSequence(), DB_common::dropSequence(), * DB_common::getSequenceName() */ function nextId($seq_name, $ondemand = true) { return $this->raiseError(DB_ERROR_NOT_CAPABLE); } // }}} // {{{ createSequence() /** * Creates a new sequence * * The name of a given sequence is determined by passing the string * provided in the <var>$seq_name</var> argument through PHP's sprintf() * function using the value from the <var>seqname_format</var> option as * the sprintf()'s format argument. * * <var>seqname_format</var> is set via setOption(). * * @param string $seq_name name of the new sequence * * @return int DB_OK on success. A DB_Error object on failure. * * @see DB_common::dropSequence(), DB_common::getSequenceName(), * DB_common::nextID() */ function createSequence($seq_name) { return $this->raiseError(DB_ERROR_NOT_CAPABLE); } // }}} // {{{ 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::createSequence(), DB_common::getSequenceName(), * DB_common::nextID() */ function dropSequence($seq_name) { return $this->raiseError(DB_ERROR_NOT_CAPABLE); } // }}} // {{{ raiseError() /** * Communicates an error and invoke error callbacks, etc * * Basically a wrapper for PEAR::raiseError without the message string. * * @param mixed integer error code, or a PEAR error object (all * other parameters are ignored if this parameter is * an object * @param int error mode, see PEAR_Error docs * @param mixed if error mode is PEAR_ERROR_TRIGGER, this is the * error level (E_USER_NOTICE etc). If error mode is * PEAR_ERROR_CALLBACK, this is the callback function, * either as a function name, or as an array of an * object and method name. For other error modes this * parameter is ignored. * @param string extra debug information. Defaults to the last * query and native error code. * @param mixed native error code, integer or string depending the * backend * * @return object the PEAR_Error object * * @see PEAR_Error */ function &raiseError($code = DB_ERROR, $mode = null, $options = null, $userinfo = null, $nativecode = null) { // The error is yet a DB error object if (is_object($code)) { // because we the static PEAR::raiseError, our global // handler should be used if it is set if ($mode === null && !empty($this->_default_error_mode)) { $mode = $this->_default_error_mode; $options = $this->_default_error_options; } $tmp = PEAR::raiseError($code, null, $mode, $options, null, null, true); return $tmp; } if ($userinfo === null) { $userinfo = $this->last_query; } if ($nativecode) { $userinfo .= ' [nativecode=' . trim($nativecode) . ']'; } else { $userinfo .= ' [DB Error: ' . DB::errorMessage($code) . ']'; } $tmp = PEAR::raiseError(null, $code, $mode, $options, $userinfo, 'DB_Error', true); return $tmp; } // }}} // {{{ errorNative() /** * Gets the DBMS' native error code produced by the last query * * @return mixed the DBMS' error code. A DB_Error object on failure. */ function errorNative() { return $this->raiseError(DB_ERROR_NOT_CAPABLE); } // }}} // {{{ errorCode() /** * Maps native error codes to DB's portable ones * * Uses the <var>$errorcode_map</var> property defined in each driver. * * @param string|int $nativecode the error code returned by the DBMS * * @return int the portable DB error code. Return DB_ERROR if the * current driver doesn't have a mapping for the * $nativecode submitted. */ function errorCode($nativecode) { if (isset($this->errorcode_map[$nativecode])) { return $this->errorcode_map[$nativecode]; } // Fall back to DB_ERROR if there was no mapping. return DB_ERROR; } // }}} // {{{ errorMessage() /** * Maps a DB error code to a textual message * * @param integer $dbcode the DB error code * * @return string the error message corresponding to the error code * submitted. FALSE if the error code is unknown. * * @see DB::errorMessage() */ function errorMessage($dbcode) { return DB::errorMessage($this->errorcode_map[$dbcode]); } // }}} // {{{ tableInfo() /** * Returns information about a table or a result set * * The format of the resulting array depends on which <var>$mode</var> * you select. The sample output below is based on this query: * <pre> * SELECT tblFoo.fldID, tblFoo.fldPhone, tblBar.fldId * FROM tblFoo * JOIN tblBar ON tblFoo.fldId = tblBar.fldId * </pre> * * <ul> * <li> * * <kbd>null</kbd> (default) * <pre> * [0] => Array ( * [table] => tblFoo * [name] => fldId * [type] => int * [len] => 11 * [flags] => primary_key not_null * ) * [1] => Array ( * [table] => tblFoo * [name] => fldPhone * [type] => string * [len] => 20 * [flags] => * ) * [2] => Array ( * [table] => tblBar * [name] => fldId * [type] => int * [len] => 11 * [flags] => primary_key not_null * ) * </pre> * * </li><li> * * <kbd>DB_TABLEINFO_ORDER</kbd> * * <p>In addition to the information found in the default output, * a notation of the number of columns is provided by the * <samp>num_fields</samp> element while the <samp>order</samp> * element provides an array with the column names as the keys and * their location index number (corresponding to the keys in the * the default output) as the values.</p> * * <p>If a result set has identical field names, the last one is * used.</p> * * <pre> * [num_fields] => 3 * [order] => Array ( * [fldId] => 2 * [fldTrans] => 1 * ) * </pre> * * </li><li> * * <kbd>DB_TABLEINFO_ORDERTABLE</kbd> * * <p>Similar to <kbd>DB_TABLEINFO_ORDER</kbd> but adds more * dimensions to the array in which the table names are keys and * the field names are sub-keys. This is helpful for queries that * join tables which have identical field names.</p> * * <pre> * [num_fields] => 3 * [ordertable] => Array ( * [tblFoo] => Array ( * [fldId] => 0 * [fldPhone] => 1 * ) * [tblBar] => Array ( * [fldId] => 2 * ) * ) * </pre> * * </li> * </ul> * * The <samp>flags</samp> element contains a space separated list * of extra information about the field. This data is inconsistent * between DBMS's due to the way each DBMS works. * + <samp>primary_key</samp> * + <samp>unique_key</samp> * + <samp>multiple_key</samp> * + <samp>not_null</samp> * * Most DBMS's only provide the <samp>table</samp> and <samp>flags</samp> * elements if <var>$result</var> is a table name. The following DBMS's * provide full information from queries: * + fbsql * + mysql * * If the 'portability' option has <samp>DB_PORTABILITY_LOWERCASE</samp> * turned on, the names of tables and fields will be lowercased. * * @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 either unused or one of the tableInfo modes: * <kbd>DB_TABLEINFO_ORDERTABLE</kbd>, * <kbd>DB_TABLEINFO_ORDER</kbd> or * <kbd>DB_TABLEINFO_FULL</kbd> (which does both). * These are bitwise, so the first two can be * combined using <kbd>|</kbd>. * * @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 the DB_<driver> class has a tableInfo() method, that one * overrides this one. But, if the driver doesn't have one, * this method runs and tells users about that fact. */ return $this->raiseError(DB_ERROR_NOT_CAPABLE); } // }}} // {{{ getTables() /** * Lists the tables in the current database * * @return array the list of tables. A DB_Error object on failure. * * @deprecated Method deprecated some time before Release 1.2 */ function getTables() { return $this->getListOf('tables'); } // }}} // {{{ getListOf() /** * Lists internal database information * * @param string $type type of information being sought. * Common items being sought are: * tables, databases, users, views, functions * Each DBMS's has its own capabilities. * * @return array an array listing the items sought. * A DB DB_Error object on failure. */ function getListOf($type) { $sql = $this->getSpecialQuery($type); if ($sql === null) { $this->last_query = ''; return $this->raiseError(DB_ERROR_UNSUPPORTED); } elseif (is_int($sql) || DB::isError($sql)) { // Previous error return $this->raiseError($sql); } elseif (is_array($sql)) { // Already the result return $sql; } // Launch this query return $this->getCol($sql); } // }}} // {{{ 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) { return $this->raiseError(DB_ERROR_UNSUPPORTED); } // }}} // {{{ _rtrimArrayValues() /** * Right-trims all strings in an array * * @param array $array the array to be trimmed (passed by reference) * * @return void * * @access protected */ function _rtrimArrayValues(&$array) { foreach ($array as $key => $value) { if (is_string($value)) { $array[$key] = rtrim($value); } } } // }}} // {{{ _convertNullArrayValuesToEmpty() /** * Converts all null values in an array to empty strings * * @param array $array the array to be de-nullified (passed by reference) * * @return void * * @access protected */ function _convertNullArrayValuesToEmpty(&$array) { foreach ($array as $key => $value) { if (is_null($value)) { $array[$key] = ''; } } } // }}} } /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: */ ?> PK 唘\�#o, , flickr/api/PEAR/index.htmlnu &1i� <html><body bgcolor="#FFFFFF"></body></html>PK 唘\�O"� �� flickr/api/PEAR/DB.phpnu &1i� <?php /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ /** * Database independent query interface * * 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 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: DB.php 32 2005-08-01 06:21:02Z dancoulter $ * @link http://pear.php.net/package/DB */ // no direct access defined('_JEXEC') or die('Restricted accessd'); /** * Obtain the PEAR class so it can be extended from */ require_once 'PEAR.php'; // {{{ constants // {{{ error codes /**#@+ * One of PEAR DB's portable error codes. * @see DB_common::errorCode(), DB::errorMessage() * * {@internal If you add an error code here, make sure you also add a textual * version of it in DB::errorMessage().}} */ /** * The code returned by many methods upon success */ define('DB_OK', 1); /** * Unkown error */ define('DB_ERROR', -1); /** * Syntax error */ define('DB_ERROR_SYNTAX', -2); /** * Tried to insert a duplicate value into a primary or unique index */ define('DB_ERROR_CONSTRAINT', -3); /** * An identifier in the query refers to a non-existant object */ define('DB_ERROR_NOT_FOUND', -4); /** * Tried to create a duplicate object */ define('DB_ERROR_ALREADY_EXISTS', -5); /** * The current driver does not support the action you attempted */ define('DB_ERROR_UNSUPPORTED', -6); /** * The number of parameters does not match the number of placeholders */ define('DB_ERROR_MISMATCH', -7); /** * A literal submitted did not match the data type expected */ define('DB_ERROR_INVALID', -8); /** * The current DBMS does not support the action you attempted */ define('DB_ERROR_NOT_CAPABLE', -9); /** * A literal submitted was too long so the end of it was removed */ define('DB_ERROR_TRUNCATED', -10); /** * A literal number submitted did not match the data type expected */ define('DB_ERROR_INVALID_NUMBER', -11); /** * A literal date submitted did not match the data type expected */ define('DB_ERROR_INVALID_DATE', -12); /** * Attempt to divide something by zero */ define('DB_ERROR_DIVZERO', -13); /** * A database needs to be selected */ define('DB_ERROR_NODBSELECTED', -14); /** * Could not create the object requested */ define('DB_ERROR_CANNOT_CREATE', -15); /** * Could not drop the database requested because it does not exist */ define('DB_ERROR_CANNOT_DROP', -17); /** * An identifier in the query refers to a non-existant table */ define('DB_ERROR_NOSUCHTABLE', -18); /** * An identifier in the query refers to a non-existant column */ define('DB_ERROR_NOSUCHFIELD', -19); /** * The data submitted to the method was inappropriate */ define('DB_ERROR_NEED_MORE_DATA', -20); /** * The attempt to lock the table failed */ define('DB_ERROR_NOT_LOCKED', -21); /** * The number of columns doesn't match the number of values */ define('DB_ERROR_VALUE_COUNT_ON_ROW', -22); /** * The DSN submitted has problems */ define('DB_ERROR_INVALID_DSN', -23); /** * Could not connect to the database */ define('DB_ERROR_CONNECT_FAILED', -24); /** * The PHP extension needed for this DBMS could not be found */ define('DB_ERROR_EXTENSION_NOT_FOUND',-25); /** * The present user has inadequate permissions to perform the task requestd */ define('DB_ERROR_ACCESS_VIOLATION', -26); /** * The database requested does not exist */ define('DB_ERROR_NOSUCHDB', -27); /** * Tried to insert a null value into a column that doesn't allow nulls */ define('DB_ERROR_CONSTRAINT_NOT_NULL',-29); /**#@-*/ // }}} // {{{ prepared statement-related /**#@+ * Identifiers for the placeholders used in prepared statements. * @see DB_common::prepare() */ /** * Indicates a scalar (<kbd>?</kbd>) placeholder was used * * Quote and escape the value as necessary. */ define('DB_PARAM_SCALAR', 1); /** * Indicates an opaque (<kbd>&</kbd>) placeholder was used * * The value presented is a file name. Extract the contents of that file * and place them in this column. */ define('DB_PARAM_OPAQUE', 2); /** * Indicates a misc (<kbd>!</kbd>) placeholder was used * * The value should not be quoted or escaped. */ define('DB_PARAM_MISC', 3); /**#@-*/ // }}} // {{{ binary data-related /**#@+ * The different ways of returning binary data from queries. */ /** * Sends the fetched data straight through to output */ define('DB_BINMODE_PASSTHRU', 1); /** * Lets you return data as usual */ define('DB_BINMODE_RETURN', 2); /** * Converts the data to hex format before returning it * * For example the string "123" would become "313233". */ define('DB_BINMODE_CONVERT', 3); /**#@-*/ // }}} // {{{ fetch modes /**#@+ * Fetch Modes. * @see DB_common::setFetchMode() */ /** * Indicates the current default fetch mode should be used * @see DB_common::$fetchmode */ define('DB_FETCHMODE_DEFAULT', 0); /** * Column data indexed by numbers, ordered from 0 and up */ define('DB_FETCHMODE_ORDERED', 1); /** * Column data indexed by column names */ define('DB_FETCHMODE_ASSOC', 2); /** * Column data as object properties */ define('DB_FETCHMODE_OBJECT', 3); /** * For multi-dimensional results, make the column name the first level * of the array and put the row number in the second level of the array * * This is flipped from the normal behavior, which puts the row numbers * in the first level of the array and the column names in the second level. */ define('DB_FETCHMODE_FLIPPED', 4); /**#@-*/ /**#@+ * Old fetch modes. Left here for compatibility. */ define('DB_GETMODE_ORDERED', DB_FETCHMODE_ORDERED); define('DB_GETMODE_ASSOC', DB_FETCHMODE_ASSOC); define('DB_GETMODE_FLIPPED', DB_FETCHMODE_FLIPPED); /**#@-*/ // }}} // {{{ tableInfo() && autoPrepare()-related /**#@+ * The type of information to return from the tableInfo() method. * * Bitwised constants, so they can be combined using <kbd>|</kbd> * and removed using <kbd>^</kbd>. * * @see DB_common::tableInfo() * * {@internal Since the TABLEINFO constants are bitwised, if more of them are * added in the future, make sure to adjust DB_TABLEINFO_FULL accordingly.}} */ define('DB_TABLEINFO_ORDER', 1); define('DB_TABLEINFO_ORDERTABLE', 2); define('DB_TABLEINFO_FULL', 3); /**#@-*/ /**#@+ * The type of query to create with the automatic query building methods. * @see DB_common::autoPrepare(), DB_common::autoExecute() */ define('DB_AUTOQUERY_INSERT', 1); define('DB_AUTOQUERY_UPDATE', 2); /**#@-*/ // }}} // {{{ portability modes /**#@+ * Portability Modes. * * Bitwised constants, so they can be combined using <kbd>|</kbd> * and removed using <kbd>^</kbd>. * * @see DB_common::setOption() * * {@internal Since the PORTABILITY constants are bitwised, if more of them are * added in the future, make sure to adjust DB_PORTABILITY_ALL accordingly.}} */ /** * Turn off all portability features */ define('DB_PORTABILITY_NONE', 0); /** * Convert names of tables and fields to lower case * when using the get*(), fetch*() and tableInfo() methods */ define('DB_PORTABILITY_LOWERCASE', 1); /** * Right trim the data output by get*() and fetch*() */ define('DB_PORTABILITY_RTRIM', 2); /** * Force reporting the number of rows deleted */ define('DB_PORTABILITY_DELETE_COUNT', 4); /** * Enable hack that makes numRows() work in Oracle */ define('DB_PORTABILITY_NUMROWS', 8); /** * Makes certain error messages in certain drivers compatible * with those from other DBMS's * * + mysql, mysqli: change unique/primary key constraints * DB_ERROR_ALREADY_EXISTS -> DB_ERROR_CONSTRAINT * * + odbc(access): MS's ODBC driver reports 'no such field' as code * 07001, which means 'too few parameters.' When this option is on * that code gets mapped to DB_ERROR_NOSUCHFIELD. */ define('DB_PORTABILITY_ERRORS', 16); /** * Convert null values to empty strings in data output by * get*() and fetch*() */ define('DB_PORTABILITY_NULL_TO_EMPTY', 32); /** * Turn on all portability features */ define('DB_PORTABILITY_ALL', 63); /**#@-*/ // }}} // }}} // {{{ class DB /** * Database independent query interface * * The main "DB" class is simply a container class with some static * methods for creating DB objects as well as some utility functions * common to all parts of DB. * * The object model of DB is as follows (indentation means inheritance): * <pre> * DB The main DB class. This is simply a utility class * with some "static" methods for creating DB objects as * well as common utility functions for other DB classes. * * DB_common The base for each DB implementation. Provides default * | implementations (in OO lingo virtual methods) for * | the actual DB implementations as well as a bunch of * | query utility functions. * | * +-DB_mysql The DB implementation for MySQL. Inherits DB_common. * When calling DB::factory or DB::connect for MySQL * connections, the object returned is an instance of this * class. * </pre> * * @category Database * @package DB * @author Stig Bakken <ssb@php.net> * @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: @package_version@ * @link http://pear.php.net/package/DB */ class DB { // {{{ &factory() /** * Create a new DB object for the specified database type but don't * connect to the database * * @param string $type the database type (eg "mysql") * @param array $options an associative array of option names and values * * @return object a new DB object. A DB_Error object on failure. * * @see DB_common::setOption() */ function &factory($type, $options = false) { if (!is_array($options)) { $options = array('persistent' => $options); } if (isset($options['debug']) && $options['debug'] >= 2) { // expose php errors with sufficient debug level include_once "DB/{$type}.php"; } else { @include_once "DB/{$type}.php"; } $classname = "DB_${type}"; if (!class_exists($classname)) { $tmp = PEAR::raiseError(null, DB_ERROR_NOT_FOUND, null, null, "Unable to include the DB/{$type}.php" . " file for '$dsn'", 'DB_Error', true); return $tmp; } @$obj =& new $classname; foreach ($options as $option => $value) { $test = $obj->setOption($option, $value); if (DB::isError($test)) { return $test; } } return $obj; } // }}} // {{{ &connect() /** * Create a new DB object including a connection to the specified database * * Example 1. * <code> * require_once 'DB.php'; * * $dsn = 'pgsql://user:password@host/database'; * $options = array( * 'debug' => 2, * 'portability' => DB_PORTABILITY_ALL, * ); * * $db =& DB::connect($dsn, $options); * if (PEAR::isError($db)) { * die($db->getMessage()); * } * </code> * * @param mixed $dsn the string "data source name" or array in the * format returned by DB::parseDSN() * @param array $options an associative array of option names and values * * @return object a new DB object. A DB_Error object on failure. * * @uses DB_dbase::connect(), DB_fbsql::connect(), DB_ibase::connect(), * DB_ifx::connect(), DB_msql::connect(), DB_mssql::connect(), * DB_mysql::connect(), DB_mysqli::connect(), DB_oci8::connect(), * DB_odbc::connect(), DB_pgsql::connect(), DB_sqlite::connect(), * DB_sybase::connect() * * @uses DB::parseDSN(), DB_common::setOption(), PEAR::isError() */ function &connect($dsn, $options = array()) { $dsninfo = DB::parseDSN($dsn); $type = $dsninfo['phptype']; if (!is_array($options)) { /* * For backwards compatibility. $options used to be boolean, * indicating whether the connection should be persistent. */ $options = array('persistent' => $options); } if (isset($options['debug']) && $options['debug'] >= 2) { // expose php errors with sufficient debug level include_once "DB/${type}.php"; } else { @include_once "DB/${type}.php"; } $classname = "DB_${type}"; if (!class_exists($classname)) { $tmp = PEAR::raiseError(null, DB_ERROR_NOT_FOUND, null, null, "Unable to include the DB/{$type}.php" . " file for '$dsn'", 'DB_Error', true); return $tmp; } @$obj =& new $classname; foreach ($options as $option => $value) { $test = $obj->setOption($option, $value); if (DB::isError($test)) { return $test; } } $err = $obj->connect($dsninfo, $obj->getOption('persistent')); if (DB::isError($err)) { $err->addUserInfo($dsn); return $err; } return $obj; } // }}} // {{{ apiVersion() /** * Return the DB API version * * @return string the DB API version number */ function apiVersion() { return '@package_version@'; } // }}} // {{{ isError() /** * Determines if a variable is a DB_Error object * * @param mixed $value the variable to check * * @return bool whether $value is DB_Error object */ function isError($value) { return is_a($value, 'DB_Error'); } // }}} // {{{ isConnection() /** * Determines if a value is a DB_<driver> object * * @param mixed $value the value to test * * @return bool whether $value is a DB_<driver> object */ function isConnection($value) { return (is_object($value) && is_subclass_of($value, 'db_common') && method_exists($value, 'simpleQuery')); } // }}} // {{{ isManip() /** * Tell whether a query is a data manipulation or data definition query * * Examples of data manipulation queries are INSERT, UPDATE and DELETE. * Examples of data definition queries are CREATE, DROP, ALTER, GRANT, * REVOKE. * * @param string $query the query * * @return boolean whether $query is a data manipulation query */ function isManip($query) { $manips = 'INSERT|UPDATE|DELETE|REPLACE|' . 'CREATE|DROP|' . 'LOAD DATA|SELECT .* INTO|COPY|' . 'ALTER|GRANT|REVOKE|' . 'LOCK|UNLOCK'; if (preg_match('/^\s*"?(' . $manips . ')\s+/i', $query)) { return true; } return false; } // }}} // {{{ errorMessage() /** * Return a textual error message for a DB error code * * @param integer $value the DB error code * * @return string the error message or false if the error code was * not recognized */ function errorMessage($value) { static $errorMessages; if (!isset($errorMessages)) { $errorMessages = array( DB_ERROR => 'unknown error', DB_ERROR_ACCESS_VIOLATION => 'insufficient permissions', DB_ERROR_ALREADY_EXISTS => 'already exists', DB_ERROR_CANNOT_CREATE => 'can not create', DB_ERROR_CANNOT_DROP => 'can not drop', DB_ERROR_CONNECT_FAILED => 'connect failed', DB_ERROR_CONSTRAINT => 'constraint violation', DB_ERROR_CONSTRAINT_NOT_NULL=> 'null value violates not-null constraint', DB_ERROR_DIVZERO => 'division by zero', DB_ERROR_EXTENSION_NOT_FOUND=> 'extension not found', DB_ERROR_INVALID => 'invalid', DB_ERROR_INVALID_DATE => 'invalid date or time', DB_ERROR_INVALID_DSN => 'invalid DSN', DB_ERROR_INVALID_NUMBER => 'invalid number', DB_ERROR_MISMATCH => 'mismatch', DB_ERROR_NEED_MORE_DATA => 'insufficient data supplied', DB_ERROR_NODBSELECTED => 'no database selected', DB_ERROR_NOSUCHDB => 'no such database', DB_ERROR_NOSUCHFIELD => 'no such field', DB_ERROR_NOSUCHTABLE => 'no such table', DB_ERROR_NOT_CAPABLE => 'DB backend not capable', DB_ERROR_NOT_FOUND => 'not found', DB_ERROR_NOT_LOCKED => 'not locked', DB_ERROR_SYNTAX => 'syntax error', DB_ERROR_UNSUPPORTED => 'not supported', DB_ERROR_TRUNCATED => 'truncated', DB_ERROR_VALUE_COUNT_ON_ROW => 'value count on row', DB_OK => 'no error', ); } if (DB::isError($value)) { $value = $value->getCode(); } return isset($errorMessages[$value]) ? $errorMessages[$value] : $errorMessages[DB_ERROR]; } // }}} // {{{ parseDSN() /** * Parse a data source name * * Additional keys can be added by appending a URI query string to the * end of the DSN. * * The format of the supplied DSN is in its fullest form: * <code> * phptype(dbsyntax)://username:password@protocol+hostspec/database?option=8&another=true * </code> * * Most variations are allowed: * <code> * phptype://username:password@protocol+hostspec:110//usr/db_file.db?mode=0644 * phptype://username:password@hostspec/database_name * phptype://username:password@hostspec * phptype://username@hostspec * phptype://hostspec/database * phptype://hostspec * phptype(dbsyntax) * phptype * </code> * * @param string $dsn Data Source Name to be parsed * * @return array an associative array with the following keys: * + phptype: Database backend used in PHP (mysql, odbc etc.) * + dbsyntax: Database used with regards to SQL syntax etc. * + protocol: Communication protocol to use (tcp, unix etc.) * + hostspec: Host specification (hostname[:port]) * + database: Database to use on the DBMS server * + username: User name for login * + password: Password for login */ function parseDSN($dsn) { $parsed = array( 'phptype' => false, 'dbsyntax' => false, 'username' => false, 'password' => false, 'protocol' => false, 'hostspec' => false, 'port' => false, 'socket' => false, 'database' => false, ); if (is_array($dsn)) { $dsn = array_merge($parsed, $dsn); if (!$dsn['dbsyntax']) { $dsn['dbsyntax'] = $dsn['phptype']; } return $dsn; } // Find phptype and dbsyntax if (($pos = strpos($dsn, '://')) !== false) { $str = substr($dsn, 0, $pos); $dsn = substr($dsn, $pos + 3); } else { $str = $dsn; $dsn = null; } // Get phptype and dbsyntax // $str => phptype(dbsyntax) if (preg_match('|^(.+?)\((.*?)\)$|', $str, $arr)) { $parsed['phptype'] = $arr[1]; $parsed['dbsyntax'] = !$arr[2] ? $arr[1] : $arr[2]; } else { $parsed['phptype'] = $str; $parsed['dbsyntax'] = $str; } if (!count($dsn)) { return $parsed; } // Get (if found): username and password // $dsn => username:password@protocol+hostspec/database if (($at = strrpos($dsn,'@')) !== false) { $str = substr($dsn, 0, $at); $dsn = substr($dsn, $at + 1); if (($pos = strpos($str, ':')) !== false) { $parsed['username'] = rawurldecode(substr($str, 0, $pos)); $parsed['password'] = rawurldecode(substr($str, $pos + 1)); } else { $parsed['username'] = rawurldecode($str); } } // Find protocol and hostspec if (preg_match('|^([^(]+)\((.*?)\)/?(.*?)$|', $dsn, $match)) { // $dsn => proto(proto_opts)/database $proto = $match[1]; $proto_opts = $match[2] ? $match[2] : false; $dsn = $match[3]; } else { // $dsn => protocol+hostspec/database (old format) if (strpos($dsn, '+') !== false) { list($proto, $dsn) = explode('+', $dsn, 2); } if (strpos($dsn, '/') !== false) { list($proto_opts, $dsn) = explode('/', $dsn, 2); } else { $proto_opts = $dsn; $dsn = null; } } // process the different protocol options $parsed['protocol'] = (!empty($proto)) ? $proto : 'tcp'; $proto_opts = rawurldecode($proto_opts); if ($parsed['protocol'] == 'tcp') { if (strpos($proto_opts, ':') !== false) { list($parsed['hostspec'], $parsed['port']) = explode(':', $proto_opts); } else { $parsed['hostspec'] = $proto_opts; } } elseif ($parsed['protocol'] == 'unix') { $parsed['socket'] = $proto_opts; } // Get dabase if any // $dsn => database if ($dsn) { if (($pos = strpos($dsn, '?')) === false) { // /database $parsed['database'] = rawurldecode($dsn); } else { // /database?param1=value1¶m2=value2 $parsed['database'] = rawurldecode(substr($dsn, 0, $pos)); $dsn = substr($dsn, $pos + 1); if (strpos($dsn, '&') !== false) { $opts = explode('&', $dsn); } else { // database?param1=value1 $opts = array($dsn); } foreach ($opts as $opt) { list($key, $value) = explode('=', $opt); if (!isset($parsed[$key])) { // don't allow params overwrite $parsed[$key] = rawurldecode($value); } } } } return $parsed; } // }}} } // }}} // {{{ class DB_Error /** * DB_Error implements a class for reporting portable database error * messages * * @category Database * @package DB * @author Stig Bakken <ssb@php.net> * @copyright 1997-2005 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 * @version Release: @package_version@ * @link http://pear.php.net/package/DB */ class DB_Error extends PEAR_Error { // {{{ constructor /** * DB_Error constructor * * @param mixed $code DB error code, or string with error message * @param int $mode what "error mode" to operate in * @param int $level what error level to use for $mode & * PEAR_ERROR_TRIGGER * @param mixed $debuginfo additional debug info, such as the last query * * @see PEAR_Error */ function DB_Error($code = DB_ERROR, $mode = PEAR_ERROR_RETURN, $level = E_USER_NOTICE, $debuginfo = null) { if (is_int($code)) { $this->PEAR_Error('DB Error: ' . DB::errorMessage($code), $code, $mode, $level, $debuginfo); } else { $this->PEAR_Error("DB Error: $code", DB_ERROR, $mode, $level, $debuginfo); } } // }}} } // }}} // {{{ class DB_result /** * This class implements a wrapper for a DB result set * * A new instance of this class will be returned by the DB implementation * after processing a query that returns data. * * @category Database * @package DB * @author Stig Bakken <ssb@php.net> * @copyright 1997-2005 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 * @version Release: @package_version@ * @link http://pear.php.net/package/DB */ class DB_result { // {{{ properties /** * Should results be freed automatically when there are no more rows? * @var boolean * @see DB_common::$options */ var $autofree; /** * A reference to the DB_<driver> object * @var object */ var $dbh; /** * The current default fetch mode * @var integer * @see DB_common::$fetchmode */ var $fetchmode; /** * The name of the class into which results should be fetched when * DB_FETCHMODE_OBJECT is in effect * * @var string * @see DB_common::$fetchmode_object_class */ var $fetchmode_object_class; /** * The number of rows to fetch from a limit query * @var integer */ var $limit_count = null; /** * The row to start fetching from in limit queries * @var integer */ var $limit_from = null; /** * The execute parameters that created this result * @var array * @since Property available since Release 1.7.0 */ var $parameters; /** * The query string that created this result * * Copied here incase it changes in $dbh, which is referenced * * @var string * @since Property available since Release 1.7.0 */ var $query; /** * The query result resource id created by PHP * @var resource */ var $result; /** * The present row being dealt with * @var integer */ var $row_counter = null; /** * The prepared statement resource id created by PHP in $dbh * * This resource is only available when the result set was created using * a driver's native execute() method, not PEAR DB's emulated one. * * Copied here incase it changes in $dbh, which is referenced * * {@internal Mainly here because the InterBase/Firebird API is only * able to retrieve data from result sets if the statemnt handle is * still in scope.}} * * @var resource * @since Property available since Release 1.7.0 */ var $statement; // }}} // {{{ constructor /** * This constructor sets the object's properties * * @param object &$dbh the DB object reference * @param resource $result the result resource id * @param array $options an associative array with result options * * @return void */ function DB_result(&$dbh, $result, $options = array()) { $this->autofree = $dbh->options['autofree']; $this->dbh = &$dbh; $this->fetchmode = $dbh->fetchmode; $this->fetchmode_object_class = $dbh->fetchmode_object_class; $this->parameters = $dbh->last_parameters; $this->query = $dbh->last_query; $this->result = $result; $this->statement = empty($dbh->last_stmt) ? null : $dbh->last_stmt; foreach ($options as $key => $value) { $this->setOption($key, $value); } } /** * Set options for the DB_result object * * @param string $key the option to set * @param mixed $value the value to set the option to * * @return void */ function setOption($key, $value = null) { switch ($key) { case 'limit_from': $this->limit_from = $value; break; case 'limit_count': $this->limit_count = $value; } } // }}} // {{{ fetchRow() /** * Fetch a row of data and return it by reference into an array * * The type of array returned can be controlled either by setting this * method's <var>$fetchmode</var> parameter or by changing the default * fetch mode setFetchMode() before calling this method. * * There are two options for standardizing the information returned * from databases, ensuring their values are consistent when changing * DBMS's. These portability options can be turned on when creating a * new DB object or by using setOption(). * * + <var>DB_PORTABILITY_LOWERCASE</var> * convert names of fields to lower case * * + <var>DB_PORTABILITY_RTRIM</var> * right trim the data * * @param int $fetchmode the constant indicating how to format the data * @param int $rownum the row number to fetch (index starts at 0) * * @return mixed an array or object containing the row's data, * NULL when the end of the result set is reached * or a DB_Error object on failure. * * @see DB_common::setOption(), DB_common::setFetchMode() */ function &fetchRow($fetchmode = DB_FETCHMODE_DEFAULT, $rownum = null) { if ($fetchmode === DB_FETCHMODE_DEFAULT) { $fetchmode = $this->fetchmode; } if ($fetchmode === DB_FETCHMODE_OBJECT) { $fetchmode = DB_FETCHMODE_ASSOC; $object_class = $this->fetchmode_object_class; } if ($this->limit_from !== null) { if ($this->row_counter === null) { $this->row_counter = $this->limit_from; // Skip rows if ($this->dbh->features['limit'] === false) { $i = 0; while ($i++ < $this->limit_from) { $this->dbh->fetchInto($this->result, $arr, $fetchmode); } } } if ($this->row_counter >= ($this->limit_from + $this->limit_count)) { if ($this->autofree) { $this->free(); } $tmp = null; return $tmp; } if ($this->dbh->features['limit'] === 'emulate') { $rownum = $this->row_counter; } $this->row_counter++; } $res = $this->dbh->fetchInto($this->result, $arr, $fetchmode, $rownum); if ($res === DB_OK) { if (isset($object_class)) { // The default mode is specified in the // DB_common::fetchmode_object_class property if ($object_class == 'stdClass') { $arr = (object) $arr; } else { $arr = &new $object_class($arr); } } return $arr; } if ($res == null && $this->autofree) { $this->free(); } return $res; } // }}} // {{{ fetchInto() /** * Fetch a row of data into an array which is passed by reference * * The type of array returned can be controlled either by setting this * method's <var>$fetchmode</var> parameter or by changing the default * fetch mode setFetchMode() before calling this method. * * There are two options for standardizing the information returned * from databases, ensuring their values are consistent when changing * DBMS's. These portability options can be turned on when creating a * new DB object or by using setOption(). * * + <var>DB_PORTABILITY_LOWERCASE</var> * convert names of fields to lower case * * + <var>DB_PORTABILITY_RTRIM</var> * right trim the data * * @param array &$arr the variable where the data should be placed * @param int $fetchmode the constant indicating how to format the data * @param int $rownum the row number to fetch (index starts at 0) * * @return mixed DB_OK if a row is processed, NULL when the end of the * result set is reached or a DB_Error object on failure * * @see DB_common::setOption(), DB_common::setFetchMode() */ function fetchInto(&$arr, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum = null) { if ($fetchmode === DB_FETCHMODE_DEFAULT) { $fetchmode = $this->fetchmode; } if ($fetchmode === DB_FETCHMODE_OBJECT) { $fetchmode = DB_FETCHMODE_ASSOC; $object_class = $this->fetchmode_object_class; } if ($this->limit_from !== null) { if ($this->row_counter === null) { $this->row_counter = $this->limit_from; // Skip rows if ($this->dbh->features['limit'] === false) { $i = 0; while ($i++ < $this->limit_from) { $this->dbh->fetchInto($this->result, $arr, $fetchmode); } } } if ($this->row_counter >= ( $this->limit_from + $this->limit_count)) { if ($this->autofree) { $this->free(); } return null; } if ($this->dbh->features['limit'] === 'emulate') { $rownum = $this->row_counter; } $this->row_counter++; } $res = $this->dbh->fetchInto($this->result, $arr, $fetchmode, $rownum); if ($res === DB_OK) { if (isset($object_class)) { // default mode specified in the // DB_common::fetchmode_object_class property if ($object_class == 'stdClass') { $arr = (object) $arr; } else { $arr = new $object_class($arr); } } return DB_OK; } if ($res == null && $this->autofree) { $this->free(); } return $res; } // }}} // {{{ numCols() /** * Get the the number of columns in a result set * * @return int the number of columns. A DB_Error object on failure. */ function numCols() { return $this->dbh->numCols($this->result); } // }}} // {{{ numRows() /** * Get the number of rows in a result set * * @return int the number of rows. A DB_Error object on failure. */ function numRows() { if ($this->dbh->features['numrows'] === 'emulate' && $this->dbh->options['portability'] & DB_PORTABILITY_NUMROWS) { if ($this->dbh->features['prepare']) { $res = $this->dbh->query($this->query, $this->parameters); } else { $res = $this->dbh->query($this->query); } if (DB::isError($res)) { return $res; } $i = 0; while ($res->fetchInto($tmp, DB_FETCHMODE_ORDERED)) { $i++; } return $i; } else { return $this->dbh->numRows($this->result); } } // }}} // {{{ nextResult() /** * Get the next result if a batch of queries was executed * * @return bool true if a new result is available or false if not */ function nextResult() { return $this->dbh->nextResult($this->result); } // }}} // {{{ free() /** * Frees the resources allocated for this result set * * @return bool true on success. A DB_Error object on failure. */ function free() { $err = $this->dbh->freeResult($this->result); if (DB::isError($err)) { return $err; } $this->result = false; $this->statement = false; return true; } // }}} // {{{ tableInfo() /** * @see DB_common::tableInfo() * @deprecated Method deprecated some time before Release 1.2 */ function tableInfo($mode = null) { if (is_string($mode)) { return $this->dbh->raiseError(DB_ERROR_NEED_MORE_DATA); } return $this->dbh->tableInfo($this, $mode); } // }}} // {{{ getQuery() /** * Determine the query string that created this result * * @return string the query string * * @since Method available since Release 1.7.0 */ function getQuery() { return $this->query; } // }}} // {{{ getRowCounter() /** * Tells which row number is currently being processed * * @return integer the current row being looked at. Starts at 1. */ function getRowCounter() { return $this->row_counter; } // }}} } // }}} // {{{ class DB_row /** * PEAR DB Row Object * * The object contains a row of data from a result set. Each column's data * is placed in a property named for the column. * * @category Database * @package DB * @author Stig Bakken <ssb@php.net> * @copyright 1997-2005 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 * @version Release: @package_version@ * @link http://pear.php.net/package/DB * @see DB_common::setFetchMode() */ class DB_row { // {{{ constructor /** * The constructor places a row's data into properties of this object * * @param array the array containing the row's data * * @return void */ function DB_row(&$arr) { foreach ($arr as $key => $value) { $this->$key = &$arr[$key]; } } // }}} } // }}} /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: */ ?> PK 唘\ߡ�%D4 D4 flickr/api/PEAR/Net/URL.phpnu &1i� <?php // +-----------------------------------------------------------------------+ // | Copyright (c) 2002-2004, Richard Heyes | // | All rights reserved. | // | | // | Redistribution and use in source and binary forms, with or without | // | modification, are permitted provided that the following conditions | // | are met: | // | | // | o Redistributions of source code must retain the above copyright | // | notice, this list of conditions and the following disclaimer. | // | o Redistributions in binary form must reproduce the above copyright | // | notice, this list of conditions and the following disclaimer in the | // | documentation and/or other materials provided with the distribution.| // | o The names of the authors may not be used to endorse or promote | // | products derived from this software without specific prior written | // | permission. | // | | // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | // | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | // | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | // | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | // | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | // | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | // | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | // | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | // | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | // | | // +-----------------------------------------------------------------------+ // | Author: Richard Heyes <richard at php net> | // +-----------------------------------------------------------------------+ // // $Id: URL.php 32 2005-08-01 06:21:02Z dancoulter $ // // Net_URL Class // no direct access defined('_JEXEC') or die('Restricted accessd'); class Net_URL { /** * Full url * @var string */ var $url; /** * Protocol * @var string */ var $protocol; /** * Username * @var string */ var $username; /** * Password * @var string */ var $password; /** * Host * @var string */ var $host; /** * Port * @var integer */ var $port; /** * Path * @var string */ var $path; /** * Query string * @var array */ var $querystring; /** * Anchor * @var string */ var $anchor; /** * Whether to use [] * @var bool */ var $useBrackets; /** * PHP4 Constructor * * @see __construct() */ function Net_URL($url = null, $useBrackets = true) { $this->__construct($url, $useBrackets); } /** * PHP5 Constructor * * Parses the given url and stores the various parts * Defaults are used in certain cases * * @param string $url Optional URL * @param bool $useBrackets Whether to use square brackets when * multiple querystrings with the same name * exist */ function __construct($url = null, $useBrackets = true) { $HTTP_SERVER_VARS = !empty($_SERVER) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS']; $this->useBrackets = $useBrackets; $this->url = $url; $this->user = ''; $this->pass = ''; $this->host = ''; $this->port = 80; $this->path = ''; $this->querystring = array(); $this->anchor = ''; // Only use defaults if not an absolute URL given if (!preg_match('/^[a-z0-9]+:\/\//i', $url)) { $this->protocol = (@$HTTP_SERVER_VARS['HTTPS'] == 'on' ? 'https' : 'http'); /** * Figure out host/port */ if (!empty($HTTP_SERVER_VARS['HTTP_HOST']) AND preg_match('/^(.*)(:([0-9]+))?$/U', $HTTP_SERVER_VARS['HTTP_HOST'], $matches)) { $host = $matches[1]; if (!empty($matches[3])) { $port = $matches[3]; } else { $port = $this->getStandardPort($this->protocol); } } $this->user = ''; $this->pass = ''; $this->host = !empty($host) ? $host : (isset($HTTP_SERVER_VARS['SERVER_NAME']) ? $HTTP_SERVER_VARS['SERVER_NAME'] : 'localhost'); $this->port = !empty($port) ? $port : (isset($HTTP_SERVER_VARS['SERVER_PORT']) ? $HTTP_SERVER_VARS['SERVER_PORT'] : $this->getStandardPort($this->protocol)); $this->path = !empty($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : '/'; $this->querystring = isset($HTTP_SERVER_VARS['QUERY_STRING']) ? $this->_parseRawQuerystring($HTTP_SERVER_VARS['QUERY_STRING']) : null; $this->anchor = ''; } // Parse the url and store the various parts if (!empty($url)) { $urlinfo = parse_url($url); // Default querystring $this->querystring = array(); foreach ($urlinfo as $key => $value) { switch ($key) { case 'scheme': $this->protocol = $value; $this->port = $this->getStandardPort($value); break; case 'user': case 'pass': case 'host': case 'port': $this->$key = $value; break; case 'path': if ($value{0} == '/') { $this->path = $value; } else { $path = dirname($this->path) == DIRECTORY_SEPARATOR ? '' : dirname($this->path); $this->path = sprintf('%s/%s', $path, $value); } break; case 'query': $this->querystring = $this->_parseRawQueryString($value); break; case 'fragment': $this->anchor = $value; break; } } } } /** * Returns full url * * @return string Full url * @access public */ function getURL() { $querystring = $this->getQueryString(); $this->url = $this->protocol . '://' . $this->user . (!empty($this->pass) ? ':' : '') . $this->pass . (!empty($this->user) ? '@' : '') . $this->host . ($this->port == $this->getStandardPort($this->protocol) ? '' : ':' . $this->port) . $this->path . (!empty($querystring) ? '?' . $querystring : '') . (!empty($this->anchor) ? '#' . $this->anchor : ''); return $this->url; } /** * Adds a querystring item * * @param string $name Name of item * @param string $value Value of item * @param bool $preencoded Whether value is urlencoded or not, default = not * @access public */ function addQueryString($name, $value, $preencoded = false) { if ($preencoded) { $this->querystring[$name] = $value; } else { $this->querystring[$name] = is_array($value) ? array_map('rawurlencode', $value): rawurlencode($value); } } /** * Removes a querystring item * * @param string $name Name of item * @access public */ function removeQueryString($name) { if (isset($this->querystring[$name])) { unset($this->querystring[$name]); } } /** * Sets the querystring to literally what you supply * * @param string $querystring The querystring data. Should be of the format foo=bar&x=y etc * @access public */ function addRawQueryString($querystring) { $this->querystring = $this->_parseRawQueryString($querystring); } /** * Returns flat querystring * * @return string Querystring * @access public */ function getQueryString() { if (!empty($this->querystring)) { foreach ($this->querystring as $name => $value) { if (is_array($value)) { foreach ($value as $k => $v) { $querystring[] = $this->useBrackets ? sprintf('%s[%s]=%s', $name, $k, $v) : ($name . '=' . $v); } } elseif (!is_null($value)) { $querystring[] = $name . '=' . $value; } else { $querystring[] = $name; } } $querystring = implode(ini_get('arg_separator.output'), $querystring); } else { $querystring = ''; } return $querystring; } /** * Parses raw querystring and returns an array of it * * @param string $querystring The querystring to parse * @return array An array of the querystring data * @access private */ function _parseRawQuerystring($querystring) { $parts = preg_split('/[' . preg_quote(ini_get('arg_separator.input'), '/') . ']/', $querystring, -1, PREG_SPLIT_NO_EMPTY); $return = array(); foreach ($parts as $part) { if (strpos($part, '=') !== false) { $value = substr($part, strpos($part, '=') + 1); $key = substr($part, 0, strpos($part, '=')); } else { $value = null; $key = $part; } if (substr($key, -2) == '[]') { $key = substr($key, 0, -2); if (@!is_array($return[$key])) { $return[$key] = array(); $return[$key][] = $value; } else { $return[$key][] = $value; } } elseif (!$this->useBrackets AND !empty($return[$key])) { $return[$key] = (array)$return[$key]; $return[$key][] = $value; } else { $return[$key] = $value; } } return $return; } /** * Resolves //, ../ and ./ from a path and returns * the result. Eg: * * /foo/bar/../boo.php => /foo/boo.php * /foo/bar/../../boo.php => /boo.php * /foo/bar/.././/boo.php => /foo/boo.php * * This method can also be called statically. * * @param string $url URL path to resolve * @return string The result */ function resolvePath($path) { $path = explode('/', str_replace('//', '/', $path)); for ($i=0; $i<count($path); $i++) { if ($path[$i] == '.') { unset($path[$i]); $path = array_values($path); $i--; } elseif ($path[$i] == '..' AND ($i > 1 OR ($i == 1 AND $path[0] != '') ) ) { unset($path[$i]); unset($path[$i-1]); $path = array_values($path); $i -= 2; } elseif ($path[$i] == '..' AND $i == 1 AND $path[0] == '') { unset($path[$i]); $path = array_values($path); $i--; } else { continue; } } return implode('/', $path); } /** * Returns the standard port number for a protocol * * @param string $scheme The protocol to lookup * @return integer Port number or NULL if no scheme matches * * @author Philippe Jausions <Philippe.Jausions@11abacus.com> */ function getStandardPort($scheme) { switch (strtolower($scheme)) { case 'http': return 80; case 'https': return 443; case 'ftp': return 21; case 'imap': return 143; case 'imaps': return 993; case 'pop3': return 110; case 'pop3s': return 995; default: return null; } } /** * Forces the URL to a particular protocol * * @param string $protocol Protocol to force the URL to * @param integer $port Optional port (standard port is used by default) */ function setProtocol($protocol, $port = null) { $this->protocol = $protocol; $this->port = is_null($port) ? $this->getStandardPort() : $port; } } ?> PK 唘\B��u=<