diff -Nru owncloud-1.1+git20110209/.htaccess owncloud-5.0.4debian/.htaccess
--- owncloud-1.1+git20110209/.htaccess 1970-01-01 00:00:00.000000000 +0000
+++ owncloud-5.0.4debian/.htaccess 2013-04-10 17:29:11.000000000 +0000
@@ -0,0 +1,36 @@
+
+
+
+SetEnvIfNoCase ^Authorization$ "(.+)" XAUTHORIZATION=$1
+RequestHeader set XAuthorization %{XAUTHORIZATION}e env=XAUTHORIZATION
+
+
+
+ErrorDocument 403 /core/templates/403.php
+ErrorDocument 404 /core/templates/404.php
+
+php_value upload_max_filesize 513M
+php_value post_max_size 513M
+php_value memory_limit 512M
+
+ SetEnv htaccessWorking true
+
+
+
+RewriteEngine on
+RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
+RewriteRule ^.well-known/host-meta /public.php?service=host-meta [QSA,L]
+RewriteRule ^.well-known/host-meta.json /public.php?service=host-meta-json [QSA,L]
+RewriteRule ^.well-known/carddav /remote.php/carddav/ [R]
+RewriteRule ^.well-known/caldav /remote.php/caldav/ [R]
+RewriteRule ^apps/calendar/caldav.php remote.php/caldav/ [QSA,L]
+RewriteRule ^apps/contacts/carddav.php remote.php/carddav/ [QSA,L]
+RewriteRule ^apps/([^/]*)/(.*\.(css|php))$ index.php?app=$1&getfile=$2 [QSA,L]
+RewriteRule ^remote/(.*) remote.php [QSA,L]
+
+
+AddType image/svg+xml svg svgz
+AddEncoding gzip svgz
+
+AddDefaultCharset utf-8
+Options -Indexes
diff -Nru owncloud-1.1+git20110209/3rdparty/Archive/Tar.php owncloud-5.0.4debian/3rdparty/Archive/Tar.php
--- owncloud-1.1+git20110209/3rdparty/Archive/Tar.php 1970-01-01 00:00:00.000000000 +0000
+++ owncloud-5.0.4debian/3rdparty/Archive/Tar.php 2013-04-10 17:29:58.000000000 +0000
@@ -0,0 +1,1973 @@
+
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * 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.
+ *
+ * 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.
+ *
+ * @category File_Formats
+ * @package Archive_Tar
+ * @author Vincent Blavet
+ * @copyright 1997-2010 The Authors
+ * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: Tar.php 324840 2012-04-05 08:44:41Z mrook $
+ * @link http://pear.php.net/package/Archive_Tar
+ */
+
+require_once 'PEAR.php';
+
+define('ARCHIVE_TAR_ATT_SEPARATOR', 90001);
+define('ARCHIVE_TAR_END_BLOCK', pack("a512", ''));
+
+/**
+* Creates a (compressed) Tar archive
+*
+* @package Archive_Tar
+* @author Vincent Blavet
+* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
+* @version $Revision: 324840 $
+*/
+class Archive_Tar extends PEAR
+{
+ /**
+ * @var string Name of the Tar
+ */
+ var $_tarname='';
+
+ /**
+ * @var boolean if true, the Tar file will be gzipped
+ */
+ var $_compress=false;
+
+ /**
+ * @var string Type of compression : 'none', 'gz' or 'bz2'
+ */
+ var $_compress_type='none';
+
+ /**
+ * @var string Explode separator
+ */
+ var $_separator=' ';
+
+ /**
+ * @var file descriptor
+ */
+ var $_file=0;
+
+ /**
+ * @var string Local Tar name of a remote Tar (http:// or ftp://)
+ */
+ var $_temp_tarname='';
+
+ /**
+ * @var string regular expression for ignoring files or directories
+ */
+ var $_ignore_regexp='';
+
+ /**
+ * @var object PEAR_Error object
+ */
+ var $error_object=null;
+
+ // {{{ constructor
+ /**
+ * Archive_Tar Class constructor. This flavour of the constructor only
+ * declare a new Archive_Tar object, identifying it by the name of the
+ * tar file.
+ * If the compress argument is set the tar will be read or created as a
+ * gzip or bz2 compressed TAR file.
+ *
+ * @param string $p_tarname The name of the tar archive to create
+ * @param string $p_compress can be null, 'gz' or 'bz2'. This
+ * parameter indicates if gzip or bz2 compression
+ * is required. For compatibility reason the
+ * boolean value 'true' means 'gz'.
+ *
+ * @access public
+ */
+ function Archive_Tar($p_tarname, $p_compress = null)
+ {
+ $this->PEAR();
+ $this->_compress = false;
+ $this->_compress_type = 'none';
+ if (($p_compress === null) || ($p_compress == '')) {
+ if (@file_exists($p_tarname)) {
+ if ($fp = @fopen($p_tarname, "rb")) {
+ // look for gzip magic cookie
+ $data = fread($fp, 2);
+ fclose($fp);
+ if ($data == "\37\213") {
+ $this->_compress = true;
+ $this->_compress_type = 'gz';
+ // No sure it's enought for a magic code ....
+ } elseif ($data == "BZ") {
+ $this->_compress = true;
+ $this->_compress_type = 'bz2';
+ }
+ }
+ } else {
+ // probably a remote file or some file accessible
+ // through a stream interface
+ if (substr($p_tarname, -2) == 'gz') {
+ $this->_compress = true;
+ $this->_compress_type = 'gz';
+ } elseif ((substr($p_tarname, -3) == 'bz2') ||
+ (substr($p_tarname, -2) == 'bz')) {
+ $this->_compress = true;
+ $this->_compress_type = 'bz2';
+ }
+ }
+ } else {
+ if (($p_compress === true) || ($p_compress == 'gz')) {
+ $this->_compress = true;
+ $this->_compress_type = 'gz';
+ } else if ($p_compress == 'bz2') {
+ $this->_compress = true;
+ $this->_compress_type = 'bz2';
+ } else {
+ $this->_error("Unsupported compression type '$p_compress'\n".
+ "Supported types are 'gz' and 'bz2'.\n");
+ return false;
+ }
+ }
+ $this->_tarname = $p_tarname;
+ if ($this->_compress) { // assert zlib or bz2 extension support
+ if ($this->_compress_type == 'gz')
+ $extname = 'zlib';
+ else if ($this->_compress_type == 'bz2')
+ $extname = 'bz2';
+
+ if (!extension_loaded($extname)) {
+ PEAR::loadExtension($extname);
+ }
+ if (!extension_loaded($extname)) {
+ $this->_error("The extension '$extname' couldn't be found.\n".
+ "Please make sure your version of PHP was built ".
+ "with '$extname' support.\n");
+ return false;
+ }
+ }
+ }
+ // }}}
+
+ // {{{ destructor
+ function _Archive_Tar()
+ {
+ $this->_close();
+ // ----- Look for a local copy to delete
+ if ($this->_temp_tarname != '')
+ @unlink($this->_temp_tarname);
+ $this->_PEAR();
+ }
+ // }}}
+
+ // {{{ create()
+ /**
+ * This method creates the archive file and add the files / directories
+ * that are listed in $p_filelist.
+ * If a file with the same name exist and is writable, it is replaced
+ * by the new tar.
+ * The method return false and a PEAR error text.
+ * The $p_filelist parameter can be an array of string, each string
+ * representing a filename or a directory name with their path if
+ * needed. It can also be a single string with names separated by a
+ * single blank.
+ * For each directory added in the archive, the files and
+ * sub-directories are also added.
+ * See also createModify() method for more details.
+ *
+ * @param array $p_filelist An array of filenames and directory names, or a
+ * single string with names separated by a single
+ * blank space.
+ *
+ * @return true on success, false on error.
+ * @see createModify()
+ * @access public
+ */
+ function create($p_filelist)
+ {
+ return $this->createModify($p_filelist, '', '');
+ }
+ // }}}
+
+ // {{{ add()
+ /**
+ * This method add the files / directories that are listed in $p_filelist in
+ * the archive. If the archive does not exist it is created.
+ * The method return false and a PEAR error text.
+ * The files and directories listed are only added at the end of the archive,
+ * even if a file with the same name is already archived.
+ * See also createModify() method for more details.
+ *
+ * @param array $p_filelist An array of filenames and directory names, or a
+ * single string with names separated by a single
+ * blank space.
+ *
+ * @return true on success, false on error.
+ * @see createModify()
+ * @access public
+ */
+ function add($p_filelist)
+ {
+ return $this->addModify($p_filelist, '', '');
+ }
+ // }}}
+
+ // {{{ extract()
+ function extract($p_path='', $p_preserve=false)
+ {
+ return $this->extractModify($p_path, '', $p_preserve);
+ }
+ // }}}
+
+ // {{{ listContent()
+ function listContent()
+ {
+ $v_list_detail = array();
+
+ if ($this->_openRead()) {
+ if (!$this->_extractList('', $v_list_detail, "list", '', '')) {
+ unset($v_list_detail);
+ $v_list_detail = 0;
+ }
+ $this->_close();
+ }
+
+ return $v_list_detail;
+ }
+ // }}}
+
+ // {{{ createModify()
+ /**
+ * This method creates the archive file and add the files / directories
+ * that are listed in $p_filelist.
+ * If the file already exists and is writable, it is replaced by the
+ * new tar. It is a create and not an add. If the file exists and is
+ * read-only or is a directory it is not replaced. The method return
+ * false and a PEAR error text.
+ * The $p_filelist parameter can be an array of string, each string
+ * representing a filename or a directory name with their path if
+ * needed. It can also be a single string with names separated by a
+ * single blank.
+ * The path indicated in $p_remove_dir will be removed from the
+ * memorized path of each file / directory listed when this path
+ * exists. By default nothing is removed (empty path '')
+ * The path indicated in $p_add_dir will be added at the beginning of
+ * the memorized path of each file / directory listed. However it can
+ * be set to empty ''. The adding of a path is done after the removing
+ * of path.
+ * The path add/remove ability enables the user to prepare an archive
+ * for extraction in a different path than the origin files are.
+ * See also addModify() method for file adding properties.
+ *
+ * @param array $p_filelist An array of filenames and directory names,
+ * or a single string with names separated by
+ * a single blank space.
+ * @param string $p_add_dir A string which contains a path to be added
+ * to the memorized path of each element in
+ * the list.
+ * @param string $p_remove_dir A string which contains a path to be
+ * removed from the memorized path of each
+ * element in the list, when relevant.
+ *
+ * @return boolean true on success, false on error.
+ * @access public
+ * @see addModify()
+ */
+ function createModify($p_filelist, $p_add_dir, $p_remove_dir='')
+ {
+ $v_result = true;
+
+ if (!$this->_openWrite())
+ return false;
+
+ if ($p_filelist != '') {
+ if (is_array($p_filelist))
+ $v_list = $p_filelist;
+ elseif (is_string($p_filelist))
+ $v_list = explode($this->_separator, $p_filelist);
+ else {
+ $this->_cleanFile();
+ $this->_error('Invalid file list');
+ return false;
+ }
+
+ $v_result = $this->_addList($v_list, $p_add_dir, $p_remove_dir);
+ }
+
+ if ($v_result) {
+ $this->_writeFooter();
+ $this->_close();
+ } else
+ $this->_cleanFile();
+
+ return $v_result;
+ }
+ // }}}
+
+ // {{{ addModify()
+ /**
+ * This method add the files / directories listed in $p_filelist at the
+ * end of the existing archive. If the archive does not yet exists it
+ * is created.
+ * The $p_filelist parameter can be an array of string, each string
+ * representing a filename or a directory name with their path if
+ * needed. It can also be a single string with names separated by a
+ * single blank.
+ * The path indicated in $p_remove_dir will be removed from the
+ * memorized path of each file / directory listed when this path
+ * exists. By default nothing is removed (empty path '')
+ * The path indicated in $p_add_dir will be added at the beginning of
+ * the memorized path of each file / directory listed. However it can
+ * be set to empty ''. The adding of a path is done after the removing
+ * of path.
+ * The path add/remove ability enables the user to prepare an archive
+ * for extraction in a different path than the origin files are.
+ * If a file/dir is already in the archive it will only be added at the
+ * end of the archive. There is no update of the existing archived
+ * file/dir. However while extracting the archive, the last file will
+ * replace the first one. This results in a none optimization of the
+ * archive size.
+ * If a file/dir does not exist the file/dir is ignored. However an
+ * error text is send to PEAR error.
+ * If a file/dir is not readable the file/dir is ignored. However an
+ * error text is send to PEAR error.
+ *
+ * @param array $p_filelist An array of filenames and directory
+ * names, or a single string with names
+ * separated by a single blank space.
+ * @param string $p_add_dir A string which contains a path to be
+ * added to the memorized path of each
+ * element in the list.
+ * @param string $p_remove_dir A string which contains a path to be
+ * removed from the memorized path of
+ * each element in the list, when
+ * relevant.
+ *
+ * @return true on success, false on error.
+ * @access public
+ */
+ function addModify($p_filelist, $p_add_dir, $p_remove_dir='')
+ {
+ $v_result = true;
+
+ if (!$this->_isArchive())
+ $v_result = $this->createModify($p_filelist, $p_add_dir,
+ $p_remove_dir);
+ else {
+ if (is_array($p_filelist))
+ $v_list = $p_filelist;
+ elseif (is_string($p_filelist))
+ $v_list = explode($this->_separator, $p_filelist);
+ else {
+ $this->_error('Invalid file list');
+ return false;
+ }
+
+ $v_result = $this->_append($v_list, $p_add_dir, $p_remove_dir);
+ }
+
+ return $v_result;
+ }
+ // }}}
+
+ // {{{ addString()
+ /**
+ * This method add a single string as a file at the
+ * end of the existing archive. If the archive does not yet exists it
+ * is created.
+ *
+ * @param string $p_filename A string which contains the full
+ * filename path that will be associated
+ * with the string.
+ * @param string $p_string The content of the file added in
+ * the archive.
+ *
+ * @return true on success, false on error.
+ * @access public
+ */
+ function addString($p_filename, $p_string)
+ {
+ $v_result = true;
+
+ if (!$this->_isArchive()) {
+ if (!$this->_openWrite()) {
+ return false;
+ }
+ $this->_close();
+ }
+
+ if (!$this->_openAppend())
+ return false;
+
+ // Need to check the get back to the temporary file ? ....
+ $v_result = $this->_addString($p_filename, $p_string);
+
+ $this->_writeFooter();
+
+ $this->_close();
+
+ return $v_result;
+ }
+ // }}}
+
+ // {{{ extractModify()
+ /**
+ * This method extract all the content of the archive in the directory
+ * indicated by $p_path. When relevant the memorized path of the
+ * files/dir can be modified by removing the $p_remove_path path at the
+ * beginning of the file/dir path.
+ * While extracting a file, if the directory path does not exists it is
+ * created.
+ * While extracting a file, if the file already exists it is replaced
+ * without looking for last modification date.
+ * While extracting a file, if the file already exists and is write
+ * protected, the extraction is aborted.
+ * While extracting a file, if a directory with the same name already
+ * exists, the extraction is aborted.
+ * While extracting a directory, if a file with the same name already
+ * exists, the extraction is aborted.
+ * While extracting a file/directory if the destination directory exist
+ * and is write protected, or does not exist but can not be created,
+ * the extraction is aborted.
+ * If after extraction an extracted file does not show the correct
+ * stored file size, the extraction is aborted.
+ * When the extraction is aborted, a PEAR error text is set and false
+ * is returned. However the result can be a partial extraction that may
+ * need to be manually cleaned.
+ *
+ * @param string $p_path The path of the directory where the
+ * files/dir need to by extracted.
+ * @param string $p_remove_path Part of the memorized path that can be
+ * removed if present at the beginning of
+ * the file/dir path.
+ * @param boolean $p_preserve Preserve user/group ownership of files
+ *
+ * @return boolean true on success, false on error.
+ * @access public
+ * @see extractList()
+ */
+ function extractModify($p_path, $p_remove_path, $p_preserve=false)
+ {
+ $v_result = true;
+ $v_list_detail = array();
+
+ if ($v_result = $this->_openRead()) {
+ $v_result = $this->_extractList($p_path, $v_list_detail,
+ "complete", 0, $p_remove_path, $p_preserve);
+ $this->_close();
+ }
+
+ return $v_result;
+ }
+ // }}}
+
+ // {{{ extractInString()
+ /**
+ * This method extract from the archive one file identified by $p_filename.
+ * The return value is a string with the file content, or NULL on error.
+ *
+ * @param string $p_filename The path of the file to extract in a string.
+ *
+ * @return a string with the file content or NULL.
+ * @access public
+ */
+ function extractInString($p_filename)
+ {
+ if ($this->_openRead()) {
+ $v_result = $this->_extractInString($p_filename);
+ $this->_close();
+ } else {
+ $v_result = null;
+ }
+
+ return $v_result;
+ }
+ // }}}
+
+ // {{{ extractList()
+ /**
+ * This method extract from the archive only the files indicated in the
+ * $p_filelist. These files are extracted in the current directory or
+ * in the directory indicated by the optional $p_path parameter.
+ * If indicated the $p_remove_path can be used in the same way as it is
+ * used in extractModify() method.
+ *
+ * @param array $p_filelist An array of filenames and directory names,
+ * or a single string with names separated
+ * by a single blank space.
+ * @param string $p_path The path of the directory where the
+ * files/dir need to by extracted.
+ * @param string $p_remove_path Part of the memorized path that can be
+ * removed if present at the beginning of
+ * the file/dir path.
+ * @param boolean $p_preserve Preserve user/group ownership of files
+ *
+ * @return true on success, false on error.
+ * @access public
+ * @see extractModify()
+ */
+ function extractList($p_filelist, $p_path='', $p_remove_path='', $p_preserve=false)
+ {
+ $v_result = true;
+ $v_list_detail = array();
+
+ if (is_array($p_filelist))
+ $v_list = $p_filelist;
+ elseif (is_string($p_filelist))
+ $v_list = explode($this->_separator, $p_filelist);
+ else {
+ $this->_error('Invalid string list');
+ return false;
+ }
+
+ if ($v_result = $this->_openRead()) {
+ $v_result = $this->_extractList($p_path, $v_list_detail, "partial",
+ $v_list, $p_remove_path, $p_preserve);
+ $this->_close();
+ }
+
+ return $v_result;
+ }
+ // }}}
+
+ // {{{ setAttribute()
+ /**
+ * This method set specific attributes of the archive. It uses a variable
+ * list of parameters, in the format attribute code + attribute values :
+ * $arch->setAttribute(ARCHIVE_TAR_ATT_SEPARATOR, ',');
+ *
+ * @param mixed $argv variable list of attributes and values
+ *
+ * @return true on success, false on error.
+ * @access public
+ */
+ function setAttribute()
+ {
+ $v_result = true;
+
+ // ----- Get the number of variable list of arguments
+ if (($v_size = func_num_args()) == 0) {
+ return true;
+ }
+
+ // ----- Get the arguments
+ $v_att_list = &func_get_args();
+
+ // ----- Read the attributes
+ $i=0;
+ while ($i<$v_size) {
+
+ // ----- Look for next option
+ switch ($v_att_list[$i]) {
+ // ----- Look for options that request a string value
+ case ARCHIVE_TAR_ATT_SEPARATOR :
+ // ----- Check the number of parameters
+ if (($i+1) >= $v_size) {
+ $this->_error('Invalid number of parameters for '
+ .'attribute ARCHIVE_TAR_ATT_SEPARATOR');
+ return false;
+ }
+
+ // ----- Get the value
+ $this->_separator = $v_att_list[$i+1];
+ $i++;
+ break;
+
+ default :
+ $this->_error('Unknow attribute code '.$v_att_list[$i].'');
+ return false;
+ }
+
+ // ----- Next attribute
+ $i++;
+ }
+
+ return $v_result;
+ }
+ // }}}
+
+ // {{{ setIgnoreRegexp()
+ /**
+ * This method sets the regular expression for ignoring files and directories
+ * at import, for example:
+ * $arch->setIgnoreRegexp("#CVS|\.svn#");
+ *
+ * @param string $regexp regular expression defining which files or directories to ignore
+ *
+ * @access public
+ */
+ function setIgnoreRegexp($regexp)
+ {
+ $this->_ignore_regexp = $regexp;
+ }
+ // }}}
+
+ // {{{ setIgnoreList()
+ /**
+ * This method sets the regular expression for ignoring all files and directories
+ * matching the filenames in the array list at import, for example:
+ * $arch->setIgnoreList(array('CVS', '.svn', 'bin/tool'));
+ *
+ * @param array $list a list of file or directory names to ignore
+ *
+ * @access public
+ */
+ function setIgnoreList($list)
+ {
+ $regexp = str_replace(array('#', '.', '^', '$'), array('\#', '\.', '\^', '\$'), $list);
+ $regexp = '#/'.join('$|/', $list).'#';
+ $this->setIgnoreRegexp($regexp);
+ }
+ // }}}
+
+ // {{{ _error()
+ function _error($p_message)
+ {
+ $this->error_object = &$this->raiseError($p_message);
+ }
+ // }}}
+
+ // {{{ _warning()
+ function _warning($p_message)
+ {
+ $this->error_object = &$this->raiseError($p_message);
+ }
+ // }}}
+
+ // {{{ _isArchive()
+ function _isArchive($p_filename=null)
+ {
+ if ($p_filename == null) {
+ $p_filename = $this->_tarname;
+ }
+ clearstatcache();
+ return @is_file($p_filename) && !@is_link($p_filename);
+ }
+ // }}}
+
+ // {{{ _openWrite()
+ function _openWrite()
+ {
+ if ($this->_compress_type == 'gz' && function_exists('gzopen'))
+ $this->_file = @gzopen($this->_tarname, "wb9");
+ else if ($this->_compress_type == 'bz2' && function_exists('bzopen'))
+ $this->_file = @bzopen($this->_tarname, "w");
+ else if ($this->_compress_type == 'none')
+ $this->_file = @fopen($this->_tarname, "wb");
+ else
+ $this->_error('Unknown or missing compression type ('
+ .$this->_compress_type.')');
+
+ if ($this->_file == 0) {
+ $this->_error('Unable to open in write mode \''
+ .$this->_tarname.'\'');
+ return false;
+ }
+
+ return true;
+ }
+ // }}}
+
+ // {{{ _openRead()
+ function _openRead()
+ {
+ if (strtolower(substr($this->_tarname, 0, 7)) == 'http://') {
+
+ // ----- Look if a local copy need to be done
+ if ($this->_temp_tarname == '') {
+ $this->_temp_tarname = uniqid('tar').'.tmp';
+ if (!$v_file_from = @fopen($this->_tarname, 'rb')) {
+ $this->_error('Unable to open in read mode \''
+ .$this->_tarname.'\'');
+ $this->_temp_tarname = '';
+ return false;
+ }
+ if (!$v_file_to = @fopen($this->_temp_tarname, 'wb')) {
+ $this->_error('Unable to open in write mode \''
+ .$this->_temp_tarname.'\'');
+ $this->_temp_tarname = '';
+ return false;
+ }
+ while ($v_data = @fread($v_file_from, 1024))
+ @fwrite($v_file_to, $v_data);
+ @fclose($v_file_from);
+ @fclose($v_file_to);
+ }
+
+ // ----- File to open if the local copy
+ $v_filename = $this->_temp_tarname;
+
+ } else
+ // ----- File to open if the normal Tar file
+ $v_filename = $this->_tarname;
+
+ if ($this->_compress_type == 'gz')
+ $this->_file = @gzopen($v_filename, "rb");
+ else if ($this->_compress_type == 'bz2')
+ $this->_file = @bzopen($v_filename, "r");
+ else if ($this->_compress_type == 'none')
+ $this->_file = @fopen($v_filename, "rb");
+ else
+ $this->_error('Unknown or missing compression type ('
+ .$this->_compress_type.')');
+
+ if ($this->_file == 0) {
+ $this->_error('Unable to open in read mode \''.$v_filename.'\'');
+ return false;
+ }
+
+ return true;
+ }
+ // }}}
+
+ // {{{ _openReadWrite()
+ function _openReadWrite()
+ {
+ if ($this->_compress_type == 'gz')
+ $this->_file = @gzopen($this->_tarname, "r+b");
+ else if ($this->_compress_type == 'bz2') {
+ $this->_error('Unable to open bz2 in read/write mode \''
+ .$this->_tarname.'\' (limitation of bz2 extension)');
+ return false;
+ } else if ($this->_compress_type == 'none')
+ $this->_file = @fopen($this->_tarname, "r+b");
+ else
+ $this->_error('Unknown or missing compression type ('
+ .$this->_compress_type.')');
+
+ if ($this->_file == 0) {
+ $this->_error('Unable to open in read/write mode \''
+ .$this->_tarname.'\'');
+ return false;
+ }
+
+ return true;
+ }
+ // }}}
+
+ // {{{ _close()
+ function _close()
+ {
+ //if (isset($this->_file)) {
+ if (is_resource($this->_file)) {
+ if ($this->_compress_type == 'gz')
+ @gzclose($this->_file);
+ else if ($this->_compress_type == 'bz2')
+ @bzclose($this->_file);
+ else if ($this->_compress_type == 'none')
+ @fclose($this->_file);
+ else
+ $this->_error('Unknown or missing compression type ('
+ .$this->_compress_type.')');
+
+ $this->_file = 0;
+ }
+
+ // ----- Look if a local copy need to be erase
+ // Note that it might be interesting to keep the url for a time : ToDo
+ if ($this->_temp_tarname != '') {
+ @unlink($this->_temp_tarname);
+ $this->_temp_tarname = '';
+ }
+
+ return true;
+ }
+ // }}}
+
+ // {{{ _cleanFile()
+ function _cleanFile()
+ {
+ $this->_close();
+
+ // ----- Look for a local copy
+ if ($this->_temp_tarname != '') {
+ // ----- Remove the local copy but not the remote tarname
+ @unlink($this->_temp_tarname);
+ $this->_temp_tarname = '';
+ } else {
+ // ----- Remove the local tarname file
+ @unlink($this->_tarname);
+ }
+ $this->_tarname = '';
+
+ return true;
+ }
+ // }}}
+
+ // {{{ _writeBlock()
+ function _writeBlock($p_binary_data, $p_len=null)
+ {
+ if (is_resource($this->_file)) {
+ if ($p_len === null) {
+ if ($this->_compress_type == 'gz')
+ @gzputs($this->_file, $p_binary_data);
+ else if ($this->_compress_type == 'bz2')
+ @bzwrite($this->_file, $p_binary_data);
+ else if ($this->_compress_type == 'none')
+ @fputs($this->_file, $p_binary_data);
+ else
+ $this->_error('Unknown or missing compression type ('
+ .$this->_compress_type.')');
+ } else {
+ if ($this->_compress_type == 'gz')
+ @gzputs($this->_file, $p_binary_data, $p_len);
+ else if ($this->_compress_type == 'bz2')
+ @bzwrite($this->_file, $p_binary_data, $p_len);
+ else if ($this->_compress_type == 'none')
+ @fputs($this->_file, $p_binary_data, $p_len);
+ else
+ $this->_error('Unknown or missing compression type ('
+ .$this->_compress_type.')');
+
+ }
+ }
+ return true;
+ }
+ // }}}
+
+ // {{{ _readBlock()
+ function _readBlock()
+ {
+ $v_block = null;
+ if (is_resource($this->_file)) {
+ if ($this->_compress_type == 'gz')
+ $v_block = @gzread($this->_file, 512);
+ else if ($this->_compress_type == 'bz2')
+ $v_block = @bzread($this->_file, 512);
+ else if ($this->_compress_type == 'none')
+ $v_block = @fread($this->_file, 512);
+ else
+ $this->_error('Unknown or missing compression type ('
+ .$this->_compress_type.')');
+ }
+ return $v_block;
+ }
+ // }}}
+
+ // {{{ _jumpBlock()
+ function _jumpBlock($p_len=null)
+ {
+ if (is_resource($this->_file)) {
+ if ($p_len === null)
+ $p_len = 1;
+
+ if ($this->_compress_type == 'gz') {
+ @gzseek($this->_file, gztell($this->_file)+($p_len*512));
+ }
+ else if ($this->_compress_type == 'bz2') {
+ // ----- Replace missing bztell() and bzseek()
+ for ($i=0; $i<$p_len; $i++)
+ $this->_readBlock();
+ } else if ($this->_compress_type == 'none')
+ @fseek($this->_file, $p_len*512, SEEK_CUR);
+ else
+ $this->_error('Unknown or missing compression type ('
+ .$this->_compress_type.')');
+
+ }
+ return true;
+ }
+ // }}}
+
+ // {{{ _writeFooter()
+ function _writeFooter()
+ {
+ if (is_resource($this->_file)) {
+ // ----- Write the last 0 filled block for end of archive
+ $v_binary_data = pack('a1024', '');
+ $this->_writeBlock($v_binary_data);
+ }
+ return true;
+ }
+ // }}}
+
+ // {{{ _addList()
+ function _addList($p_list, $p_add_dir, $p_remove_dir)
+ {
+ $v_result=true;
+ $v_header = array();
+
+ // ----- Remove potential windows directory separator
+ $p_add_dir = $this->_translateWinPath($p_add_dir);
+ $p_remove_dir = $this->_translateWinPath($p_remove_dir, false);
+
+ if (!$this->_file) {
+ $this->_error('Invalid file descriptor');
+ return false;
+ }
+
+ if (sizeof($p_list) == 0)
+ return true;
+
+ foreach ($p_list as $v_filename) {
+ if (!$v_result) {
+ break;
+ }
+
+ // ----- Skip the current tar name
+ if ($v_filename == $this->_tarname)
+ continue;
+
+ if ($v_filename == '')
+ continue;
+
+ // ----- ignore files and directories matching the ignore regular expression
+ if ($this->_ignore_regexp && preg_match($this->_ignore_regexp, '/'.$v_filename)) {
+ $this->_warning("File '$v_filename' ignored");
+ continue;
+ }
+
+ if (!file_exists($v_filename) && !is_link($v_filename)) {
+ $this->_warning("File '$v_filename' does not exist");
+ continue;
+ }
+
+ // ----- Add the file or directory header
+ if (!$this->_addFile($v_filename, $v_header, $p_add_dir, $p_remove_dir))
+ return false;
+
+ if (@is_dir($v_filename) && !@is_link($v_filename)) {
+ if (!($p_hdir = opendir($v_filename))) {
+ $this->_warning("Directory '$v_filename' can not be read");
+ continue;
+ }
+ while (false !== ($p_hitem = readdir($p_hdir))) {
+ if (($p_hitem != '.') && ($p_hitem != '..')) {
+ if ($v_filename != ".")
+ $p_temp_list[0] = $v_filename.'/'.$p_hitem;
+ else
+ $p_temp_list[0] = $p_hitem;
+
+ $v_result = $this->_addList($p_temp_list,
+ $p_add_dir,
+ $p_remove_dir);
+ }
+ }
+
+ unset($p_temp_list);
+ unset($p_hdir);
+ unset($p_hitem);
+ }
+ }
+
+ return $v_result;
+ }
+ // }}}
+
+ // {{{ _addFile()
+ function _addFile($p_filename, &$p_header, $p_add_dir, $p_remove_dir, $v_stored_filename=null)
+ {
+ if (!$this->_file) {
+ $this->_error('Invalid file descriptor');
+ return false;
+ }
+
+ if ($p_filename == '') {
+ $this->_error('Invalid file name');
+ return false;
+ }
+
+ // ownCloud change to make it possible to specify the filename to use
+ if(is_null($v_stored_filename)) {
+ // ----- Calculate the stored filename
+ $p_filename = $this->_translateWinPath($p_filename, false);
+ $v_stored_filename = $p_filename;
+ if (strcmp($p_filename, $p_remove_dir) == 0) {
+ return true;
+ }
+ if ($p_remove_dir != '') {
+ if (substr($p_remove_dir, -1) != '/')
+ $p_remove_dir .= '/';
+
+ if (substr($p_filename, 0, strlen($p_remove_dir)) == $p_remove_dir)
+ $v_stored_filename = substr($p_filename, strlen($p_remove_dir));
+ }
+ $v_stored_filename = $this->_translateWinPath($v_stored_filename);
+ if ($p_add_dir != '') {
+ if (substr($p_add_dir, -1) == '/')
+ $v_stored_filename = $p_add_dir.$v_stored_filename;
+ else
+ $v_stored_filename = $p_add_dir.'/'.$v_stored_filename;
+ }
+
+ $v_stored_filename = $this->_pathReduction($v_stored_filename);
+ }
+
+ if ($this->_isArchive($p_filename)) {
+ if (($v_file = @fopen($p_filename, "rb")) == 0) {
+ $this->_warning("Unable to open file '".$p_filename
+ ."' in binary read mode");
+ return true;
+ }
+
+ if (!$this->_writeHeader($p_filename, $v_stored_filename))
+ return false;
+
+ while (($v_buffer = fread($v_file, 512)) != '') {
+ $v_binary_data = pack("a512", "$v_buffer");
+ $this->_writeBlock($v_binary_data);
+ }
+
+ fclose($v_file);
+
+ } else {
+ // ----- Only header for dir
+ if (!$this->_writeHeader($p_filename, $v_stored_filename))
+ return false;
+ }
+
+ return true;
+ }
+ // }}}
+
+ // {{{ _addString()
+ function _addString($p_filename, $p_string)
+ {
+ if (!$this->_file) {
+ $this->_error('Invalid file descriptor');
+ return false;
+ }
+
+ if ($p_filename == '') {
+ $this->_error('Invalid file name');
+ return false;
+ }
+
+ // ----- Calculate the stored filename
+ $p_filename = $this->_translateWinPath($p_filename, false);;
+
+ if (!$this->_writeHeaderBlock($p_filename, strlen($p_string),
+ time(), 384, "", 0, 0))
+ return false;
+
+ $i=0;
+ while (($v_buffer = substr($p_string, (($i++)*512), 512)) != '') {
+ $v_binary_data = pack("a512", $v_buffer);
+ $this->_writeBlock($v_binary_data);
+ }
+
+ return true;
+ }
+ // }}}
+
+ // {{{ _writeHeader()
+ function _writeHeader($p_filename, $p_stored_filename)
+ {
+ if ($p_stored_filename == '')
+ $p_stored_filename = $p_filename;
+ $v_reduce_filename = $this->_pathReduction($p_stored_filename);
+
+ if (strlen($v_reduce_filename) > 99) {
+ if (!$this->_writeLongHeader($v_reduce_filename))
+ return false;
+ }
+
+ $v_info = lstat($p_filename);
+ $v_uid = sprintf("%07s", DecOct($v_info[4]));
+ $v_gid = sprintf("%07s", DecOct($v_info[5]));
+ $v_perms = sprintf("%07s", DecOct($v_info['mode'] & 000777));
+
+ $v_mtime = sprintf("%011s", DecOct($v_info['mtime']));
+
+ $v_linkname = '';
+
+ if (@is_link($p_filename)) {
+ $v_typeflag = '2';
+ $v_linkname = readlink($p_filename);
+ $v_size = sprintf("%011s", DecOct(0));
+ } elseif (@is_dir($p_filename)) {
+ $v_typeflag = "5";
+ $v_size = sprintf("%011s", DecOct(0));
+ } else {
+ $v_typeflag = '0';
+ clearstatcache();
+ $v_size = sprintf("%011s", DecOct($v_info['size']));
+ }
+
+ $v_magic = 'ustar ';
+
+ $v_version = ' ';
+
+ if (function_exists('posix_getpwuid'))
+ {
+ $userinfo = posix_getpwuid($v_info[4]);
+ $groupinfo = posix_getgrgid($v_info[5]);
+
+ $v_uname = $userinfo['name'];
+ $v_gname = $groupinfo['name'];
+ }
+ else
+ {
+ $v_uname = '';
+ $v_gname = '';
+ }
+
+ $v_devmajor = '';
+
+ $v_devminor = '';
+
+ $v_prefix = '';
+
+ $v_binary_data_first = pack("a100a8a8a8a12a12",
+ $v_reduce_filename, $v_perms, $v_uid,
+ $v_gid, $v_size, $v_mtime);
+ $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12",
+ $v_typeflag, $v_linkname, $v_magic,
+ $v_version, $v_uname, $v_gname,
+ $v_devmajor, $v_devminor, $v_prefix, '');
+
+ // ----- Calculate the checksum
+ $v_checksum = 0;
+ // ..... First part of the header
+ for ($i=0; $i<148; $i++)
+ $v_checksum += ord(substr($v_binary_data_first,$i,1));
+ // ..... Ignore the checksum value and replace it by ' ' (space)
+ for ($i=148; $i<156; $i++)
+ $v_checksum += ord(' ');
+ // ..... Last part of the header
+ for ($i=156, $j=0; $i<512; $i++, $j++)
+ $v_checksum += ord(substr($v_binary_data_last,$j,1));
+
+ // ----- Write the first 148 bytes of the header in the archive
+ $this->_writeBlock($v_binary_data_first, 148);
+
+ // ----- Write the calculated checksum
+ $v_checksum = sprintf("%06s ", DecOct($v_checksum));
+ $v_binary_data = pack("a8", $v_checksum);
+ $this->_writeBlock($v_binary_data, 8);
+
+ // ----- Write the last 356 bytes of the header in the archive
+ $this->_writeBlock($v_binary_data_last, 356);
+
+ return true;
+ }
+ // }}}
+
+ // {{{ _writeHeaderBlock()
+ function _writeHeaderBlock($p_filename, $p_size, $p_mtime=0, $p_perms=0,
+ $p_type='', $p_uid=0, $p_gid=0)
+ {
+ $p_filename = $this->_pathReduction($p_filename);
+
+ if (strlen($p_filename) > 99) {
+ if (!$this->_writeLongHeader($p_filename))
+ return false;
+ }
+
+ if ($p_type == "5") {
+ $v_size = sprintf("%011s", DecOct(0));
+ } else {
+ $v_size = sprintf("%011s", DecOct($p_size));
+ }
+
+ $v_uid = sprintf("%07s", DecOct($p_uid));
+ $v_gid = sprintf("%07s", DecOct($p_gid));
+ $v_perms = sprintf("%07s", DecOct($p_perms & 000777));
+
+ $v_mtime = sprintf("%11s", DecOct($p_mtime));
+
+ $v_linkname = '';
+
+ $v_magic = 'ustar ';
+
+ $v_version = ' ';
+
+ if (function_exists('posix_getpwuid'))
+ {
+ $userinfo = posix_getpwuid($p_uid);
+ $groupinfo = posix_getgrgid($p_gid);
+
+ $v_uname = $userinfo['name'];
+ $v_gname = $groupinfo['name'];
+ }
+ else
+ {
+ $v_uname = '';
+ $v_gname = '';
+ }
+
+ $v_devmajor = '';
+
+ $v_devminor = '';
+
+ $v_prefix = '';
+
+ $v_binary_data_first = pack("a100a8a8a8a12A12",
+ $p_filename, $v_perms, $v_uid, $v_gid,
+ $v_size, $v_mtime);
+ $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12",
+ $p_type, $v_linkname, $v_magic,
+ $v_version, $v_uname, $v_gname,
+ $v_devmajor, $v_devminor, $v_prefix, '');
+
+ // ----- Calculate the checksum
+ $v_checksum = 0;
+ // ..... First part of the header
+ for ($i=0; $i<148; $i++)
+ $v_checksum += ord(substr($v_binary_data_first,$i,1));
+ // ..... Ignore the checksum value and replace it by ' ' (space)
+ for ($i=148; $i<156; $i++)
+ $v_checksum += ord(' ');
+ // ..... Last part of the header
+ for ($i=156, $j=0; $i<512; $i++, $j++)
+ $v_checksum += ord(substr($v_binary_data_last,$j,1));
+
+ // ----- Write the first 148 bytes of the header in the archive
+ $this->_writeBlock($v_binary_data_first, 148);
+
+ // ----- Write the calculated checksum
+ $v_checksum = sprintf("%06s ", DecOct($v_checksum));
+ $v_binary_data = pack("a8", $v_checksum);
+ $this->_writeBlock($v_binary_data, 8);
+
+ // ----- Write the last 356 bytes of the header in the archive
+ $this->_writeBlock($v_binary_data_last, 356);
+
+ return true;
+ }
+ // }}}
+
+ // {{{ _writeLongHeader()
+ function _writeLongHeader($p_filename)
+ {
+ $v_size = sprintf("%11s ", DecOct(strlen($p_filename)));
+
+ $v_typeflag = 'L';
+
+ $v_linkname = '';
+
+ $v_magic = '';
+
+ $v_version = '';
+
+ $v_uname = '';
+
+ $v_gname = '';
+
+ $v_devmajor = '';
+
+ $v_devminor = '';
+
+ $v_prefix = '';
+
+ $v_binary_data_first = pack("a100a8a8a8a12a12",
+ '././@LongLink', 0, 0, 0, $v_size, 0);
+ $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12",
+ $v_typeflag, $v_linkname, $v_magic,
+ $v_version, $v_uname, $v_gname,
+ $v_devmajor, $v_devminor, $v_prefix, '');
+
+ // ----- Calculate the checksum
+ $v_checksum = 0;
+ // ..... First part of the header
+ for ($i=0; $i<148; $i++)
+ $v_checksum += ord(substr($v_binary_data_first,$i,1));
+ // ..... Ignore the checksum value and replace it by ' ' (space)
+ for ($i=148; $i<156; $i++)
+ $v_checksum += ord(' ');
+ // ..... Last part of the header
+ for ($i=156, $j=0; $i<512; $i++, $j++)
+ $v_checksum += ord(substr($v_binary_data_last,$j,1));
+
+ // ----- Write the first 148 bytes of the header in the archive
+ $this->_writeBlock($v_binary_data_first, 148);
+
+ // ----- Write the calculated checksum
+ $v_checksum = sprintf("%06s ", DecOct($v_checksum));
+ $v_binary_data = pack("a8", $v_checksum);
+ $this->_writeBlock($v_binary_data, 8);
+
+ // ----- Write the last 356 bytes of the header in the archive
+ $this->_writeBlock($v_binary_data_last, 356);
+
+ // ----- Write the filename as content of the block
+ $i=0;
+ while (($v_buffer = substr($p_filename, (($i++)*512), 512)) != '') {
+ $v_binary_data = pack("a512", "$v_buffer");
+ $this->_writeBlock($v_binary_data);
+ }
+
+ return true;
+ }
+ // }}}
+
+ // {{{ _readHeader()
+ function _readHeader($v_binary_data, &$v_header)
+ {
+ if (strlen($v_binary_data)==0) {
+ $v_header['filename'] = '';
+ return true;
+ }
+
+ if (strlen($v_binary_data) != 512) {
+ $v_header['filename'] = '';
+ $this->_error('Invalid block size : '.strlen($v_binary_data));
+ return false;
+ }
+
+ if (!is_array($v_header)) {
+ $v_header = array();
+ }
+ // ----- Calculate the checksum
+ $v_checksum = 0;
+ // ..... First part of the header
+ for ($i=0; $i<148; $i++)
+ $v_checksum+=ord(substr($v_binary_data,$i,1));
+ // ..... Ignore the checksum value and replace it by ' ' (space)
+ for ($i=148; $i<156; $i++)
+ $v_checksum += ord(' ');
+ // ..... Last part of the header
+ for ($i=156; $i<512; $i++)
+ $v_checksum+=ord(substr($v_binary_data,$i,1));
+
+ $v_data = unpack("a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/" .
+ "a8checksum/a1typeflag/a100link/a6magic/a2version/" .
+ "a32uname/a32gname/a8devmajor/a8devminor/a131prefix",
+ $v_binary_data);
+
+ if (strlen($v_data["prefix"]) > 0) {
+ $v_data["filename"] = "$v_data[prefix]/$v_data[filename]";
+ }
+
+ // ----- Extract the checksum
+ $v_header['checksum'] = OctDec(trim($v_data['checksum']));
+ if ($v_header['checksum'] != $v_checksum) {
+ $v_header['filename'] = '';
+
+ // ----- Look for last block (empty block)
+ if (($v_checksum == 256) && ($v_header['checksum'] == 0))
+ return true;
+
+ $this->_error('Invalid checksum for file "'.$v_data['filename']
+ .'" : '.$v_checksum.' calculated, '
+ .$v_header['checksum'].' expected');
+ return false;
+ }
+
+ // ----- Extract the properties
+ $v_header['filename'] = $v_data['filename'];
+ if ($this->_maliciousFilename($v_header['filename'])) {
+ $this->_error('Malicious .tar detected, file "' . $v_header['filename'] .
+ '" will not install in desired directory tree');
+ return false;
+ }
+ $v_header['mode'] = OctDec(trim($v_data['mode']));
+ $v_header['uid'] = OctDec(trim($v_data['uid']));
+ $v_header['gid'] = OctDec(trim($v_data['gid']));
+ $v_header['size'] = OctDec(trim($v_data['size']));
+ $v_header['mtime'] = OctDec(trim($v_data['mtime']));
+ if (($v_header['typeflag'] = $v_data['typeflag']) == "5") {
+ $v_header['size'] = 0;
+ }
+ $v_header['link'] = trim($v_data['link']);
+ /* ----- All these fields are removed form the header because
+ they do not carry interesting info
+ $v_header[magic] = trim($v_data[magic]);
+ $v_header[version] = trim($v_data[version]);
+ $v_header[uname] = trim($v_data[uname]);
+ $v_header[gname] = trim($v_data[gname]);
+ $v_header[devmajor] = trim($v_data[devmajor]);
+ $v_header[devminor] = trim($v_data[devminor]);
+ */
+
+ return true;
+ }
+ // }}}
+
+ // {{{ _maliciousFilename()
+ /**
+ * Detect and report a malicious file name
+ *
+ * @param string $file
+ *
+ * @return bool
+ * @access private
+ */
+ function _maliciousFilename($file)
+ {
+ if (strpos($file, '/../') !== false) {
+ return true;
+ }
+ if (strpos($file, '../') === 0) {
+ return true;
+ }
+ return false;
+ }
+ // }}}
+
+ // {{{ _readLongHeader()
+ function _readLongHeader(&$v_header)
+ {
+ $v_filename = '';
+ $n = floor($v_header['size']/512);
+ for ($i=0; $i<$n; $i++) {
+ $v_content = $this->_readBlock();
+ $v_filename .= $v_content;
+ }
+ if (($v_header['size'] % 512) != 0) {
+ $v_content = $this->_readBlock();
+ $v_filename .= trim($v_content);
+ }
+
+ // ----- Read the next header
+ $v_binary_data = $this->_readBlock();
+
+ if (!$this->_readHeader($v_binary_data, $v_header))
+ return false;
+
+ $v_filename = trim($v_filename);
+ $v_header['filename'] = $v_filename;
+ if ($this->_maliciousFilename($v_filename)) {
+ $this->_error('Malicious .tar detected, file "' . $v_filename .
+ '" will not install in desired directory tree');
+ return false;
+ }
+
+ return true;
+ }
+ // }}}
+
+ // {{{ _extractInString()
+ /**
+ * This method extract from the archive one file identified by $p_filename.
+ * The return value is a string with the file content, or null on error.
+ *
+ * @param string $p_filename The path of the file to extract in a string.
+ *
+ * @return a string with the file content or null.
+ * @access private
+ */
+ function _extractInString($p_filename)
+ {
+ $v_result_str = "";
+
+ While (strlen($v_binary_data = $this->_readBlock()) != 0)
+ {
+ if (!$this->_readHeader($v_binary_data, $v_header))
+ return null;
+
+ if ($v_header['filename'] == '')
+ continue;
+
+ // ----- Look for long filename
+ if ($v_header['typeflag'] == 'L') {
+ if (!$this->_readLongHeader($v_header))
+ return null;
+ }
+
+ if ($v_header['filename'] == $p_filename) {
+ if ($v_header['typeflag'] == "5") {
+ $this->_error('Unable to extract in string a directory '
+ .'entry {'.$v_header['filename'].'}');
+ return null;
+ } else {
+ $n = floor($v_header['size']/512);
+ for ($i=0; $i<$n; $i++) {
+ $v_result_str .= $this->_readBlock();
+ }
+ if (($v_header['size'] % 512) != 0) {
+ $v_content = $this->_readBlock();
+ $v_result_str .= substr($v_content, 0,
+ ($v_header['size'] % 512));
+ }
+ return $v_result_str;
+ }
+ } else {
+ $this->_jumpBlock(ceil(($v_header['size']/512)));
+ }
+ }
+
+ return null;
+ }
+ // }}}
+
+ // {{{ _extractList()
+ function _extractList($p_path, &$p_list_detail, $p_mode,
+ $p_file_list, $p_remove_path, $p_preserve=false)
+ {
+ $v_result=true;
+ $v_nb = 0;
+ $v_extract_all = true;
+ $v_listing = false;
+
+ $p_path = $this->_translateWinPath($p_path, false);
+ if ($p_path == '' || (substr($p_path, 0, 1) != '/'
+ && substr($p_path, 0, 3) != "../" && !strpos($p_path, ':'))) {
+ $p_path = "./".$p_path;
+ }
+ $p_remove_path = $this->_translateWinPath($p_remove_path);
+
+ // ----- Look for path to remove format (should end by /)
+ if (($p_remove_path != '') && (substr($p_remove_path, -1) != '/'))
+ $p_remove_path .= '/';
+ $p_remove_path_size = strlen($p_remove_path);
+
+ switch ($p_mode) {
+ case "complete" :
+ $v_extract_all = true;
+ $v_listing = false;
+ break;
+ case "partial" :
+ $v_extract_all = false;
+ $v_listing = false;
+ break;
+ case "list" :
+ $v_extract_all = false;
+ $v_listing = true;
+ break;
+ default :
+ $this->_error('Invalid extract mode ('.$p_mode.')');
+ return false;
+ }
+
+ clearstatcache();
+
+ while (strlen($v_binary_data = $this->_readBlock()) != 0)
+ {
+ $v_extract_file = FALSE;
+ $v_extraction_stopped = 0;
+
+ if (!$this->_readHeader($v_binary_data, $v_header))
+ return false;
+
+ if ($v_header['filename'] == '') {
+ continue;
+ }
+
+ // ----- Look for long filename
+ if ($v_header['typeflag'] == 'L') {
+ if (!$this->_readLongHeader($v_header))
+ return false;
+ }
+
+ if ((!$v_extract_all) && (is_array($p_file_list))) {
+ // ----- By default no unzip if the file is not found
+ $v_extract_file = false;
+
+ for ($i=0; $i strlen($p_file_list[$i]))
+ && (substr($v_header['filename'], 0, strlen($p_file_list[$i]))
+ == $p_file_list[$i])) {
+ $v_extract_file = true;
+ break;
+ }
+ }
+
+ // ----- It is a file, so compare the file names
+ elseif ($p_file_list[$i] == $v_header['filename']) {
+ $v_extract_file = true;
+ break;
+ }
+ }
+ } else {
+ $v_extract_file = true;
+ }
+
+ // ----- Look if this file need to be extracted
+ if (($v_extract_file) && (!$v_listing))
+ {
+ if (($p_remove_path != '')
+ && (substr($v_header['filename'], 0, $p_remove_path_size)
+ == $p_remove_path))
+ $v_header['filename'] = substr($v_header['filename'],
+ $p_remove_path_size);
+ if (($p_path != './') && ($p_path != '/')) {
+ while (substr($p_path, -1) == '/')
+ $p_path = substr($p_path, 0, strlen($p_path)-1);
+
+ if (substr($v_header['filename'], 0, 1) == '/')
+ $v_header['filename'] = $p_path.$v_header['filename'];
+ else
+ $v_header['filename'] = $p_path.'/'.$v_header['filename'];
+ }
+ if (file_exists($v_header['filename'])) {
+ if ( (@is_dir($v_header['filename']))
+ && ($v_header['typeflag'] == '')) {
+ $this->_error('File '.$v_header['filename']
+ .' already exists as a directory');
+ return false;
+ }
+ if ( ($this->_isArchive($v_header['filename']))
+ && ($v_header['typeflag'] == "5")) {
+ $this->_error('Directory '.$v_header['filename']
+ .' already exists as a file');
+ return false;
+ }
+ if (!is_writeable($v_header['filename'])) {
+ $this->_error('File '.$v_header['filename']
+ .' already exists and is write protected');
+ return false;
+ }
+ if (filemtime($v_header['filename']) > $v_header['mtime']) {
+ // To be completed : An error or silent no replace ?
+ }
+ }
+
+ // ----- Check the directory availability and create it if necessary
+ elseif (($v_result
+ = $this->_dirCheck(($v_header['typeflag'] == "5"
+ ?$v_header['filename']
+ :dirname($v_header['filename'])))) != 1) {
+ $this->_error('Unable to create path for '.$v_header['filename']);
+ return false;
+ }
+
+ if ($v_extract_file) {
+ if ($v_header['typeflag'] == "5") {
+ if (!@file_exists($v_header['filename'])) {
+ if (!@mkdir($v_header['filename'], 0777)) {
+ $this->_error('Unable to create directory {'
+ .$v_header['filename'].'}');
+ return false;
+ }
+ }
+ } elseif ($v_header['typeflag'] == "2") {
+ if (@file_exists($v_header['filename'])) {
+ @unlink($v_header['filename']);
+ }
+ if (!@symlink($v_header['link'], $v_header['filename'])) {
+ $this->_error('Unable to extract symbolic link {'
+ .$v_header['filename'].'}');
+ return false;
+ }
+ } else {
+ if (($v_dest_file = @fopen($v_header['filename'], "wb")) == 0) {
+ $this->_error('Error while opening {'.$v_header['filename']
+ .'} in write binary mode');
+ return false;
+ } else {
+ $n = floor($v_header['size']/512);
+ for ($i=0; $i<$n; $i++) {
+ $v_content = $this->_readBlock();
+ fwrite($v_dest_file, $v_content, 512);
+ }
+ if (($v_header['size'] % 512) != 0) {
+ $v_content = $this->_readBlock();
+ fwrite($v_dest_file, $v_content, ($v_header['size'] % 512));
+ }
+
+ @fclose($v_dest_file);
+
+ if ($p_preserve) {
+ @chown($v_header['filename'], $v_header['uid']);
+ @chgrp($v_header['filename'], $v_header['gid']);
+ }
+
+ // ----- Change the file mode, mtime
+ @touch($v_header['filename'], $v_header['mtime']);
+ if ($v_header['mode'] & 0111) {
+ // make file executable, obey umask
+ $mode = fileperms($v_header['filename']) | (~umask() & 0111);
+ @chmod($v_header['filename'], $mode);
+ }
+ }
+
+ // ----- Check the file size
+ clearstatcache();
+ if (!is_file($v_header['filename'])) {
+ $this->_error('Extracted file '.$v_header['filename']
+ .'does not exist. Archive may be corrupted.');
+ return false;
+ }
+
+ $filesize = filesize($v_header['filename']);
+ if ($filesize != $v_header['size']) {
+ $this->_error('Extracted file '.$v_header['filename']
+ .' does not have the correct file size \''
+ .$filesize
+ .'\' ('.$v_header['size']
+ .' expected). Archive may be corrupted.');
+ return false;
+ }
+ }
+ } else {
+ $this->_jumpBlock(ceil(($v_header['size']/512)));
+ }
+ } else {
+ $this->_jumpBlock(ceil(($v_header['size']/512)));
+ }
+
+ /* TBC : Seems to be unused ...
+ if ($this->_compress)
+ $v_end_of_file = @gzeof($this->_file);
+ else
+ $v_end_of_file = @feof($this->_file);
+ */
+
+ if ($v_listing || $v_extract_file || $v_extraction_stopped) {
+ // ----- Log extracted files
+ if (($v_file_dir = dirname($v_header['filename']))
+ == $v_header['filename'])
+ $v_file_dir = '';
+ if ((substr($v_header['filename'], 0, 1) == '/') && ($v_file_dir == ''))
+ $v_file_dir = '/';
+
+ $p_list_detail[$v_nb++] = $v_header;
+ if (is_array($p_file_list) && (count($p_list_detail) == count($p_file_list))) {
+ return true;
+ }
+ }
+ }
+
+ return true;
+ }
+ // }}}
+
+ // {{{ _openAppend()
+ function _openAppend()
+ {
+ if (filesize($this->_tarname) == 0)
+ return $this->_openWrite();
+
+ if ($this->_compress) {
+ $this->_close();
+
+ if (!@rename($this->_tarname, $this->_tarname.".tmp")) {
+ $this->_error('Error while renaming \''.$this->_tarname
+ .'\' to temporary file \''.$this->_tarname
+ .'.tmp\'');
+ return false;
+ }
+
+ if ($this->_compress_type == 'gz')
+ $v_temp_tar = @gzopen($this->_tarname.".tmp", "rb");
+ elseif ($this->_compress_type == 'bz2')
+ $v_temp_tar = @bzopen($this->_tarname.".tmp", "r");
+
+ if ($v_temp_tar == 0) {
+ $this->_error('Unable to open file \''.$this->_tarname
+ .'.tmp\' in binary read mode');
+ @rename($this->_tarname.".tmp", $this->_tarname);
+ return false;
+ }
+
+ if (!$this->_openWrite()) {
+ @rename($this->_tarname.".tmp", $this->_tarname);
+ return false;
+ }
+
+ if ($this->_compress_type == 'gz') {
+ $end_blocks = 0;
+
+ while (!@gzeof($v_temp_tar)) {
+ $v_buffer = @gzread($v_temp_tar, 512);
+ if ($v_buffer == ARCHIVE_TAR_END_BLOCK || strlen($v_buffer) == 0) {
+ $end_blocks++;
+ // do not copy end blocks, we will re-make them
+ // after appending
+ continue;
+ } elseif ($end_blocks > 0) {
+ for ($i = 0; $i < $end_blocks; $i++) {
+ $this->_writeBlock(ARCHIVE_TAR_END_BLOCK);
+ }
+ $end_blocks = 0;
+ }
+ $v_binary_data = pack("a512", $v_buffer);
+ $this->_writeBlock($v_binary_data);
+ }
+
+ @gzclose($v_temp_tar);
+ }
+ elseif ($this->_compress_type == 'bz2') {
+ $end_blocks = 0;
+
+ while (strlen($v_buffer = @bzread($v_temp_tar, 512)) > 0) {
+ if ($v_buffer == ARCHIVE_TAR_END_BLOCK || strlen($v_buffer) == 0) {
+ $end_blocks++;
+ // do not copy end blocks, we will re-make them
+ // after appending
+ continue;
+ } elseif ($end_blocks > 0) {
+ for ($i = 0; $i < $end_blocks; $i++) {
+ $this->_writeBlock(ARCHIVE_TAR_END_BLOCK);
+ }
+ $end_blocks = 0;
+ }
+ $v_binary_data = pack("a512", $v_buffer);
+ $this->_writeBlock($v_binary_data);
+ }
+
+ @bzclose($v_temp_tar);
+ }
+
+ if (!@unlink($this->_tarname.".tmp")) {
+ $this->_error('Error while deleting temporary file \''
+ .$this->_tarname.'.tmp\'');
+ }
+
+ } else {
+ // ----- For not compressed tar, just add files before the last
+ // one or two 512 bytes block
+ if (!$this->_openReadWrite())
+ return false;
+
+ clearstatcache();
+ $v_size = filesize($this->_tarname);
+
+ // We might have zero, one or two end blocks.
+ // The standard is two, but we should try to handle
+ // other cases.
+ fseek($this->_file, $v_size - 1024);
+ if (fread($this->_file, 512) == ARCHIVE_TAR_END_BLOCK) {
+ fseek($this->_file, $v_size - 1024);
+ }
+ elseif (fread($this->_file, 512) == ARCHIVE_TAR_END_BLOCK) {
+ fseek($this->_file, $v_size - 512);
+ }
+ }
+
+ return true;
+ }
+ // }}}
+
+ // {{{ _append()
+ function _append($p_filelist, $p_add_dir='', $p_remove_dir='')
+ {
+ if (!$this->_openAppend())
+ return false;
+
+ if ($this->_addList($p_filelist, $p_add_dir, $p_remove_dir))
+ $this->_writeFooter();
+
+ $this->_close();
+
+ return true;
+ }
+ // }}}
+
+ // {{{ _dirCheck()
+
+ /**
+ * Check if a directory exists and create it (including parent
+ * dirs) if not.
+ *
+ * @param string $p_dir directory to check
+ *
+ * @return bool true if the directory exists or was created
+ */
+ function _dirCheck($p_dir)
+ {
+ clearstatcache();
+ if ((@is_dir($p_dir)) || ($p_dir == ''))
+ return true;
+
+ $p_parent_dir = dirname($p_dir);
+
+ if (($p_parent_dir != $p_dir) &&
+ ($p_parent_dir != '') &&
+ (!$this->_dirCheck($p_parent_dir)))
+ return false;
+
+ if (!@mkdir($p_dir, 0777)) {
+ $this->_error("Unable to create directory '$p_dir'");
+ return false;
+ }
+
+ return true;
+ }
+
+ // }}}
+
+ // {{{ _pathReduction()
+
+ /**
+ * Compress path by changing for example "/dir/foo/../bar" to "/dir/bar",
+ * rand emove double slashes.
+ *
+ * @param string $p_dir path to reduce
+ *
+ * @return string reduced path
+ *
+ * @access private
+ *
+ */
+ function _pathReduction($p_dir)
+ {
+ $v_result = '';
+
+ // ----- Look for not empty path
+ if ($p_dir != '') {
+ // ----- Explode path by directory names
+ $v_list = explode('/', $p_dir);
+
+ // ----- Study directories from last to first
+ for ($i=sizeof($v_list)-1; $i>=0; $i--) {
+ // ----- Look for current path
+ if ($v_list[$i] == ".") {
+ // ----- Ignore this directory
+ // Should be the first $i=0, but no check is done
+ }
+ else if ($v_list[$i] == "..") {
+ // ----- Ignore it and ignore the $i-1
+ $i--;
+ }
+ else if ( ($v_list[$i] == '')
+ && ($i!=(sizeof($v_list)-1))
+ && ($i!=0)) {
+ // ----- Ignore only the double '//' in path,
+ // but not the first and last /
+ } else {
+ $v_result = $v_list[$i].($i!=(sizeof($v_list)-1)?'/'
+ .$v_result:'');
+ }
+ }
+ }
+
+ if (defined('OS_WINDOWS') && OS_WINDOWS) {
+ $v_result = strtr($v_result, '\\', '/');
+ }
+
+ return $v_result;
+ }
+
+ // }}}
+
+ // {{{ _translateWinPath()
+ function _translateWinPath($p_path, $p_remove_disk_letter=true)
+ {
+ if (defined('OS_WINDOWS') && OS_WINDOWS) {
+ // ----- Look for potential disk letter
+ if ( ($p_remove_disk_letter)
+ && (($v_position = strpos($p_path, ':')) != false)) {
+ $p_path = substr($p_path, $v_position+1);
+ }
+ // ----- Change potential windows directory separator
+ if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0,1) == '\\')) {
+ $p_path = strtr($p_path, '\\', '/');
+ }
+ }
+ return $p_path;
+ }
+ // }}}
+
+}
+?>
diff -Nru owncloud-1.1+git20110209/3rdparty/Dropbox/API.php owncloud-5.0.4debian/3rdparty/Dropbox/API.php
--- owncloud-1.1+git20110209/3rdparty/Dropbox/API.php 1970-01-01 00:00:00.000000000 +0000
+++ owncloud-5.0.4debian/3rdparty/Dropbox/API.php 2013-04-10 17:29:58.000000000 +0000
@@ -0,0 +1,380 @@
+oauth = $oauth;
+ $this->root = $root;
+ $this->useSSL = $useSSL;
+ if (!$this->useSSL)
+ {
+ throw new Dropbox_Exception('Dropbox REST API now requires that all requests use SSL');
+ }
+
+ }
+
+ /**
+ * Returns information about the current dropbox account
+ *
+ * @return stdclass
+ */
+ public function getAccountInfo() {
+
+ $data = $this->oauth->fetch($this->api_url . 'account/info');
+ return json_decode($data['body'],true);
+
+ }
+
+ /**
+ * Returns a file's contents
+ *
+ * @param string $path path
+ * @param string $root Use this to override the default root path (sandbox/dropbox)
+ * @return string
+ */
+ public function getFile($path = '', $root = null) {
+
+ if (is_null($root)) $root = $this->root;
+ $path = str_replace(array('%2F','~'), array('/','%7E'), rawurlencode($path));
+ $result = $this->oauth->fetch($this->api_content_url . 'files/' . $root . '/' . ltrim($path,'/'));
+ return $result['body'];
+
+ }
+
+ /**
+ * Uploads a new file
+ *
+ * @param string $path Target path (including filename)
+ * @param string $file Either a path to a file or a stream resource
+ * @param string $root Use this to override the default root path (sandbox/dropbox)
+ * @return bool
+ */
+ public function putFile($path, $file, $root = null) {
+
+ $directory = dirname($path);
+ $filename = basename($path);
+
+ if($directory==='.') $directory = '';
+ $directory = str_replace(array('%2F','~'), array('/','%7E'), rawurlencode($directory));
+// $filename = str_replace('~', '%7E', rawurlencode($filename));
+ if (is_null($root)) $root = $this->root;
+
+ if (is_string($file)) {
+
+ $file = fopen($file,'rb');
+
+ } elseif (!is_resource($file)) {
+ throw new Dropbox_Exception('File must be a file-resource or a string');
+ }
+ $result=$this->multipartFetch($this->api_content_url . 'files/' .
+ $root . '/' . trim($directory,'/'), $file, $filename);
+
+ if(!isset($result["httpStatus"]) || $result["httpStatus"] != 200)
+ throw new Dropbox_Exception("Uploading file to Dropbox failed");
+
+ return true;
+ }
+
+
+ /**
+ * Copies a file or directory from one location to another
+ *
+ * This method returns the file information of the newly created file.
+ *
+ * @param string $from source path
+ * @param string $to destination path
+ * @param string $root Use this to override the default root path (sandbox/dropbox)
+ * @return stdclass
+ */
+ public function copy($from, $to, $root = null) {
+
+ if (is_null($root)) $root = $this->root;
+ $response = $this->oauth->fetch($this->api_url . 'fileops/copy', array('from_path' => $from, 'to_path' => $to, 'root' => $root), 'POST');
+
+ return json_decode($response['body'],true);
+
+ }
+
+ /**
+ * Creates a new folder
+ *
+ * This method returns the information from the newly created directory
+ *
+ * @param string $path
+ * @param string $root Use this to override the default root path (sandbox/dropbox)
+ * @return stdclass
+ */
+ public function createFolder($path, $root = null) {
+
+ if (is_null($root)) $root = $this->root;
+
+ // Making sure the path starts with a /
+// $path = '/' . ltrim($path,'/');
+
+ $response = $this->oauth->fetch($this->api_url . 'fileops/create_folder', array('path' => $path, 'root' => $root),'POST');
+ return json_decode($response['body'],true);
+
+ }
+
+ /**
+ * Deletes a file or folder.
+ *
+ * This method will return the metadata information from the deleted file or folder, if successful.
+ *
+ * @param string $path Path to new folder
+ * @param string $root Use this to override the default root path (sandbox/dropbox)
+ * @return array
+ */
+ public function delete($path, $root = null) {
+
+ if (is_null($root)) $root = $this->root;
+ $response = $this->oauth->fetch($this->api_url . 'fileops/delete', array('path' => $path, 'root' => $root), 'POST');
+ return json_decode($response['body']);
+
+ }
+
+ /**
+ * Moves a file or directory to a new location
+ *
+ * This method returns the information from the newly created directory
+ *
+ * @param mixed $from Source path
+ * @param mixed $to destination path
+ * @param string $root Use this to override the default root path (sandbox/dropbox)
+ * @return stdclass
+ */
+ public function move($from, $to, $root = null) {
+
+ if (is_null($root)) $root = $this->root;
+ $response = $this->oauth->fetch($this->api_url . 'fileops/move', array('from_path' => rawurldecode($from), 'to_path' => rawurldecode($to), 'root' => $root), 'POST');
+
+ return json_decode($response['body'],true);
+
+ }
+
+ /**
+ * Returns file and directory information
+ *
+ * @param string $path Path to receive information from
+ * @param bool $list When set to true, this method returns information from all files in a directory. When set to false it will only return infromation from the specified directory.
+ * @param string $hash If a hash is supplied, this method simply returns true if nothing has changed since the last request. Good for caching.
+ * @param int $fileLimit Maximum number of file-information to receive
+ * @param string $root Use this to override the default root path (sandbox/dropbox)
+ * @return array|true
+ */
+ public function getMetaData($path, $list = true, $hash = null, $fileLimit = null, $root = null) {
+
+ if (is_null($root)) $root = $this->root;
+
+ $args = array(
+ 'list' => $list,
+ );
+
+ if (!is_null($hash)) $args['hash'] = $hash;
+ if (!is_null($fileLimit)) $args['file_limit'] = $fileLimit;
+
+ $path = str_replace(array('%2F','~'), array('/','%7E'), rawurlencode($path));
+ $response = $this->oauth->fetch($this->api_url . 'metadata/' . $root . '/' . ltrim($path,'/'), $args);
+
+ /* 304 is not modified */
+ if ($response['httpStatus']==304) {
+ return true;
+ } else {
+ return json_decode($response['body'],true);
+ }
+
+ }
+
+ /**
+ * A way of letting you keep up with changes to files and folders in a user's Dropbox. You can periodically call /delta to get a list of "delta entries", which are instructions on how to update your local state to match the server's state.
+ *
+ * This method returns the information from the newly created directory
+ *
+ * @param string $cursor A string that is used to keep track of your current state. On the next call pass in this value to return delta entries that have been recorded since the cursor was returned.
+ * @return stdclass
+ */
+ public function delta($cursor) {
+
+ $arg['cursor'] = $cursor;
+
+ $response = $this->oauth->fetch($this->api_url . 'delta', $arg, 'POST');
+ return json_decode($response['body'],true);
+
+ }
+
+ /**
+ * Returns a thumbnail (as a string) for a file path.
+ *
+ * @param string $path Path to file
+ * @param string $size small, medium or large
+ * @param string $root Use this to override the default root path (sandbox/dropbox)
+ * @return string
+ */
+ public function getThumbnail($path, $size = 'small', $root = null) {
+
+ if (is_null($root)) $root = $this->root;
+ $path = str_replace(array('%2F','~'), array('/','%7E'), rawurlencode($path));
+ $response = $this->oauth->fetch($this->api_content_url . 'thumbnails/' . $root . '/' . ltrim($path,'/'),array('size' => $size));
+
+ return $response['body'];
+
+ }
+
+ /**
+ * This method is used to generate multipart POST requests for file upload
+ *
+ * @param string $uri
+ * @param array $arguments
+ * @return bool
+ */
+ protected function multipartFetch($uri, $file, $filename) {
+
+ /* random string */
+ $boundary = 'R50hrfBj5JYyfR3vF3wR96GPCC9Fd2q2pVMERvEaOE3D8LZTgLLbRpNwXek3';
+
+ $headers = array(
+ 'Content-Type' => 'multipart/form-data; boundary=' . $boundary,
+ );
+
+ $body="--" . $boundary . "\r\n";
+ $body.="Content-Disposition: form-data; name=file; filename=".rawurldecode($filename)."\r\n";
+ $body.="Content-type: application/octet-stream\r\n";
+ $body.="\r\n";
+ $body.=stream_get_contents($file);
+ $body.="\r\n";
+ $body.="--" . $boundary . "--";
+
+ // Dropbox requires the filename to also be part of the regular arguments, so it becomes
+ // part of the signature.
+ $uri.='?file=' . $filename;
+
+ return $this->oauth->fetch($uri, $body, 'POST', $headers);
+
+ }
+
+
+ /**
+ * Search
+ *
+ * Returns metadata for all files and folders that match the search query.
+ *
+ * @added by: diszo.sasil
+ *
+ * @param string $query
+ * @param string $root Use this to override the default root path (sandbox/dropbox)
+ * @param string $path
+ * @return array
+ */
+ public function search($query = '', $root = null, $path = ''){
+ if (is_null($root)) $root = $this->root;
+ if(!empty($path)){
+ $path = str_replace(array('%2F','~'), array('/','%7E'), rawurlencode($path));
+ }
+ $response = $this->oauth->fetch($this->api_url . 'search/' . $root . '/' . ltrim($path,'/'),array('query' => $query));
+ return json_decode($response['body'],true);
+ }
+
+ /**
+ * Creates and returns a shareable link to files or folders.
+ *
+ * Note: Links created by the /shares API call expire after thirty days.
+ *
+ * @param type $path
+ * @param type $root
+ * @return type
+ */
+ public function share($path, $root = null) {
+ if (is_null($root)) $root = $this->root;
+ $path = str_replace(array('%2F','~'), array('/','%7E'), rawurlencode($path));
+ $response = $this->oauth->fetch($this->api_url. 'shares/'. $root . '/' . ltrim($path, '/'), array(), 'POST');
+ return json_decode($response['body'],true);
+
+ }
+
+ /**
+ * Returns a link directly to a file.
+ * Similar to /shares. The difference is that this bypasses the Dropbox webserver, used to provide a preview of the file, so that you can effectively stream the contents of your media.
+ *
+ * Note: The /media link expires after four hours, allotting enough time to stream files, but not enough to leave a connection open indefinitely.
+ *
+ * @param type $path
+ * @param type $root
+ * @return type
+ */
+ public function media($path, $root = null) {
+
+ if (is_null($root)) $root = $this->root;
+ $path = str_replace(array('%2F','~'), array('/','%7E'), rawurlencode($path));
+ $response = $this->oauth->fetch($this->api_url. 'media/'. $root . '/' . ltrim($path, '/'), array(), 'POST');
+ return json_decode($response['body'],true);
+
+ }
+
+ /**
+ * Creates and returns a copy_ref to a file. This reference string can be used to copy that file to another user's Dropbox by passing it in as the from_copy_ref parameter on /fileops/copy.
+ *
+ * @param type $path
+ * @param type $root
+ * @return type
+ */
+ public function copy_ref($path, $root = null) {
+
+ if (is_null($root)) $root = $this->root;
+ $path = str_replace(array('%2F','~'), array('/','%7E'), rawurlencode($path));
+ $response = $this->oauth->fetch($this->api_url. 'copy_ref/'. $root . '/' . ltrim($path, '/'));
+ return json_decode($response['body'],true);
+
+ }
+
+
+}
diff -Nru owncloud-1.1+git20110209/3rdparty/Dropbox/Exception/Forbidden.php owncloud-5.0.4debian/3rdparty/Dropbox/Exception/Forbidden.php
--- owncloud-1.1+git20110209/3rdparty/Dropbox/Exception/Forbidden.php 1970-01-01 00:00:00.000000000 +0000
+++ owncloud-5.0.4debian/3rdparty/Dropbox/Exception/Forbidden.php 2013-04-10 17:29:58.000000000 +0000
@@ -0,0 +1,18 @@
+consumerRequest instanceof HTTP_OAuth_Consumer_Request) {
+ $this->consumerRequest = new HTTP_OAuth_Consumer_Request;
+ }
+
+ // TODO: Change this and add in code to validate the SSL cert.
+ // see https://github.com/bagder/curl/blob/master/lib/mk-ca-bundle.pl
+ $this->consumerRequest->setConfig(array(
+ 'ssl_verify_peer' => false,
+ 'ssl_verify_host' => false
+ ));
+
+ return $this->consumerRequest;
+ }
+}
diff -Nru owncloud-1.1+git20110209/3rdparty/Dropbox/OAuth/Curl.php owncloud-5.0.4debian/3rdparty/Dropbox/OAuth/Curl.php
--- owncloud-1.1+git20110209/3rdparty/Dropbox/OAuth/Curl.php 1970-01-01 00:00:00.000000000 +0000
+++ owncloud-5.0.4debian/3rdparty/Dropbox/OAuth/Curl.php 2013-04-10 17:29:58.000000000 +0000
@@ -0,0 +1,282 @@
+consumerKey = $consumerKey;
+ $this->consumerSecret = $consumerSecret;
+ }
+
+ /**
+ * Fetches a secured oauth url and returns the response body.
+ *
+ * @param string $uri
+ * @param mixed $arguments
+ * @param string $method
+ * @param array $httpHeaders
+ * @return string
+ */
+ public function fetch($uri, $arguments = array(), $method = 'GET', $httpHeaders = array()) {
+
+ $uri=str_replace('http://', 'https://', $uri); // all https, upload makes problems if not
+ if (is_string($arguments) and strtoupper($method) == 'POST') {
+ preg_match("/\?file=(.*)$/i", $uri, $matches);
+ if (isset($matches[1])) {
+ $uri = str_replace($matches[0], "", $uri);
+ $filename = $matches[1];
+ $httpHeaders=array_merge($httpHeaders,$this->getOAuthHeader($uri, array("file" => $filename), $method));
+ }
+ } else {
+ $httpHeaders=array_merge($httpHeaders,$this->getOAuthHeader($uri, $arguments, $method));
+ }
+ $ch = curl_init();
+ if (strtoupper($method) == 'POST') {
+ curl_setopt($ch, CURLOPT_URL, $uri);
+ curl_setopt($ch, CURLOPT_POST, true);
+// if (is_array($arguments))
+// $arguments=http_build_query($arguments);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $arguments);
+// $httpHeaders['Content-Length']=strlen($arguments);
+ } else {
+ curl_setopt($ch, CURLOPT_URL, $uri.'?'.http_build_query($arguments));
+ curl_setopt($ch, CURLOPT_POST, false);
+ }
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_TIMEOUT, 300);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
+// curl_setopt($ch, CURLOPT_CAINFO, "rootca");
+ curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
+ //Build header
+ $headers = array();
+ foreach ($httpHeaders as $name => $value) {
+ $headers[] = "{$name}: $value";
+ }
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
+ if (!ini_get('safe_mode') && !ini_get('open_basedir'))
+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true );
+ if (function_exists($this->ProgressFunction) and defined('CURLOPT_PROGRESSFUNCTION')) {
+ curl_setopt($ch, CURLOPT_NOPROGRESS, false);
+ curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, $this->ProgressFunction);
+ curl_setopt($ch, CURLOPT_BUFFERSIZE, 512);
+ }
+ $response=curl_exec($ch);
+ $errorno=curl_errno($ch);
+ $error=curl_error($ch);
+ $status=curl_getinfo($ch,CURLINFO_HTTP_CODE);
+ curl_close($ch);
+
+
+ if (!empty($errorno))
+ throw new Dropbox_Exception_NotFound('Curl error: ('.$errorno.') '.$error."\n");
+
+ if ($status>=300) {
+ $body = json_decode($response,true);
+ switch ($status) {
+ // Not modified
+ case 304 :
+ return array(
+ 'httpStatus' => 304,
+ 'body' => null,
+ );
+ break;
+ case 403 :
+ throw new Dropbox_Exception_Forbidden('Forbidden.
+ This could mean a bad OAuth request, or a file or folder already existing at the target location.
+ ' . $body["error"] . "\n");
+ case 404 :
+ throw new Dropbox_Exception_NotFound('Resource at uri: ' . $uri . ' could not be found. ' .
+ $body["error"] . "\n");
+ case 507 :
+ throw new Dropbox_Exception_OverQuota('This dropbox is full. ' .
+ $body["error"] . "\n");
+ }
+ if (!empty($body["error"]))
+ throw new Dropbox_Exception_RequestToken('Error: ('.$status.') '.$body["error"]."\n");
+ }
+
+ return array(
+ 'body' => $response,
+ 'httpStatus' => $status
+ );
+ }
+
+ /**
+ * Returns named array with oauth parameters for further use
+ * @return array Array with oauth_ parameters
+ */
+ private function getOAuthBaseParams() {
+ $params['oauth_version'] = '1.0';
+ $params['oauth_signature_method'] = 'HMAC-SHA1';
+
+ $params['oauth_consumer_key'] = $this->consumerKey;
+ $tokens = $this->getToken();
+ if (isset($tokens['token']) && $tokens['token']) {
+ $params['oauth_token'] = $tokens['token'];
+ }
+ $params['oauth_timestamp'] = time();
+ $params['oauth_nonce'] = md5(microtime() . mt_rand());
+ return $params;
+ }
+
+ /**
+ * Creates valid Authorization header for OAuth, based on URI and Params
+ *
+ * @param string $uri
+ * @param array $params
+ * @param string $method GET or POST, standard is GET
+ * @param array $oAuthParams optional, pass your own oauth_params here
+ * @return array Array for request's headers section like
+ * array('Authorization' => 'OAuth ...');
+ */
+ private function getOAuthHeader($uri, $params, $method = 'GET', $oAuthParams = null) {
+ $oAuthParams = $oAuthParams ? $oAuthParams : $this->getOAuthBaseParams();
+
+ // create baseString to encode for the sent parameters
+ $baseString = $method . '&';
+ $baseString .= $this->oauth_urlencode($uri) . "&";
+
+ // OAuth header does not include GET-Parameters
+ $signatureParams = array_merge($params, $oAuthParams);
+
+ // sorting the parameters
+ ksort($signatureParams);
+
+ $encodedParams = array();
+ foreach ($signatureParams as $key => $value) {
+ $encodedParams[] = $this->oauth_urlencode($key) . '=' . $this->oauth_urlencode($value);
+ }
+
+ $baseString .= $this->oauth_urlencode(implode('&', $encodedParams));
+
+ // encode the signature
+ $tokens = $this->getToken();
+ $hash = $this->hash_hmac_sha1($this->consumerSecret.'&'.$tokens['token_secret'], $baseString);
+ $signature = base64_encode($hash);
+
+ // add signature to oAuthParams
+ $oAuthParams['oauth_signature'] = $signature;
+
+ $oAuthEncoded = array();
+ foreach ($oAuthParams as $key => $value) {
+ $oAuthEncoded[] = $key . '="' . $this->oauth_urlencode($value) . '"';
+ }
+
+ return array('Authorization' => 'OAuth ' . implode(', ', $oAuthEncoded));
+ }
+
+ /**
+ * Requests the OAuth request token.
+ *
+ * @return void
+ */
+ public function getRequestToken() {
+ $result = $this->fetch(self::URI_REQUEST_TOKEN, array(), 'POST');
+ if ($result['httpStatus'] == "200") {
+ $tokens = array();
+ parse_str($result['body'], $tokens);
+ $this->setToken($tokens['oauth_token'], $tokens['oauth_token_secret']);
+ return $this->getToken();
+ } else {
+ throw new Dropbox_Exception_RequestToken('We were unable to fetch request tokens. This likely means that your consumer key and/or secret are incorrect.');
+ }
+ }
+
+ /**
+ * Requests the OAuth access tokens.
+ *
+ * This method requires the 'unauthorized' request tokens
+ * and, if successful will set the authorized request tokens.
+ *
+ * @return void
+ */
+ public function getAccessToken() {
+ $result = $this->fetch(self::URI_ACCESS_TOKEN, array(), 'POST');
+ if ($result['httpStatus'] == "200") {
+ $tokens = array();
+ parse_str($result['body'], $tokens);
+ $this->setToken($tokens['oauth_token'], $tokens['oauth_token_secret']);
+ return $this->getToken();
+ } else {
+ throw new Dropbox_Exception_RequestToken('We were unable to fetch request tokens. This likely means that your consumer key and/or secret are incorrect.');
+ }
+ }
+
+ /**
+ * Helper function to properly urlencode parameters.
+ * See http://php.net/manual/en/function.oauth-urlencode.php
+ *
+ * @param string $string
+ * @return string
+ */
+ private function oauth_urlencode($string) {
+ return str_replace('%E7', '~', rawurlencode($string));
+ }
+
+ /**
+ * Hash function for hmac_sha1; uses native function if available.
+ *
+ * @param string $key
+ * @param string $data
+ * @return string
+ */
+ private function hash_hmac_sha1($key, $data) {
+ if (function_exists('hash_hmac') && in_array('sha1', hash_algos())) {
+ return hash_hmac('sha1', $data, $key, true);
+ } else {
+ $blocksize = 64;
+ $hashfunc = 'sha1';
+ if (strlen($key) > $blocksize) {
+ $key = pack('H*', $hashfunc($key));
+ }
+
+ $key = str_pad($key, $blocksize, chr(0x00));
+ $ipad = str_repeat(chr(0x36), $blocksize);
+ $opad = str_repeat(chr(0x5c), $blocksize);
+ $hash = pack('H*', $hashfunc(( $key ^ $opad ) . pack('H*', $hashfunc(($key ^ $ipad) . $data))));
+
+ return $hash;
+ }
+ }
+
+
+}
\ No newline at end of file
diff -Nru owncloud-1.1+git20110209/3rdparty/Dropbox/OAuth.php owncloud-5.0.4debian/3rdparty/Dropbox/OAuth.php
--- owncloud-1.1+git20110209/3rdparty/Dropbox/OAuth.php 1970-01-01 00:00:00.000000000 +0000
+++ owncloud-5.0.4debian/3rdparty/Dropbox/OAuth.php 2013-04-10 17:29:58.000000000 +0000
@@ -0,0 +1,151 @@
+oauth_token = $token['token'];
+ $this->oauth_token_secret = $token['token_secret'];
+ } else {
+ $this->oauth_token = $token;
+ $this->oauth_token_secret = $token_secret;
+ }
+
+ }
+
+ /**
+ * Returns the oauth request tokens as an associative array.
+ *
+ * The array will contain the elements 'token' and 'token_secret'.
+ *
+ * @return array
+ */
+ public function getToken() {
+
+ return array(
+ 'token' => $this->oauth_token,
+ 'token_secret' => $this->oauth_token_secret,
+ );
+
+ }
+
+ /**
+ * Returns the authorization url
+ *
+ * @param string $callBack Specify a callback url to automatically redirect the user back
+ * @return string
+ */
+ public function getAuthorizeUrl($callBack = null) {
+
+ // Building the redirect uri
+ $token = $this->getToken();
+ $uri = self::URI_AUTHORIZE . '?oauth_token=' . $token['token'];
+ if ($callBack) $uri.='&oauth_callback=' . $callBack;
+ return $uri;
+ }
+
+ /**
+ * Fetches a secured oauth url and returns the response body.
+ *
+ * @param string $uri
+ * @param mixed $arguments
+ * @param string $method
+ * @param array $httpHeaders
+ * @return string
+ */
+ public abstract function fetch($uri, $arguments = array(), $method = 'GET', $httpHeaders = array());
+
+ /**
+ * Requests the OAuth request token.
+ *
+ * @return array
+ */
+ abstract public function getRequestToken();
+
+ /**
+ * Requests the OAuth access tokens.
+ *
+ * @return array
+ */
+ abstract public function getAccessToken();
+
+}
diff -Nru owncloud-1.1+git20110209/3rdparty/Dropbox/README.md owncloud-5.0.4debian/3rdparty/Dropbox/README.md
--- owncloud-1.1+git20110209/3rdparty/Dropbox/README.md 1970-01-01 00:00:00.000000000 +0000
+++ owncloud-5.0.4debian/3rdparty/Dropbox/README.md 2013-04-10 17:29:58.000000000 +0000
@@ -0,0 +1,31 @@
+Dropbox-php
+===========
+
+This PHP library allows you to easily integrate dropbox with PHP.
+
+The following PHP extension is required:
+
+* json
+
+The library makes use of OAuth. At the moment you can use either of these libraries:
+
+[PHP OAuth extension](http://pecl.php.net/package/oauth)
+[PEAR's HTTP_OAUTH package](http://pear.php.net/package/http_oauth)
+
+The extension is recommended, but if you can't install php extensions you should go for the pear package.
+Installing
+----------
+
+ pear channel-discover pear.dropbox-php.com
+ pear install dropbox-php/Dropbox-alpha
+
+Documentation
+-------------
+Check out the [documentation](http://www.dropbox-php.com/docs).
+
+Questions?
+----------
+
+[Dropbox-php Mailing list](http://groups.google.com/group/dropbox-php)
+[Official Dropbox developer forum](http://forums.dropbox.com/forum.php?id=5)
+
diff -Nru owncloud-1.1+git20110209/3rdparty/Dropbox/autoload.php owncloud-5.0.4debian/3rdparty/Dropbox/autoload.php
--- owncloud-1.1+git20110209/3rdparty/Dropbox/autoload.php 1970-01-01 00:00:00.000000000 +0000
+++ owncloud-5.0.4debian/3rdparty/Dropbox/autoload.php 2013-04-10 17:29:58.000000000 +0000
@@ -0,0 +1,29 @@
+key = $key;
+ $this->secret = $secret;
+ $this->callback_url = $callback_url;
+ }/*}}}*/
+}/*}}}*/
+
+class OAuthToken {/*{{{*/
+ // access tokens and request tokens
+ public $key;
+ public $secret;
+
+ /**
+ * key = the token
+ * secret = the token secret
+ */
+ function __construct($key, $secret) {/*{{{*/
+ $this->key = $key;
+ $this->secret = $secret;
+ }/*}}}*/
+
+ /**
+ * generates the basic string serialization of a token that a server
+ * would respond to request_token and access_token calls with
+ */
+ function to_string() {/*{{{*/
+ return "oauth_token=" . OAuthUtil::urlencodeRFC3986($this->key) .
+ "&oauth_token_secret=" . OAuthUtil::urlencodeRFC3986($this->secret);
+ }/*}}}*/
+
+ function __toString() {/*{{{*/
+ return $this->to_string();
+ }/*}}}*/
+}/*}}}*/
+
+class OAuthSignatureMethod {/*{{{*/
+ public function check_signature(&$request, $consumer, $token, $signature) {
+ $built = $this->build_signature($request, $consumer, $token);
+ return $built == $signature;
+ }
+}/*}}}*/
+
+class OAuthSignatureMethod_HMAC_SHA1 extends OAuthSignatureMethod {/*{{{*/
+ function get_name() {/*{{{*/
+ return "HMAC-SHA1";
+ }/*}}}*/
+
+ public function build_signature($request, $consumer, $token, $privKey=NULL) {/*{{{*/
+ $base_string = $request->get_signature_base_string();
+ $request->base_string = $base_string;
+
+ $key_parts = array(
+ $consumer->secret,
+ ($token) ? $token->secret : ""
+ );
+
+ $key_parts = array_map(array('OAuthUtil','urlencodeRFC3986'), $key_parts);
+ $key = implode('&', $key_parts);
+
+ return base64_encode( hash_hmac('sha1', $base_string, $key, true));
+ }/*}}}*/
+}/*}}}*/
+
+class OAuthSignatureMethod_RSA_SHA1 extends OAuthSignatureMethod {/*{{{*/
+ public function get_name() {/*{{{*/
+ return "RSA-SHA1";
+ }/*}}}*/
+
+ protected function fetch_public_cert(&$request) {/*{{{*/
+ // not implemented yet, ideas are:
+ // (1) do a lookup in a table of trusted certs keyed off of consumer
+ // (2) fetch via http using a url provided by the requester
+ // (3) some sort of specific discovery code based on request
+ //
+ // either way should return a string representation of the certificate
+ throw Exception("fetch_public_cert not implemented");
+ }/*}}}*/
+
+ protected function fetch_private_cert($privKey) {//&$request) {/*{{{*/
+ // not implemented yet, ideas are:
+ // (1) do a lookup in a table of trusted certs keyed off of consumer
+ //
+ // either way should return a string representation of the certificate
+ throw Exception("fetch_private_cert not implemented");
+ }/*}}}*/
+
+ public function build_signature(&$request, $consumer, $token, $privKey) {/*{{{*/
+ $base_string = $request->get_signature_base_string();
+
+ // Fetch the private key cert based on the request
+ //$cert = $this->fetch_private_cert($consumer->privKey);
+
+ //Pull the private key ID from the certificate
+ //$privatekeyid = openssl_get_privatekey($cert);
+
+ // hacked in
+ if ($privKey == '') {
+ $fp = fopen($GLOBALS['PRIV_KEY_FILE'], "r");
+ $privKey = fread($fp, 8192);
+ fclose($fp);
+ }
+ $privatekeyid = openssl_get_privatekey($privKey);
+
+ //Check the computer signature against the one passed in the query
+ $ok = openssl_sign($base_string, $signature, $privatekeyid);
+
+ //Release the key resource
+ openssl_free_key($privatekeyid);
+
+ return base64_encode($signature);
+ } /*}}}*/
+
+ public function check_signature(&$request, $consumer, $token, $signature) {/*{{{*/
+ $decoded_sig = base64_decode($signature);
+
+ $base_string = $request->get_signature_base_string();
+
+ // Fetch the public key cert based on the request
+ $cert = $this->fetch_public_cert($request);
+
+ //Pull the public key ID from the certificate
+ $publickeyid = openssl_get_publickey($cert);
+
+ //Check the computer signature against the one passed in the query
+ $ok = openssl_verify($base_string, $decoded_sig, $publickeyid);
+
+ //Release the key resource
+ openssl_free_key($publickeyid);
+
+ return $ok == 1;
+ } /*}}}*/
+}/*}}}*/
+
+class OAuthRequest {/*{{{*/
+ private $parameters;
+ private $http_method;
+ private $http_url;
+ // for debug purposes
+ public $base_string;
+ public static $version = '1.0';
+
+ function __construct($http_method, $http_url, $parameters=NULL) {/*{{{*/
+ @$parameters or $parameters = array();
+ $this->parameters = $parameters;
+ $this->http_method = $http_method;
+ $this->http_url = $http_url;
+ }/*}}}*/
+
+
+ /**
+ * attempt to build up a request from what was passed to the server
+ */
+ public static function from_request($http_method=NULL, $http_url=NULL, $parameters=NULL) {/*{{{*/
+ $scheme = (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != "on") ? 'http' : 'https';
+ @$http_url or $http_url = $scheme . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
+ @$http_method or $http_method = $_SERVER['REQUEST_METHOD'];
+
+ $request_headers = OAuthRequest::get_headers();
+
+ // let the library user override things however they'd like, if they know
+ // which parameters to use then go for it, for example XMLRPC might want to
+ // do this
+ if ($parameters) {
+ $req = new OAuthRequest($http_method, $http_url, $parameters);
+ }
+ // next check for the auth header, we need to do some extra stuff
+ // if that is the case, namely suck in the parameters from GET or POST
+ // so that we can include them in the signature
+ else if (@substr($request_headers['Authorization'], 0, 5) == "OAuth") {
+ $header_parameters = OAuthRequest::split_header($request_headers['Authorization']);
+ if ($http_method == "GET") {
+ $req_parameters = $_GET;
+ }
+ else if ($http_method = "POST") {
+ $req_parameters = $_POST;
+ }
+ $parameters = array_merge($header_parameters, $req_parameters);
+ $req = new OAuthRequest($http_method, $http_url, $parameters);
+ }
+ else if ($http_method == "GET") {
+ $req = new OAuthRequest($http_method, $http_url, $_GET);
+ }
+ else if ($http_method == "POST") {
+ $req = new OAuthRequest($http_method, $http_url, $_POST);
+ }
+ return $req;
+ }/*}}}*/
+
+ /**
+ * pretty much a helper function to set up the request
+ */
+ public static function from_consumer_and_token($consumer, $token, $http_method, $http_url, $parameters=NULL) {/*{{{*/
+ @$parameters or $parameters = array();
+ $defaults = array("oauth_version" => OAuthRequest::$version,
+ "oauth_nonce" => OAuthRequest::generate_nonce(),
+ "oauth_timestamp" => OAuthRequest::generate_timestamp(),
+ "oauth_consumer_key" => $consumer->key);
+ $parameters = array_merge($defaults, $parameters);
+
+ if ($token) {
+ $parameters['oauth_token'] = $token->key;
+ }
+
+ // oauth v1.0a
+ /*if (isset($_REQUEST['oauth_verifier'])) {
+ $parameters['oauth_verifier'] = $_REQUEST['oauth_verifier'];
+ }*/
+
+
+ return new OAuthRequest($http_method, $http_url, $parameters);
+ }/*}}}*/
+
+ public function set_parameter($name, $value) {/*{{{*/
+ $this->parameters[$name] = $value;
+ }/*}}}*/
+
+ public function get_parameter($name) {/*{{{*/
+ return $this->parameters[$name];
+ }/*}}}*/
+
+ public function get_parameters() {/*{{{*/
+ return $this->parameters;
+ }/*}}}*/
+
+ /**
+ * Returns the normalized parameters of the request
+ *
+ * This will be all (except oauth_signature) parameters,
+ * sorted first by key, and if duplicate keys, then by
+ * value.
+ *
+ * The returned string will be all the key=value pairs
+ * concated by &.
+ *
+ * @return string
+ */
+ public function get_signable_parameters() {/*{{{*/
+ // Grab all parameters
+ $params = $this->parameters;
+
+ // Remove oauth_signature if present
+ if (isset($params['oauth_signature'])) {
+ unset($params['oauth_signature']);
+ }
+
+ // Urlencode both keys and values
+ $keys = array_map(array('OAuthUtil', 'urlencodeRFC3986'), array_keys($params));
+ $values = array_map(array('OAuthUtil', 'urlencodeRFC3986'), array_values($params));
+ $params = array_combine($keys, $values);
+
+ // Sort by keys (natsort)
+ uksort($params, 'strnatcmp');
+
+if(isset($params['title']) && isset($params['title-exact'])) {
+ $temp = $params['title-exact'];
+ $title = $params['title'];
+
+ unset($params['title']);
+ unset($params['title-exact']);
+
+ $params['title-exact'] = $temp;
+ $params['title'] = $title;
+}
+
+ // Generate key=value pairs
+ $pairs = array();
+ foreach ($params as $key=>$value ) {
+ if (is_array($value)) {
+ // If the value is an array, it's because there are multiple
+ // with the same key, sort them, then add all the pairs
+ natsort($value);
+ foreach ($value as $v2) {
+ $pairs[] = $key . '=' . $v2;
+ }
+ } else {
+ $pairs[] = $key . '=' . $value;
+ }
+ }
+
+ // Return the pairs, concated with &
+ return implode('&', $pairs);
+ }/*}}}*/
+
+ /**
+ * Returns the base string of this request
+ *
+ * The base string defined as the method, the url
+ * and the parameters (normalized), each urlencoded
+ * and the concated with &.
+ */
+ public function get_signature_base_string() {/*{{{*/
+ $parts = array(
+ $this->get_normalized_http_method(),
+ $this->get_normalized_http_url(),
+ $this->get_signable_parameters()
+ );
+
+ $parts = array_map(array('OAuthUtil', 'urlencodeRFC3986'), $parts);
+
+ return implode('&', $parts);
+ }/*}}}*/
+
+ /**
+ * just uppercases the http method
+ */
+ public function get_normalized_http_method() {/*{{{*/
+ return strtoupper($this->http_method);
+ }/*}}}*/
+
+/**
+ * parses the url and rebuilds it to be
+ * scheme://host/path
+ */
+ public function get_normalized_http_url() {
+ $parts = parse_url($this->http_url);
+
+ $scheme = (isset($parts['scheme'])) ? $parts['scheme'] : 'http';
+ $port = (isset($parts['port'])) ? $parts['port'] : (($scheme == 'https') ? '443' : '80');
+ $host = (isset($parts['host'])) ? strtolower($parts['host']) : '';
+ $path = (isset($parts['path'])) ? $parts['path'] : '';
+
+ if (($scheme == 'https' && $port != '443')
+ || ($scheme == 'http' && $port != '80')) {
+ $host = "$host:$port";
+ }
+ return "$scheme://$host$path";
+ }
+
+ /**
+ * builds a url usable for a GET request
+ */
+ public function to_url() {/*{{{*/
+ $out = $this->get_normalized_http_url() . "?";
+ $out .= $this->to_postdata();
+ return $out;
+ }/*}}}*/
+
+ /**
+ * builds the data one would send in a POST request
+ */
+ public function to_postdata() {/*{{{*/
+ $total = array();
+ foreach ($this->parameters as $k => $v) {
+ $total[] = OAuthUtil::urlencodeRFC3986($k) . "=" . OAuthUtil::urlencodeRFC3986($v);
+ }
+ $out = implode("&", $total);
+ return $out;
+ }/*}}}*/
+
+ /**
+ * builds the Authorization: header
+ */
+ public function to_header() {/*{{{*/
+ $out ='Authorization: OAuth ';
+ $total = array();
+
+ /*
+ $sig = $this->parameters['oauth_signature'];
+ unset($this->parameters['oauth_signature']);
+ uksort($this->parameters, 'strnatcmp');
+ $this->parameters['oauth_signature'] = $sig;
+ */
+
+ foreach ($this->parameters as $k => $v) {
+ if (substr($k, 0, 5) != "oauth") continue;
+ $out .= OAuthUtil::urlencodeRFC3986($k) . '="' . OAuthUtil::urlencodeRFC3986($v) . '", ';
+ }
+ $out = substr_replace($out, '', strlen($out) - 2);
+
+ return $out;
+ }/*}}}*/
+
+ public function __toString() {/*{{{*/
+ return $this->to_url();
+ }/*}}}*/
+
+
+ public function sign_request($signature_method, $consumer, $token, $privKey=NULL) {/*{{{*/
+ $this->set_parameter("oauth_signature_method", $signature_method->get_name());
+ $signature = $this->build_signature($signature_method, $consumer, $token, $privKey);
+ $this->set_parameter("oauth_signature", $signature);
+ }/*}}}*/
+
+ public function build_signature($signature_method, $consumer, $token, $privKey=NULL) {/*{{{*/
+ $signature = $signature_method->build_signature($this, $consumer, $token, $privKey);
+ return $signature;
+ }/*}}}*/
+
+ /**
+ * util function: current timestamp
+ */
+ private static function generate_timestamp() {/*{{{*/
+ return time();
+ }/*}}}*/
+
+ /**
+ * util function: current nonce
+ */
+ private static function generate_nonce() {/*{{{*/
+ $mt = microtime();
+ $rand = mt_rand();
+
+ return md5($mt . $rand); // md5s look nicer than numbers
+ }/*}}}*/
+
+ /**
+ * util function for turning the Authorization: header into
+ * parameters, has to do some unescaping
+ */
+ private static function split_header($header) {/*{{{*/
+ // this should be a regex
+ // error cases: commas in parameter values
+ $parts = explode(",", $header);
+ $out = array();
+ foreach ($parts as $param) {
+ $param = ltrim($param);
+ // skip the "realm" param, nobody ever uses it anyway
+ if (substr($param, 0, 5) != "oauth") continue;
+
+ $param_parts = explode("=", $param);
+
+ // rawurldecode() used because urldecode() will turn a "+" in the
+ // value into a space
+ $out[$param_parts[0]] = rawurldecode(substr($param_parts[1], 1, -1));
+ }
+ return $out;
+ }/*}}}*/
+
+ /**
+ * helper to try to sort out headers for people who aren't running apache
+ */
+ private static function get_headers() {/*{{{*/
+ if (function_exists('apache_request_headers')) {
+ // we need this to get the actual Authorization: header
+ // because apache tends to tell us it doesn't exist
+ return apache_request_headers();
+ }
+ // otherwise we don't have apache and are just going to have to hope
+ // that $_SERVER actually contains what we need
+ $out = array();
+ foreach ($_SERVER as $key => $value) {
+ if (substr($key, 0, 5) == "HTTP_") {
+ // this is chaos, basically it is just there to capitalize the first
+ // letter of every word that is not an initial HTTP and strip HTTP
+ // code from przemek
+ $key = str_replace(" ", "-", ucwords(strtolower(str_replace("_", " ", substr($key, 5)))));
+ $out[$key] = $value;
+ }
+ }
+ return $out;
+ }/*}}}*/
+}/*}}}*/
+
+class OAuthServer {/*{{{*/
+ protected $timestamp_threshold = 300; // in seconds, five minutes
+ protected $version = 1.0; // hi blaine
+ protected $signature_methods = array();
+
+ protected $data_store;
+
+ function __construct($data_store) {/*{{{*/
+ $this->data_store = $data_store;
+ }/*}}}*/
+
+ public function add_signature_method($signature_method) {/*{{{*/
+ $this->signature_methods[$signature_method->get_name()] =
+ $signature_method;
+ }/*}}}*/
+
+ // high level functions
+
+ /**
+ * process a request_token request
+ * returns the request token on success
+ */
+ public function fetch_request_token(&$request) {/*{{{*/
+ $this->get_version($request);
+
+ $consumer = $this->get_consumer($request);
+
+ // no token required for the initial token request
+ $token = NULL;
+
+ $this->check_signature($request, $consumer, $token);
+
+ $new_token = $this->data_store->new_request_token($consumer);
+
+ return $new_token;
+ }/*}}}*/
+
+ /**
+ * process an access_token request
+ * returns the access token on success
+ */
+ public function fetch_access_token(&$request) {/*{{{*/
+ $this->get_version($request);
+
+ $consumer = $this->get_consumer($request);
+
+ // requires authorized request token
+ $token = $this->get_token($request, $consumer, "request");
+
+ $this->check_signature($request, $consumer, $token);
+
+ $new_token = $this->data_store->new_access_token($token, $consumer);
+
+ return $new_token;
+ }/*}}}*/
+
+ /**
+ * verify an api call, checks all the parameters
+ */
+ public function verify_request(&$request) {/*{{{*/
+ $this->get_version($request);
+ $consumer = $this->get_consumer($request);
+ $token = $this->get_token($request, $consumer, "access");
+ $this->check_signature($request, $consumer, $token);
+ return array($consumer, $token);
+ }/*}}}*/
+
+ // Internals from here
+ /**
+ * version 1
+ */
+ private function get_version(&$request) {/*{{{*/
+ $version = $request->get_parameter("oauth_version");
+ if (!$version) {
+ $version = 1.0;
+ }
+ if ($version && $version != $this->version) {
+ throw new OAuthException("OAuth version '$version' not supported");
+ }
+ return $version;
+ }/*}}}*/
+
+ /**
+ * figure out the signature with some defaults
+ */
+ private function get_signature_method(&$request) {/*{{{*/
+ $signature_method =
+ @$request->get_parameter("oauth_signature_method");
+ if (!$signature_method) {
+ $signature_method = "PLAINTEXT";
+ }
+ if (!in_array($signature_method,
+ array_keys($this->signature_methods))) {
+ throw new OAuthException(
+ "Signature method '$signature_method' not supported try one of the following: " . implode(", ", array_keys($this->signature_methods))
+ );
+ }
+ return $this->signature_methods[$signature_method];
+ }/*}}}*/
+
+ /**
+ * try to find the consumer for the provided request's consumer key
+ */
+ private function get_consumer(&$request) {/*{{{*/
+ $consumer_key = @$request->get_parameter("oauth_consumer_key");
+ if (!$consumer_key) {
+ throw new OAuthException("Invalid consumer key");
+ }
+
+ $consumer = $this->data_store->lookup_consumer($consumer_key);
+ if (!$consumer) {
+ throw new OAuthException("Invalid consumer");
+ }
+
+ return $consumer;
+ }/*}}}*/
+
+ /**
+ * try to find the token for the provided request's token key
+ */
+ private function get_token(&$request, $consumer, $token_type="access") {/*{{{*/
+ $token_field = @$request->get_parameter('oauth_token');
+ $token = $this->data_store->lookup_token(
+ $consumer, $token_type, $token_field
+ );
+ if (!$token) {
+ throw new OAuthException("Invalid $token_type token: $token_field");
+ }
+ return $token;
+ }/*}}}*/
+
+ /**
+ * all-in-one function to check the signature on a request
+ * should guess the signature method appropriately
+ */
+ private function check_signature(&$request, $consumer, $token) {/*{{{*/
+ // this should probably be in a different method
+ $timestamp = @$request->get_parameter('oauth_timestamp');
+ $nonce = @$request->get_parameter('oauth_nonce');
+
+ $this->check_timestamp($timestamp);
+ $this->check_nonce($consumer, $token, $nonce, $timestamp);
+
+ $signature_method = $this->get_signature_method($request);
+
+ $signature = $request->get_parameter('oauth_signature');
+ $valid_sig = $signature_method->check_signature(
+ $request,
+ $consumer,
+ $token,
+ $signature
+ );
+
+ if (!$valid_sig) {
+ throw new OAuthException("Invalid signature");
+ }
+ }/*}}}*/
+
+ /**
+ * check that the timestamp is new enough
+ */
+ private function check_timestamp($timestamp) {/*{{{*/
+ // verify that timestamp is recentish
+ $now = time();
+ if ($now - $timestamp > $this->timestamp_threshold) {
+ throw new OAuthException("Expired timestamp, yours $timestamp, ours $now");
+ }
+ }/*}}}*/
+
+ /**
+ * check that the nonce is not repeated
+ */
+ private function check_nonce($consumer, $token, $nonce, $timestamp) {/*{{{*/
+ // verify that the nonce is uniqueish
+ $found = $this->data_store->lookup_nonce($consumer, $token, $nonce, $timestamp);
+ if ($found) {
+ throw new OAuthException("Nonce already used: $nonce");
+ }
+ }/*}}}*/
+
+
+
+}/*}}}*/
+
+class OAuthDataStore {/*{{{*/
+ function lookup_consumer($consumer_key) {/*{{{*/
+ // implement me
+ }/*}}}*/
+
+ function lookup_token($consumer, $token_type, $token) {/*{{{*/
+ // implement me
+ }/*}}}*/
+
+ function lookup_nonce($consumer, $token, $nonce, $timestamp) {/*{{{*/
+ // implement me
+ }/*}}}*/
+
+ function fetch_request_token($consumer) {/*{{{*/
+ // return a new token attached to this consumer
+ }/*}}}*/
+
+ function fetch_access_token($token, $consumer) {/*{{{*/
+ // return a new access token attached to this consumer
+ // for the user associated with this token if the request token
+ // is authorized
+ // should also invalidate the request token
+ }/*}}}*/
+
+}/*}}}*/
+
+
+/* A very naive dbm-based oauth storage
+ */
+class SimpleOAuthDataStore extends OAuthDataStore {/*{{{*/
+ private $dbh;
+
+ function __construct($path = "oauth.gdbm") {/*{{{*/
+ $this->dbh = dba_popen($path, 'c', 'gdbm');
+ }/*}}}*/
+
+ function __destruct() {/*{{{*/
+ dba_close($this->dbh);
+ }/*}}}*/
+
+ function lookup_consumer($consumer_key) {/*{{{*/
+ $rv = dba_fetch("consumer_$consumer_key", $this->dbh);
+ if ($rv === FALSE) {
+ return NULL;
+ }
+ $obj = unserialize($rv);
+ if (!($obj instanceof OAuthConsumer)) {
+ return NULL;
+ }
+ return $obj;
+ }/*}}}*/
+
+ function lookup_token($consumer, $token_type, $token) {/*{{{*/
+ $rv = dba_fetch("${token_type}_${token}", $this->dbh);
+ if ($rv === FALSE) {
+ return NULL;
+ }
+ $obj = unserialize($rv);
+ if (!($obj instanceof OAuthToken)) {
+ return NULL;
+ }
+ return $obj;
+ }/*}}}*/
+
+ function lookup_nonce($consumer, $token, $nonce, $timestamp) {/*{{{*/
+ return dba_exists("nonce_$nonce", $this->dbh);
+ }/*}}}*/
+
+ function new_token($consumer, $type="request") {/*{{{*/
+ $key = md5(time());
+ $secret = time() + time();
+ $token = new OAuthToken($key, md5(md5($secret)));
+ if (!dba_insert("${type}_$key", serialize($token), $this->dbh)) {
+ throw new OAuthException("doooom!");
+ }
+ return $token;
+ }/*}}}*/
+
+ function new_request_token($consumer) {/*{{{*/
+ return $this->new_token($consumer, "request");
+ }/*}}}*/
+
+ function new_access_token($token, $consumer) {/*{{{*/
+
+ $token = $this->new_token($consumer, 'access');
+ dba_delete("request_" . $token->key, $this->dbh);
+ return $token;
+ }/*}}}*/
+}/*}}}*/
+
+class OAuthUtil {/*{{{*/
+ public static function urlencodeRFC3986($string) {/*{{{*/
+ return str_replace('%7E', '~', rawurlencode($string));
+ }/*}}}*/
+
+ public static function urldecodeRFC3986($string) {/*{{{*/
+ return rawurldecode($string);
+ }/*}}}*/
+}/*}}}*/
+
+?>
\ No newline at end of file
diff -Nru owncloud-1.1+git20110209/3rdparty/Google/common.inc.php owncloud-5.0.4debian/3rdparty/Google/common.inc.php
--- owncloud-1.1+git20110209/3rdparty/Google/common.inc.php 1970-01-01 00:00:00.000000000 +0000
+++ owncloud-5.0.4debian/3rdparty/Google/common.inc.php 2013-04-10 17:29:58.000000000 +0000
@@ -0,0 +1,185 @@
+
+ */
+
+$PRIV_KEY_FILE = '/path/to/your/rsa_private_key.pem';
+
+// OAuth library - http://oauth.googlecode.com/svn/code/php/
+require_once('OAuth.php');
+
+// Google's accepted signature methods
+$hmac_method = new OAuthSignatureMethod_HMAC_SHA1();
+$rsa_method = new OAuthSignatureMethod_RSA_SHA1();
+$SIG_METHODS = array($rsa_method->get_name() => $rsa_method,
+ $hmac_method->get_name() => $hmac_method);
+
+/**
+ * Makes an HTTP request to the specified URL
+ *
+ * @param string $http_method The HTTP method (GET, POST, PUT, DELETE)
+ * @param string $url Full URL of the resource to access
+ * @param array $extraHeaders (optional) Additional headers to include in each
+ * request. Elements are header/value pair strings ('Host: example.com')
+ * @param string $postData (optional) POST/PUT request body
+ * @param bool $returnResponseHeaders True if resp. headers should be returned.
+ * @return string Response body from the server
+ */
+function send_signed_request($http_method, $url, $extraHeaders=null,
+ $postData=null, $returnResponseHeaders=true) {
+ $curl = curl_init($url);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($curl, CURLOPT_FAILONERROR, false);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
+
+ // Return request headers in the reponse
+// curl_setopt($curl, CURLINFO_HEADER_OUT, true);
+
+ // Return response headers ni the response?
+ if ($returnResponseHeaders) {
+ curl_setopt($curl, CURLOPT_HEADER, true);
+ }
+
+ $headers = array();
+ //$headers[] = 'GData-Version: 2.0'; // use GData v2 by default
+ if (is_array($extraHeaders)) {
+ $headers = array_merge($headers, $extraHeaders);
+ }
+
+ // Setup default curl options for each type of HTTP request.
+ // This is also a great place to add additional headers for each request.
+ switch($http_method) {
+ case 'GET':
+ curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
+ break;
+ case 'POST':
+ curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
+ curl_setopt($curl, CURLOPT_POST, 1);
+ curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
+ break;
+ case 'PUT':
+ $headers[] = 'If-Match: *';
+ curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
+ curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $http_method);
+ curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
+ break;
+ case 'DELETE':
+ $headers[] = 'If-Match: *';
+ curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
+ curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $http_method);
+ break;
+ default:
+ curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
+ }
+
+ // Execute the request. If an error occures, fill the response body with it.
+ $response = curl_exec($curl);
+ if (!$response) {
+ $response = curl_error($curl);
+ }
+
+ // Add server's response headers to our response body
+ $response = curl_getinfo($curl, CURLINFO_HEADER_OUT) . $response;
+
+ curl_close($curl);
+
+ return $response;
+}
+
+/**
+* Takes XML as a string and returns it nicely indented
+*
+* @param string $xml The xml to beautify
+* @param boolean $html_output True if returned XML should be escaped for HTML.
+* @return string The beautified xml
+*/
+function xml_pretty_printer($xml, $html_output=false) {
+ $xml_obj = new SimpleXMLElement($xml);
+ $level = 2;
+
+ // Get an array containing each XML element
+ $xml = explode("\n", preg_replace('/>\s*', ">\n<", $xml_obj->asXML()));
+
+ // Hold current indentation level
+ $indent = 0;
+
+ $pretty = array();
+
+ // Shift off opening XML tag if present
+ if (count($xml) && preg_match('/^<\?\s*xml/', $xml[0])) {
+ $pretty[] = array_shift($xml);
+ }
+
+ foreach ($xml as $el) {
+ if (preg_match('/^<([\w])+[^>\/]*>$/U', $el)) {
+ // opening tag, increase indent
+ $pretty[] = str_repeat(' ', $indent) . $el;
+ $indent += $level;
+ } else {
+ if (preg_match('/^<\/.+>$/', $el)) {
+ $indent -= $level; // closing tag, decrease indent
+ }
+ if ($indent < 0) {
+ $indent += $level;
+ }
+ $pretty[] = str_repeat(' ', $indent) . $el;
+ }
+ }
+
+ $xml = implode("\n", $pretty);
+ return $html_output ? htmlentities($xml) : $xml;
+}
+
+/**
+ * Joins key/value pairs by $inner_glue and each pair together by $outer_glue.
+ *
+ * Example: implode_assoc('=', '&', array('a' => 1, 'b' => 2)) === 'a=1&b=2'
+ *
+ * @param string $inner_glue What to implode each key/value pair with
+ * @param string $outer_glue What to impode each key/value string subset with
+ * @param array $array Associative array of query parameters
+ * @return string Urlencoded string of query parameters
+ */
+function implode_assoc($inner_glue, $outer_glue, $array) {
+ $output = array();
+ foreach($array as $key => $item) {
+ $output[] = $key . $inner_glue . urlencode($item);
+ }
+ return implode($outer_glue, $output);
+}
+
+/**
+ * Explodes a string of key/value url parameters into an associative array.
+ * This method performs the compliment operations of implode_assoc().
+ *
+ * Example: explode_assoc('=', '&', 'a=1&b=2') === array('a' => 1, 'b' => 2)
+ *
+ * @param string $inner_glue What each key/value pair is joined with
+ * @param string $outer_glue What each set of key/value pairs is joined with.
+ * @param array $array Associative array of query parameters
+ * @return array Urlencoded string of query parameters
+ */
+function explode_assoc($inner_glue, $outer_glue, $params) {
+ $tempArr = explode($outer_glue, $params);
+ foreach($tempArr as $val) {
+ $pos = strpos($val, $inner_glue);
+ $key = substr($val, 0, $pos);
+ $array2[$key] = substr($val, $pos + 1, strlen($val));
+ }
+ return $array2;
+}
+
+?>
\ No newline at end of file
diff -Nru owncloud-1.1+git20110209/3rdparty/LICENSE INFO owncloud-5.0.4debian/3rdparty/LICENSE INFO
--- owncloud-1.1+git20110209/3rdparty/LICENSE INFO 1970-01-01 00:00:00.000000000 +0000
+++ owncloud-5.0.4debian/3rdparty/LICENSE INFO 2013-04-10 17:29:58.000000000 +0000
@@ -0,0 +1,27 @@
+Licenses:
+Archive - New BSD License
+aws-sdk - apache 2.0
+class.phpmailer.php - LGPL
+class.smtp.php - LGPL
+Console - PHP License 3.0
+Crypt_Blowfish - PHP License 3.0
+chosen - MIT License
+css - see chosen
+DropBox - MIT
+fullcalendar - GPL / MIT
+getid3 - GPL
+Google - MIT
+js - see chosen
+MDB2 - BSD
+mediawiki - Apache 2.0
+miniColors - GPL / MIT
+openid - GPLv3
+OS - New BSD License
+PEAR - Simplified BSD License
+php-cloudfiles - MIT
+phpass - Public domain
+Sabre - New BSD License
+smb4php - GPL
+System.php - New BSD License
+timepicker - GPL / MIT
+XML - New BSD License
\ No newline at end of file
diff -Nru owncloud-1.1+git20110209/3rdparty/MDB2/Date.php owncloud-5.0.4debian/3rdparty/MDB2/Date.php
--- owncloud-1.1+git20110209/3rdparty/MDB2/Date.php 1970-01-01 00:00:00.000000000 +0000
+++ owncloud-5.0.4debian/3rdparty/MDB2/Date.php 2013-04-10 17:29:58.000000000 +0000
@@ -0,0 +1,183 @@
+ |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+//
+
+/**
+ * @package MDB2
+ * @category Database
+ * @author Lukas Smith
+ */
+
+/**
+ * Several methods to convert the MDB2 native timestamp format (ISO based)
+ * to and from data structures that are convenient to worth with in side of php.
+ * For more complex date arithmetic please take a look at the Date package in PEAR
+ *
+ * @package MDB2
+ * @category Database
+ * @author Lukas Smith
+ */
+class MDB2_Date
+{
+ // {{{ mdbNow()
+
+ /**
+ * return the current datetime
+ *
+ * @return string current datetime in the MDB2 format
+ * @access public
+ */
+ function mdbNow()
+ {
+ return date('Y-m-d H:i:s');
+ }
+ // }}}
+
+ // {{{ mdbToday()
+
+ /**
+ * return the current date
+ *
+ * @return string current date in the MDB2 format
+ * @access public
+ */
+ function mdbToday()
+ {
+ return date('Y-m-d');
+ }
+ // }}}
+
+ // {{{ mdbTime()
+
+ /**
+ * return the current time
+ *
+ * @return string current time in the MDB2 format
+ * @access public
+ */
+ function mdbTime()
+ {
+ return date('H:i:s');
+ }
+ // }}}
+
+ // {{{ date2Mdbstamp()
+
+ /**
+ * convert a date into a MDB2 timestamp
+ *
+ * @param int hour of the date
+ * @param int minute of the date
+ * @param int second of the date
+ * @param int month of the date
+ * @param int day of the date
+ * @param int year of the date
+ *
+ * @return string a valid MDB2 timestamp
+ * @access public
+ */
+ function date2Mdbstamp($hour = null, $minute = null, $second = null,
+ $month = null, $day = null, $year = null)
+ {
+ return MDB2_Date::unix2Mdbstamp(mktime($hour, $minute, $second, $month, $day, $year, -1));
+ }
+ // }}}
+
+ // {{{ unix2Mdbstamp()
+
+ /**
+ * convert a unix timestamp into a MDB2 timestamp
+ *
+ * @param int a valid unix timestamp
+ *
+ * @return string a valid MDB2 timestamp
+ * @access public
+ */
+ function unix2Mdbstamp($unix_timestamp)
+ {
+ return date('Y-m-d H:i:s', $unix_timestamp);
+ }
+ // }}}
+
+ // {{{ mdbstamp2Unix()
+
+ /**
+ * convert a MDB2 timestamp into a unix timestamp
+ *
+ * @param int a valid MDB2 timestamp
+ * @return string unix timestamp with the time stored in the MDB2 format
+ *
+ * @access public
+ */
+ function mdbstamp2Unix($mdb_timestamp)
+ {
+ $arr = MDB2_Date::mdbstamp2Date($mdb_timestamp);
+
+ return mktime($arr['hour'], $arr['minute'], $arr['second'], $arr['month'], $arr['day'], $arr['year'], -1);
+ }
+ // }}}
+
+ // {{{ mdbstamp2Date()
+
+ /**
+ * convert a MDB2 timestamp into an array containing all
+ * values necessary to pass to php's date() function
+ *
+ * @param int a valid MDB2 timestamp
+ *
+ * @return array with the time split
+ * @access public
+ */
+ function mdbstamp2Date($mdb_timestamp)
+ {
+ list($arr['year'], $arr['month'], $arr['day'], $arr['hour'], $arr['minute'], $arr['second']) =
+ sscanf($mdb_timestamp, "%04u-%02u-%02u %02u:%02u:%02u");
+ return $arr;
+ }
+ // }}}
+}
+
+?>
diff -Nru owncloud-1.1+git20110209/3rdparty/MDB2/Driver/Datatype/Common.php owncloud-5.0.4debian/3rdparty/MDB2/Driver/Datatype/Common.php
--- owncloud-1.1+git20110209/3rdparty/MDB2/Driver/Datatype/Common.php 1970-01-01 00:00:00.000000000 +0000
+++ owncloud-5.0.4debian/3rdparty/MDB2/Driver/Datatype/Common.php 2013-04-10 17:29:58.000000000 +0000
@@ -0,0 +1,1842 @@
+ |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+require_once 'MDB2/LOB.php';
+
+/**
+ * @package MDB2
+ * @category Database
+ * @author Lukas Smith
+ */
+
+/**
+ * MDB2_Driver_Common: Base class that is extended by each MDB2 driver
+ *
+ * To load this module in the MDB2 object:
+ * $mdb->loadModule('Datatype');
+ *
+ * @package MDB2
+ * @category Database
+ * @author Lukas Smith
+ */
+class MDB2_Driver_Datatype_Common extends MDB2_Module_Common
+{
+ var $valid_default_values = array(
+ 'text' => '',
+ 'boolean' => true,
+ 'integer' => 0,
+ 'decimal' => 0.0,
+ 'float' => 0.0,
+ 'timestamp' => '1970-01-01 00:00:00',
+ 'time' => '00:00:00',
+ 'date' => '1970-01-01',
+ 'clob' => '',
+ 'blob' => '',
+ );
+
+ /**
+ * contains all LOB objects created with this MDB2 instance
+ * @var array
+ * @access protected
+ */
+ var $lobs = array();
+
+ // }}}
+ // {{{ getValidTypes()
+
+ /**
+ * Get the list of valid types
+ *
+ * This function returns an array of valid types as keys with the values
+ * being possible default values for all native datatypes and mapped types
+ * for custom datatypes.
+ *
+ * @return mixed array on success, a MDB2 error on failure
+ * @access public
+ */
+ function getValidTypes()
+ {
+ $types = $this->valid_default_values;
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+ if (!empty($db->options['datatype_map'])) {
+ foreach ($db->options['datatype_map'] as $type => $mapped_type) {
+ if (array_key_exists($mapped_type, $types)) {
+ $types[$type] = $types[$mapped_type];
+ } elseif (!empty($db->options['datatype_map_callback'][$type])) {
+ $parameter = array('type' => $type, 'mapped_type' => $mapped_type);
+ $default = call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter));
+ $types[$type] = $default;
+ }
+ }
+ }
+ return $types;
+ }
+
+ // }}}
+ // {{{ checkResultTypes()
+
+ /**
+ * Define the list of types to be associated with the columns of a given
+ * result set.
+ *
+ * This function may be called before invoking fetchRow(), fetchOne()
+ * fetchCole() and fetchAll() so that the necessary data type
+ * conversions are performed on the data to be retrieved by them. If this
+ * function is not called, the type of all result set columns is assumed
+ * to be text, thus leading to not perform any conversions.
+ *
+ * @param array $types array variable that lists the
+ * data types to be expected in the result set columns. If this array
+ * contains less types than the number of columns that are returned
+ * in the result set, the remaining columns are assumed to be of the
+ * type text. Currently, the types clob and blob are not fully
+ * supported.
+ * @return mixed MDB2_OK on success, a MDB2 error on failure
+ * @access public
+ */
+ function checkResultTypes($types)
+ {
+ $types = is_array($types) ? $types : array($types);
+ foreach ($types as $key => $type) {
+ if (!isset($this->valid_default_values[$type])) {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+ if (empty($db->options['datatype_map'][$type])) {
+ return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+ $type.' for '.$key.' is not a supported column type', __FUNCTION__);
+ }
+ }
+ }
+ return $types;
+ }
+
+ // }}}
+ // {{{ _baseConvertResult()
+
+ /**
+ * General type conversion method
+ *
+ * @param mixed $value reference to a value to be converted
+ * @param string $type specifies which type to convert to
+ * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text
+ * @return object an MDB2 error on failure
+ * @access protected
+ */
+ function _baseConvertResult($value, $type, $rtrim = true)
+ {
+ switch ($type) {
+ case 'text':
+ if ($rtrim) {
+ $value = rtrim($value);
+ }
+ return $value;
+ case 'integer':
+ return intval($value);
+ case 'boolean':
+ return !empty($value);
+ case 'decimal':
+ return $value;
+ case 'float':
+ return doubleval($value);
+ case 'date':
+ return $value;
+ case 'time':
+ return $value;
+ case 'timestamp':
+ return $value;
+ case 'clob':
+ case 'blob':
+ $this->lobs[] = array(
+ 'buffer' => null,
+ 'position' => 0,
+ 'lob_index' => null,
+ 'endOfLOB' => false,
+ 'resource' => $value,
+ 'value' => null,
+ 'loaded' => false,
+ );
+ end($this->lobs);
+ $lob_index = key($this->lobs);
+ $this->lobs[$lob_index]['lob_index'] = $lob_index;
+ return fopen('MDB2LOB://'.$lob_index.'@'.$this->db_index, 'r+');
+ }
+
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ return $db->raiseError(MDB2_ERROR_INVALID, null, null,
+ 'attempt to convert result value to an unknown type :' . $type, __FUNCTION__);
+ }
+
+ // }}}
+ // {{{ convertResult()
+
+ /**
+ * Convert a value to a RDBMS indipendent MDB2 type
+ *
+ * @param mixed $value value to be converted
+ * @param string $type specifies which type to convert to
+ * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text
+ * @return mixed converted value
+ * @access public
+ */
+ function convertResult($value, $type, $rtrim = true)
+ {
+ if (null === $value) {
+ return null;
+ }
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+ if (!empty($db->options['datatype_map'][$type])) {
+ $type = $db->options['datatype_map'][$type];
+ if (!empty($db->options['datatype_map_callback'][$type])) {
+ $parameter = array('type' => $type, 'value' => $value, 'rtrim' => $rtrim);
+ return call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter));
+ }
+ }
+ return $this->_baseConvertResult($value, $type, $rtrim);
+ }
+
+ // }}}
+ // {{{ convertResultRow()
+
+ /**
+ * Convert a result row
+ *
+ * @param array $types
+ * @param array $row specifies the types to convert to
+ * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text
+ * @return mixed MDB2_OK on success, an MDB2 error on failure
+ * @access public
+ */
+ function convertResultRow($types, $row, $rtrim = true)
+ {
+ //$types = $this->_sortResultFieldTypes(array_keys($row), $types);
+ $keys = array_keys($row);
+ if (is_int($keys[0])) {
+ $types = $this->_sortResultFieldTypes($keys, $types);
+ }
+ foreach ($row as $key => $value) {
+ if (empty($types[$key])) {
+ continue;
+ }
+ $value = $this->convertResult($row[$key], $types[$key], $rtrim);
+ if (PEAR::isError($value)) {
+ return $value;
+ }
+ $row[$key] = $value;
+ }
+ return $row;
+ }
+
+ // }}}
+ // {{{ _sortResultFieldTypes()
+
+ /**
+ * convert a result row
+ *
+ * @param array $types
+ * @param array $row specifies the types to convert to
+ * @param bool $rtrim if to rtrim text values or not
+ * @return mixed MDB2_OK on success, a MDB2 error on failure
+ * @access public
+ */
+ function _sortResultFieldTypes($columns, $types)
+ {
+ $n_cols = count($columns);
+ $n_types = count($types);
+ if ($n_cols > $n_types) {
+ for ($i= $n_cols - $n_types; $i >= 0; $i--) {
+ $types[] = null;
+ }
+ }
+ $sorted_types = array();
+ foreach ($columns as $col) {
+ $sorted_types[$col] = null;
+ }
+ foreach ($types as $name => $type) {
+ if (array_key_exists($name, $sorted_types)) {
+ $sorted_types[$name] = $type;
+ unset($types[$name]);
+ }
+ }
+ // if there are left types in the array, fill the null values of the
+ // sorted array with them, in order.
+ if (count($types)) {
+ reset($types);
+ foreach (array_keys($sorted_types) as $k) {
+ if (null === $sorted_types[$k]) {
+ $sorted_types[$k] = current($types);
+ next($types);
+ }
+ }
+ }
+ return $sorted_types;
+ }
+
+ // }}}
+ // {{{ getDeclaration()
+
+ /**
+ * Obtain DBMS specific SQL code portion needed to declare
+ * of the given type
+ *
+ * @param string $type type to which the value should be converted to
+ * @param string $name name the field to be declared.
+ * @param string $field definition of the field
+ * @return string DBMS specific SQL code portion that should be used to
+ * declare the specified field.
+ * @access public
+ */
+ function getDeclaration($type, $name, $field)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ if (!empty($db->options['datatype_map'][$type])) {
+ $type = $db->options['datatype_map'][$type];
+ if (!empty($db->options['datatype_map_callback'][$type])) {
+ $parameter = array('type' => $type, 'name' => $name, 'field' => $field);
+ return call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter));
+ }
+ $field['type'] = $type;
+ }
+
+ if (!method_exists($this, "_get{$type}Declaration")) {
+ return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+ 'type not defined: '.$type, __FUNCTION__);
+ }
+ return $this->{"_get{$type}Declaration"}($name, $field);
+ }
+
+ // }}}
+ // {{{ getTypeDeclaration()
+
+ /**
+ * Obtain DBMS specific SQL code portion needed to declare an text type
+ * field to be used in statements like CREATE TABLE.
+ *
+ * @param array $field associative array with the name of the properties
+ * of the field being declared as array indexes. Currently, the types
+ * of supported field properties are as follows:
+ *
+ * length
+ * Integer value that determines the maximum length of the text
+ * field. If this argument is missing the field should be
+ * declared to have the longest length allowed by the DBMS.
+ *
+ * default
+ * Text value to be used as default for this field.
+ *
+ * notnull
+ * Boolean flag that indicates whether this field is constrained
+ * to not be set to null.
+ * @return string DBMS specific SQL code portion that should be used to
+ * declare the specified field.
+ * @access public
+ */
+ function getTypeDeclaration($field)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ switch ($field['type']) {
+ case 'text':
+ $length = !empty($field['length']) ? $field['length'] : $db->options['default_text_field_length'];
+ $fixed = !empty($field['fixed']) ? $field['fixed'] : false;
+ return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$db->options['default_text_field_length'].')')
+ : ($length ? 'VARCHAR('.$length.')' : 'TEXT');
+ case 'clob':
+ return 'TEXT';
+ case 'blob':
+ return 'TEXT';
+ case 'integer':
+ return 'INT';
+ case 'boolean':
+ return 'INT';
+ case 'date':
+ return 'CHAR ('.strlen('YYYY-MM-DD').')';
+ case 'time':
+ return 'CHAR ('.strlen('HH:MM:SS').')';
+ case 'timestamp':
+ return 'CHAR ('.strlen('YYYY-MM-DD HH:MM:SS').')';
+ case 'float':
+ return 'TEXT';
+ case 'decimal':
+ return 'TEXT';
+ }
+ return '';
+ }
+
+ // }}}
+ // {{{ _getDeclaration()
+
+ /**
+ * Obtain DBMS specific SQL code portion needed to declare a generic type
+ * field to be used in statements like CREATE TABLE.
+ *
+ * @param string $name name the field to be declared.
+ * @param array $field associative array with the name of the properties
+ * of the field being declared as array indexes. Currently, the types
+ * of supported field properties are as follows:
+ *
+ * length
+ * Integer value that determines the maximum length of the text
+ * field. If this argument is missing the field should be
+ * declared to have the longest length allowed by the DBMS.
+ *
+ * default
+ * Text value to be used as default for this field.
+ *
+ * notnull
+ * Boolean flag that indicates whether this field is constrained
+ * to not be set to null.
+ * charset
+ * Text value with the default CHARACTER SET for this field.
+ * collation
+ * Text value with the default COLLATION for this field.
+ * @return string DBMS specific SQL code portion that should be used to
+ * declare the specified field, or a MDB2_Error on failure
+ * @access protected
+ */
+ function _getDeclaration($name, $field)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ $name = $db->quoteIdentifier($name, true);
+ $declaration_options = $db->datatype->_getDeclarationOptions($field);
+ if (PEAR::isError($declaration_options)) {
+ return $declaration_options;
+ }
+ return $name.' '.$this->getTypeDeclaration($field).$declaration_options;
+ }
+
+ // }}}
+ // {{{ _getDeclarationOptions()
+
+ /**
+ * Obtain DBMS specific SQL code portion needed to declare a generic type
+ * field to be used in statement like CREATE TABLE, without the field name
+ * and type values (ie. just the character set, default value, if the
+ * field is permitted to be NULL or not, and the collation options).
+ *
+ * @param array $field associative array with the name of the properties
+ * of the field being declared as array indexes. Currently, the types
+ * of supported field properties are as follows:
+ *
+ * default
+ * Text value to be used as default for this field.
+ * notnull
+ * Boolean flag that indicates whether this field is constrained
+ * to not be set to null.
+ * charset
+ * Text value with the default CHARACTER SET for this field.
+ * collation
+ * Text value with the default COLLATION for this field.
+ * @return string DBMS specific SQL code portion that should be used to
+ * declare the specified field's options.
+ * @access protected
+ */
+ function _getDeclarationOptions($field)
+ {
+ $charset = empty($field['charset']) ? '' :
+ ' '.$this->_getCharsetFieldDeclaration($field['charset']);
+
+ $notnull = empty($field['notnull']) ? '' : ' NOT NULL';
+ $default = '';
+ if (array_key_exists('default', $field)) {
+ if ($field['default'] === '') {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+ $valid_default_values = $this->getValidTypes();
+ $field['default'] = $valid_default_values[$field['type']];
+ if ($field['default'] === '' && ($db->options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL)) {
+ $field['default'] = ' ';
+ }
+ }
+ if (null !== $field['default']) {
+ $default = ' DEFAULT ' . $this->quote($field['default'], $field['type']);
+ }
+ }
+
+ $collation = empty($field['collation']) ? '' :
+ ' '.$this->_getCollationFieldDeclaration($field['collation']);
+
+ return $charset.$default.$notnull.$collation;
+ }
+
+ // }}}
+ // {{{ _getCharsetFieldDeclaration()
+
+ /**
+ * Obtain DBMS specific SQL code portion needed to set the CHARACTER SET
+ * of a field declaration to be used in statements like CREATE TABLE.
+ *
+ * @param string $charset name of the charset
+ * @return string DBMS specific SQL code portion needed to set the CHARACTER SET
+ * of a field declaration.
+ */
+ function _getCharsetFieldDeclaration($charset)
+ {
+ return '';
+ }
+
+ // }}}
+ // {{{ _getCollationFieldDeclaration()
+
+ /**
+ * Obtain DBMS specific SQL code portion needed to set the COLLATION
+ * of a field declaration to be used in statements like CREATE TABLE.
+ *
+ * @param string $collation name of the collation
+ * @return string DBMS specific SQL code portion needed to set the COLLATION
+ * of a field declaration.
+ */
+ function _getCollationFieldDeclaration($collation)
+ {
+ return '';
+ }
+
+ // }}}
+ // {{{ _getIntegerDeclaration()
+
+ /**
+ * Obtain DBMS specific SQL code portion needed to declare an integer type
+ * field to be used in statements like CREATE TABLE.
+ *
+ * @param string $name name the field to be declared.
+ * @param array $field associative array with the name of the properties
+ * of the field being declared as array indexes. Currently, the types
+ * of supported field properties are as follows:
+ *
+ * unsigned
+ * Boolean flag that indicates whether the field should be
+ * declared as unsigned integer if possible.
+ *
+ * default
+ * Integer value to be used as default for this field.
+ *
+ * notnull
+ * Boolean flag that indicates whether this field is constrained
+ * to not be set to null.
+ * @return string DBMS specific SQL code portion that should be used to
+ * declare the specified field.
+ * @access protected
+ */
+ function _getIntegerDeclaration($name, $field)
+ {
+ if (!empty($field['unsigned'])) {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ $db->warnings[] = "unsigned integer field \"$name\" is being declared as signed integer";
+ }
+ return $this->_getDeclaration($name, $field);
+ }
+
+ // }}}
+ // {{{ _getTextDeclaration()
+
+ /**
+ * Obtain DBMS specific SQL code portion needed to declare an text type
+ * field to be used in statements like CREATE TABLE.
+ *
+ * @param string $name name the field to be declared.
+ * @param array $field associative array with the name of the properties
+ * of the field being declared as array indexes. Currently, the types
+ * of supported field properties are as follows:
+ *
+ * length
+ * Integer value that determines the maximum length of the text
+ * field. If this argument is missing the field should be
+ * declared to have the longest length allowed by the DBMS.
+ *
+ * default
+ * Text value to be used as default for this field.
+ *
+ * notnull
+ * Boolean flag that indicates whether this field is constrained
+ * to not be set to null.
+ * @return string DBMS specific SQL code portion that should be used to
+ * declare the specified field.
+ * @access protected
+ */
+ function _getTextDeclaration($name, $field)
+ {
+ return $this->_getDeclaration($name, $field);
+ }
+
+ // }}}
+ // {{{ _getCLOBDeclaration()
+
+ /**
+ * Obtain DBMS specific SQL code portion needed to declare an character
+ * large object type field to be used in statements like CREATE TABLE.
+ *
+ * @param string $name name the field to be declared.
+ * @param array $field associative array with the name of the properties
+ * of the field being declared as array indexes. Currently, the types
+ * of supported field properties are as follows:
+ *
+ * length
+ * Integer value that determines the maximum length of the large
+ * object field. If this argument is missing the field should be
+ * declared to have the longest length allowed by the DBMS.
+ *
+ * notnull
+ * Boolean flag that indicates whether this field is constrained
+ * to not be set to null.
+ * @return string DBMS specific SQL code portion that should be used to
+ * declare the specified field.
+ * @access public
+ */
+ function _getCLOBDeclaration($name, $field)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ $notnull = empty($field['notnull']) ? '' : ' NOT NULL';
+ $name = $db->quoteIdentifier($name, true);
+ return $name.' '.$this->getTypeDeclaration($field).$notnull;
+ }
+
+ // }}}
+ // {{{ _getBLOBDeclaration()
+
+ /**
+ * Obtain DBMS specific SQL code portion needed to declare an binary large
+ * object type field to be used in statements like CREATE TABLE.
+ *
+ * @param string $name name the field to be declared.
+ * @param array $field associative array with the name of the properties
+ * of the field being declared as array indexes. Currently, the types
+ * of supported field properties are as follows:
+ *
+ * length
+ * Integer value that determines the maximum length of the large
+ * object field. If this argument is missing the field should be
+ * declared to have the longest length allowed by the DBMS.
+ *
+ * notnull
+ * Boolean flag that indicates whether this field is constrained
+ * to not be set to null.
+ * @return string DBMS specific SQL code portion that should be used to
+ * declare the specified field.
+ * @access protected
+ */
+ function _getBLOBDeclaration($name, $field)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ $notnull = empty($field['notnull']) ? '' : ' NOT NULL';
+ $name = $db->quoteIdentifier($name, true);
+ return $name.' '.$this->getTypeDeclaration($field).$notnull;
+ }
+
+ // }}}
+ // {{{ _getBooleanDeclaration()
+
+ /**
+ * Obtain DBMS specific SQL code portion needed to declare a boolean type
+ * field to be used in statements like CREATE TABLE.
+ *
+ * @param string $name name the field to be declared.
+ * @param array $field associative array with the name of the properties
+ * of the field being declared as array indexes. Currently, the types
+ * of supported field properties are as follows:
+ *
+ * default
+ * Boolean value to be used as default for this field.
+ *
+ * notnullL
+ * Boolean flag that indicates whether this field is constrained
+ * to not be set to null.
+ * @return string DBMS specific SQL code portion that should be used to
+ * declare the specified field.
+ * @access protected
+ */
+ function _getBooleanDeclaration($name, $field)
+ {
+ return $this->_getDeclaration($name, $field);
+ }
+
+ // }}}
+ // {{{ _getDateDeclaration()
+
+ /**
+ * Obtain DBMS specific SQL code portion needed to declare a date type
+ * field to be used in statements like CREATE TABLE.
+ *
+ * @param string $name name the field to be declared.
+ * @param array $field associative array with the name of the properties
+ * of the field being declared as array indexes. Currently, the types
+ * of supported field properties are as follows:
+ *
+ * default
+ * Date value to be used as default for this field.
+ *
+ * notnull
+ * Boolean flag that indicates whether this field is constrained
+ * to not be set to null.
+ * @return string DBMS specific SQL code portion that should be used to
+ * declare the specified field.
+ * @access protected
+ */
+ function _getDateDeclaration($name, $field)
+ {
+ return $this->_getDeclaration($name, $field);
+ }
+
+ // }}}
+ // {{{ _getTimestampDeclaration()
+
+ /**
+ * Obtain DBMS specific SQL code portion needed to declare a timestamp
+ * field to be used in statements like CREATE TABLE.
+ *
+ * @param string $name name the field to be declared.
+ * @param array $field associative array with the name of the properties
+ * of the field being declared as array indexes. Currently, the types
+ * of supported field properties are as follows:
+ *
+ * default
+ * Timestamp value to be used as default for this field.
+ *
+ * notnull
+ * Boolean flag that indicates whether this field is constrained
+ * to not be set to null.
+ * @return string DBMS specific SQL code portion that should be used to
+ * declare the specified field.
+ * @access protected
+ */
+ function _getTimestampDeclaration($name, $field)
+ {
+ return $this->_getDeclaration($name, $field);
+ }
+
+ // }}}
+ // {{{ _getTimeDeclaration()
+
+ /**
+ * Obtain DBMS specific SQL code portion needed to declare a time
+ * field to be used in statements like CREATE TABLE.
+ *
+ * @param string $name name the field to be declared.
+ * @param array $field associative array with the name of the properties
+ * of the field being declared as array indexes. Currently, the types
+ * of supported field properties are as follows:
+ *
+ * default
+ * Time value to be used as default for this field.
+ *
+ * notnull
+ * Boolean flag that indicates whether this field is constrained
+ * to not be set to null.
+ * @return string DBMS specific SQL code portion that should be used to
+ * declare the specified field.
+ * @access protected
+ */
+ function _getTimeDeclaration($name, $field)
+ {
+ return $this->_getDeclaration($name, $field);
+ }
+
+ // }}}
+ // {{{ _getFloatDeclaration()
+
+ /**
+ * Obtain DBMS specific SQL code portion needed to declare a float type
+ * field to be used in statements like CREATE TABLE.
+ *
+ * @param string $name name the field to be declared.
+ * @param array $field associative array with the name of the properties
+ * of the field being declared as array indexes. Currently, the types
+ * of supported field properties are as follows:
+ *
+ * default
+ * Float value to be used as default for this field.
+ *
+ * notnull
+ * Boolean flag that indicates whether this field is constrained
+ * to not be set to null.
+ * @return string DBMS specific SQL code portion that should be used to
+ * declare the specified field.
+ * @access protected
+ */
+ function _getFloatDeclaration($name, $field)
+ {
+ return $this->_getDeclaration($name, $field);
+ }
+
+ // }}}
+ // {{{ _getDecimalDeclaration()
+
+ /**
+ * Obtain DBMS specific SQL code portion needed to declare a decimal type
+ * field to be used in statements like CREATE TABLE.
+ *
+ * @param string $name name the field to be declared.
+ * @param array $field associative array with the name of the properties
+ * of the field being declared as array indexes. Currently, the types
+ * of supported field properties are as follows:
+ *
+ * default
+ * Decimal value to be used as default for this field.
+ *
+ * notnull
+ * Boolean flag that indicates whether this field is constrained
+ * to not be set to null.
+ * @return string DBMS specific SQL code portion that should be used to
+ * declare the specified field.
+ * @access protected
+ */
+ function _getDecimalDeclaration($name, $field)
+ {
+ return $this->_getDeclaration($name, $field);
+ }
+
+ // }}}
+ // {{{ compareDefinition()
+
+ /**
+ * Obtain an array of changes that may need to applied
+ *
+ * @param array $current new definition
+ * @param array $previous old definition
+ * @return array containing all changes that will need to be applied
+ * @access public
+ */
+ function compareDefinition($current, $previous)
+ {
+ $type = !empty($current['type']) ? $current['type'] : null;
+
+ if (!method_exists($this, "_compare{$type}Definition")) {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+ if (!empty($db->options['datatype_map_callback'][$type])) {
+ $parameter = array('current' => $current, 'previous' => $previous);
+ $change = call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter));
+ return $change;
+ }
+ return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+ 'type "'.$current['type'].'" is not yet supported', __FUNCTION__);
+ }
+
+ if (empty($previous['type']) || $previous['type'] != $type) {
+ return $current;
+ }
+
+ $change = $this->{"_compare{$type}Definition"}($current, $previous);
+
+ if ($previous['type'] != $type) {
+ $change['type'] = true;
+ }
+
+ $previous_notnull = !empty($previous['notnull']) ? $previous['notnull'] : false;
+ $notnull = !empty($current['notnull']) ? $current['notnull'] : false;
+ if ($previous_notnull != $notnull) {
+ $change['notnull'] = true;
+ }
+
+ $previous_default = array_key_exists('default', $previous) ? $previous['default'] :
+ ($previous_notnull ? '' : null);
+ $default = array_key_exists('default', $current) ? $current['default'] :
+ ($notnull ? '' : null);
+ if ($previous_default !== $default) {
+ $change['default'] = true;
+ }
+
+ return $change;
+ }
+
+ // }}}
+ // {{{ _compareIntegerDefinition()
+
+ /**
+ * Obtain an array of changes that may need to applied to an integer field
+ *
+ * @param array $current new definition
+ * @param array $previous old definition
+ * @return array containing all changes that will need to be applied
+ * @access protected
+ */
+ function _compareIntegerDefinition($current, $previous)
+ {
+ $change = array();
+ $previous_unsigned = !empty($previous['unsigned']) ? $previous['unsigned'] : false;
+ $unsigned = !empty($current['unsigned']) ? $current['unsigned'] : false;
+ if ($previous_unsigned != $unsigned) {
+ $change['unsigned'] = true;
+ }
+ $previous_autoincrement = !empty($previous['autoincrement']) ? $previous['autoincrement'] : false;
+ $autoincrement = !empty($current['autoincrement']) ? $current['autoincrement'] : false;
+ if ($previous_autoincrement != $autoincrement) {
+ $change['autoincrement'] = true;
+ }
+ return $change;
+ }
+
+ // }}}
+ // {{{ _compareTextDefinition()
+
+ /**
+ * Obtain an array of changes that may need to applied to an text field
+ *
+ * @param array $current new definition
+ * @param array $previous old definition
+ * @return array containing all changes that will need to be applied
+ * @access protected
+ */
+ function _compareTextDefinition($current, $previous)
+ {
+ $change = array();
+ $previous_length = !empty($previous['length']) ? $previous['length'] : 0;
+ $length = !empty($current['length']) ? $current['length'] : 0;
+ if ($previous_length != $length) {
+ $change['length'] = true;
+ }
+ $previous_fixed = !empty($previous['fixed']) ? $previous['fixed'] : 0;
+ $fixed = !empty($current['fixed']) ? $current['fixed'] : 0;
+ if ($previous_fixed != $fixed) {
+ $change['fixed'] = true;
+ }
+ return $change;
+ }
+
+ // }}}
+ // {{{ _compareCLOBDefinition()
+
+ /**
+ * Obtain an array of changes that may need to applied to an CLOB field
+ *
+ * @param array $current new definition
+ * @param array $previous old definition
+ * @return array containing all changes that will need to be applied
+ * @access protected
+ */
+ function _compareCLOBDefinition($current, $previous)
+ {
+ return $this->_compareTextDefinition($current, $previous);
+ }
+
+ // }}}
+ // {{{ _compareBLOBDefinition()
+
+ /**
+ * Obtain an array of changes that may need to applied to an BLOB field
+ *
+ * @param array $current new definition
+ * @param array $previous old definition
+ * @return array containing all changes that will need to be applied
+ * @access protected
+ */
+ function _compareBLOBDefinition($current, $previous)
+ {
+ return $this->_compareTextDefinition($current, $previous);
+ }
+
+ // }}}
+ // {{{ _compareDateDefinition()
+
+ /**
+ * Obtain an array of changes that may need to applied to an date field
+ *
+ * @param array $current new definition
+ * @param array $previous old definition
+ * @return array containing all changes that will need to be applied
+ * @access protected
+ */
+ function _compareDateDefinition($current, $previous)
+ {
+ return array();
+ }
+
+ // }}}
+ // {{{ _compareTimeDefinition()
+
+ /**
+ * Obtain an array of changes that may need to applied to an time field
+ *
+ * @param array $current new definition
+ * @param array $previous old definition
+ * @return array containing all changes that will need to be applied
+ * @access protected
+ */
+ function _compareTimeDefinition($current, $previous)
+ {
+ return array();
+ }
+
+ // }}}
+ // {{{ _compareTimestampDefinition()
+
+ /**
+ * Obtain an array of changes that may need to applied to an timestamp field
+ *
+ * @param array $current new definition
+ * @param array $previous old definition
+ * @return array containing all changes that will need to be applied
+ * @access protected
+ */
+ function _compareTimestampDefinition($current, $previous)
+ {
+ return array();
+ }
+
+ // }}}
+ // {{{ _compareBooleanDefinition()
+
+ /**
+ * Obtain an array of changes that may need to applied to an boolean field
+ *
+ * @param array $current new definition
+ * @param array $previous old definition
+ * @return array containing all changes that will need to be applied
+ * @access protected
+ */
+ function _compareBooleanDefinition($current, $previous)
+ {
+ return array();
+ }
+
+ // }}}
+ // {{{ _compareFloatDefinition()
+
+ /**
+ * Obtain an array of changes that may need to applied to an float field
+ *
+ * @param array $current new definition
+ * @param array $previous old definition
+ * @return array containing all changes that will need to be applied
+ * @access protected
+ */
+ function _compareFloatDefinition($current, $previous)
+ {
+ return array();
+ }
+
+ // }}}
+ // {{{ _compareDecimalDefinition()
+
+ /**
+ * Obtain an array of changes that may need to applied to an decimal field
+ *
+ * @param array $current new definition
+ * @param array $previous old definition
+ * @return array containing all changes that will need to be applied
+ * @access protected
+ */
+ function _compareDecimalDefinition($current, $previous)
+ {
+ return array();
+ }
+
+ // }}}
+ // {{{ quote()
+
+ /**
+ * Convert a text value into a DBMS specific format that is suitable to
+ * compose query statements.
+ *
+ * @param string $value text string value that is intended to be converted.
+ * @param string $type type to which the value should be converted to
+ * @param bool $quote determines if the value should be quoted and escaped
+ * @param bool $escape_wildcards if to escape escape wildcards
+ * @return string text string that represents the given argument value in
+ * a DBMS specific format.
+ * @access public
+ */
+ function quote($value, $type = null, $quote = true, $escape_wildcards = false)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ if ((null === $value)
+ || ($value === '' && $db->options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL)
+ ) {
+ if (!$quote) {
+ return null;
+ }
+ return 'NULL';
+ }
+
+ if (null === $type) {
+ switch (gettype($value)) {
+ case 'integer':
+ $type = 'integer';
+ break;
+ case 'double':
+ // todo: default to decimal as float is quite unusual
+ // $type = 'float';
+ $type = 'decimal';
+ break;
+ case 'boolean':
+ $type = 'boolean';
+ break;
+ case 'array':
+ $value = serialize($value);
+ case 'object':
+ $type = 'text';
+ break;
+ default:
+ if (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/', $value)) {
+ $type = 'timestamp';
+ } elseif (preg_match('/^\d{2}:\d{2}$/', $value)) {
+ $type = 'time';
+ } elseif (preg_match('/^\d{4}-\d{2}-\d{2}$/', $value)) {
+ $type = 'date';
+ } else {
+ $type = 'text';
+ }
+ break;
+ }
+ } elseif (!empty($db->options['datatype_map'][$type])) {
+ $type = $db->options['datatype_map'][$type];
+ if (!empty($db->options['datatype_map_callback'][$type])) {
+ $parameter = array('type' => $type, 'value' => $value, 'quote' => $quote, 'escape_wildcards' => $escape_wildcards);
+ return call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter));
+ }
+ }
+
+ if (!method_exists($this, "_quote{$type}")) {
+ return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+ 'type not defined: '.$type, __FUNCTION__);
+ }
+ $value = $this->{"_quote{$type}"}($value, $quote, $escape_wildcards);
+ if ($quote && $escape_wildcards && $db->string_quoting['escape_pattern']
+ && $db->string_quoting['escape'] !== $db->string_quoting['escape_pattern']
+ ) {
+ $value.= $this->patternEscapeString();
+ }
+ return $value;
+ }
+
+ // }}}
+ // {{{ _quoteInteger()
+
+ /**
+ * Convert a text value into a DBMS specific format that is suitable to
+ * compose query statements.
+ *
+ * @param string $value text string value that is intended to be converted.
+ * @param bool $quote determines if the value should be quoted and escaped
+ * @param bool $escape_wildcards if to escape escape wildcards
+ * @return string text string that represents the given argument value in
+ * a DBMS specific format.
+ * @access protected
+ */
+ function _quoteInteger($value, $quote, $escape_wildcards)
+ {
+ return (int)$value;
+ }
+
+ // }}}
+ // {{{ _quoteText()
+
+ /**
+ * Convert a text value into a DBMS specific format that is suitable to
+ * compose query statements.
+ *
+ * @param string $value text string value that is intended to be converted.
+ * @param bool $quote determines if the value should be quoted and escaped
+ * @param bool $escape_wildcards if to escape escape wildcards
+ * @return string text string that already contains any DBMS specific
+ * escaped character sequences.
+ * @access protected
+ */
+ function _quoteText($value, $quote, $escape_wildcards)
+ {
+ if (!$quote) {
+ return $value;
+ }
+
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ $value = $db->escape($value, $escape_wildcards);
+ if (PEAR::isError($value)) {
+ return $value;
+ }
+ return "'".$value."'";
+ }
+
+ // }}}
+ // {{{ _readFile()
+
+ /**
+ * Convert a text value into a DBMS specific format that is suitable to
+ * compose query statements.
+ *
+ * @param string $value text string value that is intended to be converted.
+ * @return string text string that represents the given argument value in
+ * a DBMS specific format.
+ * @access protected
+ */
+ function _readFile($value)
+ {
+ $close = false;
+ if (preg_match('/^(\w+:\/\/)(.*)$/', $value, $match)) {
+ $close = true;
+ if (strtolower($match[1]) == 'file://') {
+ $value = $match[2];
+ }
+ $value = @fopen($value, 'r');
+ }
+
+ if (is_resource($value)) {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ $fp = $value;
+ $value = '';
+ while (!@feof($fp)) {
+ $value.= @fread($fp, $db->options['lob_buffer_length']);
+ }
+ if ($close) {
+ @fclose($fp);
+ }
+ }
+
+ return $value;
+ }
+
+ // }}}
+ // {{{ _quoteLOB()
+
+ /**
+ * Convert a text value into a DBMS specific format that is suitable to
+ * compose query statements.
+ *
+ * @param string $value text string value that is intended to be converted.
+ * @param bool $quote determines if the value should be quoted and escaped
+ * @param bool $escape_wildcards if to escape escape wildcards
+ * @return string text string that represents the given argument value in
+ * a DBMS specific format.
+ * @access protected
+ */
+ function _quoteLOB($value, $quote, $escape_wildcards)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+ if ($db->options['lob_allow_url_include']) {
+ $value = $this->_readFile($value);
+ if (PEAR::isError($value)) {
+ return $value;
+ }
+ }
+ return $this->_quoteText($value, $quote, $escape_wildcards);
+ }
+
+ // }}}
+ // {{{ _quoteCLOB()
+
+ /**
+ * Convert a text value into a DBMS specific format that is suitable to
+ * compose query statements.
+ *
+ * @param string $value text string value that is intended to be converted.
+ * @param bool $quote determines if the value should be quoted and escaped
+ * @param bool $escape_wildcards if to escape escape wildcards
+ * @return string text string that represents the given argument value in
+ * a DBMS specific format.
+ * @access protected
+ */
+ function _quoteCLOB($value, $quote, $escape_wildcards)
+ {
+ return $this->_quoteLOB($value, $quote, $escape_wildcards);
+ }
+
+ // }}}
+ // {{{ _quoteBLOB()
+
+ /**
+ * Convert a text value into a DBMS specific format that is suitable to
+ * compose query statements.
+ *
+ * @param string $value text string value that is intended to be converted.
+ * @param bool $quote determines if the value should be quoted and escaped
+ * @param bool $escape_wildcards if to escape escape wildcards
+ * @return string text string that represents the given argument value in
+ * a DBMS specific format.
+ * @access protected
+ */
+ function _quoteBLOB($value, $quote, $escape_wildcards)
+ {
+ return $this->_quoteLOB($value, $quote, $escape_wildcards);
+ }
+
+ // }}}
+ // {{{ _quoteBoolean()
+
+ /**
+ * Convert a text value into a DBMS specific format that is suitable to
+ * compose query statements.
+ *
+ * @param string $value text string value that is intended to be converted.
+ * @param bool $quote determines if the value should be quoted and escaped
+ * @param bool $escape_wildcards if to escape escape wildcards
+ * @return string text string that represents the given argument value in
+ * a DBMS specific format.
+ * @access protected
+ */
+ function _quoteBoolean($value, $quote, $escape_wildcards)
+ {
+ return ($value ? 1 : 0);
+ }
+
+ // }}}
+ // {{{ _quoteDate()
+
+ /**
+ * Convert a text value into a DBMS specific format that is suitable to
+ * compose query statements.
+ *
+ * @param string $value text string value that is intended to be converted.
+ * @param bool $quote determines if the value should be quoted and escaped
+ * @param bool $escape_wildcards if to escape escape wildcards
+ * @return string text string that represents the given argument value in
+ * a DBMS specific format.
+ * @access protected
+ */
+ function _quoteDate($value, $quote, $escape_wildcards)
+ {
+ if ($value === 'CURRENT_DATE') {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+ if (isset($db->function) && is_object($this->function) && is_a($db->function, 'MDB2_Driver_Function_Common')) {
+ return $db->function->now('date');
+ }
+ return 'CURRENT_DATE';
+ }
+ return $this->_quoteText($value, $quote, $escape_wildcards);
+ }
+
+ // }}}
+ // {{{ _quoteTimestamp()
+
+ /**
+ * Convert a text value into a DBMS specific format that is suitable to
+ * compose query statements.
+ *
+ * @param string $value text string value that is intended to be converted.
+ * @param bool $quote determines if the value should be quoted and escaped
+ * @param bool $escape_wildcards if to escape escape wildcards
+ * @return string text string that represents the given argument value in
+ * a DBMS specific format.
+ * @access protected
+ */
+ function _quoteTimestamp($value, $quote, $escape_wildcards)
+ {
+ if ($value === 'CURRENT_TIMESTAMP') {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+ if (isset($db->function) && is_object($db->function) && is_a($db->function, 'MDB2_Driver_Function_Common')) {
+ return $db->function->now('timestamp');
+ }
+ return 'CURRENT_TIMESTAMP';
+ }
+ return $this->_quoteText($value, $quote, $escape_wildcards);
+ }
+
+ // }}}
+ // {{{ _quoteTime()
+
+ /**
+ * Convert a text value into a DBMS specific format that is suitable to
+ * compose query statements.
+ *
+ * @param string $value text string value that is intended to be converted.
+ * @param bool $quote determines if the value should be quoted and escaped
+ * @param bool $escape_wildcards if to escape escape wildcards
+ * @return string text string that represents the given argument value in
+ * a DBMS specific format.
+ * @access protected
+ */
+ function _quoteTime($value, $quote, $escape_wildcards)
+ {
+ if ($value === 'CURRENT_TIME') {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+ if (isset($db->function) && is_object($this->function) && is_a($db->function, 'MDB2_Driver_Function_Common')) {
+ return $db->function->now('time');
+ }
+ return 'CURRENT_TIME';
+ }
+ return $this->_quoteText($value, $quote, $escape_wildcards);
+ }
+
+ // }}}
+ // {{{ _quoteFloat()
+
+ /**
+ * Convert a text value into a DBMS specific format that is suitable to
+ * compose query statements.
+ *
+ * @param string $value text string value that is intended to be converted.
+ * @param bool $quote determines if the value should be quoted and escaped
+ * @param bool $escape_wildcards if to escape escape wildcards
+ * @return string text string that represents the given argument value in
+ * a DBMS specific format.
+ * @access protected
+ */
+ function _quoteFloat($value, $quote, $escape_wildcards)
+ {
+ if (preg_match('/^(.*)e([-+])(\d+)$/i', $value, $matches)) {
+ $decimal = $this->_quoteDecimal($matches[1], $quote, $escape_wildcards);
+ $sign = $matches[2];
+ $exponent = str_pad($matches[3], 2, '0', STR_PAD_LEFT);
+ $value = $decimal.'E'.$sign.$exponent;
+ } else {
+ $value = $this->_quoteDecimal($value, $quote, $escape_wildcards);
+ }
+ return $value;
+ }
+
+ // }}}
+ // {{{ _quoteDecimal()
+
+ /**
+ * Convert a text value into a DBMS specific format that is suitable to
+ * compose query statements.
+ *
+ * @param string $value text string value that is intended to be converted.
+ * @param bool $quote determines if the value should be quoted and escaped
+ * @param bool $escape_wildcards if to escape escape wildcards
+ * @return string text string that represents the given argument value in
+ * a DBMS specific format.
+ * @access protected
+ */
+ function _quoteDecimal($value, $quote, $escape_wildcards)
+ {
+ $value = (string)$value;
+ $value = preg_replace('/[^\d\.,\-+eE]/', '', $value);
+ if (preg_match('/[^\.\d]/', $value)) {
+ if (strpos($value, ',')) {
+ // 1000,00
+ if (!strpos($value, '.')) {
+ // convert the last "," to a "."
+ $value = strrev(str_replace(',', '.', strrev($value)));
+ // 1.000,00
+ } elseif (strpos($value, '.') && strpos($value, '.') < strpos($value, ',')) {
+ $value = str_replace('.', '', $value);
+ // convert the last "," to a "."
+ $value = strrev(str_replace(',', '.', strrev($value)));
+ // 1,000.00
+ } else {
+ $value = str_replace(',', '', $value);
+ }
+ }
+ }
+ return $value;
+ }
+
+ // }}}
+ // {{{ writeLOBToFile()
+
+ /**
+ * retrieve LOB from the database
+ *
+ * @param resource $lob stream handle
+ * @param string $file name of the file into which the LOb should be fetched
+ * @return mixed MDB2_OK on success, a MDB2 error on failure
+ * @access protected
+ */
+ function writeLOBToFile($lob, $file)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ if (preg_match('/^(\w+:\/\/)(.*)$/', $file, $match)) {
+ if ($match[1] == 'file://') {
+ $file = $match[2];
+ }
+ }
+
+ $fp = @fopen($file, 'wb');
+ while (!@feof($lob)) {
+ $result = @fread($lob, $db->options['lob_buffer_length']);
+ $read = strlen($result);
+ if (@fwrite($fp, $result, $read) != $read) {
+ @fclose($fp);
+ return $db->raiseError(MDB2_ERROR, null, null,
+ 'could not write to the output file', __FUNCTION__);
+ }
+ }
+ @fclose($fp);
+ return MDB2_OK;
+ }
+
+ // }}}
+ // {{{ _retrieveLOB()
+
+ /**
+ * retrieve LOB from the database
+ *
+ * @param array $lob array
+ * @return mixed MDB2_OK on success, a MDB2 error on failure
+ * @access protected
+ */
+ function _retrieveLOB(&$lob)
+ {
+ if (null === $lob['value']) {
+ $lob['value'] = $lob['resource'];
+ }
+ $lob['loaded'] = true;
+ return MDB2_OK;
+ }
+
+ // }}}
+ // {{{ readLOB()
+
+ /**
+ * Read data from large object input stream.
+ *
+ * @param resource $lob stream handle
+ * @param string $data reference to a variable that will hold data
+ * to be read from the large object input stream
+ * @param integer $length value that indicates the largest ammount ofdata
+ * to be read from the large object input stream.
+ * @return mixed the effective number of bytes read from the large object
+ * input stream on sucess or an MDB2 error object.
+ * @access public
+ * @see endOfLOB()
+ */
+ function _readLOB($lob, $length)
+ {
+ return substr($lob['value'], $lob['position'], $length);
+ }
+
+ // }}}
+ // {{{ _endOfLOB()
+
+ /**
+ * Determine whether it was reached the end of the large object and
+ * therefore there is no more data to be read for the its input stream.
+ *
+ * @param array $lob array
+ * @return mixed true or false on success, a MDB2 error on failure
+ * @access protected
+ */
+ function _endOfLOB($lob)
+ {
+ return $lob['endOfLOB'];
+ }
+
+ // }}}
+ // {{{ destroyLOB()
+
+ /**
+ * Free any resources allocated during the lifetime of the large object
+ * handler object.
+ *
+ * @param resource $lob stream handle
+ * @access public
+ */
+ function destroyLOB($lob)
+ {
+ $lob_data = stream_get_meta_data($lob);
+ $lob_index = $lob_data['wrapper_data']->lob_index;
+ fclose($lob);
+ if (isset($this->lobs[$lob_index])) {
+ $this->_destroyLOB($this->lobs[$lob_index]);
+ unset($this->lobs[$lob_index]);
+ }
+ return MDB2_OK;
+ }
+
+ // }}}
+ // {{{ _destroyLOB()
+
+ /**
+ * Free any resources allocated during the lifetime of the large object
+ * handler object.
+ *
+ * @param array $lob array
+ * @access private
+ */
+ function _destroyLOB(&$lob)
+ {
+ return MDB2_OK;
+ }
+
+ // }}}
+ // {{{ implodeArray()
+
+ /**
+ * apply a type to all values of an array and return as a comma seperated string
+ * useful for generating IN statements
+ *
+ * @access public
+ *
+ * @param array $array data array
+ * @param string $type determines type of the field
+ *
+ * @return string comma seperated values
+ */
+ function implodeArray($array, $type = false)
+ {
+ if (!is_array($array) || empty($array)) {
+ return 'NULL';
+ }
+ if ($type) {
+ foreach ($array as $value) {
+ $return[] = $this->quote($value, $type);
+ }
+ } else {
+ $return = $array;
+ }
+ return implode(', ', $return);
+ }
+
+ // }}}
+ // {{{ matchPattern()
+
+ /**
+ * build a pattern matching string
+ *
+ * @access public
+ *
+ * @param array $pattern even keys are strings, odd are patterns (% and _)
+ * @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future)
+ * @param string $field optional field name that is being matched against
+ * (might be required when emulating ILIKE)
+ *
+ * @return string SQL pattern
+ */
+ function matchPattern($pattern, $operator = null, $field = null)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ $match = '';
+ if (null !== $operator) {
+ $operator = strtoupper($operator);
+ switch ($operator) {
+ // case insensitive
+ case 'ILIKE':
+ if (null === $field) {
+ return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+ 'case insensitive LIKE matching requires passing the field name', __FUNCTION__);
+ }
+ $db->loadModule('Function', null, true);
+ $match = $db->function->lower($field).' LIKE ';
+ break;
+ case 'NOT ILIKE':
+ if (null === $field) {
+ return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+ 'case insensitive NOT ILIKE matching requires passing the field name', __FUNCTION__);
+ }
+ $db->loadModule('Function', null, true);
+ $match = $db->function->lower($field).' NOT LIKE ';
+ break;
+ // case sensitive
+ case 'LIKE':
+ $match = (null === $field) ? 'LIKE ' : ($field.' LIKE ');
+ break;
+ case 'NOT LIKE':
+ $match = (null === $field) ? 'NOT LIKE ' : ($field.' NOT LIKE ');
+ break;
+ default:
+ return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+ 'not a supported operator type:'. $operator, __FUNCTION__);
+ }
+ }
+ $match.= "'";
+ foreach ($pattern as $key => $value) {
+ if ($key % 2) {
+ $match.= $value;
+ } else {
+ $escaped = $db->escape($value);
+ if (PEAR::isError($escaped)) {
+ return $escaped;
+ }
+ $match.= $db->escapePattern($escaped);
+ }
+ }
+ $match.= "'";
+ $match.= $this->patternEscapeString();
+ return $match;
+ }
+
+ // }}}
+ // {{{ patternEscapeString()
+
+ /**
+ * build string to define pattern escape character
+ *
+ * @access public
+ *
+ * @return string define pattern escape character
+ */
+ function patternEscapeString()
+ {
+ return '';
+ }
+
+ // }}}
+ // {{{ mapNativeDatatype()
+
+ /**
+ * Maps a native array description of a field to a MDB2 datatype and length
+ *
+ * @param array $field native field description
+ * @return array containing the various possible types, length, sign, fixed
+ * @access public
+ */
+ function mapNativeDatatype($field)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ // If the user has specified an option to map the native field
+ // type to a custom MDB2 datatype...
+ $db_type = strtok($field['type'], '(), ');
+ if (!empty($db->options['nativetype_map_callback'][$db_type])) {
+ return call_user_func_array($db->options['nativetype_map_callback'][$db_type], array($db, $field));
+ }
+
+ // Otherwise perform the built-in (i.e. normal) MDB2 native type to
+ // MDB2 datatype conversion
+ return $this->_mapNativeDatatype($field);
+ }
+
+ // }}}
+ // {{{ _mapNativeDatatype()
+
+ /**
+ * Maps a native array description of a field to a MDB2 datatype and length
+ *
+ * @param array $field native field description
+ * @return array containing the various possible types, length, sign, fixed
+ * @access public
+ */
+ function _mapNativeDatatype($field)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+ 'method not implemented', __FUNCTION__);
+ }
+
+ // }}}
+ // {{{ mapPrepareDatatype()
+
+ /**
+ * Maps an mdb2 datatype to mysqli prepare type
+ *
+ * @param string $type
+ * @return string
+ * @access public
+ */
+ function mapPrepareDatatype($type)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ if (!empty($db->options['datatype_map'][$type])) {
+ $type = $db->options['datatype_map'][$type];
+ if (!empty($db->options['datatype_map_callback'][$type])) {
+ $parameter = array('type' => $type);
+ return call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter));
+ }
+ }
+
+ return $type;
+ }
+}
+?>
diff -Nru owncloud-1.1+git20110209/3rdparty/MDB2/Driver/Datatype/mysql.php owncloud-5.0.4debian/3rdparty/MDB2/Driver/Datatype/mysql.php
--- owncloud-1.1+git20110209/3rdparty/MDB2/Driver/Datatype/mysql.php 1970-01-01 00:00:00.000000000 +0000
+++ owncloud-5.0.4debian/3rdparty/MDB2/Driver/Datatype/mysql.php 2013-04-10 17:29:58.000000000 +0000
@@ -0,0 +1,602 @@
+ |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+//
+
+require_once 'MDB2/Driver/Datatype/Common.php';
+
+/**
+ * MDB2 MySQL driver
+ *
+ * @package MDB2
+ * @category Database
+ * @author Lukas Smith
+ */
+class MDB2_Driver_Datatype_mysql extends MDB2_Driver_Datatype_Common
+{
+ // {{{ _getCharsetFieldDeclaration()
+
+ /**
+ * Obtain DBMS specific SQL code portion needed to set the CHARACTER SET
+ * of a field declaration to be used in statements like CREATE TABLE.
+ *
+ * @param string $charset name of the charset
+ * @return string DBMS specific SQL code portion needed to set the CHARACTER SET
+ * of a field declaration.
+ */
+ function _getCharsetFieldDeclaration($charset)
+ {
+ return 'CHARACTER SET '.$charset;
+ }
+
+ // }}}
+ // {{{ _getCollationFieldDeclaration()
+
+ /**
+ * Obtain DBMS specific SQL code portion needed to set the COLLATION
+ * of a field declaration to be used in statements like CREATE TABLE.
+ *
+ * @param string $collation name of the collation
+ * @return string DBMS specific SQL code portion needed to set the COLLATION
+ * of a field declaration.
+ */
+ function _getCollationFieldDeclaration($collation)
+ {
+ return 'COLLATE '.$collation;
+ }
+
+ // }}}
+ // {{{ getDeclaration()
+
+ /**
+ * Obtain DBMS specific SQL code portion needed to declare
+ * of the given type
+ *
+ * @param string $type type to which the value should be converted to
+ * @param string $name name the field to be declared.
+ * @param string $field definition of the field
+ *
+ * @return string DBMS-specific SQL code portion that should be used to
+ * declare the specified field.
+ * @access public
+ */
+ function getDeclaration($type, $name, $field)
+ {
+ // MySQL DDL syntax forbids combining NOT NULL with DEFAULT NULL.
+ // To get a default of NULL for NOT NULL columns, omit it.
+ if ( isset($field['notnull'])
+ && !empty($field['notnull'])
+ && array_key_exists('default', $field) // do not use isset() here!
+ && null === $field['default']
+ ) {
+ unset($field['default']);
+ }
+ return parent::getDeclaration($type, $name, $field);
+ }
+
+ // }}}
+ // {{{ getTypeDeclaration()
+
+ /**
+ * Obtain DBMS specific SQL code portion needed to declare an text type
+ * field to be used in statements like CREATE TABLE.
+ *
+ * @param array $field associative array with the name of the properties
+ * of the field being declared as array indexes. Currently, the types
+ * of supported field properties are as follows:
+ *
+ * length
+ * Integer value that determines the maximum length of the text
+ * field. If this argument is missing the field should be
+ * declared to have the longest length allowed by the DBMS.
+ *
+ * default
+ * Text value to be used as default for this field.
+ *
+ * notnull
+ * Boolean flag that indicates whether this field is constrained
+ * to not be set to null.
+ * @return string DBMS specific SQL code portion that should be used to
+ * declare the specified field.
+ * @access public
+ */
+ function getTypeDeclaration($field)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ switch ($field['type']) {
+ case 'text':
+ if (empty($field['length']) && array_key_exists('default', $field)) {
+ $field['length'] = $db->varchar_max_length;
+ }
+ $length = !empty($field['length']) ? $field['length'] : false;
+ $fixed = !empty($field['fixed']) ? $field['fixed'] : false;
+ return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR(255)')
+ : ($length ? 'VARCHAR('.$length.')' : 'TEXT');
+ case 'clob':
+ if (!empty($field['length'])) {
+ $length = $field['length'];
+ if ($length <= 255) {
+ return 'TINYTEXT';
+ } elseif ($length <= 65532) {
+ return 'TEXT';
+ } elseif ($length <= 16777215) {
+ return 'MEDIUMTEXT';
+ }
+ }
+ return 'LONGTEXT';
+ case 'blob':
+ if (!empty($field['length'])) {
+ $length = $field['length'];
+ if ($length <= 255) {
+ return 'TINYBLOB';
+ } elseif ($length <= 65532) {
+ return 'BLOB';
+ } elseif ($length <= 16777215) {
+ return 'MEDIUMBLOB';
+ }
+ }
+ return 'LONGBLOB';
+ case 'integer':
+ if (!empty($field['length'])) {
+ $length = $field['length'];
+ if ($length <= 1) {
+ return 'TINYINT';
+ } elseif ($length == 2) {
+ return 'SMALLINT';
+ } elseif ($length == 3) {
+ return 'MEDIUMINT';
+ } elseif ($length == 4) {
+ return 'INT';
+ } elseif ($length > 4) {
+ return 'BIGINT';
+ }
+ }
+ return 'INT';
+ case 'boolean':
+ return 'TINYINT(1)';
+ case 'date':
+ return 'DATE';
+ case 'time':
+ return 'TIME';
+ case 'timestamp':
+ return 'DATETIME';
+ case 'float':
+ $l = '';
+ if (!empty($field['length'])) {
+ $l = '(' . $field['length'];
+ if (!empty($field['scale'])) {
+ $l .= ',' . $field['scale'];
+ }
+ $l .= ')';
+ }
+ return 'DOUBLE' . $l;
+ case 'decimal':
+ $length = !empty($field['length']) ? $field['length'] : 18;
+ $scale = !empty($field['scale']) ? $field['scale'] : $db->options['decimal_places'];
+ return 'DECIMAL('.$length.','.$scale.')';
+ }
+ return '';
+ }
+
+ // }}}
+ // {{{ _getIntegerDeclaration()
+
+ /**
+ * Obtain DBMS specific SQL code portion needed to declare an integer type
+ * field to be used in statements like CREATE TABLE.
+ *
+ * @param string $name name the field to be declared.
+ * @param string $field associative array with the name of the properties
+ * of the field being declared as array indexes.
+ * Currently, the types of supported field
+ * properties are as follows:
+ *
+ * unsigned
+ * Boolean flag that indicates whether the field
+ * should be declared as unsigned integer if
+ * possible.
+ *
+ * default
+ * Integer value to be used as default for this
+ * field.
+ *
+ * notnull
+ * Boolean flag that indicates whether this field is
+ * constrained to not be set to null.
+ * @return string DBMS specific SQL code portion that should be used to
+ * declare the specified field.
+ * @access protected
+ */
+ function _getIntegerDeclaration($name, $field)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ $default = $autoinc = '';
+ if (!empty($field['autoincrement'])) {
+ $autoinc = ' AUTO_INCREMENT PRIMARY KEY';
+ } elseif (array_key_exists('default', $field)) {
+ if ($field['default'] === '') {
+ $field['default'] = empty($field['notnull']) ? null : 0;
+ }
+ $default = ' DEFAULT '.$this->quote($field['default'], 'integer');
+ }
+
+ $notnull = empty($field['notnull']) ? '' : ' NOT NULL';
+ $unsigned = empty($field['unsigned']) ? '' : ' UNSIGNED';
+ if (empty($default) && empty($notnull)) {
+ $default = ' DEFAULT NULL';
+ }
+ $name = $db->quoteIdentifier($name, true);
+ return $name.' '.$this->getTypeDeclaration($field).$unsigned.$default.$notnull.$autoinc;
+ }
+
+ // }}}
+ // {{{ _getFloatDeclaration()
+
+ /**
+ * Obtain DBMS specific SQL code portion needed to declare an float type
+ * field to be used in statements like CREATE TABLE.
+ *
+ * @param string $name name the field to be declared.
+ * @param string $field associative array with the name of the properties
+ * of the field being declared as array indexes.
+ * Currently, the types of supported field
+ * properties are as follows:
+ *
+ * unsigned
+ * Boolean flag that indicates whether the field
+ * should be declared as unsigned float if
+ * possible.
+ *
+ * default
+ * float value to be used as default for this
+ * field.
+ *
+ * notnull
+ * Boolean flag that indicates whether this field is
+ * constrained to not be set to null.
+ * @return string DBMS specific SQL code portion that should be used to
+ * declare the specified field.
+ * @access protected
+ */
+ function _getFloatDeclaration($name, $field)
+ {
+ // Since AUTO_INCREMENT can be used for integer or floating-point types,
+ // reuse the INTEGER declaration
+ // @see http://bugs.mysql.com/bug.php?id=31032
+ return $this->_getIntegerDeclaration($name, $field);
+ }
+
+ // }}}
+ // {{{ _getDecimalDeclaration()
+
+ /**
+ * Obtain DBMS specific SQL code portion needed to declare an decimal type
+ * field to be used in statements like CREATE TABLE.
+ *
+ * @param string $name name the field to be declared.
+ * @param string $field associative array with the name of the properties
+ * of the field being declared as array indexes.
+ * Currently, the types of supported field
+ * properties are as follows:
+ *
+ * unsigned
+ * Boolean flag that indicates whether the field
+ * should be declared as unsigned integer if
+ * possible.
+ *
+ * default
+ * Decimal value to be used as default for this
+ * field.
+ *
+ * notnull
+ * Boolean flag that indicates whether this field is
+ * constrained to not be set to null.
+ * @return string DBMS specific SQL code portion that should be used to
+ * declare the specified field.
+ * @access protected
+ */
+ function _getDecimalDeclaration($name, $field)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ $default = '';
+ if (array_key_exists('default', $field)) {
+ if ($field['default'] === '') {
+ $field['default'] = empty($field['notnull']) ? null : 0;
+ }
+ $default = ' DEFAULT '.$this->quote($field['default'], 'integer');
+ } elseif (empty($field['notnull'])) {
+ $default = ' DEFAULT NULL';
+ }
+
+ $notnull = empty($field['notnull']) ? '' : ' NOT NULL';
+ $unsigned = empty($field['unsigned']) ? '' : ' UNSIGNED';
+ $name = $db->quoteIdentifier($name, true);
+ return $name.' '.$this->getTypeDeclaration($field).$unsigned.$default.$notnull;
+ }
+
+ // }}}
+ // {{{ matchPattern()
+
+ /**
+ * build a pattern matching string
+ *
+ * @access public
+ *
+ * @param array $pattern even keys are strings, odd are patterns (% and _)
+ * @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future)
+ * @param string $field optional field name that is being matched against
+ * (might be required when emulating ILIKE)
+ *
+ * @return string SQL pattern
+ */
+ function matchPattern($pattern, $operator = null, $field = null)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ $match = '';
+ if (null !== $operator) {
+ $field = (null === $field) ? '' : $field.' ';
+ $operator = strtoupper($operator);
+ switch ($operator) {
+ // case insensitive
+ case 'ILIKE':
+ $match = $field.'LIKE ';
+ break;
+ case 'NOT ILIKE':
+ $match = $field.'NOT LIKE ';
+ break;
+ // case sensitive
+ case 'LIKE':
+ $match = $field.'LIKE BINARY ';
+ break;
+ case 'NOT LIKE':
+ $match = $field.'NOT LIKE BINARY ';
+ break;
+ default:
+ return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+ 'not a supported operator type:'. $operator, __FUNCTION__);
+ }
+ }
+ $match.= "'";
+ foreach ($pattern as $key => $value) {
+ if ($key % 2) {
+ $match.= $value;
+ } else {
+ $match.= $db->escapePattern($db->escape($value));
+ }
+ }
+ $match.= "'";
+ $match.= $this->patternEscapeString();
+ return $match;
+ }
+
+ // }}}
+ // {{{ _mapNativeDatatype()
+
+ /**
+ * Maps a native array description of a field to a MDB2 datatype and length
+ *
+ * @param array $field native field description
+ * @return array containing the various possible types, length, sign, fixed
+ * @access public
+ */
+ function _mapNativeDatatype($field)
+ {
+ $db_type = strtolower($field['type']);
+ $db_type = strtok($db_type, '(), ');
+ if ($db_type == 'national') {
+ $db_type = strtok('(), ');
+ }
+ if (!empty($field['length'])) {
+ $length = strtok($field['length'], ', ');
+ $decimal = strtok(', ');
+ } else {
+ $length = strtok('(), ');
+ $decimal = strtok('(), ');
+ }
+ $type = array();
+ $unsigned = $fixed = null;
+ switch ($db_type) {
+ case 'tinyint':
+ $type[] = 'integer';
+ $type[] = 'boolean';
+ if (preg_match('/^(is|has)/', $field['name'])) {
+ $type = array_reverse($type);
+ }
+ $unsigned = preg_match('/ unsigned/i', $field['type']);
+ $length = 1;
+ break;
+ case 'smallint':
+ $type[] = 'integer';
+ $unsigned = preg_match('/ unsigned/i', $field['type']);
+ $length = 2;
+ break;
+ case 'mediumint':
+ $type[] = 'integer';
+ $unsigned = preg_match('/ unsigned/i', $field['type']);
+ $length = 3;
+ break;
+ case 'int':
+ case 'integer':
+ $type[] = 'integer';
+ $unsigned = preg_match('/ unsigned/i', $field['type']);
+ $length = 4;
+ break;
+ case 'bigint':
+ $type[] = 'integer';
+ $unsigned = preg_match('/ unsigned/i', $field['type']);
+ $length = 8;
+ break;
+ case 'tinytext':
+ case 'mediumtext':
+ case 'longtext':
+ case 'text':
+ case 'varchar':
+ $fixed = false;
+ case 'string':
+ case 'char':
+ $type[] = 'text';
+ if ($length == '1') {
+ $type[] = 'boolean';
+ if (preg_match('/^(is|has)/', $field['name'])) {
+ $type = array_reverse($type);
+ }
+ } elseif (strstr($db_type, 'text')) {
+ $type[] = 'clob';
+ if ($decimal == 'binary') {
+ $type[] = 'blob';
+ }
+ $type = array_reverse($type);
+ }
+ if ($fixed !== false) {
+ $fixed = true;
+ }
+ break;
+ case 'enum':
+ $type[] = 'text';
+ preg_match_all('/\'.+\'/U', $field['type'], $matches);
+ $length = 0;
+ $fixed = false;
+ if (is_array($matches)) {
+ foreach ($matches[0] as $value) {
+ $length = max($length, strlen($value)-2);
+ }
+ if ($length == '1' && count($matches[0]) == 2) {
+ $type[] = 'boolean';
+ if (preg_match('/^(is|has)/', $field['name'])) {
+ $type = array_reverse($type);
+ }
+ }
+ }
+ $type[] = 'integer';
+ case 'set':
+ $fixed = false;
+ $type[] = 'text';
+ $type[] = 'integer';
+ break;
+ case 'date':
+ $type[] = 'date';
+ $length = null;
+ break;
+ case 'datetime':
+ case 'timestamp':
+ $type[] = 'timestamp';
+ $length = null;
+ break;
+ case 'time':
+ $type[] = 'time';
+ $length = null;
+ break;
+ case 'float':
+ case 'double':
+ case 'real':
+ $type[] = 'float';
+ $unsigned = preg_match('/ unsigned/i', $field['type']);
+ if ($decimal !== false) {
+ $length = $length.','.$decimal;
+ }
+ break;
+ case 'unknown':
+ case 'decimal':
+ case 'numeric':
+ $type[] = 'decimal';
+ $unsigned = preg_match('/ unsigned/i', $field['type']);
+ if ($decimal !== false) {
+ $length = $length.','.$decimal;
+ }
+ break;
+ case 'tinyblob':
+ case 'mediumblob':
+ case 'longblob':
+ case 'blob':
+ $type[] = 'blob';
+ $length = null;
+ break;
+ case 'binary':
+ case 'varbinary':
+ $type[] = 'blob';
+ break;
+ case 'year':
+ $type[] = 'integer';
+ $type[] = 'date';
+ $length = null;
+ break;
+ default:
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+ 'unknown database attribute type: '.$db_type, __FUNCTION__);
+ }
+
+ if ((int)$length <= 0) {
+ $length = null;
+ }
+
+ return array($type, $length, $unsigned, $fixed);
+ }
+
+ // }}}
+}
+
+?>
\ No newline at end of file
diff -Nru owncloud-1.1+git20110209/3rdparty/MDB2/Driver/Datatype/oci8.php owncloud-5.0.4debian/3rdparty/MDB2/Driver/Datatype/oci8.php
--- owncloud-1.1+git20110209/3rdparty/MDB2/Driver/Datatype/oci8.php 1970-01-01 00:00:00.000000000 +0000
+++ owncloud-5.0.4debian/3rdparty/MDB2/Driver/Datatype/oci8.php 2013-04-10 17:29:58.000000000 +0000
@@ -0,0 +1,499 @@
+ |
+// +----------------------------------------------------------------------+
+
+// $Id: oci8.php 295587 2010-02-28 17:16:38Z quipo $
+
+require_once 'MDB2/Driver/Datatype/Common.php';
+
+/**
+ * MDB2 OCI8 driver
+ *
+ * @package MDB2
+ * @category Database
+ * @author Lukas Smith
+ */
+class MDB2_Driver_Datatype_oci8 extends MDB2_Driver_Datatype_Common
+{
+ // {{{ _baseConvertResult()
+
+ /**
+ * general type conversion method
+ *
+ * @param mixed $value refernce to a value to be converted
+ * @param string $type specifies which type to convert to
+ * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text
+ * @return object a MDB2 error on failure
+ * @access protected
+ */
+ function _baseConvertResult($value, $type, $rtrim = true)
+ {
+ if (null === $value) {
+ return null;
+ }
+ switch ($type) {
+ case 'text':
+ if (is_object($value) && is_a($value, 'OCI-Lob')) {
+ //LOB => fetch into variable
+ $clob = $this->_baseConvertResult($value, 'clob', $rtrim);
+ if (!PEAR::isError($clob) && is_resource($clob)) {
+ $clob_value = '';
+ while (!feof($clob)) {
+ $clob_value .= fread($clob, 8192);
+ }
+ $this->destroyLOB($clob);
+ }
+ $value = $clob_value;
+ }
+ if ($rtrim) {
+ $value = rtrim($value);
+ }
+ return $value;
+ case 'date':
+ return substr($value, 0, strlen('YYYY-MM-DD'));
+ case 'time':
+ return substr($value, strlen('YYYY-MM-DD '), strlen('HH:MI:SS'));
+ }
+ return parent::_baseConvertResult($value, $type, $rtrim);
+ }
+
+ // }}}
+ // {{{ getTypeDeclaration()
+
+ /**
+ * Obtain DBMS specific SQL code portion needed to declare an text type
+ * field to be used in statements like CREATE TABLE.
+ *
+ * @param array $field associative array with the name of the properties
+ * of the field being declared as array indexes. Currently, the types
+ * of supported field properties are as follows:
+ *
+ * length
+ * Integer value that determines the maximum length of the text
+ * field. If this argument is missing the field should be
+ * declared to have the longest length allowed by the DBMS.
+ *
+ * default
+ * Text value to be used as default for this field.
+ *
+ * notnull
+ * Boolean flag that indicates whether this field is constrained
+ * to not be set to null.
+ * @return string DBMS specific SQL code portion that should be used to
+ * declare the specified field.
+ * @access public
+ */
+ function getTypeDeclaration($field)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ switch ($field['type']) {
+ case 'text':
+ $length = !empty($field['length'])
+ ? $field['length'] : $db->options['default_text_field_length'];
+ $fixed = !empty($field['fixed']) ? $field['fixed'] : false;
+ return $fixed ? 'CHAR('.$length.')' : 'VARCHAR2('.$length.')';
+ case 'clob':
+ return 'CLOB';
+ case 'blob':
+ return 'BLOB';
+ case 'integer':
+ if (!empty($field['length'])) {
+ switch((int)$field['length']) {
+ case 1: $digit = 3; break;
+ case 2: $digit = 5; break;
+ case 3: $digit = 8; break;
+ case 4: $digit = 10; break;
+ case 5: $digit = 13; break;
+ case 6: $digit = 15; break;
+ case 7: $digit = 17; break;
+ case 8: $digit = 20; break;
+ default: $digit = 10;
+ }
+ return 'NUMBER('.$digit.')';
+ }
+ return 'INT';
+ case 'boolean':
+ return 'NUMBER(1)';
+ case 'date':
+ case 'time':
+ case 'timestamp':
+ return 'DATE';
+ case 'float':
+ return 'NUMBER';
+ case 'decimal':
+ $scale = !empty($field['scale']) ? $field['scale'] : $db->options['decimal_places'];
+ return 'NUMBER(*,'.$scale.')';
+ }
+ }
+
+ // }}}
+ // {{{ _quoteCLOB()
+
+ /**
+ * Convert a text value into a DBMS specific format that is suitable to
+ * compose query statements.
+ *
+ * @param string $value text string value that is intended to be converted.
+ * @param bool $quote determines if the value should be quoted and escaped
+ * @param bool $escape_wildcards if to escape escape wildcards
+ * @return string text string that represents the given argument value in
+ * a DBMS specific format.
+ * @access protected
+ */
+ function _quoteCLOB($value, $quote, $escape_wildcards)
+ {
+ return 'EMPTY_CLOB()';
+ }
+
+ // }}}
+ // {{{ _quoteBLOB()
+
+ /**
+ * Convert a text value into a DBMS specific format that is suitable to
+ * compose query statements.
+ *
+ * @param string $value text string value that is intended to be converted.
+ * @param bool $quote determines if the value should be quoted and escaped
+ * @param bool $escape_wildcards if to escape escape wildcards
+ * @return string text string that represents the given argument value in
+ * a DBMS specific format.
+ * @access protected
+ */
+ function _quoteBLOB($value, $quote, $escape_wildcards)
+ {
+ return 'EMPTY_BLOB()';
+ }
+
+ // }}}
+ // {{{ _quoteDate()
+
+ /**
+ * Convert a text value into a DBMS specific format that is suitable to
+ * compose query statements.
+ *
+ * @param string $value text string value that is intended to be converted.
+ * @param bool $quote determines if the value should be quoted and escaped
+ * @param bool $escape_wildcards if to escape escape wildcards
+ * @return string text string that represents the given argument value in
+ * a DBMS specific format.
+ * @access protected
+ */
+ function _quoteDate($value, $quote, $escape_wildcards)
+ {
+ return $this->_quoteText("$value 00:00:00", $quote, $escape_wildcards);
+ }
+
+ // }}}
+ // {{{ _quoteTimestamp()
+
+ /**
+ * Convert a text value into a DBMS specific format that is suitable to
+ * compose query statements.
+ *
+ * @param string $value text string value that is intended to be converted.
+ * @param bool $quote determines if the value should be quoted and escaped
+ * @param bool $escape_wildcards if to escape escape wildcards
+ * @return string text string that represents the given argument value in
+ * a DBMS specific format.
+ * @access protected
+ */
+ //function _quoteTimestamp($value, $quote, $escape_wildcards)
+ //{
+ // return $this->_quoteText($value, $quote, $escape_wildcards);
+ //}
+
+ // }}}
+ // {{{ _quoteTime()
+
+ /**
+ * Convert a text value into a DBMS specific format that is suitable to
+ * compose query statements.
+ *
+ * @param string $value text string value that is intended to be converted.
+ * @param bool $quote determines if the value should be quoted and escaped
+ * @param bool $escape_wildcards if to escape escape wildcards
+ * @return string text string that represents the given argument value in
+ * a DBMS specific format.
+ * @access protected
+ */
+ function _quoteTime($value, $quote, $escape_wildcards)
+ {
+ return $this->_quoteText("0001-01-01 $value", $quote, $escape_wildcards);
+ }
+
+ // }}}
+ // {{{ writeLOBToFile()
+
+ /**
+ * retrieve LOB from the database
+ *
+ * @param array $lob array
+ * @param string $file name of the file into which the LOb should be fetched
+ * @return mixed MDB2_OK on success, a MDB2 error on failure
+ * @access protected
+ */
+ function writeLOBToFile($lob, $file)
+ {
+ if (preg_match('/^(\w+:\/\/)(.*)$/', $file, $match)) {
+ if ($match[1] == 'file://') {
+ $file = $match[2];
+ }
+ }
+ $lob_data = stream_get_meta_data($lob);
+ $lob_index = $lob_data['wrapper_data']->lob_index;
+ $result = $this->lobs[$lob_index]['resource']->writetofile($file);
+ $this->lobs[$lob_index]['resource']->seek(0);
+ if (!$result) {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ return $db->raiseError(null, null, null,
+ 'Unable to write LOB to file', __FUNCTION__);
+ }
+ return MDB2_OK;
+ }
+
+ // }}}
+ // {{{ _retrieveLOB()
+
+ /**
+ * retrieve LOB from the database
+ *
+ * @param array $lob array
+ * @return mixed MDB2_OK on success, a MDB2 error on failure
+ * @access protected
+ */
+ function _retrieveLOB(&$lob)
+ {
+ if (!is_object($lob['resource'])) {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+ 'attemped to retrieve LOB from non existing or NULL column', __FUNCTION__);
+ }
+
+ if (!$lob['loaded']
+# && !method_exists($lob['resource'], 'read')
+ ) {
+ $lob['value'] = $lob['resource']->load();
+ $lob['resource']->seek(0);
+ }
+ $lob['loaded'] = true;
+ return MDB2_OK;
+ }
+
+ // }}}
+ // {{{ _readLOB()
+
+ /**
+ * Read data from large object input stream.
+ *
+ * @param array $lob array
+ * @param blob $data reference to a variable that will hold data to be
+ * read from the large object input stream
+ * @param int $length integer value that indicates the largest ammount of
+ * data to be read from the large object input stream.
+ * @return mixed length on success, a MDB2 error on failure
+ * @access protected
+ */
+ function _readLOB($lob, $length)
+ {
+ if ($lob['loaded']) {
+ return parent::_readLOB($lob, $length);
+ }
+
+ if (!is_object($lob['resource'])) {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+ 'attemped to retrieve LOB from non existing or NULL column', __FUNCTION__);
+ }
+
+ $data = $lob['resource']->read($length);
+ if (!is_string($data)) {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ return $db->raiseError(null, null, null,
+ 'Unable to read LOB', __FUNCTION__);
+ }
+ return $data;
+ }
+
+ // }}}
+ // {{{ patternEscapeString()
+
+ /**
+ * build string to define escape pattern string
+ *
+ * @access public
+ *
+ *
+ * @return string define escape pattern
+ */
+ function patternEscapeString()
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+ return " ESCAPE '". $db->string_quoting['escape_pattern'] ."'";
+ }
+
+ // }}}
+ // {{{ _mapNativeDatatype()
+
+ /**
+ * Maps a native array description of a field to a MDB2 datatype and length
+ *
+ * @param array $field native field description
+ * @return array containing the various possible types, length, sign, fixed
+ * @access public
+ */
+ function _mapNativeDatatype($field)
+ {
+ $db_type = strtolower($field['type']);
+ $type = array();
+ $length = $unsigned = $fixed = null;
+ if (!empty($field['length'])) {
+ $length = $field['length'];
+ }
+ switch ($db_type) {
+ case 'integer':
+ case 'pls_integer':
+ case 'binary_integer':
+ $type[] = 'integer';
+ if ($length == '1') {
+ $type[] = 'boolean';
+ if (preg_match('/^(is|has)/', $field['name'])) {
+ $type = array_reverse($type);
+ }
+ }
+ break;
+ case 'varchar':
+ case 'varchar2':
+ case 'nvarchar2':
+ $fixed = false;
+ case 'char':
+ case 'nchar':
+ $type[] = 'text';
+ if ($length == '1') {
+ $type[] = 'boolean';
+ if (preg_match('/^(is|has)/', $field['name'])) {
+ $type = array_reverse($type);
+ }
+ }
+ if ($fixed !== false) {
+ $fixed = true;
+ }
+ break;
+ case 'date':
+ case 'timestamp':
+ $type[] = 'timestamp';
+ $length = null;
+ break;
+ case 'float':
+ $type[] = 'float';
+ break;
+ case 'number':
+ if (!empty($field['scale'])) {
+ $type[] = 'decimal';
+ $length = $length.','.$field['scale'];
+ } else {
+ $type[] = 'integer';
+ if ($length == '1') {
+ $type[] = 'boolean';
+ if (preg_match('/^(is|has)/', $field['name'])) {
+ $type = array_reverse($type);
+ }
+ }
+ }
+ break;
+ case 'long':
+ $type[] = 'text';
+ case 'clob':
+ case 'nclob':
+ $type[] = 'clob';
+ break;
+ case 'blob':
+ case 'raw':
+ case 'long raw':
+ case 'bfile':
+ $type[] = 'blob';
+ $length = null;
+ break;
+ case 'rowid':
+ case 'urowid':
+ default:
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+ 'unknown database attribute type: '.$db_type, __FUNCTION__);
+ }
+
+ if ((int)$length <= 0) {
+ $length = null;
+ }
+
+ return array($type, $length, $unsigned, $fixed);
+ }
+}
+
+?>
\ No newline at end of file
diff -Nru owncloud-1.1+git20110209/3rdparty/MDB2/Driver/Datatype/pgsql.php owncloud-5.0.4debian/3rdparty/MDB2/Driver/Datatype/pgsql.php
--- owncloud-1.1+git20110209/3rdparty/MDB2/Driver/Datatype/pgsql.php 1970-01-01 00:00:00.000000000 +0000
+++ owncloud-5.0.4debian/3rdparty/MDB2/Driver/Datatype/pgsql.php 2013-04-10 17:29:58.000000000 +0000
@@ -0,0 +1,579 @@
+ |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+require_once 'MDB2/Driver/Datatype/Common.php';
+
+/**
+ * MDB2 PostGreSQL driver
+ *
+ * @package MDB2
+ * @category Database
+ * @author Paul Cooper
+ */
+class MDB2_Driver_Datatype_pgsql extends MDB2_Driver_Datatype_Common
+{
+ // {{{ _baseConvertResult()
+
+ /**
+ * General type conversion method
+ *
+ * @param mixed $value refernce to a value to be converted
+ * @param string $type specifies which type to convert to
+ * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text
+ * @return object a MDB2 error on failure
+ * @access protected
+ */
+ function _baseConvertResult($value, $type, $rtrim = true)
+ {
+ if (null === $value) {
+ return null;
+ }
+ switch ($type) {
+ case 'boolean':
+ return $value == 't';
+ case 'float':
+ return doubleval($value);
+ case 'date':
+ return $value;
+ case 'time':
+ return substr($value, 0, strlen('HH:MM:SS'));
+ case 'timestamp':
+ return substr($value, 0, strlen('YYYY-MM-DD HH:MM:SS'));
+ case 'blob':
+ $value = pg_unescape_bytea($value);
+ return parent::_baseConvertResult($value, $type, $rtrim);
+ }
+ return parent::_baseConvertResult($value, $type, $rtrim);
+ }
+
+ // }}}
+ // {{{ getTypeDeclaration()
+
+ /**
+ * Obtain DBMS specific SQL code portion needed to declare an text type
+ * field to be used in statements like CREATE TABLE.
+ *
+ * @param array $field associative array with the name of the properties
+ * of the field being declared as array indexes. Currently, the types
+ * of supported field properties are as follows:
+ *
+ * length
+ * Integer value that determines the maximum length of the text
+ * field. If this argument is missing the field should be
+ * declared to have the longest length allowed by the DBMS.
+ *
+ * default
+ * Text value to be used as default for this field.
+ *
+ * notnull
+ * Boolean flag that indicates whether this field is constrained
+ * to not be set to null.
+ * @return string DBMS specific SQL code portion that should be used to
+ * declare the specified field.
+ * @access public
+ */
+ function getTypeDeclaration($field)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ switch ($field['type']) {
+ case 'text':
+ $length = !empty($field['length']) ? $field['length'] : false;
+ $fixed = !empty($field['fixed']) ? $field['fixed'] : false;
+ return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$db->options['default_text_field_length'].')')
+ : ($length ? 'VARCHAR('.$length.')' : 'TEXT');
+ case 'clob':
+ return 'TEXT';
+ case 'blob':
+ return 'BYTEA';
+ case 'integer':
+ if (!empty($field['autoincrement'])) {
+ if (!empty($field['length'])) {
+ $length = $field['length'];
+ if ($length > 4) {
+ return 'BIGSERIAL PRIMARY KEY';
+ }
+ }
+ return 'SERIAL PRIMARY KEY';
+ }
+ if (!empty($field['length'])) {
+ $length = $field['length'];
+ if ($length <= 2) {
+ return 'SMALLINT';
+ } elseif ($length == 3 || $length == 4) {
+ return 'INT';
+ } elseif ($length > 4) {
+ return 'BIGINT';
+ }
+ }
+ return 'INT';
+ case 'boolean':
+ return 'BOOLEAN';
+ case 'date':
+ return 'DATE';
+ case 'time':
+ return 'TIME without time zone';
+ case 'timestamp':
+ return 'TIMESTAMP without time zone';
+ case 'float':
+ return 'FLOAT8';
+ case 'decimal':
+ $length = !empty($field['length']) ? $field['length'] : 18;
+ $scale = !empty($field['scale']) ? $field['scale'] : $db->options['decimal_places'];
+ return 'NUMERIC('.$length.','.$scale.')';
+ }
+ }
+
+ // }}}
+ // {{{ _getIntegerDeclaration()
+
+ /**
+ * Obtain DBMS specific SQL code portion needed to declare an integer type
+ * field to be used in statements like CREATE TABLE.
+ *
+ * @param string $name name the field to be declared.
+ * @param array $field associative array with the name of the properties
+ * of the field being declared as array indexes. Currently, the types
+ * of supported field properties are as follows:
+ *
+ * unsigned
+ * Boolean flag that indicates whether the field should be
+ * declared as unsigned integer if possible.
+ *
+ * default
+ * Integer value to be used as default for this field.
+ *
+ * notnull
+ * Boolean flag that indicates whether this field is constrained
+ * to not be set to null.
+ * @return string DBMS specific SQL code portion that should be used to
+ * declare the specified field.
+ * @access protected
+ */
+ function _getIntegerDeclaration($name, $field)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ if (!empty($field['unsigned'])) {
+ $db->warnings[] = "unsigned integer field \"$name\" is being declared as signed integer";
+ }
+ if (!empty($field['autoincrement'])) {
+ $name = $db->quoteIdentifier($name, true);
+ return $name.' '.$this->getTypeDeclaration($field);
+ }
+ $default = '';
+ if (array_key_exists('default', $field)) {
+ if ($field['default'] === '') {
+ $field['default'] = empty($field['notnull']) ? null : 0;
+ }
+ $default = ' DEFAULT '.$this->quote($field['default'], 'integer');
+ }
+
+ $notnull = empty($field['notnull']) ? '' : ' NOT NULL';
+ if (empty($default) && empty($notnull)) {
+ $default = ' DEFAULT NULL';
+ }
+ $name = $db->quoteIdentifier($name, true);
+ return $name.' '.$this->getTypeDeclaration($field).$default.$notnull;
+ }
+
+ // }}}
+ // {{{ _quoteCLOB()
+
+ /**
+ * Convert a text value into a DBMS specific format that is suitable to
+ * compose query statements.
+ *
+ * @param string $value text string value that is intended to be converted.
+ * @param bool $quote determines if the value should be quoted and escaped
+ * @param bool $escape_wildcards if to escape escape wildcards
+ * @return string text string that represents the given argument value in
+ * a DBMS specific format.
+ * @access protected
+ */
+ function _quoteCLOB($value, $quote, $escape_wildcards)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+ if ($db->options['lob_allow_url_include']) {
+ $value = $this->_readFile($value);
+ if (PEAR::isError($value)) {
+ return $value;
+ }
+ }
+ return $this->_quoteText($value, $quote, $escape_wildcards);
+ }
+
+ // }}}
+ // {{{ _quoteBLOB()
+
+ /**
+ * Convert a text value into a DBMS specific format that is suitable to
+ * compose query statements.
+ *
+ * @param string $value text string value that is intended to be converted.
+ * @param bool $quote determines if the value should be quoted and escaped
+ * @param bool $escape_wildcards if to escape escape wildcards
+ * @return string text string that represents the given argument value in
+ * a DBMS specific format.
+ * @access protected
+ */
+ function _quoteBLOB($value, $quote, $escape_wildcards)
+ {
+ if (!$quote) {
+ return $value;
+ }
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+ if ($db->options['lob_allow_url_include']) {
+ $value = $this->_readFile($value);
+ if (PEAR::isError($value)) {
+ return $value;
+ }
+ }
+ if (version_compare(PHP_VERSION, '5.2.0RC6', '>=')) {
+ $connection = $db->getConnection();
+ if (PEAR::isError($connection)) {
+ return $connection;
+ }
+ $value = @pg_escape_bytea($connection, $value);
+ } else {
+ $value = @pg_escape_bytea($value);
+ }
+ return "'".$value."'";
+ }
+
+ // }}}
+ // {{{ _quoteBoolean()
+
+ /**
+ * Convert a text value into a DBMS specific format that is suitable to
+ * compose query statements.
+ *
+ * @param string $value text string value that is intended to be converted.
+ * @param bool $quote determines if the value should be quoted and escaped
+ * @param bool $escape_wildcards if to escape escape wildcards
+ * @return string text string that represents the given argument value in
+ * a DBMS specific format.
+ * @access protected
+ */
+ function _quoteBoolean($value, $quote, $escape_wildcards)
+ {
+ $value = $value ? 't' : 'f';
+ if (!$quote) {
+ return $value;
+ }
+ return "'".$value."'";
+ }
+
+ // }}}
+ // {{{ matchPattern()
+
+ /**
+ * build a pattern matching string
+ *
+ * @access public
+ *
+ * @param array $pattern even keys are strings, odd are patterns (% and _)
+ * @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future)
+ * @param string $field optional field name that is being matched against
+ * (might be required when emulating ILIKE)
+ *
+ * @return string SQL pattern
+ */
+ function matchPattern($pattern, $operator = null, $field = null)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ $match = '';
+ if (null !== $operator) {
+ $field = (null === $field) ? '' : $field.' ';
+ $operator = strtoupper($operator);
+ switch ($operator) {
+ // case insensitive
+ case 'ILIKE':
+ $match = $field.'ILIKE ';
+ break;
+ case 'NOT ILIKE':
+ $match = $field.'NOT ILIKE ';
+ break;
+ // case sensitive
+ case 'LIKE':
+ $match = $field.'LIKE ';
+ break;
+ case 'NOT LIKE':
+ $match = $field.'NOT LIKE ';
+ break;
+ default:
+ return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+ 'not a supported operator type:'. $operator, __FUNCTION__);
+ }
+ }
+ $match.= "'";
+ foreach ($pattern as $key => $value) {
+ if ($key % 2) {
+ $match.= $value;
+ } else {
+ $match.= $db->escapePattern($db->escape($value));
+ }
+ }
+ $match.= "'";
+ $match.= $this->patternEscapeString();
+ return $match;
+ }
+
+ // }}}
+ // {{{ patternEscapeString()
+
+ /**
+ * build string to define escape pattern string
+ *
+ * @access public
+ *
+ *
+ * @return string define escape pattern
+ */
+ function patternEscapeString()
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+ return ' ESCAPE '.$this->quote($db->string_quoting['escape_pattern']);
+ }
+
+ // }}}
+ // {{{ _mapNativeDatatype()
+
+ /**
+ * Maps a native array description of a field to a MDB2 datatype and length
+ *
+ * @param array $field native field description
+ * @return array containing the various possible types, length, sign, fixed
+ * @access public
+ */
+ function _mapNativeDatatype($field)
+ {
+ $db_type = strtolower($field['type']);
+ $length = $field['length'];
+ $type = array();
+ $unsigned = $fixed = null;
+ switch ($db_type) {
+ case 'smallint':
+ case 'int2':
+ $type[] = 'integer';
+ $unsigned = false;
+ $length = 2;
+ if ($length == '2') {
+ $type[] = 'boolean';
+ if (preg_match('/^(is|has)/', $field['name'])) {
+ $type = array_reverse($type);
+ }
+ }
+ break;
+ case 'int':
+ case 'int4':
+ case 'integer':
+ case 'serial':
+ case 'serial4':
+ $type[] = 'integer';
+ $unsigned = false;
+ $length = 4;
+ break;
+ case 'bigint':
+ case 'int8':
+ case 'bigserial':
+ case 'serial8':
+ $type[] = 'integer';
+ $unsigned = false;
+ $length = 8;
+ break;
+ case 'bool':
+ case 'boolean':
+ $type[] = 'boolean';
+ $length = null;
+ break;
+ case 'text':
+ case 'varchar':
+ $fixed = false;
+ case 'unknown':
+ case 'char':
+ case 'bpchar':
+ $type[] = 'text';
+ if ($length == '1') {
+ $type[] = 'boolean';
+ if (preg_match('/^(is|has)/', $field['name'])) {
+ $type = array_reverse($type);
+ }
+ } elseif (strstr($db_type, 'text')) {
+ $type[] = 'clob';
+ $type = array_reverse($type);
+ }
+ if ($fixed !== false) {
+ $fixed = true;
+ }
+ break;
+ case 'date':
+ $type[] = 'date';
+ $length = null;
+ break;
+ case 'datetime':
+ case 'timestamp':
+ case 'timestamptz':
+ $type[] = 'timestamp';
+ $length = null;
+ break;
+ case 'time':
+ $type[] = 'time';
+ $length = null;
+ break;
+ case 'float':
+ case 'float4':
+ case 'float8':
+ case 'double':
+ case 'real':
+ $type[] = 'float';
+ break;
+ case 'decimal':
+ case 'money':
+ case 'numeric':
+ $type[] = 'decimal';
+ if (isset($field['scale'])) {
+ $length = $length.','.$field['scale'];
+ }
+ break;
+ case 'tinyblob':
+ case 'mediumblob':
+ case 'longblob':
+ case 'blob':
+ case 'bytea':
+ $type[] = 'blob';
+ $length = null;
+ break;
+ case 'oid':
+ $type[] = 'blob';
+ $type[] = 'clob';
+ $length = null;
+ break;
+ case 'year':
+ $type[] = 'integer';
+ $type[] = 'date';
+ $length = null;
+ break;
+ default:
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+ return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+ 'unknown database attribute type: '.$db_type, __FUNCTION__);
+ }
+
+ if ((int)$length <= 0) {
+ $length = null;
+ }
+
+ return array($type, $length, $unsigned, $fixed);
+ }
+
+ // }}}
+ // {{{ mapPrepareDatatype()
+
+ /**
+ * Maps an mdb2 datatype to native prepare type
+ *
+ * @param string $type
+ * @return string
+ * @access public
+ */
+ function mapPrepareDatatype($type)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ if (!empty($db->options['datatype_map'][$type])) {
+ $type = $db->options['datatype_map'][$type];
+ if (!empty($db->options['datatype_map_callback'][$type])) {
+ $parameter = array('type' => $type);
+ return call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter));
+ }
+ }
+
+ switch ($type) {
+ case 'integer':
+ return 'int';
+ case 'boolean':
+ return 'bool';
+ case 'decimal':
+ case 'float':
+ return 'numeric';
+ case 'clob':
+ return 'text';
+ case 'blob':
+ return 'bytea';
+ default:
+ break;
+ }
+ return $type;
+ }
+ // }}}
+}
+?>
\ No newline at end of file
diff -Nru owncloud-1.1+git20110209/3rdparty/MDB2/Driver/Datatype/sqlite.php owncloud-5.0.4debian/3rdparty/MDB2/Driver/Datatype/sqlite.php
--- owncloud-1.1+git20110209/3rdparty/MDB2/Driver/Datatype/sqlite.php 1970-01-01 00:00:00.000000000 +0000
+++ owncloud-5.0.4debian/3rdparty/MDB2/Driver/Datatype/sqlite.php 2013-04-10 17:29:58.000000000 +0000
@@ -0,0 +1,418 @@
+ |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+//
+
+require_once 'MDB2/Driver/Datatype/Common.php';
+
+/**
+ * MDB2 SQLite driver
+ *
+ * @package MDB2
+ * @category Database
+ * @author Lukas Smith
+ */
+class MDB2_Driver_Datatype_sqlite extends MDB2_Driver_Datatype_Common
+{
+ // {{{ _getCollationFieldDeclaration()
+
+ /**
+ * Obtain DBMS specific SQL code portion needed to set the COLLATION
+ * of a field declaration to be used in statements like CREATE TABLE.
+ *
+ * @param string $collation name of the collation
+ *
+ * @return string DBMS specific SQL code portion needed to set the COLLATION
+ * of a field declaration.
+ */
+ function _getCollationFieldDeclaration($collation)
+ {
+ return 'COLLATE '.$collation;
+ }
+
+ // }}}
+ // {{{ getTypeDeclaration()
+
+ /**
+ * Obtain DBMS specific SQL code portion needed to declare an text type
+ * field to be used in statements like CREATE TABLE.
+ *
+ * @param array $field associative array with the name of the properties
+ * of the field being declared as array indexes. Currently, the types
+ * of supported field properties are as follows:
+ *
+ * length
+ * Integer value that determines the maximum length of the text
+ * field. If this argument is missing the field should be
+ * declared to have the longest length allowed by the DBMS.
+ *
+ * default
+ * Text value to be used as default for this field.
+ *
+ * notnull
+ * Boolean flag that indicates whether this field is constrained
+ * to not be set to null.
+ * @return string DBMS specific SQL code portion that should be used to
+ * declare the specified field.
+ * @access public
+ */
+ function getTypeDeclaration($field)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ switch ($field['type']) {
+ case 'text':
+ $length = !empty($field['length'])
+ ? $field['length'] : false;
+ $fixed = !empty($field['fixed']) ? $field['fixed'] : false;
+ return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$db->options['default_text_field_length'].')')
+ : ($length ? 'VARCHAR('.$length.')' : 'TEXT');
+ case 'clob':
+ if (!empty($field['length'])) {
+ $length = $field['length'];
+ if ($length <= 255) {
+ return 'TINYTEXT';
+ } elseif ($length <= 65532) {
+ return 'TEXT';
+ } elseif ($length <= 16777215) {
+ return 'MEDIUMTEXT';
+ }
+ }
+ return 'LONGTEXT';
+ case 'blob':
+ if (!empty($field['length'])) {
+ $length = $field['length'];
+ if ($length <= 255) {
+ return 'TINYBLOB';
+ } elseif ($length <= 65532) {
+ return 'BLOB';
+ } elseif ($length <= 16777215) {
+ return 'MEDIUMBLOB';
+ }
+ }
+ return 'LONGBLOB';
+ case 'integer':
+ if (!empty($field['length'])) {
+ $length = $field['length'];
+ if ($length <= 2) {
+ return 'SMALLINT';
+ } elseif ($length == 3 || $length == 4) {
+ return 'INTEGER';
+ } elseif ($length > 4) {
+ return 'BIGINT';
+ }
+ }
+ return 'INTEGER';
+ case 'boolean':
+ return 'BOOLEAN';
+ case 'date':
+ return 'DATE';
+ case 'time':
+ return 'TIME';
+ case 'timestamp':
+ return 'DATETIME';
+ case 'float':
+ return 'DOUBLE'.($db->options['fixed_float'] ? '('.
+ ($db->options['fixed_float']+2).','.$db->options['fixed_float'].')' : '');
+ case 'decimal':
+ $length = !empty($field['length']) ? $field['length'] : 18;
+ $scale = !empty($field['scale']) ? $field['scale'] : $db->options['decimal_places'];
+ return 'DECIMAL('.$length.','.$scale.')';
+ }
+ return '';
+ }
+
+ // }}}
+ // {{{ _getIntegerDeclaration()
+
+ /**
+ * Obtain DBMS specific SQL code portion needed to declare an integer type
+ * field to be used in statements like CREATE TABLE.
+ *
+ * @param string $name name the field to be declared.
+ * @param string $field associative array with the name of the properties
+ * of the field being declared as array indexes.
+ * Currently, the types of supported field
+ * properties are as follows:
+ *
+ * unsigned
+ * Boolean flag that indicates whether the field
+ * should be declared as unsigned integer if
+ * possible.
+ *
+ * default
+ * Integer value to be used as default for this
+ * field.
+ *
+ * notnull
+ * Boolean flag that indicates whether this field is
+ * constrained to not be set to null.
+ * @return string DBMS specific SQL code portion that should be used to
+ * declare the specified field.
+ * @access protected
+ */
+ function _getIntegerDeclaration($name, $field)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ $default = $autoinc = '';
+ if (!empty($field['autoincrement'])) {
+ $autoinc = ' PRIMARY KEY';
+ } elseif (array_key_exists('default', $field)) {
+ if ($field['default'] === '') {
+ $field['default'] = empty($field['notnull']) ? null : 0;
+ }
+ $default = ' DEFAULT '.$this->quote($field['default'], 'integer');
+ }
+
+ $notnull = empty($field['notnull']) ? '' : ' NOT NULL';
+ $unsigned = empty($field['unsigned']) ? '' : ' UNSIGNED';
+ if (empty($default) && empty($notnull)) {
+ $default = ' DEFAULT NULL';
+ }
+ $name = $db->quoteIdentifier($name, true);
+ return $name.' '.$this->getTypeDeclaration($field).$unsigned.$default.$notnull.$autoinc;
+ }
+
+ // }}}
+ // {{{ matchPattern()
+
+ /**
+ * build a pattern matching string
+ *
+ * @access public
+ *
+ * @param array $pattern even keys are strings, odd are patterns (% and _)
+ * @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future)
+ * @param string $field optional field name that is being matched against
+ * (might be required when emulating ILIKE)
+ *
+ * @return string SQL pattern
+ */
+ function matchPattern($pattern, $operator = null, $field = null)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ $match = '';
+ if (null !== $operator) {
+ $field = (null === $field) ? '' : $field.' ';
+ $operator = strtoupper($operator);
+ switch ($operator) {
+ // case insensitive
+ case 'ILIKE':
+ $match = $field.'LIKE ';
+ break;
+ case 'NOT ILIKE':
+ $match = $field.'NOT LIKE ';
+ break;
+ // case sensitive
+ case 'LIKE':
+ $match = $field.'LIKE ';
+ break;
+ case 'NOT LIKE':
+ $match = $field.'NOT LIKE ';
+ break;
+ default:
+ return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+ 'not a supported operator type:'. $operator, __FUNCTION__);
+ }
+ }
+ $match.= "'";
+ foreach ($pattern as $key => $value) {
+ if ($key % 2) {
+ $match.= $value;
+ } else {
+ $match.= $db->escapePattern($db->escape($value));
+ }
+ }
+ $match.= "'";
+ $match.= $this->patternEscapeString();
+ return $match;
+ }
+
+ // }}}
+ // {{{ _mapNativeDatatype()
+
+ /**
+ * Maps a native array description of a field to a MDB2 datatype and length
+ *
+ * @param array $field native field description
+ * @return array containing the various possible types, length, sign, fixed
+ * @access public
+ */
+ function _mapNativeDatatype($field)
+ {
+ $db_type = strtolower($field['type']);
+ $length = !empty($field['length']) ? $field['length'] : null;
+ $unsigned = !empty($field['unsigned']) ? $field['unsigned'] : null;
+ $fixed = null;
+ $type = array();
+ switch ($db_type) {
+ case 'boolean':
+ $type[] = 'boolean';
+ break;
+ case 'tinyint':
+ $type[] = 'integer';
+ $type[] = 'boolean';
+ if (preg_match('/^(is|has)/', $field['name'])) {
+ $type = array_reverse($type);
+ }
+ $unsigned = preg_match('/ unsigned/i', $field['type']);
+ $length = 1;
+ break;
+ case 'smallint':
+ $type[] = 'integer';
+ $unsigned = preg_match('/ unsigned/i', $field['type']);
+ $length = 2;
+ break;
+ case 'mediumint':
+ $type[] = 'integer';
+ $unsigned = preg_match('/ unsigned/i', $field['type']);
+ $length = 3;
+ break;
+ case 'int':
+ case 'integer':
+ case 'serial':
+ $type[] = 'integer';
+ $unsigned = preg_match('/ unsigned/i', $field['type']);
+ $length = 4;
+ break;
+ case 'bigint':
+ case 'bigserial':
+ $type[] = 'integer';
+ $unsigned = preg_match('/ unsigned/i', $field['type']);
+ $length = 8;
+ break;
+ case 'clob':
+ $type[] = 'clob';
+ $fixed = false;
+ break;
+ case 'tinytext':
+ case 'mediumtext':
+ case 'longtext':
+ case 'text':
+ case 'varchar':
+ case 'varchar2':
+ $fixed = false;
+ case 'char':
+ $type[] = 'text';
+ if ($length == '1') {
+ $type[] = 'boolean';
+ if (preg_match('/^(is|has)/', $field['name'])) {
+ $type = array_reverse($type);
+ }
+ } elseif (strstr($db_type, 'text')) {
+ $type[] = 'clob';
+ $type = array_reverse($type);
+ }
+ if ($fixed !== false) {
+ $fixed = true;
+ }
+ break;
+ case 'date':
+ $type[] = 'date';
+ $length = null;
+ break;
+ case 'datetime':
+ case 'timestamp':
+ $type[] = 'timestamp';
+ $length = null;
+ break;
+ case 'time':
+ $type[] = 'time';
+ $length = null;
+ break;
+ case 'float':
+ case 'double':
+ case 'real':
+ $type[] = 'float';
+ break;
+ case 'decimal':
+ case 'numeric':
+ $type[] = 'decimal';
+ $length = $length.','.$field['decimal'];
+ break;
+ case 'tinyblob':
+ case 'mediumblob':
+ case 'longblob':
+ case 'blob':
+ $type[] = 'blob';
+ $length = null;
+ break;
+ case 'year':
+ $type[] = 'integer';
+ $type[] = 'date';
+ $length = null;
+ break;
+ default:
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+ return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+ 'unknown database attribute type: '.$db_type, __FUNCTION__);
+ }
+
+ if ((int)$length <= 0) {
+ $length = null;
+ }
+
+ return array($type, $length, $unsigned, $fixed);
+ }
+
+ // }}}
+}
+
+?>
\ No newline at end of file
diff -Nru owncloud-1.1+git20110209/3rdparty/MDB2/Driver/Datatype/sqlsrv.php owncloud-5.0.4debian/3rdparty/MDB2/Driver/Datatype/sqlsrv.php
--- owncloud-1.1+git20110209/3rdparty/MDB2/Driver/Datatype/sqlsrv.php 1970-01-01 00:00:00.000000000 +0000
+++ owncloud-5.0.4debian/3rdparty/MDB2/Driver/Datatype/sqlsrv.php 2013-04-10 17:29:58.000000000 +0000
@@ -0,0 +1,459 @@
+ |
+// | Daniel Convissor |
+// +----------------------------------------------------------------------+
+
+require_once 'MDB2/Driver/Datatype/Common.php';
+
+/**
+ * MDB2 MS SQL driver
+ *
+ * @package MDB2
+ * @category Database
+ */
+class MDB2_Driver_Datatype_sqlsrv extends MDB2_Driver_Datatype_Common
+{
+ // {{{ _baseConvertResult()
+
+ /**
+ * general type conversion method
+ *
+ * @param mixed $value refernce to a value to be converted
+ * @param string $type specifies which type to convert to
+ * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text
+ * @return object a MDB2 error on failure
+ * @access protected
+ */
+ function _baseConvertResult($value, $type, $rtrim = true)
+ {
+ if (null === $value) {
+ return null;
+ }
+ switch ($type) {
+ case 'boolean':
+ return $value == '1';
+ case 'date':
+ if (strlen($value) > 10) {
+ $value = substr($value,0,10);
+ }
+ return $value;
+ case 'time':
+ if (strlen($value) > 8) {
+ $value = substr($value,11,8);
+ }
+ return $value;
+ }
+ return parent::_baseConvertResult($value, $type, $rtrim);
+ }
+
+ // }}}
+ // {{{ _getCollationFieldDeclaration()
+
+ /**
+ * Obtain DBMS specific SQL code portion needed to set the COLLATION
+ * of a field declaration to be used in statements like CREATE TABLE.
+ *
+ * @param string $collation name of the collation
+ *
+ * @return string DBMS specific SQL code portion needed to set the COLLATION
+ * of a field declaration.
+ */
+ function _getCollationFieldDeclaration($collation)
+ {
+ return 'COLLATE '.$collation;
+ }
+
+ // }}}
+ // {{{ getTypeDeclaration()
+
+ /**
+ * Obtain DBMS specific SQL code portion needed to declare an text type
+ * field to be used in statements like CREATE TABLE.
+ *
+ * @param array $field associative array with the name of the properties
+ * of the field being declared as array indexes. Currently, the types
+ * of supported field properties are as follows:
+ *
+ * length
+ * Integer value that determines the maximum length of the text
+ * field. If this argument is missing the field should be
+ * declared to have the longest length allowed by the DBMS.
+ *
+ * default
+ * Text value to be used as default for this field.
+ *
+ * notnull
+ * Boolean flag that indicates whether this field is constrained
+ * to not be set to null.
+ * @return string DBMS specific SQL code portion that should be used to
+ * declare the specified field.
+ * @access public
+ */
+ function getTypeDeclaration($field)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ switch ($field['type']) {
+ case 'text':
+ $length = !empty($field['length'])
+ ? $field['length'] : false;
+ $fixed = !empty($field['fixed']) ? $field['fixed'] : false;
+ return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$db->options['default_text_field_length'].')')
+ : ($length ? 'VARCHAR('.$length.')' : 'VARCHAR(MAX)');
+ case 'clob':
+ if (!empty($field['length'])) {
+ $length = $field['length'];
+ if ($length <= 8000) {
+ return 'VARCHAR('.$length.')';
+ }
+ }
+ return 'VARCHAR(MAX)';
+ case 'blob':
+ if (!empty($field['length'])) {
+ $length = $field['length'];
+ if ($length <= 8000) {
+ return "VARBINARY($length)";
+ }
+ }
+ return 'IMAGE';
+ case 'integer':
+ return 'INT';
+ case 'boolean':
+ return 'BIT';
+ case 'date':
+ return 'CHAR ('.strlen('YYYY-MM-DD').')';
+ case 'time':
+ return 'CHAR ('.strlen('HH:MM:SS').')';
+ case 'timestamp':
+ return 'CHAR ('.strlen('YYYY-MM-DD HH:MM:SS').')';
+ case 'float':
+ return 'FLOAT';
+ case 'decimal':
+ $length = !empty($field['length']) ? $field['length'] : 18;
+ $scale = !empty($field['scale']) ? $field['scale'] : $db->options['decimal_places'];
+ return 'DECIMAL('.$length.','.$scale.')';
+ }
+ return '';
+ }
+
+ // }}}
+ // {{{ _getIntegerDeclaration()
+
+ /**
+ * Obtain DBMS specific SQL code portion needed to declare an integer type
+ * field to be used in statements like CREATE TABLE.
+ *
+ * @param string $name name the field to be declared.
+ * @param string $field associative array with the name of the properties
+ * of the field being declared as array indexes.
+ * Currently, the types of supported field
+ * properties are as follows:
+ *
+ * unsigned
+ * Boolean flag that indicates whether the field
+ * should be declared as unsigned integer if
+ * possible.
+ *
+ * default
+ * Integer value to be used as default for this
+ * field.
+ *
+ * notnull
+ * Boolean flag that indicates whether this field is
+ * constrained to not be set to null.
+ * @return string DBMS specific SQL code portion that should be used to
+ * declare the specified field.
+ * @access protected
+ */
+ function _getIntegerDeclaration($name, $field)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ $notnull = empty($field['notnull']) ? ' NULL' : ' NOT NULL';
+ $default = $autoinc = '';
+ if (!empty($field['autoincrement'])) {
+ $autoinc = ' IDENTITY PRIMARY KEY';
+ } elseif (array_key_exists('default', $field)) {
+ if ($field['default'] === '') {
+ $field['default'] = 0;
+ }
+ if (null === $field['default']) {
+ $default = ' DEFAULT (NULL)';
+ } else {
+ $default = ' DEFAULT (' . $this->quote($field['default'], 'integer') . ')';
+ }
+ }
+
+ if (!empty($field['unsigned'])) {
+ $db->warnings[] = "unsigned integer field \"$name\" is being declared as signed integer";
+ }
+
+ $name = $db->quoteIdentifier($name, true);
+ return $name.' '.$this->getTypeDeclaration($field).$notnull.$default.$autoinc;
+ }
+
+ // }}}
+ // {{{ _getCLOBDeclaration()
+
+ /**
+ * Obtain DBMS specific SQL code portion needed to declare an character
+ * large object type field to be used in statements like CREATE TABLE.
+ *
+ * @param string $name name the field to be declared.
+ * @param array $field associative array with the name of the properties
+ * of the field being declared as array indexes. Currently, the types
+ * of supported field properties are as follows:
+ *
+ * length
+ * Integer value that determines the maximum length of the large
+ * object field. If this argument is missing the field should be
+ * declared to have the longest length allowed by the DBMS.
+ *
+ * notnull
+ * Boolean flag that indicates whether this field is constrained
+ * to not be set to null.
+ * @return string DBMS specific SQL code portion that should be used to
+ * declare the specified field.
+ * @access public
+ */
+ function _getCLOBDeclaration($name, $field)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ $notnull = empty($field['notnull']) ? ' NULL' : ' NOT NULL';
+ $name = $db->quoteIdentifier($name, true);
+ return $name.' '.$this->getTypeDeclaration($field).$notnull;
+ }
+
+ // }}}
+ // {{{ _getBLOBDeclaration()
+
+ /**
+ * Obtain DBMS specific SQL code portion needed to declare an binary large
+ * object type field to be used in statements like CREATE TABLE.
+ *
+ * @param string $name name the field to be declared.
+ * @param array $field associative array with the name of the properties
+ * of the field being declared as array indexes. Currently, the types
+ * of supported field properties are as follows:
+ *
+ * length
+ * Integer value that determines the maximum length of the large
+ * object field. If this argument is missing the field should be
+ * declared to have the longest length allowed by the DBMS.
+ *
+ * notnull
+ * Boolean flag that indicates whether this field is constrained
+ * to not be set to null.
+ * @return string DBMS specific SQL code portion that should be used to
+ * declare the specified field.
+ * @access protected
+ */
+ function _getBLOBDeclaration($name, $field)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ $notnull = empty($field['notnull']) ? ' NULL' : ' NOT NULL';
+ $name = $db->quoteIdentifier($name, true);
+ return $name.' '.$this->getTypeDeclaration($field).$notnull;
+ }
+
+ // }}}
+ // {{{ _quoteBLOB()
+
+ /**
+ * Convert a text value into a DBMS specific format that is suitable to
+ * compose query statements.
+ *
+ * @param string $value text string value that is intended to be converted.
+ * @param bool $quote determines if the value should be quoted and escaped
+ * @param bool $escape_wildcards if to escape escape wildcards
+ * @return string text string that represents the given argument value in
+ * a DBMS specific format.
+ * @access protected
+ */
+ function _quoteBLOB($value, $quote, $escape_wildcards)
+ {
+ if (!$quote) {
+ return $value;
+ }
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+ if ($db->options['lob_allow_url_include']) {
+ $value = '0x'.bin2hex($this->_readFile($value));
+ }
+ return "'".$value."'";
+ }
+
+ // }}}
+ // {{{ _mapNativeDatatype()
+
+ /**
+ * Maps a native array description of a field to a MDB2 datatype and length
+ *
+ * @param array $field native field description
+ * @return array containing the various possible types, length, sign, fixed
+ * @access public
+ */
+ function _mapNativeDatatype($field)
+ {
+ // todo: handle length of various int variations
+ $db_type = $field['type'];
+ $length = $field['length'];
+ $type = array();
+ // todo: unsigned handling seems to be missing
+ $unsigned = $fixed = null;
+ switch ($db_type) {
+ case 'bit':
+ case SQLSRV_SQLTYPE_BIT:
+ $type[0] = 'boolean';
+ break;
+ case 'tinyint':
+ case SQLSRV_SQLTYPE_TINYINT:
+ $type[0] = 'integer';
+ $length = 1;
+ break;
+ case 'smallint':
+ case SQLSRV_SQLTYPE_SMALLINT:
+ $type[0] = 'integer';
+ $length = 2;
+ break;
+ case 'int':
+ case SQLSRV_SQLTYPE_INT:
+ $type[0] = 'integer';
+ $length = 4;
+ break;
+ case 'bigint':
+ case SQLSRV_SQLTYPE_BIGINT:
+ $type[0] = 'integer';
+ $length = 8;
+ break;
+ case 'datetime':
+ case SQLSRV_SQLTYPE_DATETIME:
+ $type[0] = 'timestamp';
+ break;
+ case 'float':
+ case SQLSRV_SQLTYPE_FLOAT:
+ case 'real':
+ case SQLSRV_SQLTYPE_REAL:
+ $type[0] = 'float';
+ break;
+ case 'numeric':
+// case SQLSRV_SQLTYPE_NUMERIC:
+ case 'decimal':
+// case SQLSRV_SQLTYPE_DECIMAL:
+ case 'money':
+ case SQLSRV_SQLTYPE_MONEY:
+ $type[0] = 'decimal';
+ $length = $field['numeric_precision'].','.$field['numeric_scale'];
+ break;
+ case 'text':
+ case SQLSRV_SQLTYPE_TEXT:
+ case 'ntext':
+ case SQLSRV_SQLTYPE_NTEXT:
+ case 'varchar':
+// case SQLSRV_SQLTYPE_VARCHAR:
+ case 'nvarchar':
+// case SQLSRV_SQLTYPE_NVARCHAR:
+ $fixed = false;
+ case 'char':
+// case SQLSRV_SQLTYPE_CHAR:
+ case 'nchar':
+// case SQLSRV_SQLTYPE_NCHAR:
+ $type[0] = 'text';
+ if ($length == '1') {
+ $type[] = 'boolean';
+ if (preg_match('/^(is|has)/', $field['name'])) {
+ $type = array_reverse($type);
+ }
+ } elseif (strstr($db_type, 'text') || strstr($db_type, SQLSRV_SQLTYPE_TEXT)) {
+ $type[] = 'clob';
+ $type = array_reverse($type);
+ }
+ if ($fixed !== false) {
+ $fixed = true;
+ }
+ break;
+ case 'image':
+ case SQLSRV_SQLTYPE_IMAGE:
+ case 'varbinary':
+// case SQLSRV_SQLTYPE_VARBINARY:
+ case 'timestamp':
+ case SQLSRV_SQLTYPE_TIMESTAMP:
+ $type[] = 'blob';
+ $length = null;
+ break;
+ default:
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+ return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+ 'unknown database attribute type: '.$db_type, __FUNCTION__);
+ }
+
+ if ((int)$length <= 0) {
+ $length = null;
+ }
+
+ return array($type, $length, $unsigned, $fixed);
+ }
+ // }}}
+}
+
+?>
\ No newline at end of file
diff -Nru owncloud-1.1+git20110209/3rdparty/MDB2/Driver/Function/Common.php owncloud-5.0.4debian/3rdparty/MDB2/Driver/Function/Common.php
--- owncloud-1.1+git20110209/3rdparty/MDB2/Driver/Function/Common.php 1970-01-01 00:00:00.000000000 +0000
+++ owncloud-5.0.4debian/3rdparty/MDB2/Driver/Function/Common.php 2013-04-10 17:29:58.000000000 +0000
@@ -0,0 +1,293 @@
+ |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+//
+
+/**
+ * @package MDB2
+ * @category Database
+ * @author Lukas Smith
+ */
+
+/**
+ * Base class for the function modules that is extended by each MDB2 driver
+ *
+ * To load this module in the MDB2 object:
+ * $mdb->loadModule('Function');
+ *
+ * @package MDB2
+ * @category Database
+ * @author Lukas Smith
+ */
+class MDB2_Driver_Function_Common extends MDB2_Module_Common
+{
+ // {{{ executeStoredProc()
+
+ /**
+ * Execute a stored procedure and return any results
+ *
+ * @param string $name string that identifies the function to execute
+ * @param mixed $params array that contains the paramaters to pass the stored proc
+ * @param mixed $types array that contains the types of the columns in
+ * the result set
+ * @param mixed $result_class string which specifies which result class to use
+ * @param mixed $result_wrap_class string which specifies which class to wrap results in
+ *
+ * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure
+ * @access public
+ */
+ function executeStoredProc($name, $params = null, $types = null, $result_class = true, $result_wrap_class = false)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ $error = $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+ 'method not implemented', __FUNCTION__);
+ return $error;
+ }
+
+ // }}}
+ // {{{ functionTable()
+
+ /**
+ * return string for internal table used when calling only a function
+ *
+ * @return string for internal table used when calling only a function
+ * @access public
+ */
+ function functionTable()
+ {
+ return '';
+ }
+
+ // }}}
+ // {{{ now()
+
+ /**
+ * Return string to call a variable with the current timestamp inside an SQL statement
+ * There are three special variables for current date and time:
+ * - CURRENT_TIMESTAMP (date and time, TIMESTAMP type)
+ * - CURRENT_DATE (date, DATE type)
+ * - CURRENT_TIME (time, TIME type)
+ *
+ * @param string $type 'timestamp' | 'time' | 'date'
+ *
+ * @return string to call a variable with the current timestamp
+ * @access public
+ */
+ function now($type = 'timestamp')
+ {
+ switch ($type) {
+ case 'time':
+ return 'CURRENT_TIME';
+ case 'date':
+ return 'CURRENT_DATE';
+ case 'timestamp':
+ default:
+ return 'CURRENT_TIMESTAMP';
+ }
+ }
+
+ // }}}
+ // {{{ unixtimestamp()
+
+ /**
+ * return string to call a function to get the unix timestamp from a iso timestamp
+ *
+ * @param string $expression
+ *
+ * @return string to call a variable with the timestamp
+ * @access public
+ */
+ function unixtimestamp($expression)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ $error = $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+ 'method not implemented', __FUNCTION__);
+ return $error;
+ }
+
+ // }}}
+ // {{{ substring()
+
+ /**
+ * return string to call a function to get a substring inside an SQL statement
+ *
+ * @return string to call a function to get a substring
+ * @access public
+ */
+ function substring($value, $position = 1, $length = null)
+ {
+ if (null !== $length) {
+ return "SUBSTRING($value FROM $position FOR $length)";
+ }
+ return "SUBSTRING($value FROM $position)";
+ }
+
+ // }}}
+ // {{{ replace()
+
+ /**
+ * return string to call a function to get replace inside an SQL statement.
+ *
+ * @return string to call a function to get a replace
+ * @access public
+ */
+ function replace($str, $from_str, $to_str)
+ {
+ return "REPLACE($str, $from_str , $to_str)";
+ }
+
+ // }}}
+ // {{{ concat()
+
+ /**
+ * Returns string to concatenate two or more string parameters
+ *
+ * @param string $value1
+ * @param string $value2
+ * @param string $values...
+ *
+ * @return string to concatenate two strings
+ * @access public
+ */
+ function concat($value1, $value2)
+ {
+ $args = func_get_args();
+ return "(".implode(' || ', $args).")";
+ }
+
+ // }}}
+ // {{{ random()
+
+ /**
+ * return string to call a function to get random value inside an SQL statement
+ *
+ * @return return string to generate float between 0 and 1
+ * @access public
+ */
+ function random()
+ {
+ return 'RAND()';
+ }
+
+ // }}}
+ // {{{ lower()
+
+ /**
+ * return string to call a function to lower the case of an expression
+ *
+ * @param string $expression
+ *
+ * @return return string to lower case of an expression
+ * @access public
+ */
+ function lower($expression)
+ {
+ return "LOWER($expression)";
+ }
+
+ // }}}
+ // {{{ upper()
+
+ /**
+ * return string to call a function to upper the case of an expression
+ *
+ * @param string $expression
+ *
+ * @return return string to upper case of an expression
+ * @access public
+ */
+ function upper($expression)
+ {
+ return "UPPER($expression)";
+ }
+
+ // }}}
+ // {{{ length()
+
+ /**
+ * return string to call a function to get the length of a string expression
+ *
+ * @param string $expression
+ *
+ * @return return string to get the string expression length
+ * @access public
+ */
+ function length($expression)
+ {
+ return "LENGTH($expression)";
+ }
+
+ // }}}
+ // {{{ guid()
+
+ /**
+ * Returns global unique identifier
+ *
+ * @return string to get global unique identifier
+ * @access public
+ */
+ function guid()
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ $error = $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+ 'method not implemented', __FUNCTION__);
+ return $error;
+ }
+
+ // }}}
+}
+?>
\ No newline at end of file
diff -Nru owncloud-1.1+git20110209/3rdparty/MDB2/Driver/Function/mysql.php owncloud-5.0.4debian/3rdparty/MDB2/Driver/Function/mysql.php
--- owncloud-1.1+git20110209/3rdparty/MDB2/Driver/Function/mysql.php 1970-01-01 00:00:00.000000000 +0000
+++ owncloud-5.0.4debian/3rdparty/MDB2/Driver/Function/mysql.php 2013-04-10 17:29:58.000000000 +0000
@@ -0,0 +1,136 @@
+ |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+//
+
+require_once 'MDB2/Driver/Function/Common.php';
+
+/**
+ * MDB2 MySQL driver for the function modules
+ *
+ * @package MDB2
+ * @category Database
+ * @author Lukas Smith
+ */
+class MDB2_Driver_Function_mysql extends MDB2_Driver_Function_Common
+{
+ // }}}
+ // {{{ executeStoredProc()
+
+ /**
+ * Execute a stored procedure and return any results
+ *
+ * @param string $name string that identifies the function to execute
+ * @param mixed $params array that contains the paramaters to pass the stored proc
+ * @param mixed $types array that contains the types of the columns in
+ * the result set
+ * @param mixed $result_class string which specifies which result class to use
+ * @param mixed $result_wrap_class string which specifies which class to wrap results in
+ * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure
+ * @access public
+ */
+ function executeStoredProc($name, $params = null, $types = null, $result_class = true, $result_wrap_class = false)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ $query = 'CALL '.$name;
+ $query .= $params ? '('.implode(', ', $params).')' : '()';
+ return $db->query($query, $types, $result_class, $result_wrap_class);
+ }
+
+ // }}}
+ // {{{ unixtimestamp()
+
+ /**
+ * return string to call a function to get the unix timestamp from a iso timestamp
+ *
+ * @param string $expression
+ *
+ * @return string to call a variable with the timestamp
+ * @access public
+ */
+ function unixtimestamp($expression)
+ {
+ return 'UNIX_TIMESTAMP('. $expression.')';
+ }
+
+ // }}}
+ // {{{ concat()
+
+ /**
+ * Returns string to concatenate two or more string parameters
+ *
+ * @param string $value1
+ * @param string $value2
+ * @param string $values...
+ * @return string to concatenate two strings
+ * @access public
+ **/
+ function concat($value1, $value2)
+ {
+ $args = func_get_args();
+ return "CONCAT(".implode(', ', $args).")";
+ }
+
+ // }}}
+ // {{{ guid()
+
+ /**
+ * Returns global unique identifier
+ *
+ * @return string to get global unique identifier
+ * @access public
+ */
+ function guid()
+ {
+ return 'UUID()';
+ }
+
+ // }}}
+}
+?>
\ No newline at end of file
diff -Nru owncloud-1.1+git20110209/3rdparty/MDB2/Driver/Function/oci8.php owncloud-5.0.4debian/3rdparty/MDB2/Driver/Function/oci8.php
--- owncloud-1.1+git20110209/3rdparty/MDB2/Driver/Function/oci8.php 1970-01-01 00:00:00.000000000 +0000
+++ owncloud-5.0.4debian/3rdparty/MDB2/Driver/Function/oci8.php 2013-04-10 17:29:58.000000000 +0000
@@ -0,0 +1,187 @@
+ |
+// +----------------------------------------------------------------------+
+
+// $Id: oci8.php 295587 2010-02-28 17:16:38Z quipo $
+
+require_once 'MDB2/Driver/Function/Common.php';
+
+/**
+ * MDB2 oci8 driver for the function modules
+ *
+ * @package MDB2
+ * @category Database
+ * @author Lukas Smith
+ */
+class MDB2_Driver_Function_oci8 extends MDB2_Driver_Function_Common
+{
+ // {{{ executeStoredProc()
+
+ /**
+ * Execute a stored procedure and return any results
+ *
+ * @param string $name string that identifies the function to execute
+ * @param mixed $params array that contains the paramaters to pass the stored proc
+ * @param mixed $types array that contains the types of the columns in
+ * the result set
+ * @param mixed $result_class string which specifies which result class to use
+ * @param mixed $result_wrap_class string which specifies which class to wrap results in
+ * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure
+ * @access public
+ */
+ function executeStoredProc($name, $params = null, $types = null, $result_class = true, $result_wrap_class = false)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ $query = 'EXEC '.$name;
+ $query .= $params ? '('.implode(', ', $params).')' : '()';
+ return $db->query($query, $types, $result_class, $result_wrap_class);
+ }
+
+ // }}}
+ // {{{ functionTable()
+
+ /**
+ * return string for internal table used when calling only a function
+ *
+ * @return string for internal table used when calling only a function
+ * @access public
+ */
+ function functionTable()
+ {
+ return ' FROM dual';
+ }
+
+ // }}}
+ // {{{ now()
+
+ /**
+ * Return string to call a variable with the current timestamp inside an SQL statement
+ * There are three special variables for current date and time:
+ * - CURRENT_TIMESTAMP (date and time, TIMESTAMP type)
+ * - CURRENT_DATE (date, DATE type)
+ * - CURRENT_TIME (time, TIME type)
+ *
+ * @return string to call a variable with the current timestamp
+ * @access public
+ */
+ function now($type = 'timestamp')
+ {
+ switch ($type) {
+ case 'date':
+ case 'time':
+ case 'timestamp':
+ default:
+ return 'TO_CHAR(CURRENT_TIMESTAMP, \'YYYY-MM-DD HH24:MI:SS\')';
+ }
+ }
+
+ // }}}
+ // {{{ unixtimestamp()
+
+ /**
+ * return string to call a function to get the unix timestamp from a iso timestamp
+ *
+ * @param string $expression
+ *
+ * @return string to call a variable with the timestamp
+ * @access public
+ */
+ function unixtimestamp($expression)
+ {
+ $utc_offset = 'CAST(SYS_EXTRACT_UTC(SYSTIMESTAMP) AS DATE) - CAST(SYSTIMESTAMP AS DATE)';
+ $epoch_date = 'to_date(\'19700101\', \'YYYYMMDD\')';
+ return '(CAST('.$expression.' AS DATE) - '.$epoch_date.' + '.$utc_offset.') * 86400 seconds';
+ }
+
+ // }}}
+ // {{{ substring()
+
+ /**
+ * return string to call a function to get a substring inside an SQL statement
+ *
+ * @return string to call a function to get a substring
+ * @access public
+ */
+ function substring($value, $position = 1, $length = null)
+ {
+ if (null !== $length) {
+ return "SUBSTR($value, $position, $length)";
+ }
+ return "SUBSTR($value, $position)";
+ }
+
+ // }}}
+ // {{{ random()
+
+ /**
+ * return string to call a function to get random value inside an SQL statement
+ *
+ * @return return string to generate float between 0 and 1
+ * @access public
+ */
+ function random()
+ {
+ return 'dbms_random.value';
+ }
+
+ // }}}}
+ // {{{ guid()
+
+ /**
+ * Returns global unique identifier
+ *
+ * @return string to get global unique identifier
+ * @access public
+ */
+ function guid()
+ {
+ return 'SYS_GUID()';
+ }
+
+ // }}}}
+}
+?>
\ No newline at end of file
diff -Nru owncloud-1.1+git20110209/3rdparty/MDB2/Driver/Function/pgsql.php owncloud-5.0.4debian/3rdparty/MDB2/Driver/Function/pgsql.php
--- owncloud-1.1+git20110209/3rdparty/MDB2/Driver/Function/pgsql.php 1970-01-01 00:00:00.000000000 +0000
+++ owncloud-5.0.4debian/3rdparty/MDB2/Driver/Function/pgsql.php 2013-04-10 17:29:58.000000000 +0000
@@ -0,0 +1,132 @@
+ |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+require_once 'MDB2/Driver/Function/Common.php';
+
+/**
+ * MDB2 MySQL driver for the function modules
+ *
+ * @package MDB2
+ * @category Database
+ * @author Lukas Smith
+ */
+class MDB2_Driver_Function_pgsql extends MDB2_Driver_Function_Common
+{
+ // {{{ executeStoredProc()
+
+ /**
+ * Execute a stored procedure and return any results
+ *
+ * @param string $name string that identifies the function to execute
+ * @param mixed $params array that contains the paramaters to pass the stored proc
+ * @param mixed $types array that contains the types of the columns in
+ * the result set
+ * @param mixed $result_class string which specifies which result class to use
+ * @param mixed $result_wrap_class string which specifies which class to wrap results in
+ * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure
+ * @access public
+ */
+ function executeStoredProc($name, $params = null, $types = null, $result_class = true, $result_wrap_class = false)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ $query = 'SELECT * FROM '.$name;
+ $query .= $params ? '('.implode(', ', $params).')' : '()';
+ return $db->query($query, $types, $result_class, $result_wrap_class);
+ }
+ // }}}
+ // {{{ unixtimestamp()
+
+ /**
+ * return string to call a function to get the unix timestamp from a iso timestamp
+ *
+ * @param string $expression
+ *
+ * @return string to call a variable with the timestamp
+ * @access public
+ */
+ function unixtimestamp($expression)
+ {
+ return 'EXTRACT(EPOCH FROM DATE_TRUNC(\'seconds\', CAST ((' . $expression . ') AS TIMESTAMP)))';
+ }
+
+ // }}}
+ // {{{ substring()
+
+ /**
+ * return string to call a function to get a substring inside an SQL statement
+ *
+ * @return string to call a function to get a substring
+ * @access public
+ */
+ function substring($value, $position = 1, $length = null)
+ {
+ if (null !== $length) {
+ return "SUBSTRING(CAST($value AS VARCHAR) FROM $position FOR $length)";
+ }
+ return "SUBSTRING(CAST($value AS VARCHAR) FROM $position)";
+ }
+
+ // }}}
+ // {{{ random()
+
+ /**
+ * return string to call a function to get random value inside an SQL statement
+ *
+ * @return return string to generate float between 0 and 1
+ * @access public
+ */
+ function random()
+ {
+ return 'RANDOM()';
+ }
+
+ // }}}
+}
+?>
\ No newline at end of file
diff -Nru owncloud-1.1+git20110209/3rdparty/MDB2/Driver/Function/sqlite.php owncloud-5.0.4debian/3rdparty/MDB2/Driver/Function/sqlite.php
--- owncloud-1.1+git20110209/3rdparty/MDB2/Driver/Function/sqlite.php 1970-01-01 00:00:00.000000000 +0000
+++ owncloud-5.0.4debian/3rdparty/MDB2/Driver/Function/sqlite.php 2013-04-10 17:29:58.000000000 +0000
@@ -0,0 +1,162 @@
+ |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+//
+
+require_once 'MDB2/Driver/Function/Common.php';
+
+/**
+ * MDB2 SQLite driver for the function modules
+ *
+ * @package MDB2
+ * @category Database
+ * @author Lukas Smith
+ */
+class MDB2_Driver_Function_sqlite extends MDB2_Driver_Function_Common
+{
+ // {{{ constructor
+
+ /**
+ * Constructor
+ */
+ function __construct($db_index)
+ {
+ parent::__construct($db_index);
+ // create all sorts of UDFs
+ }
+
+ // {{{ now()
+
+ /**
+ * Return string to call a variable with the current timestamp inside an SQL statement
+ * There are three special variables for current date and time.
+ *
+ * @return string to call a variable with the current timestamp
+ * @access public
+ */
+ function now($type = 'timestamp')
+ {
+ switch ($type) {
+ case 'time':
+ return 'time(\'now\')';
+ case 'date':
+ return 'date(\'now\')';
+ case 'timestamp':
+ default:
+ return 'datetime(\'now\')';
+ }
+ }
+
+ // }}}
+ // {{{ unixtimestamp()
+
+ /**
+ * return string to call a function to get the unix timestamp from a iso timestamp
+ *
+ * @param string $expression
+ *
+ * @return string to call a variable with the timestamp
+ * @access public
+ */
+ function unixtimestamp($expression)
+ {
+ return 'strftime("%s",'. $expression.', "utc")';
+ }
+
+ // }}}
+ // {{{ substring()
+
+ /**
+ * return string to call a function to get a substring inside an SQL statement
+ *
+ * @return string to call a function to get a substring
+ * @access public
+ */
+ function substring($value, $position = 1, $length = null)
+ {
+ if (null !== $length) {
+ return "substr($value, $position, $length)";
+ }
+ return "substr($value, $position, length($value))";
+ }
+
+ // }}}
+ // {{{ random()
+
+ /**
+ * return string to call a function to get random value inside an SQL statement
+ *
+ * @return return string to generate float between 0 and 1
+ * @access public
+ */
+ function random()
+ {
+ return '((RANDOM()+2147483648)/4294967296)';
+ }
+
+ // }}}
+ // {{{ replace()
+
+ /**
+ * return string to call a function to get a replacement inside an SQL statement.
+ *
+ * @return string to call a function to get a replace
+ * @access public
+ */
+ function replace($str, $from_str, $to_str)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ $error = $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+ 'method not implemented', __FUNCTION__);
+ return $error;
+ }
+
+ // }}}
+}
+?>
diff -Nru owncloud-1.1+git20110209/3rdparty/MDB2/Driver/Function/sqlsrv.php owncloud-5.0.4debian/3rdparty/MDB2/Driver/Function/sqlsrv.php
--- owncloud-1.1+git20110209/3rdparty/MDB2/Driver/Function/sqlsrv.php 1970-01-01 00:00:00.000000000 +0000
+++ owncloud-5.0.4debian/3rdparty/MDB2/Driver/Function/sqlsrv.php 2013-04-10 17:29:58.000000000 +0000
@@ -0,0 +1,189 @@
+ |
+// +----------------------------------------------------------------------+
+
+require_once 'MDB2/Driver/Function/Common.php';
+
+// {{{ class MDB2_Driver_Function_sqlsrv
+/**
+ * MDB2 MSSQL driver for the function modules
+ *
+ * @package MDB2
+ * @category Database
+ */
+class MDB2_Driver_Function_sqlsrv extends MDB2_Driver_Function_Common
+{
+ // {{{ executeStoredProc()
+
+ /**
+ * Execute a stored procedure and return any results
+ *
+ * @param string $name string that identifies the function to execute
+ * @param mixed $params array that contains the paramaters to pass the stored proc
+ * @param mixed $types array that contains the types of the columns in
+ * the result set
+ * @param mixed $result_class string which specifies which result class to use
+ * @param mixed $result_wrap_class string which specifies which class to wrap results in
+ * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure
+ * @access public
+ */
+ function executeStoredProc($name, $params = null, $types = null, $result_class = true, $result_wrap_class = false)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ $query = 'EXECUTE '.$name;
+ $query .= $params ? ' '.implode(', ', $params) : '';
+ return $db->query($query, $types, $result_class, $result_wrap_class);
+ }
+
+ // }}}
+ // {{{ now()
+
+ /**
+ * Return string to call a variable with the current timestamp inside an SQL statement
+ * There are three special variables for current date and time:
+ * - CURRENT_TIMESTAMP (date and time, TIMESTAMP type)
+ * - CURRENT_DATE (date, DATE type)
+ * - CURRENT_TIME (time, TIME type)
+ *
+ * @return string to call a variable with the current timestamp
+ * @access public
+ */
+ function now($type = 'timestamp')
+ {
+ switch ($type) {
+ case 'time':
+ case 'date':
+ case 'timestamp':
+ default:
+ return 'GETDATE()';
+ }
+ }
+
+ // }}}
+ // {{{ unixtimestamp()
+
+ /**
+ * return string to call a function to get the unix timestamp from a iso timestamp
+ *
+ * @param string $expression
+ *
+ * @return string to call a variable with the timestamp
+ * @access public
+ */
+ function unixtimestamp($expression)
+ {
+ return 'DATEDIFF(second, \'19700101\', '. $expression.') + DATEDIFF(second, GETDATE(), GETUTCDATE())';
+ }
+
+ // }}}
+ // {{{ substring()
+
+ /**
+ * return string to call a function to get a substring inside an SQL statement
+ *
+ * @return string to call a function to get a substring
+ * @access public
+ */
+ function substring($value, $position = 1, $length = null)
+ {
+ if (null !== $length) {
+ return "SUBSTRING($value, $position, $length)";
+ }
+ return "SUBSTRING($value, $position, LEN($value) - $position + 1)";
+ }
+
+ // }}}
+ // {{{ concat()
+
+ /**
+ * Returns string to concatenate two or more string parameters
+ *
+ * @param string $value1
+ * @param string $value2
+ * @param string $values...
+ * @return string to concatenate two strings
+ * @access public
+ **/
+ function concat($value1, $value2)
+ {
+ $args = func_get_args();
+ return "(".implode(' + ', $args).")";
+ }
+
+ // }}}
+ // {{{ length()
+
+ /**
+ * return string to call a function to get the length of a string expression
+ *
+ * @param string $expression
+ * @return return string to get the string expression length
+ * @access public
+ */
+ function length($expression)
+ {
+ return "LEN($expression)";
+ }
+
+ // }}}
+ // {{{ guid()
+
+ /**
+ * Returns global unique identifier
+ *
+ * @return string to get global unique identifier
+ * @access public
+ */
+ function guid()
+ {
+ return 'NEWID()';
+ }
+
+ // }}}
+}
+// }}}
+?>
\ No newline at end of file
diff -Nru owncloud-1.1+git20110209/3rdparty/MDB2/Driver/Manager/Common.php owncloud-5.0.4debian/3rdparty/MDB2/Driver/Manager/Common.php
--- owncloud-1.1+git20110209/3rdparty/MDB2/Driver/Manager/Common.php 1970-01-01 00:00:00.000000000 +0000
+++ owncloud-5.0.4debian/3rdparty/MDB2/Driver/Manager/Common.php 2013-04-10 17:29:58.000000000 +0000
@@ -0,0 +1,1038 @@
+ |
+// | Lorenzo Alberton |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+//
+
+/**
+ * @package MDB2
+ * @category Database
+ * @author Lukas Smith
+ * @author Lorenzo Alberton
+ */
+
+/**
+ * Base class for the management modules that is extended by each MDB2 driver
+ *
+ * To load this module in the MDB2 object:
+ * $mdb->loadModule('Manager');
+ *
+ * @package MDB2
+ * @category Database
+ * @author Lukas Smith
+ */
+class MDB2_Driver_Manager_Common extends MDB2_Module_Common
+{
+ // {{{ splitTableSchema()
+
+ /**
+ * Split the "[owner|schema].table" notation into an array
+ *
+ * @param string $table [schema and] table name
+ *
+ * @return array array(schema, table)
+ * @access private
+ */
+ function splitTableSchema($table)
+ {
+ $ret = array();
+ if (strpos($table, '.') !== false) {
+ return explode('.', $table);
+ }
+ return array(null, $table);
+ }
+
+ // }}}
+ // {{{ getFieldDeclarationList()
+
+ /**
+ * Get declaration of a number of field in bulk
+ *
+ * @param array $fields a multidimensional associative array.
+ * The first dimension determines the field name, while the second
+ * dimension is keyed with the name of the properties
+ * of the field being declared as array indexes. Currently, the types
+ * of supported field properties are as follows:
+ *
+ * default
+ * Boolean value to be used as default for this field.
+ *
+ * notnull
+ * Boolean flag that indicates whether this field is constrained
+ * to not be set to null.
+ *
+ * @return mixed string on success, a MDB2 error on failure
+ * @access public
+ */
+ function getFieldDeclarationList($fields)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ if (!is_array($fields) || empty($fields)) {
+ return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
+ 'missing any fields', __FUNCTION__);
+ }
+ foreach ($fields as $field_name => $field) {
+ $query = $db->getDeclaration($field['type'], $field_name, $field);
+ if (PEAR::isError($query)) {
+ return $query;
+ }
+ $query_fields[] = $query;
+ }
+ return implode(', ', $query_fields);
+ }
+
+ // }}}
+ // {{{ _fixSequenceName()
+
+ /**
+ * Removes any formatting in an sequence name using the 'seqname_format' option
+ *
+ * @param string $sqn string that containts name of a potential sequence
+ * @param bool $check if only formatted sequences should be returned
+ * @return string name of the sequence with possible formatting removed
+ * @access protected
+ */
+ function _fixSequenceName($sqn, $check = false)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ $seq_pattern = '/^'.preg_replace('/%s/', '([a-z0-9_]+)', $db->options['seqname_format']).'$/i';
+ $seq_name = preg_replace($seq_pattern, '\\1', $sqn);
+ if ($seq_name && !strcasecmp($sqn, $db->getSequenceName($seq_name))) {
+ return $seq_name;
+ }
+ if ($check) {
+ return false;
+ }
+ return $sqn;
+ }
+
+ // }}}
+ // {{{ _fixIndexName()
+
+ /**
+ * Removes any formatting in an index name using the 'idxname_format' option
+ *
+ * @param string $idx string that containts name of anl index
+ * @return string name of the index with eventual formatting removed
+ * @access protected
+ */
+ function _fixIndexName($idx)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ $idx_pattern = '/^'.preg_replace('/%s/', '([a-z0-9_]+)', $db->options['idxname_format']).'$/i';
+ $idx_name = preg_replace($idx_pattern, '\\1', $idx);
+ if ($idx_name && !strcasecmp($idx, $db->getIndexName($idx_name))) {
+ return $idx_name;
+ }
+ return $idx;
+ }
+
+ // }}}
+ // {{{ createDatabase()
+
+ /**
+ * create a new database
+ *
+ * @param string $name name of the database that should be created
+ * @param array $options array with charset, collation info
+ *
+ * @return mixed MDB2_OK on success, a MDB2 error on failure
+ * @access public
+ */
+ function createDatabase($database, $options = array())
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+ 'method not implemented', __FUNCTION__);
+ }
+
+ // }}}
+ // {{{ alterDatabase()
+
+ /**
+ * alter an existing database
+ *
+ * @param string $name name of the database that should be created
+ * @param array $options array with charset, collation info
+ *
+ * @return mixed MDB2_OK on success, a MDB2 error on failure
+ * @access public
+ */
+ function alterDatabase($database, $options = array())
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+ 'method not implemented', __FUNCTION__);
+ }
+
+ // }}}
+ // {{{ dropDatabase()
+
+ /**
+ * drop an existing database
+ *
+ * @param string $name name of the database that should be dropped
+ * @return mixed MDB2_OK on success, a MDB2 error on failure
+ * @access public
+ */
+ function dropDatabase($database)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+ 'method not implemented', __FUNCTION__);
+ }
+
+ // }}}
+ // {{{ _getCreateTableQuery()
+
+ /**
+ * Create a basic SQL query for a new table creation
+ *
+ * @param string $name Name of the database that should be created
+ * @param array $fields Associative array that contains the definition of each field of the new table
+ * @param array $options An associative array of table options
+ *
+ * @return mixed string (the SQL query) on success, a MDB2 error on failure
+ * @see createTable()
+ */
+ function _getCreateTableQuery($name, $fields, $options = array())
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ if (!$name) {
+ return $db->raiseError(MDB2_ERROR_CANNOT_CREATE, null, null,
+ 'no valid table name specified', __FUNCTION__);
+ }
+ if (empty($fields)) {
+ return $db->raiseError(MDB2_ERROR_CANNOT_CREATE, null, null,
+ 'no fields specified for table "'.$name.'"', __FUNCTION__);
+ }
+ $query_fields = $this->getFieldDeclarationList($fields);
+ if (PEAR::isError($query_fields)) {
+ return $query_fields;
+ }
+ if (!empty($options['primary'])) {
+ $query_fields.= ', PRIMARY KEY ('.implode(', ', array_keys($options['primary'])).')';
+ }
+
+ $name = $db->quoteIdentifier($name, true);
+ $result = 'CREATE ';
+ if (!empty($options['temporary'])) {
+ $result .= $this->_getTemporaryTableQuery();
+ }
+ $result .= " TABLE $name ($query_fields)";
+ return $result;
+ }
+
+ // }}}
+ // {{{ _getTemporaryTableQuery()
+
+ /**
+ * A method to return the required SQL string that fits between CREATE ... TABLE
+ * to create the table as a temporary table.
+ *
+ * Should be overridden in driver classes to return the correct string for the
+ * specific database type.
+ *
+ * The default is to return the string "TEMPORARY" - this will result in a
+ * SQL error for any database that does not support temporary tables, or that
+ * requires a different SQL command from "CREATE TEMPORARY TABLE".
+ *
+ * @return string The string required to be placed between "CREATE" and "TABLE"
+ * to generate a temporary table, if possible.
+ */
+ function _getTemporaryTableQuery()
+ {
+ return 'TEMPORARY';
+ }
+
+ // }}}
+ // {{{ createTable()
+
+ /**
+ * create a new table
+ *
+ * @param string $name Name of the database that should be created
+ * @param array $fields Associative array that contains the definition of each field of the new table
+ * The indexes of the array entries are the names of the fields of the table an
+ * the array entry values are associative arrays like those that are meant to be
+ * passed with the field definitions to get[Type]Declaration() functions.
+ * array(
+ * 'id' => array(
+ * 'type' => 'integer',
+ * 'unsigned' => 1
+ * 'notnull' => 1
+ * 'default' => 0
+ * ),
+ * 'name' => array(
+ * 'type' => 'text',
+ * 'length' => 12
+ * ),
+ * 'password' => array(
+ * 'type' => 'text',
+ * 'length' => 12
+ * )
+ * );
+ * @param array $options An associative array of table options:
+ * array(
+ * 'comment' => 'Foo',
+ * 'temporary' => true|false,
+ * );
+ * @return mixed MDB2_OK on success, a MDB2 error on failure
+ * @access public
+ */
+ function createTable($name, $fields, $options = array())
+ {
+ $query = $this->_getCreateTableQuery($name, $fields, $options);
+ if (PEAR::isError($query)) {
+ return $query;
+ }
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+ $result = $db->exec($query);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+ return MDB2_OK;
+ }
+
+ // }}}
+ // {{{ dropTable()
+
+ /**
+ * drop an existing table
+ *
+ * @param string $name name of the table that should be dropped
+ * @return mixed MDB2_OK on success, a MDB2 error on failure
+ * @access public
+ */
+ function dropTable($name)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ $name = $db->quoteIdentifier($name, true);
+ $result = $db->exec("DROP TABLE $name");
+ if (MDB2::isError($result)) {
+ return $result;
+ }
+ return MDB2_OK;
+ }
+
+ // }}}
+ // {{{ truncateTable()
+
+ /**
+ * Truncate an existing table (if the TRUNCATE TABLE syntax is not supported,
+ * it falls back to a DELETE FROM TABLE query)
+ *
+ * @param string $name name of the table that should be truncated
+ * @return mixed MDB2_OK on success, a MDB2 error on failure
+ * @access public
+ */
+ function truncateTable($name)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ $name = $db->quoteIdentifier($name, true);
+ $result = $db->exec("DELETE FROM $name");
+ if (MDB2::isError($result)) {
+ return $result;
+ }
+ return MDB2_OK;
+ }
+
+ // }}}
+ // {{{ vacuum()
+
+ /**
+ * Optimize (vacuum) all the tables in the db (or only the specified table)
+ * and optionally run ANALYZE.
+ *
+ * @param string $table table name (all the tables if empty)
+ * @param array $options an array with driver-specific options:
+ * - timeout [int] (in seconds) [mssql-only]
+ * - analyze [boolean] [pgsql and mysql]
+ * - full [boolean] [pgsql-only]
+ * - freeze [boolean] [pgsql-only]
+ *
+ * @return mixed MDB2_OK success, a MDB2 error on failure
+ * @access public
+ */
+ function vacuum($table = null, $options = array())
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+ 'method not implemented', __FUNCTION__);
+ }
+
+ // }}}
+ // {{{ alterTable()
+
+ /**
+ * alter an existing table
+ *
+ * @param string $name name of the table that is intended to be changed.
+ * @param array $changes associative array that contains the details of each type
+ * of change that is intended to be performed. The types of
+ * changes that are currently supported are defined as follows:
+ *
+ * name
+ *
+ * New name for the table.
+ *
+ * add
+ *
+ * Associative array with the names of fields to be added as
+ * indexes of the array. The value of each entry of the array
+ * should be set to another associative array with the properties
+ * of the fields to be added. The properties of the fields should
+ * be the same as defined by the MDB2 parser.
+ *
+ *
+ * remove
+ *
+ * Associative array with the names of fields to be removed as indexes
+ * of the array. Currently the values assigned to each entry are ignored.
+ * An empty array should be used for future compatibility.
+ *
+ * rename
+ *
+ * Associative array with the names of fields to be renamed as indexes
+ * of the array. The value of each entry of the array should be set to
+ * another associative array with the entry named name with the new
+ * field name and the entry named Declaration that is expected to contain
+ * the portion of the field declaration already in DBMS specific SQL code
+ * as it is used in the CREATE TABLE statement.
+ *
+ * change
+ *
+ * Associative array with the names of the fields to be changed as indexes
+ * of the array. Keep in mind that if it is intended to change either the
+ * name of a field and any other properties, the change array entries
+ * should have the new names of the fields as array indexes.
+ *
+ * The value of each entry of the array should be set to another associative
+ * array with the properties of the fields to that are meant to be changed as
+ * array entries. These entries should be assigned to the new values of the
+ * respective properties. The properties of the fields should be the same
+ * as defined by the MDB2 parser.
+ *
+ * Example
+ * array(
+ * 'name' => 'userlist',
+ * 'add' => array(
+ * 'quota' => array(
+ * 'type' => 'integer',
+ * 'unsigned' => 1
+ * )
+ * ),
+ * 'remove' => array(
+ * 'file_limit' => array(),
+ * 'time_limit' => array()
+ * ),
+ * 'change' => array(
+ * 'name' => array(
+ * 'length' => '20',
+ * 'definition' => array(
+ * 'type' => 'text',
+ * 'length' => 20,
+ * ),
+ * )
+ * ),
+ * 'rename' => array(
+ * 'sex' => array(
+ * 'name' => 'gender',
+ * 'definition' => array(
+ * 'type' => 'text',
+ * 'length' => 1,
+ * 'default' => 'M',
+ * ),
+ * )
+ * )
+ * )
+ *
+ * @param boolean $check indicates whether the function should just check if the DBMS driver
+ * can perform the requested table alterations if the value is true or
+ * actually perform them otherwise.
+ * @access public
+ *
+ * @return mixed MDB2_OK on success, a MDB2 error on failure
+ */
+ function alterTable($name, $changes, $check)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+ 'method not implemented', __FUNCTION__);
+ }
+
+ // }}}
+ // {{{ listDatabases()
+
+ /**
+ * list all databases
+ *
+ * @return mixed array of database names on success, a MDB2 error on failure
+ * @access public
+ */
+ function listDatabases()
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+ 'method not implementedd', __FUNCTION__);
+ }
+
+ // }}}
+ // {{{ listUsers()
+
+ /**
+ * list all users
+ *
+ * @return mixed array of user names on success, a MDB2 error on failure
+ * @access public
+ */
+ function listUsers()
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+ 'method not implemented', __FUNCTION__);
+ }
+
+ // }}}
+ // {{{ listViews()
+
+ /**
+ * list all views in the current database
+ *
+ * @param string database, the current is default
+ * NB: not all the drivers can get the view names from
+ * a database other than the current one
+ * @return mixed array of view names on success, a MDB2 error on failure
+ * @access public
+ */
+ function listViews($database = null)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+ 'method not implemented', __FUNCTION__);
+ }
+
+ // }}}
+ // {{{ listTableViews()
+
+ /**
+ * list the views in the database that reference a given table
+ *
+ * @param string table for which all referenced views should be found
+ * @return mixed array of view names on success, a MDB2 error on failure
+ * @access public
+ */
+ function listTableViews($table)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+ 'method not implemented', __FUNCTION__);
+ }
+
+ // }}}
+ // {{{ listTableTriggers()
+
+ /**
+ * list all triggers in the database that reference a given table
+ *
+ * @param string table for which all referenced triggers should be found
+ * @return mixed array of trigger names on success, a MDB2 error on failure
+ * @access public
+ */
+ function listTableTriggers($table = null)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+ 'method not implemented', __FUNCTION__);
+ }
+
+ // }}}
+ // {{{ listFunctions()
+
+ /**
+ * list all functions in the current database
+ *
+ * @return mixed array of function names on success, a MDB2 error on failure
+ * @access public
+ */
+ function listFunctions()
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+ 'method not implemented', __FUNCTION__);
+ }
+
+ // }}}
+ // {{{ listTables()
+
+ /**
+ * list all tables in the current database
+ *
+ * @param string database, the current is default.
+ * NB: not all the drivers can get the table names from
+ * a database other than the current one
+ * @return mixed array of table names on success, a MDB2 error on failure
+ * @access public
+ */
+ function listTables($database = null)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+ 'method not implemented', __FUNCTION__);
+ }
+
+ // }}}
+ // {{{ listTableFields()
+
+ /**
+ * list all fields in a table in the current database
+ *
+ * @param string $table name of table that should be used in method
+ * @return mixed array of field names on success, a MDB2 error on failure
+ * @access public
+ */
+ function listTableFields($table)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+ 'method not implemented', __FUNCTION__);
+ }
+
+ // }}}
+ // {{{ createIndex()
+
+ /**
+ * Get the stucture of a field into an array
+ *
+ * @param string $table name of the table on which the index is to be created
+ * @param string $name name of the index to be created
+ * @param array $definition associative array that defines properties of the index to be created.
+ * Currently, only one property named FIELDS is supported. This property
+ * is also an associative with the names of the index fields as array
+ * indexes. Each entry of this array is set to another type of associative
+ * array that specifies properties of the index that are specific to
+ * each field.
+ *
+ * Currently, only the sorting property is supported. It should be used
+ * to define the sorting direction of the index. It may be set to either
+ * ascending or descending.
+ *
+ * Not all DBMS support index sorting direction configuration. The DBMS
+ * drivers of those that do not support it ignore this property. Use the
+ * function supports() to determine whether the DBMS driver can manage indexes.
+ *
+ * Example
+ * array(
+ * 'fields' => array(
+ * 'user_name' => array(
+ * 'sorting' => 'ascending'
+ * ),
+ * 'last_login' => array()
+ * )
+ * )
+ * @return mixed MDB2_OK on success, a MDB2 error on failure
+ * @access public
+ */
+ function createIndex($table, $name, $definition)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ $table = $db->quoteIdentifier($table, true);
+ $name = $db->quoteIdentifier($db->getIndexName($name), true);
+ $query = "CREATE INDEX $name ON $table";
+ $fields = array();
+ foreach (array_keys($definition['fields']) as $field) {
+ $fields[] = $db->quoteIdentifier($field, true);
+ }
+ $query .= ' ('. implode(', ', $fields) . ')';
+ $result = $db->exec($query);
+ if (MDB2::isError($result)) {
+ return $result;
+ }
+ return MDB2_OK;
+ }
+
+ // }}}
+ // {{{ dropIndex()
+
+ /**
+ * drop existing index
+ *
+ * @param string $table name of table that should be used in method
+ * @param string $name name of the index to be dropped
+ * @return mixed MDB2_OK on success, a MDB2 error on failure
+ * @access public
+ */
+ function dropIndex($table, $name)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ $name = $db->quoteIdentifier($db->getIndexName($name), true);
+ $result = $db->exec("DROP INDEX $name");
+ if (MDB2::isError($result)) {
+ return $result;
+ }
+ return MDB2_OK;
+ }
+
+ // }}}
+ // {{{ listTableIndexes()
+
+ /**
+ * list all indexes in a table
+ *
+ * @param string $table name of table that should be used in method
+ * @return mixed array of index names on success, a MDB2 error on failure
+ * @access public
+ */
+ function listTableIndexes($table)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+ 'method not implemented', __FUNCTION__);
+ }
+
+ // }}}
+ // {{{ _getAdvancedFKOptions()
+
+ /**
+ * Return the FOREIGN KEY query section dealing with non-standard options
+ * as MATCH, INITIALLY DEFERRED, ON UPDATE, ...
+ *
+ * @param array $definition
+ * @return string
+ * @access protected
+ */
+ function _getAdvancedFKOptions($definition)
+ {
+ return '';
+ }
+
+ // }}}
+ // {{{ createConstraint()
+
+ /**
+ * create a constraint on a table
+ *
+ * @param string $table name of the table on which the constraint is to be created
+ * @param string $name name of the constraint to be created
+ * @param array $definition associative array that defines properties of the constraint to be created.
+ * The full structure of the array looks like this:
+ *
+ * @access public
+ */
+ function getTableConstraintDefinition($table, $index)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+ 'method not implemented', __FUNCTION__);
+ }
+
+ // }}}
+ // {{{ getSequenceDefinition()
+
+ /**
+ * Get the structure of a sequence into an array
+ *
+ * @param string $sequence name of sequence that should be used in method
+ * @return mixed data array on success, a MDB2 error on failure
+ * The returned array has this structure:
+ *
+ * array (
+ * [start] => n
+ * );
+ *
+ * @access public
+ */
+ function getSequenceDefinition($sequence)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ $start = $db->currId($sequence);
+ if (PEAR::isError($start)) {
+ return $start;
+ }
+ if ($db->supports('current_id')) {
+ $start++;
+ } else {
+ $db->warnings[] = 'database does not support getting current
+ sequence value, the sequence value was incremented';
+ }
+ $definition = array();
+ if ($start != 1) {
+ $definition = array('start' => $start);
+ }
+ return $definition;
+ }
+
+ // }}}
+ // {{{ getTriggerDefinition()
+
+ /**
+ * Get the structure of a trigger into an array
+ *
+ * EXPERIMENTAL
+ *
+ * WARNING: this function is experimental and may change the returned value
+ * at any time until labelled as non-experimental
+ *
+ * @param string $trigger name of trigger that should be used in method
+ * @return mixed data array on success, a MDB2 error on failure
+ * The returned array has this structure:
+ *
+ * The oci8 driver also returns a [when_clause] index.
+ * @access public
+ */
+ function getTriggerDefinition($trigger)
+ {
+ $db = $this->getDBInstance();
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+ 'method not implemented', __FUNCTION__);
+ }
+
+ // }}}
+ // {{{ tableInfo()
+
+ /**
+ * Returns information about a table or a result set
+ *
+ * The format of the resulting array depends on which $mode
+ * you select. The sample output below is based on this query:
+ *
+ * SELECT tblFoo.fldID, tblFoo.fldPhone, tblBar.fldId
+ * FROM tblFoo
+ * JOIN tblBar ON tblFoo.fldId = tblBar.fldId
+ *
In addition to the information found in the default output,
+ * a notation of the number of columns is provided by the
+ * num_fields element while the order
+ * 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.
+ *
+ *
If a result set has identical field names, the last one is
+ * used.
Similar to MDB2_TABLEINFO_ORDER 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.
+ *
+ * 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:
+ *
$eol";
+ if ($output) {
+ call_user_func($output, $buffer);
+ } else {
+ fwrite($fp, $buffer);
+ }
+
+ if (isset($sequences[$table_name])) {
+ foreach ($sequences[$table_name] as $sequence) {
+ $result = $this->dumpSequence($database_definition['sequences'][$sequence],
+ $sequence, $eol, $dump);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+
+ if ($output) {
+ call_user_func($output, $result);
+ } else {
+ fwrite($fp, $result);
+ }
+ }
+ }
+ }
+ }
+
+ if (isset($sequences[''])) {
+ foreach ($sequences[''] as $sequence) {
+ $result = $this->dumpSequence($database_definition['sequences'][$sequence],
+ $sequence, $eol, $dump);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+
+ if ($output) {
+ call_user_func($output, $result);
+ } else {
+ fwrite($fp, $result);
+ }
+ }
+ }
+
+ $buffer = "$eol$eol";
+ if ($output) {
+ call_user_func($output, $buffer);
+ } else {
+ fwrite($fp, $buffer);
+ fclose($fp);
+ }
+
+ return MDB2_OK;
+ }
+
+ // }}}
+ // {{{ writeExpression()
+
+ /**
+ * Dumps the structure of an element. Elements can be value, column,
+ * function or expression.
+ *
+ * @param array $element multi dimensional array that represents the parsed element
+ * of a DML instruction.
+ * @param integer $offset base indentation width
+ * @param array $arguments associative array that takes pairs of tag
+ * names and values that define dump options.
+ *
+ * @return string
+ *
+ * @access public
+ * @see MDB2_Schema_Writer::dumpDatabase()
+ */
+ function writeExpression($element, $offset = 0, $arguments = null)
+ {
+ $eol = isset($arguments['end_of_line']) ? $arguments['end_of_line'] : "\n";
+ $str = '';
+
+ $indent = str_repeat(' ', $offset);
+ $noffset = $offset + 1;
+
+ switch ($element['type']) {
+ case 'value':
+ $str .= "$indent".$this->_escapeSpecialChars($element['data'])."$eol";
+ break;
+ case 'column':
+ $str .= "$indent".$this->_escapeSpecialChars($element['data'])."$eol";
+ break;
+ case 'function':
+ $str .= "$indent$eol$indent ".$this->_escapeSpecialChars($element['data']['name'])."$eol";
+
+ if (!empty($element['data']['arguments'])
+ && is_array($element['data']['arguments'])
+ ) {
+ foreach ($element['data']['arguments'] as $v) {
+ $str .= $this->writeExpression($v, $noffset, $arguments);
+ }
+ }
+
+ $str .= "$indent$eol";
+ break;
+ case 'expression':
+ $str .= "$indent$eol";
+ $str .= $this->writeExpression($element['data']['operants'][0], $noffset, $arguments);
+ $str .= "$indent ".$element['data']['operator']."$eol";
+ $str .= $this->writeExpression($element['data']['operants'][1], $noffset, $arguments);
+ $str .= "$indent$eol";
+ break;
+ }
+ return $str;
+ }
+
+ // }}}
+}
diff -Nru owncloud-1.1+git20110209/3rdparty/MDB2/Schema.php owncloud-5.0.4debian/3rdparty/MDB2/Schema.php
--- owncloud-1.1+git20110209/3rdparty/MDB2/Schema.php 1970-01-01 00:00:00.000000000 +0000
+++ owncloud-5.0.4debian/3rdparty/MDB2/Schema.php 2013-04-10 17:29:58.000000000 +0000
@@ -0,0 +1,2797 @@
+
+ * @author Igor Feghali
+ * @license BSD http://www.opensource.org/licenses/bsd-license.php
+ * @version SVN: $Id$
+ * @link http://pear.php.net/packages/MDB2_Schema
+ */
+
+require_once 'MDB2.php';
+
+define('MDB2_SCHEMA_DUMP_ALL', 0);
+define('MDB2_SCHEMA_DUMP_STRUCTURE', 1);
+define('MDB2_SCHEMA_DUMP_CONTENT', 2);
+
+/**
+ * If you add an error code here, make sure you also add a textual
+ * version of it in MDB2_Schema::errorMessage().
+ */
+
+define('MDB2_SCHEMA_ERROR', -1);
+define('MDB2_SCHEMA_ERROR_PARSE', -2);
+define('MDB2_SCHEMA_ERROR_VALIDATE', -3);
+define('MDB2_SCHEMA_ERROR_UNSUPPORTED', -4); // Driver does not support this function
+define('MDB2_SCHEMA_ERROR_INVALID', -5); // Invalid attribute value
+define('MDB2_SCHEMA_ERROR_WRITER', -6);
+
+/**
+ * The database manager is a class that provides a set of database
+ * management services like installing, altering and dumping the data
+ * structures of databases.
+ *
+ * @category Database
+ * @package MDB2_Schema
+ * @author Lukas Smith
+ * @license BSD http://www.opensource.org/licenses/bsd-license.php
+ * @link http://pear.php.net/packages/MDB2_Schema
+ */
+class MDB2_Schema extends PEAR
+{
+ // {{{ properties
+
+ var $db;
+
+ var $warnings = array();
+
+ var $options = array(
+ 'fail_on_invalid_names' => true,
+ 'dtd_file' => false,
+ 'valid_types' => array(),
+ 'force_defaults' => true,
+ 'parser' => 'MDB2_Schema_Parser',
+ 'writer' => 'MDB2_Schema_Writer',
+ 'validate' => 'MDB2_Schema_Validate',
+ 'drop_obsolete_objects' => false
+ );
+
+ // }}}
+ // {{{ apiVersion()
+
+ /**
+ * Return the MDB2 API version
+ *
+ * @return string the MDB2 API version number
+ * @access public
+ */
+ function apiVersion()
+ {
+ return '0.4.3';
+ }
+
+ // }}}
+ // {{{ arrayMergeClobber()
+
+ /**
+ * Clobbers two arrays together
+ *
+ * @param array $a1 array that should be clobbered
+ * @param array $a2 array that should be clobbered
+ *
+ * @return array|false array on success and false on error
+ *
+ * @access public
+ * @author kc@hireability.com
+ */
+ function arrayMergeClobber($a1, $a2)
+ {
+ if (!is_array($a1) || !is_array($a2)) {
+ return false;
+ }
+ foreach ($a2 as $key => $val) {
+ if (is_array($val) && array_key_exists($key, $a1) && is_array($a1[$key])) {
+ $a1[$key] = MDB2_Schema::arrayMergeClobber($a1[$key], $val);
+ } else {
+ $a1[$key] = $val;
+ }
+ }
+ return $a1;
+ }
+
+ // }}}
+ // {{{ resetWarnings()
+
+ /**
+ * reset the warning array
+ *
+ * @access public
+ * @return void
+ */
+ function resetWarnings()
+ {
+ $this->warnings = array();
+ }
+
+ // }}}
+ // {{{ getWarnings()
+
+ /**
+ * Get all warnings in reverse order
+ *
+ * This means that the last warning is the first element in the array
+ *
+ * @return array with warnings
+ * @access public
+ * @see resetWarnings()
+ */
+ function getWarnings()
+ {
+ return array_reverse($this->warnings);
+ }
+
+ // }}}
+ // {{{ setOption()
+
+ /**
+ * Sets the option for the db class
+ *
+ * @param string $option option name
+ * @param mixed $value value for the option
+ *
+ * @return bool|MDB2_Error MDB2_OK or error object
+ * @access public
+ */
+ function setOption($option, $value)
+ {
+ if (isset($this->options[$option])) {
+ if (is_null($value)) {
+ return $this->raiseError(MDB2_SCHEMA_ERROR, null, null,
+ 'may not set an option to value null');
+ }
+ $this->options[$option] = $value;
+ return MDB2_OK;
+ }
+ return $this->raiseError(MDB2_SCHEMA_ERROR_UNSUPPORTED, null, null,
+ "unknown option $option");
+ }
+
+ // }}}
+ // {{{ getOption()
+
+ /**
+ * returns the value of an option
+ *
+ * @param string $option option name
+ *
+ * @return mixed the option value or error object
+ * @access public
+ */
+ function getOption($option)
+ {
+ if (isset($this->options[$option])) {
+ return $this->options[$option];
+ }
+ return $this->raiseError(MDB2_SCHEMA_ERROR_UNSUPPORTED,
+ null, null, "unknown option $option");
+ }
+
+ // }}}
+ // {{{ factory()
+
+ /**
+ * Create a new MDB2 object for the specified database type
+ * type
+ *
+ * @param string|array|MDB2_Driver_Common &$db 'data source name', see the
+ * MDB2::parseDSN method for a description of the dsn format.
+ * Can also be specified as an array of the
+ * format returned by @see MDB2::parseDSN.
+ * Finally you can also pass an existing db object to be used.
+ * @param array $options An associative array of option names and their values.
+ *
+ * @return bool|MDB2_Error MDB2_OK or error object
+ * @access public
+ * @see MDB2::parseDSN
+ */
+ static function &factory(&$db, $options = array())
+ {
+ $obj = new MDB2_Schema();
+
+ $result = $obj->connect($db, $options);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+ return $obj;
+ }
+
+ // }}}
+ // {{{ connect()
+
+ /**
+ * Create a new MDB2 connection object and connect to the specified
+ * database
+ *
+ * @param string|array|MDB2_Driver_Common &$db 'data source name', see the
+ * MDB2::parseDSN method for a description of the dsn format.
+ * Can also be specified as an array of the
+ * format returned by MDB2::parseDSN.
+ * Finally you can also pass an existing db object to be used.
+ * @param array $options An associative array of option names and their values.
+ *
+ * @return bool|MDB2_Error MDB2_OK or error object
+ * @access public
+ * @see MDB2::parseDSN
+ */
+ function connect(&$db, $options = array())
+ {
+ $db_options = array();
+ if (is_array($options)) {
+ foreach ($options as $option => $value) {
+ if (array_key_exists($option, $this->options)) {
+ $result = $this->setOption($option, $value);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+ } else {
+ $db_options[$option] = $value;
+ }
+ }
+ }
+
+ $this->disconnect();
+ if (!MDB2::isConnection($db)) {
+ $db = MDB2::factory($db, $db_options);
+ }
+
+ if (PEAR::isError($db)) {
+ return $db;
+ }
+
+ $this->db = $db;
+ $this->db->loadModule('Datatype');
+ $this->db->loadModule('Manager');
+ $this->db->loadModule('Reverse');
+ $this->db->loadModule('Function');
+ if (empty($this->options['valid_types'])) {
+ $this->options['valid_types'] = $this->db->datatype->getValidTypes();
+ }
+
+ return MDB2_OK;
+ }
+
+ // }}}
+ // {{{ disconnect()
+
+ /**
+ * Log out and disconnect from the database.
+ *
+ * @access public
+ * @return void
+ */
+ function disconnect()
+ {
+ if (MDB2::isConnection($this->db)) {
+ $this->db->disconnect();
+ unset($this->db);
+ }
+ }
+
+ // }}}
+ // {{{ parseDatabaseDefinition()
+
+ /**
+ * Parse a database definition from a file or an array
+ *
+ * @param string|array $schema the database schema array or file name
+ * @param bool $skip_unreadable if non readable files should be skipped
+ * @param array $variables associative array that the defines the text string values
+ * that are meant to be used to replace the variables that are
+ * used in the schema description.
+ * @param bool $fail_on_invalid_names make function fail on invalid names
+ * @param array $structure database structure definition
+ *
+ * @access public
+ * @return array
+ */
+ function parseDatabaseDefinition($schema, $skip_unreadable = false, $variables = array(),
+ $fail_on_invalid_names = true, $structure = false)
+ {
+ $database_definition = false;
+ if (is_string($schema)) {
+ // if $schema is not readable then we just skip it
+ // and simply copy the $current_schema file to that file name
+ if (is_readable($schema)) {
+ $database_definition = $this->parseDatabaseDefinitionFile($schema, $variables, $fail_on_invalid_names, $structure);
+ }
+ } elseif (is_array($schema)) {
+ $database_definition = $schema;
+ }
+ if (!$database_definition && !$skip_unreadable) {
+ $database_definition = $this->raiseError(MDB2_SCHEMA_ERROR, null, null,
+ 'invalid data type of schema or unreadable data source');
+ }
+ return $database_definition;
+ }
+
+ // }}}
+ // {{{ parseDatabaseDefinitionFile()
+
+ /**
+ * Parse a database definition file by creating a schema format
+ * parser object and passing the file contents as parser input data stream.
+ *
+ * @param string $input_file the database schema file.
+ * @param array $variables associative array that the defines the text string values
+ * that are meant to be used to replace the variables that are
+ * used in the schema description.
+ * @param bool $fail_on_invalid_names make function fail on invalid names
+ * @param array $structure database structure definition
+ *
+ * @access public
+ * @return array
+ */
+ function parseDatabaseDefinitionFile($input_file, $variables = array(),
+ $fail_on_invalid_names = true, $structure = false)
+ {
+ $dtd_file = $this->options['dtd_file'];
+ if ($dtd_file) {
+ include_once 'XML/DTD/XmlValidator.php';
+ $dtd = new XML_DTD_XmlValidator;
+ if (!$dtd->isValid($dtd_file, $input_file)) {
+ return $this->raiseError(MDB2_SCHEMA_ERROR_PARSE, null, null, $dtd->getMessage());
+ }
+ }
+
+ $class_name = $this->options['parser'];
+
+ $result = MDB2::loadClass($class_name, $this->db->getOption('debug'));
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+
+ $max_identifiers_length = null;
+ if (isset($this->db->options['max_identifiers_length'])) {
+ $max_identifiers_length = $this->db->options['max_identifiers_length'];
+ }
+
+ $parser = new $class_name($variables, $fail_on_invalid_names, $structure,
+ $this->options['valid_types'], $this->options['force_defaults'],
+ $max_identifiers_length
+ );
+
+ $result = $parser->setInputFile($input_file);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+
+ $result = $parser->parse();
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+ if (PEAR::isError($parser->error)) {
+ return $parser->error;
+ }
+
+ return $parser->database_definition;
+ }
+
+ // }}}
+ // {{{ getDefinitionFromDatabase()
+
+ /**
+ * Attempt to reverse engineer a schema structure from an existing MDB2
+ * This method can be used if no xml schema file exists yet.
+ * The resulting xml schema file may need some manual adjustments.
+ *
+ * @return array|MDB2_Error array with definition or error object
+ * @access public
+ */
+ function getDefinitionFromDatabase()
+ {
+ $database = $this->db->database_name;
+ if (empty($database)) {
+ return $this->raiseError(MDB2_SCHEMA_ERROR_INVALID, null, null,
+ 'it was not specified a valid database name');
+ }
+
+ $class_name = $this->options['validate'];
+
+ $result = MDB2::loadClass($class_name, $this->db->getOption('debug'));
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+
+ $max_identifiers_length = null;
+ if (isset($this->db->options['max_identifiers_length'])) {
+ $max_identifiers_length = $this->db->options['max_identifiers_length'];
+ }
+
+ $val = new $class_name(
+ $this->options['fail_on_invalid_names'],
+ $this->options['valid_types'],
+ $this->options['force_defaults'],
+ $max_identifiers_length
+ );
+
+ $database_definition = array(
+ 'name' => $database,
+ 'create' => true,
+ 'overwrite' => false,
+ 'charset' => 'utf8',
+ 'description' => '',
+ 'comments' => '',
+ 'tables' => array(),
+ 'sequences' => array(),
+ );
+
+ $tables = $this->db->manager->listTables();
+ if (PEAR::isError($tables)) {
+ return $tables;
+ }
+
+ foreach ($tables as $table_name) {
+ $fields = $this->db->manager->listTableFields($table_name);
+ if (PEAR::isError($fields)) {
+ return $fields;
+ }
+
+ $database_definition['tables'][$table_name] = array(
+ 'was' => '',
+ 'description' => '',
+ 'comments' => '',
+ 'fields' => array(),
+ 'indexes' => array(),
+ 'constraints' => array(),
+ 'initialization' => array()
+ );
+
+ $table_definition = $database_definition['tables'][$table_name];
+ foreach ($fields as $field_name) {
+ $definition = $this->db->reverse->getTableFieldDefinition($table_name, $field_name);
+ if (PEAR::isError($definition)) {
+ return $definition;
+ }
+
+ if (!empty($definition[0]['autoincrement'])) {
+ $definition[0]['default'] = '0';
+ }
+
+ $table_definition['fields'][$field_name] = $definition[0];
+
+ $field_choices = count($definition);
+ if ($field_choices > 1) {
+ $warning = "There are $field_choices type choices in the table $table_name field $field_name (#1 is the default): ";
+
+ $field_choice_cnt = 1;
+
+ $table_definition['fields'][$field_name]['choices'] = array();
+ foreach ($definition as $field_choice) {
+ $table_definition['fields'][$field_name]['choices'][] = $field_choice;
+
+ $warning .= 'choice #'.($field_choice_cnt).': '.serialize($field_choice);
+ $field_choice_cnt++;
+ }
+ $this->warnings[] = $warning;
+ }
+
+ /**
+ * The first parameter is used to verify if there are duplicated
+ * fields which we can guarantee that won't happen when reverse engineering
+ */
+ $result = $val->validateField(array(), $table_definition['fields'][$field_name], $field_name);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+ }
+
+ $keys = array();
+
+ $indexes = $this->db->manager->listTableIndexes($table_name);
+ if (PEAR::isError($indexes)) {
+ return $indexes;
+ }
+
+ if (is_array($indexes)) {
+ foreach ($indexes as $index_name) {
+ $this->db->expectError(MDB2_ERROR_NOT_FOUND);
+ $definition = $this->db->reverse->getTableIndexDefinition($table_name, $index_name);
+ $this->db->popExpect();
+ if (PEAR::isError($definition)) {
+ if (PEAR::isError($definition, MDB2_ERROR_NOT_FOUND)) {
+ continue;
+ }
+ return $definition;
+ }
+
+ $keys[$index_name] = $definition;
+ }
+ }
+
+ $constraints = $this->db->manager->listTableConstraints($table_name);
+ if (PEAR::isError($constraints)) {
+ return $constraints;
+ }
+
+ if (is_array($constraints)) {
+ foreach ($constraints as $constraint_name) {
+ $this->db->expectError(MDB2_ERROR_NOT_FOUND);
+ $definition = $this->db->reverse->getTableConstraintDefinition($table_name, $constraint_name);
+ $this->db->popExpect();
+ if (PEAR::isError($definition)) {
+ if (PEAR::isError($definition, MDB2_ERROR_NOT_FOUND)) {
+ continue;
+ }
+ return $definition;
+ }
+
+ $keys[$constraint_name] = $definition;
+ }
+ }
+
+ foreach ($keys as $key_name => $definition) {
+ if (array_key_exists('foreign', $definition)
+ && $definition['foreign']
+ ) {
+ /**
+ * The first parameter is used to verify if there are duplicated
+ * foreign keys which we can guarantee that won't happen when reverse engineering
+ */
+ $result = $val->validateConstraint(array(), $definition, $key_name);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+
+ foreach ($definition['fields'] as $field_name => $field) {
+ /**
+ * The first parameter is used to verify if there are duplicated
+ * referencing fields which we can guarantee that won't happen when reverse engineering
+ */
+ $result = $val->validateConstraintField(array(), $field_name);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+
+ $definition['fields'][$field_name] = '';
+ }
+
+ foreach ($definition['references']['fields'] as $field_name => $field) {
+ /**
+ * The first parameter is used to verify if there are duplicated
+ * referenced fields which we can guarantee that won't happen when reverse engineering
+ */
+ $result = $val->validateConstraintReferencedField(array(), $field_name);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+
+ $definition['references']['fields'][$field_name] = '';
+ }
+
+ $table_definition['constraints'][$key_name] = $definition;
+ } else {
+ /**
+ * The first parameter is used to verify if there are duplicated
+ * indices which we can guarantee that won't happen when reverse engineering
+ */
+ $result = $val->validateIndex(array(), $definition, $key_name);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+
+ foreach ($definition['fields'] as $field_name => $field) {
+ /**
+ * The first parameter is used to verify if there are duplicated
+ * index fields which we can guarantee that won't happen when reverse engineering
+ */
+ $result = $val->validateIndexField(array(), $field, $field_name);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+
+ $definition['fields'][$field_name] = $field;
+ }
+
+ $table_definition['indexes'][$key_name] = $definition;
+ }
+ }
+
+ /**
+ * The first parameter is used to verify if there are duplicated
+ * tables which we can guarantee that won't happen when reverse engineering
+ */
+ $result = $val->validateTable(array(), $table_definition, $table_name);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+ $database_definition['tables'][$table_name]=$table_definition;
+
+ }
+
+ $sequences = $this->db->manager->listSequences();
+ if (PEAR::isError($sequences)) {
+ return $sequences;
+ }
+
+ if (is_array($sequences)) {
+ foreach ($sequences as $sequence_name) {
+ $definition = $this->db->reverse->getSequenceDefinition($sequence_name);
+ if (PEAR::isError($definition)) {
+ return $definition;
+ }
+ if (isset($database_definition['tables'][$sequence_name])
+ && isset($database_definition['tables'][$sequence_name]['indexes'])
+ ) {
+ foreach ($database_definition['tables'][$sequence_name]['indexes'] as $index) {
+ if (isset($index['primary']) && $index['primary']
+ && count($index['fields'] == 1)
+ ) {
+ $definition['on'] = array(
+ 'table' => $sequence_name,
+ 'field' => key($index['fields']),
+ );
+ break;
+ }
+ }
+ }
+
+ /**
+ * The first parameter is used to verify if there are duplicated
+ * sequences which we can guarantee that won't happen when reverse engineering
+ */
+ $result = $val->validateSequence(array(), $definition, $sequence_name);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+
+ $database_definition['sequences'][$sequence_name] = $definition;
+ }
+ }
+
+ $result = $val->validateDatabase($database_definition);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+
+ return $database_definition;
+ }
+
+ // }}}
+ // {{{ createTableIndexes()
+
+ /**
+ * A method to create indexes for an existing table
+ *
+ * @param string $table_name Name of the table
+ * @param array $indexes An array of indexes to be created
+ * @param boolean $overwrite If the table/index should be overwritten if it already exists
+ *
+ * @return mixed MDB2_Error if there is an error creating an index, MDB2_OK otherwise
+ * @access public
+ */
+ function createTableIndexes($table_name, $indexes, $overwrite = false)
+ {
+ if (!$this->db->supports('indexes')) {
+ $this->db->debug('Indexes are not supported', __FUNCTION__);
+ return MDB2_OK;
+ }
+
+ $errorcodes = array(MDB2_ERROR_UNSUPPORTED, MDB2_ERROR_NOT_CAPABLE);
+ foreach ($indexes as $index_name => $index) {
+
+ // Does the index already exist, and if so, should it be overwritten?
+ $create_index = true;
+ $this->db->expectError($errorcodes);
+ if (!empty($index['primary']) || !empty($index['unique'])) {
+ $current_indexes = $this->db->manager->listTableConstraints($table_name);
+ } else {
+ $current_indexes = $this->db->manager->listTableIndexes($table_name);
+ }
+
+ $this->db->popExpect();
+ if (PEAR::isError($current_indexes)) {
+ if (!MDB2::isError($current_indexes, $errorcodes)) {
+ return $current_indexes;
+ }
+ } elseif (is_array($current_indexes) && in_array($index_name, $current_indexes)) {
+ if (!$overwrite) {
+ $this->db->debug('Index already exists: '.$index_name, __FUNCTION__);
+ $create_index = false;
+ } else {
+ $this->db->debug('Preparing to overwrite index: '.$index_name, __FUNCTION__);
+
+ $this->db->expectError(MDB2_ERROR_NOT_FOUND);
+ if (!empty($index['primary']) || !empty($index['unique'])) {
+ $result = $this->db->manager->dropConstraint($table_name, $index_name);
+ } else {
+ $result = $this->db->manager->dropIndex($table_name, $index_name);
+ }
+ $this->db->popExpect();
+ if (PEAR::isError($result) && !MDB2::isError($result, MDB2_ERROR_NOT_FOUND)) {
+ return $result;
+ }
+ }
+ }
+
+ // Check if primary is being used and if it's supported
+ if (!empty($index['primary']) && !$this->db->supports('primary_key')) {
+
+ // Primary not supported so we fallback to UNIQUE and making the field NOT NULL
+ $index['unique'] = true;
+
+ $changes = array();
+
+ foreach ($index['fields'] as $field => $empty) {
+ $field_info = $this->db->reverse->getTableFieldDefinition($table_name, $field);
+ if (PEAR::isError($field_info)) {
+ return $field_info;
+ }
+ if (!$field_info[0]['notnull']) {
+ $changes['change'][$field] = $field_info[0];
+
+ $changes['change'][$field]['notnull'] = true;
+ }
+ }
+ if (!empty($changes)) {
+ $this->db->manager->alterTable($table_name, $changes, false);
+ }
+ }
+
+ // Should the index be created?
+ if ($create_index) {
+ if (!empty($index['primary']) || !empty($index['unique'])) {
+ $result = $this->db->manager->createConstraint($table_name, $index_name, $index);
+ } else {
+ $result = $this->db->manager->createIndex($table_name, $index_name, $index);
+ }
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+ }
+ }
+ return MDB2_OK;
+ }
+
+ // }}}
+ // {{{ createTableConstraints()
+
+ /**
+ * A method to create foreign keys for an existing table
+ *
+ * @param string $table_name Name of the table
+ * @param array $constraints An array of foreign keys to be created
+ * @param boolean $overwrite If the foreign key should be overwritten if it already exists
+ *
+ * @return mixed MDB2_Error if there is an error creating a foreign key, MDB2_OK otherwise
+ * @access public
+ */
+ function createTableConstraints($table_name, $constraints, $overwrite = false)
+ {
+ if (!$this->db->supports('indexes')) {
+ $this->db->debug('Indexes are not supported', __FUNCTION__);
+ return MDB2_OK;
+ }
+
+ $errorcodes = array(MDB2_ERROR_UNSUPPORTED, MDB2_ERROR_NOT_CAPABLE);
+ foreach ($constraints as $constraint_name => $constraint) {
+
+ // Does the foreign key already exist, and if so, should it be overwritten?
+ $create_constraint = true;
+ $this->db->expectError($errorcodes);
+ $current_constraints = $this->db->manager->listTableConstraints($table_name);
+ $this->db->popExpect();
+ if (PEAR::isError($current_constraints)) {
+ if (!MDB2::isError($current_constraints, $errorcodes)) {
+ return $current_constraints;
+ }
+ } elseif (is_array($current_constraints) && in_array($constraint_name, $current_constraints)) {
+ if (!$overwrite) {
+ $this->db->debug('Foreign key already exists: '.$constraint_name, __FUNCTION__);
+ $create_constraint = false;
+ } else {
+ $this->db->debug('Preparing to overwrite foreign key: '.$constraint_name, __FUNCTION__);
+ $result = $this->db->manager->dropConstraint($table_name, $constraint_name);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+ }
+ }
+
+ // Should the foreign key be created?
+ if ($create_constraint) {
+ $result = $this->db->manager->createConstraint($table_name, $constraint_name, $constraint);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+ }
+ }
+ return MDB2_OK;
+ }
+
+ // }}}
+ // {{{ createTable()
+
+ /**
+ * Create a table and inititialize the table if data is available
+ *
+ * @param string $table_name name of the table to be created
+ * @param array $table multi dimensional array that contains the
+ * structure and optional data of the table
+ * @param bool $overwrite if the table/index should be overwritten if it already exists
+ * @param array $options an array of options to be passed to the database specific driver
+ * version of MDB2_Driver_Manager_Common::createTable().
+ *
+ * @return bool|MDB2_Error MDB2_OK or error object
+ * @access public
+ */
+ function createTable($table_name, $table, $overwrite = false, $options = array())
+ {
+ $create = true;
+
+ $errorcodes = array(MDB2_ERROR_UNSUPPORTED, MDB2_ERROR_NOT_CAPABLE);
+
+ $this->db->expectError($errorcodes);
+
+ $tables = $this->db->manager->listTables();
+
+ $this->db->popExpect();
+ if (PEAR::isError($tables)) {
+ if (!MDB2::isError($tables, $errorcodes)) {
+ return $tables;
+ }
+ } elseif (is_array($tables) && in_array($table_name, $tables)) {
+ if (!$overwrite) {
+ $create = false;
+ $this->db->debug('Table already exists: '.$table_name, __FUNCTION__);
+ } else {
+ $result = $this->db->manager->dropTable($table_name);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+ $this->db->debug('Overwritting table: '.$table_name, __FUNCTION__);
+ }
+ }
+
+ if ($create) {
+ $result = $this->db->manager->createTable($table_name, $table['fields'], $options);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+ }
+
+ if (!empty($table['initialization']) && is_array($table['initialization'])) {
+ $result = $this->initializeTable($table_name, $table);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+ }
+
+ if (!empty($table['indexes']) && is_array($table['indexes'])) {
+ $result = $this->createTableIndexes($table_name, $table['indexes'], $overwrite);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+ }
+
+ if (!empty($table['constraints']) && is_array($table['constraints'])) {
+ $result = $this->createTableConstraints($table_name, $table['constraints'], $overwrite);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+ }
+
+ return MDB2_OK;
+ }
+
+ // }}}
+ // {{{ initializeTable()
+
+ /**
+ * Inititialize the table with data
+ *
+ * @param string $table_name name of the table
+ * @param array $table multi dimensional array that contains the
+ * structure and optional data of the table
+ *
+ * @return bool|MDB2_Error MDB2_OK or error object
+ * @access public
+ */
+ function initializeTable($table_name, $table)
+ {
+ $query_insertselect = 'INSERT INTO %s (%s) (SELECT %s FROM %s %s)';
+
+ $query_insert = 'INSERT INTO %s (%s) VALUES (%s)';
+ $query_update = 'UPDATE %s SET %s %s';
+ $query_delete = 'DELETE FROM %s %s';
+
+ $table_name = $this->db->quoteIdentifier($table_name, true);
+
+ $result = MDB2_OK;
+
+ $support_transactions = $this->db->supports('transactions');
+
+ foreach ($table['initialization'] as $instruction) {
+ $query = '';
+ switch ($instruction['type']) {
+ case 'insert':
+ if (!isset($instruction['data']['select'])) {
+ $data = $this->getInstructionFields($instruction['data'], $table['fields']);
+ if (!empty($data)) {
+ $fields = implode(', ', array_keys($data));
+ $values = implode(', ', array_values($data));
+
+ $query = sprintf($query_insert, $table_name, $fields, $values);
+ }
+ } else {
+ $data = $this->getInstructionFields($instruction['data']['select'], $table['fields']);
+ $where = $this->getInstructionWhere($instruction['data']['select'], $table['fields']);
+
+ $select_table_name = $this->db->quoteIdentifier($instruction['data']['select']['table'], true);
+ if (!empty($data)) {
+ $fields = implode(', ', array_keys($data));
+ $values = implode(', ', array_values($data));
+
+ $query = sprintf($query_insertselect, $table_name, $fields, $values, $select_table_name, $where);
+ }
+ }
+ break;
+ case 'update':
+ $data = $this->getInstructionFields($instruction['data'], $table['fields']);
+ $where = $this->getInstructionWhere($instruction['data'], $table['fields']);
+ if (!empty($data)) {
+ array_walk($data, array($this, 'buildFieldValue'));
+ $fields_values = implode(', ', $data);
+
+ $query = sprintf($query_update, $table_name, $fields_values, $where);
+ }
+ break;
+ case 'delete':
+ $where = $this->getInstructionWhere($instruction['data'], $table['fields']);
+ $query = sprintf($query_delete, $table_name, $where);
+ break;
+ }
+ if ($query) {
+ if ($support_transactions && PEAR::isError($res = $this->db->beginNestedTransaction())) {
+ return $res;
+ }
+
+ $result = $this->db->exec($query);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+
+ if ($support_transactions && PEAR::isError($res = $this->db->completeNestedTransaction())) {
+ return $res;
+ }
+ }
+ }
+ return $result;
+ }
+
+ // }}}
+ // {{{ buildFieldValue()
+
+ /**
+ * Appends the contents of second argument + '=' to the beginning of first
+ * argument.
+ *
+ * Used with array_walk() in initializeTable() for UPDATEs.
+ *
+ * @param string &$element value of array's element
+ * @param string $key key of array's element
+ *
+ * @return void
+ *
+ * @access public
+ * @see MDB2_Schema::initializeTable()
+ */
+ function buildFieldValue(&$element, $key)
+ {
+ $element = $key."=$element";
+ }
+
+ // }}}
+ // {{{ getExpression()
+
+ /**
+ * Generates a string that represents a value that would be associated
+ * with a column in a DML instruction.
+ *
+ * @param array $element multi dimensional array that contains the
+ * structure of the current DML instruction.
+ * @param array $fields_definition multi dimensional array that contains the
+ * definition for current table's fields
+ * @param string $type type of given field
+ *
+ * @return string
+ *
+ * @access public
+ * @see MDB2_Schema::getInstructionFields(), MDB2_Schema::getInstructionWhere()
+ */
+ function getExpression($element, $fields_definition = array(), $type = null)
+ {
+ $str = '';
+ switch ($element['type']) {
+ case 'null':
+ $str .= 'NULL';
+ break;
+ case 'value':
+ $str .= $this->db->quote($element['data'], $type);
+ break;
+ case 'column':
+ $str .= $this->db->quoteIdentifier($element['data'], true);
+ break;
+ case 'function':
+ $arguments = array();
+ if (!empty($element['data']['arguments'])
+ && is_array($element['data']['arguments'])
+ ) {
+ foreach ($element['data']['arguments'] as $v) {
+ $arguments[] = $this->getExpression($v, $fields_definition);
+ }
+ }
+ if (method_exists($this->db->function, $element['data']['name'])) {
+ $user_func = array(&$this->db->function, $element['data']['name']);
+
+ $str .= call_user_func_array($user_func, $arguments);
+ } else {
+ $str .= $element['data']['name'].'(';
+ $str .= implode(', ', $arguments);
+ $str .= ')';
+ }
+ break;
+ case 'expression':
+ $type0 = $type1 = null;
+ if ($element['data']['operants'][0]['type'] == 'column'
+ && array_key_exists($element['data']['operants'][0]['data'], $fields_definition)
+ ) {
+ $type0 = $fields_definition[$element['data']['operants'][0]['data']]['type'];
+ }
+
+ if ($element['data']['operants'][1]['type'] == 'column'
+ && array_key_exists($element['data']['operants'][1]['data'], $fields_definition)
+ ) {
+ $type1 = $fields_definition[$element['data']['operants'][1]['data']]['type'];
+ }
+
+ $str .= '(';
+ $str .= $this->getExpression($element['data']['operants'][0], $fields_definition, $type1);
+ $str .= $this->getOperator($element['data']['operator']);
+ $str .= $this->getExpression($element['data']['operants'][1], $fields_definition, $type0);
+ $str .= ')';
+ break;
+ }
+
+ return $str;
+ }
+
+ // }}}
+ // {{{ getOperator()
+
+ /**
+ * Returns the matching SQL operator
+ *
+ * @param string $op parsed descriptive operator
+ *
+ * @return string matching SQL operator
+ *
+ * @access public
+ * @static
+ * @see MDB2_Schema::getExpression()
+ */
+ function getOperator($op)
+ {
+ switch ($op) {
+ case 'PLUS':
+ return ' + ';
+ case 'MINUS':
+ return ' - ';
+ case 'TIMES':
+ return ' * ';
+ case 'DIVIDED':
+ return ' / ';
+ case 'EQUAL':
+ return ' = ';
+ case 'NOT EQUAL':
+ return ' != ';
+ case 'LESS THAN':
+ return ' < ';
+ case 'GREATER THAN':
+ return ' > ';
+ case 'LESS THAN OR EQUAL':
+ return ' <= ';
+ case 'GREATER THAN OR EQUAL':
+ return ' >= ';
+ default:
+ return ' '.$op.' ';
+ }
+ }
+
+ // }}}
+ // {{{ getInstructionFields()
+
+ /**
+ * Walks the parsed DML instruction array, field by field,
+ * storing them and their processed values inside a new array.
+ *
+ * @param array $instruction multi dimensional array that contains the
+ * structure of the current DML instruction.
+ * @param array $fields_definition multi dimensional array that contains the
+ * definition for current table's fields
+ *
+ * @return array array of strings in the form 'field_name' => 'value'
+ *
+ * @access public
+ * @static
+ * @see MDB2_Schema::initializeTable()
+ */
+ function getInstructionFields($instruction, $fields_definition = array())
+ {
+ $fields = array();
+ if (!empty($instruction['field']) && is_array($instruction['field'])) {
+ foreach ($instruction['field'] as $field) {
+ $field_name = $this->db->quoteIdentifier($field['name'], true);
+
+ $fields[$field_name] = $this->getExpression($field['group'], $fields_definition);
+ }
+ }
+ return $fields;
+ }
+
+ // }}}
+ // {{{ getInstructionWhere()
+
+ /**
+ * Translates the parsed WHERE expression of a DML instruction
+ * (array structure) to a SQL WHERE clause (string).
+ *
+ * @param array $instruction multi dimensional array that contains the
+ * structure of the current DML instruction.
+ * @param array $fields_definition multi dimensional array that contains the
+ * definition for current table's fields.
+ *
+ * @return string SQL WHERE clause
+ *
+ * @access public
+ * @static
+ * @see MDB2_Schema::initializeTable()
+ */
+ function getInstructionWhere($instruction, $fields_definition = array())
+ {
+ $where = '';
+ if (!empty($instruction['where'])) {
+ $where = 'WHERE '.$this->getExpression($instruction['where'], $fields_definition);
+ }
+ return $where;
+ }
+
+ // }}}
+ // {{{ createSequence()
+
+ /**
+ * Create a sequence
+ *
+ * @param string $sequence_name name of the sequence to be created
+ * @param array $sequence multi dimensional array that contains the
+ * structure and optional data of the table
+ * @param bool $overwrite if the sequence should be overwritten if it already exists
+ *
+ * @return bool|MDB2_Error MDB2_OK or error object
+ * @access public
+ */
+ function createSequence($sequence_name, $sequence, $overwrite = false)
+ {
+ if (!$this->db->supports('sequences')) {
+ $this->db->debug('Sequences are not supported', __FUNCTION__);
+ return MDB2_OK;
+ }
+
+ $errorcodes = array(MDB2_ERROR_UNSUPPORTED, MDB2_ERROR_NOT_CAPABLE);
+ $this->db->expectError($errorcodes);
+ $sequences = $this->db->manager->listSequences();
+ $this->db->popExpect();
+ if (PEAR::isError($sequences)) {
+ if (!MDB2::isError($sequences, $errorcodes)) {
+ return $sequences;
+ }
+ } elseif (is_array($sequence) && in_array($sequence_name, $sequences)) {
+ if (!$overwrite) {
+ $this->db->debug('Sequence already exists: '.$sequence_name, __FUNCTION__);
+ return MDB2_OK;
+ }
+
+ $result = $this->db->manager->dropSequence($sequence_name);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+ $this->db->debug('Overwritting sequence: '.$sequence_name, __FUNCTION__);
+ }
+
+ $start = 1;
+ $field = '';
+ if (!empty($sequence['on'])) {
+ $table = $sequence['on']['table'];
+ $field = $sequence['on']['field'];
+
+ $errorcodes = array(MDB2_ERROR_UNSUPPORTED, MDB2_ERROR_NOT_CAPABLE);
+ $this->db->expectError($errorcodes);
+ $tables = $this->db->manager->listTables();
+ $this->db->popExpect();
+ if (PEAR::isError($tables) && !MDB2::isError($tables, $errorcodes)) {
+ return $tables;
+ }
+
+ if (!PEAR::isError($tables) && is_array($tables) && in_array($table, $tables)) {
+ if ($this->db->supports('summary_functions')) {
+ $query = "SELECT MAX($field) FROM ".$this->db->quoteIdentifier($table, true);
+ } else {
+ $query = "SELECT $field FROM ".$this->db->quoteIdentifier($table, true)." ORDER BY $field DESC";
+ }
+ $start = $this->db->queryOne($query, 'integer');
+ if (PEAR::isError($start)) {
+ return $start;
+ }
+ ++$start;
+ } else {
+ $this->warnings[] = 'Could not sync sequence: '.$sequence_name;
+ }
+ } elseif (!empty($sequence['start']) && is_numeric($sequence['start'])) {
+ $start = $sequence['start'];
+ $table = '';
+ }
+
+ $result = $this->db->manager->createSequence($sequence_name, $start);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+
+ return MDB2_OK;
+ }
+
+ // }}}
+ // {{{ createDatabase()
+
+ /**
+ * Create a database space within which may be created database objects
+ * like tables, indexes and sequences. The implementation of this function
+ * is highly DBMS specific and may require special permissions to run
+ * successfully. Consult the documentation or the DBMS drivers that you
+ * use to be aware of eventual configuration requirements.
+ *
+ * @param array $database_definition multi dimensional array that contains the current definition
+ * @param array $options an array of options to be passed to the
+ * database specific driver version of
+ * MDB2_Driver_Manager_Common::createTable().
+ *
+ * @return bool|MDB2_Error MDB2_OK or error object
+ * @access public
+ */
+ function createDatabase($database_definition, $options = array())
+ {
+ if (!isset($database_definition['name']) || !$database_definition['name']) {
+ return $this->raiseError(MDB2_SCHEMA_ERROR_INVALID, null, null,
+ 'no valid database name specified');
+ }
+
+ $create = (isset($database_definition['create']) && $database_definition['create']);
+ $overwrite = (isset($database_definition['overwrite']) && $database_definition['overwrite']);
+
+ /**
+ *
+ * We need to clean up database name before any query to prevent
+ * database driver from using a inexistent database
+ *
+ */
+ $previous_database_name = $this->db->setDatabase('');
+
+ // Lower / Upper case the db name if the portability deems so.
+ if ($this->db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+ $func = $this->db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper';
+
+ $db_name = $func($database_definition['name']);
+ } else {
+ $db_name = $database_definition['name'];
+ }
+
+ if ($create) {
+
+ $dbExists = $this->db->databaseExists($db_name);
+ if (PEAR::isError($dbExists)) {
+ return $dbExists;
+ }
+
+ if ($dbExists && $overwrite) {
+ $this->db->expectError(MDB2_ERROR_CANNOT_DROP);
+ $result = $this->db->manager->dropDatabase($db_name);
+ $this->db->popExpect();
+ if (PEAR::isError($result) && !MDB2::isError($result, MDB2_ERROR_CANNOT_DROP)) {
+ return $result;
+ }
+ $dbExists = false;
+ $this->db->debug('Overwritting database: ' . $db_name, __FUNCTION__);
+ }
+
+ $dbOptions = array();
+ if (array_key_exists('charset', $database_definition)
+ && !empty($database_definition['charset'])) {
+ $dbOptions['charset'] = $database_definition['charset'];
+ }
+
+ if ($dbExists) {
+ $this->db->debug('Database already exists: ' . $db_name, __FUNCTION__);
+ if (!empty($dbOptions)) {
+ $errorcodes = array(MDB2_ERROR_UNSUPPORTED, MDB2_ERROR_NO_PERMISSION);
+ $this->db->expectError($errorcodes);
+ $result = $this->db->manager->alterDatabase($db_name, $dbOptions);
+ $this->db->popExpect();
+ if (PEAR::isError($result) && !MDB2::isError($result, $errorcodes)) {
+ return $result;
+ }
+ }
+ $create = false;
+ } else {
+ $this->db->expectError(MDB2_ERROR_UNSUPPORTED);
+ $result = $this->db->manager->createDatabase($db_name, $dbOptions);
+ $this->db->popExpect();
+ if (PEAR::isError($result) && !MDB2::isError($result, MDB2_ERROR_UNSUPPORTED)) {
+ return $result;
+ }
+ $this->db->debug('Creating database: ' . $db_name, __FUNCTION__);
+ }
+ }
+
+ $this->db->setDatabase($db_name);
+ if (($support_transactions = $this->db->supports('transactions'))
+ && PEAR::isError($result = $this->db->beginNestedTransaction())
+ ) {
+ return $result;
+ }
+
+ $created_objects = 0;
+ if (isset($database_definition['tables'])
+ && is_array($database_definition['tables'])
+ ) {
+ foreach ($database_definition['tables'] as $table_name => $table) {
+ $result = $this->createTable($table_name, $table, $overwrite, $options);
+ if (PEAR::isError($result)) {
+ break;
+ }
+ $created_objects++;
+ }
+ }
+ if (!PEAR::isError($result)
+ && isset($database_definition['sequences'])
+ && is_array($database_definition['sequences'])
+ ) {
+ foreach ($database_definition['sequences'] as $sequence_name => $sequence) {
+ $result = $this->createSequence($sequence_name, $sequence, false, $overwrite);
+
+ if (PEAR::isError($result)) {
+ break;
+ }
+ $created_objects++;
+ }
+ }
+
+ if ($support_transactions) {
+ $res = $this->db->completeNestedTransaction();
+ if (PEAR::isError($res)) {
+ $result = $this->raiseError(MDB2_SCHEMA_ERROR, null, null,
+ 'Could not end transaction ('.
+ $res->getMessage().' ('.$res->getUserinfo().'))');
+ }
+ } elseif (PEAR::isError($result) && $created_objects) {
+ $result = $this->raiseError(MDB2_SCHEMA_ERROR, null, null,
+ 'the database was only partially created ('.
+ $result->getMessage().' ('.$result->getUserinfo().'))');
+ }
+
+ $this->db->setDatabase($previous_database_name);
+
+ if (PEAR::isError($result) && $create
+ && PEAR::isError($result2 = $this->db->manager->dropDatabase($db_name))
+ ) {
+ if (!MDB2::isError($result2, MDB2_ERROR_UNSUPPORTED)) {
+ return $this->raiseError(MDB2_SCHEMA_ERROR, null, null,
+ 'Could not drop the created database after unsuccessful creation attempt ('.
+ $result2->getMessage().' ('.$result2->getUserinfo().'))');
+ }
+ }
+
+ return $result;
+ }
+
+ // }}}
+ // {{{ compareDefinitions()
+
+ /**
+ * Compare a previous definition with the currently parsed definition
+ *
+ * @param array $current_definition multi dimensional array that contains the current definition
+ * @param array $previous_definition multi dimensional array that contains the previous definition
+ *
+ * @return array|MDB2_Error array of changes on success, or a error object
+ * @access public
+ */
+ function compareDefinitions($current_definition, $previous_definition)
+ {
+ $changes = array();
+
+ if (!empty($current_definition['tables']) && is_array($current_definition['tables'])) {
+ $changes['tables'] = $defined_tables = array();
+ foreach ($current_definition['tables'] as $table_name => $table) {
+ $previous_tables = array();
+ if (!empty($previous_definition) && is_array($previous_definition)) {
+ $previous_tables = $previous_definition['tables'];
+ }
+ $change = $this->compareTableDefinitions($table_name, $table, $previous_tables, $defined_tables);
+ if (PEAR::isError($change)) {
+ return $change;
+ }
+ if (!empty($change)) {
+ $changes['tables'] = MDB2_Schema::arrayMergeClobber($changes['tables'], $change);
+ }
+ }
+ }
+ if (!empty($previous_definition['tables'])
+ && is_array($previous_definition['tables'])
+ ) {
+ foreach ($previous_definition['tables'] as $table_name => $table) {
+ if (empty($defined_tables[$table_name])) {
+ $changes['tables']['remove'][$table_name] = true;
+ }
+ }
+ }
+
+ if (!empty($current_definition['sequences']) && is_array($current_definition['sequences'])) {
+ $changes['sequences'] = $defined_sequences = array();
+ foreach ($current_definition['sequences'] as $sequence_name => $sequence) {
+ $previous_sequences = array();
+ if (!empty($previous_definition) && is_array($previous_definition)) {
+ $previous_sequences = $previous_definition['sequences'];
+ }
+
+ $change = $this->compareSequenceDefinitions($sequence_name,
+ $sequence,
+ $previous_sequences,
+ $defined_sequences);
+ if (PEAR::isError($change)) {
+ return $change;
+ }
+ if (!empty($change)) {
+ $changes['sequences'] = MDB2_Schema::arrayMergeClobber($changes['sequences'], $change);
+ }
+ }
+ }
+ if (!empty($previous_definition['sequences'])
+ && is_array($previous_definition['sequences'])
+ ) {
+ foreach ($previous_definition['sequences'] as $sequence_name => $sequence) {
+ if (empty($defined_sequences[$sequence_name])) {
+ $changes['sequences']['remove'][$sequence_name] = true;
+ }
+ }
+ }
+
+ return $changes;
+ }
+
+ // }}}
+ // {{{ compareTableFieldsDefinitions()
+
+ /**
+ * Compare a previous definition with the currently parsed definition
+ *
+ * @param string $table_name name of the table
+ * @param array $current_definition multi dimensional array that contains the current definition
+ * @param array $previous_definition multi dimensional array that contains the previous definition
+ *
+ * @return array|MDB2_Error array of changes on success, or a error object
+ * @access public
+ */
+ function compareTableFieldsDefinitions($table_name, $current_definition,
+ $previous_definition)
+ {
+ $changes = $defined_fields = array();
+
+ if (is_array($current_definition)) {
+ foreach ($current_definition as $field_name => $field) {
+ $was_field_name = $field['was'];
+ if (!empty($previous_definition[$field_name])
+ && (
+ (isset($previous_definition[$field_name]['was'])
+ && $previous_definition[$field_name]['was'] == $was_field_name)
+ || !isset($previous_definition[$was_field_name])
+ )) {
+ $was_field_name = $field_name;
+ }
+
+ if (!empty($previous_definition[$was_field_name])) {
+ if ($was_field_name != $field_name) {
+ $changes['rename'][$was_field_name] = array('name' => $field_name, 'definition' => $field);
+ }
+
+ if (!empty($defined_fields[$was_field_name])) {
+ return $this->raiseError(MDB2_SCHEMA_ERROR_INVALID, null, null,
+ 'the field "'.$was_field_name.
+ '" was specified for more than one field of table');
+ }
+
+ $defined_fields[$was_field_name] = true;
+
+ $change = $this->db->compareDefinition($field, $previous_definition[$was_field_name]);
+ if (PEAR::isError($change)) {
+ return $change;
+ }
+
+ if (!empty($change)) {
+ if (array_key_exists('default', $change)
+ && $change['default']
+ && !array_key_exists('default', $field)) {
+ $field['default'] = null;
+ }
+
+ $change['definition'] = $field;
+
+ $changes['change'][$field_name] = $change;
+ }
+ } else {
+ if ($field_name != $was_field_name) {
+ return $this->raiseError(MDB2_SCHEMA_ERROR_INVALID, null, null,
+ 'it was specified a previous field name ("'.
+ $was_field_name.'") for field "'.$field_name.'" of table "'.
+ $table_name.'" that does not exist');
+ }
+
+ $changes['add'][$field_name] = $field;
+ }
+ }
+ }
+
+ if (isset($previous_definition) && is_array($previous_definition)) {
+ foreach ($previous_definition as $field_previous_name => $field_previous) {
+ if (empty($defined_fields[$field_previous_name])) {
+ $changes['remove'][$field_previous_name] = true;
+ }
+ }
+ }
+
+ return $changes;
+ }
+
+ // }}}
+ // {{{ compareTableIndexesDefinitions()
+
+ /**
+ * Compare a previous definition with the currently parsed definition
+ *
+ * @param string $table_name name of the table
+ * @param array $current_definition multi dimensional array that contains the current definition
+ * @param array $previous_definition multi dimensional array that contains the previous definition
+ *
+ * @return array|MDB2_Error array of changes on success, or a error object
+ * @access public
+ */
+ function compareTableIndexesDefinitions($table_name, $current_definition,
+ $previous_definition)
+ {
+ $changes = $defined_indexes = array();
+
+ if (is_array($current_definition)) {
+ foreach ($current_definition as $index_name => $index) {
+ $was_index_name = $index['was'];
+ if (!empty($previous_definition[$index_name])
+ && isset($previous_definition[$index_name]['was'])
+ && $previous_definition[$index_name]['was'] == $was_index_name
+ ) {
+ $was_index_name = $index_name;
+ }
+ if (!empty($previous_definition[$was_index_name])) {
+ $change = array();
+ if ($was_index_name != $index_name) {
+ $change['name'] = $was_index_name;
+ }
+
+ if (!empty($defined_indexes[$was_index_name])) {
+ return $this->raiseError(MDB2_SCHEMA_ERROR_INVALID, null, null,
+ 'the index "'.$was_index_name.'" was specified for'.
+ ' more than one index of table "'.$table_name.'"');
+ }
+ $defined_indexes[$was_index_name] = true;
+
+ $previous_unique = array_key_exists('unique', $previous_definition[$was_index_name])
+ ? $previous_definition[$was_index_name]['unique'] : false;
+
+ $unique = array_key_exists('unique', $index) ? $index['unique'] : false;
+ if ($previous_unique != $unique) {
+ $change['unique'] = $unique;
+ }
+
+ $previous_primary = array_key_exists('primary', $previous_definition[$was_index_name])
+ ? $previous_definition[$was_index_name]['primary'] : false;
+
+ $primary = array_key_exists('primary', $index) ? $index['primary'] : false;
+ if ($previous_primary != $primary) {
+ $change['primary'] = $primary;
+ }
+
+ $defined_fields = array();
+ $previous_fields = $previous_definition[$was_index_name]['fields'];
+ if (!empty($index['fields']) && is_array($index['fields'])) {
+ foreach ($index['fields'] as $field_name => $field) {
+ if (!empty($previous_fields[$field_name])) {
+ $defined_fields[$field_name] = true;
+
+ $previous_sorting = array_key_exists('sorting', $previous_fields[$field_name])
+ ? $previous_fields[$field_name]['sorting'] : '';
+
+ $sorting = array_key_exists('sorting', $field) ? $field['sorting'] : '';
+ if ($previous_sorting != $sorting) {
+ $change['change'] = true;
+ }
+ } else {
+ $change['change'] = true;
+ }
+ }
+ }
+ if (isset($previous_fields) && is_array($previous_fields)) {
+ foreach ($previous_fields as $field_name => $field) {
+ if (empty($defined_fields[$field_name])) {
+ $change['change'] = true;
+ }
+ }
+ }
+ if (!empty($change)) {
+ $changes['change'][$index_name] = $current_definition[$index_name];
+ }
+ } else {
+ if ($index_name != $was_index_name) {
+ return $this->raiseError(MDB2_SCHEMA_ERROR_INVALID, null, null,
+ 'it was specified a previous index name ("'.$was_index_name.
+ ') for index "'.$index_name.'" of table "'.$table_name.'" that does not exist');
+ }
+ $changes['add'][$index_name] = $current_definition[$index_name];
+ }
+ }
+ }
+ foreach ($previous_definition as $index_previous_name => $index_previous) {
+ if (empty($defined_indexes[$index_previous_name])) {
+ $changes['remove'][$index_previous_name] = $index_previous;
+ }
+ }
+ return $changes;
+ }
+
+ // }}}
+ // {{{ compareTableDefinitions()
+
+ /**
+ * Compare a previous definition with the currently parsed definition
+ *
+ * @param string $table_name name of the table
+ * @param array $current_definition multi dimensional array that contains the current definition
+ * @param array $previous_definition multi dimensional array that contains the previous definition
+ * @param array &$defined_tables table names in the schema
+ *
+ * @return array|MDB2_Error array of changes on success, or a error object
+ * @access public
+ */
+ function compareTableDefinitions($table_name, $current_definition,
+ $previous_definition, &$defined_tables)
+ {
+ $changes = array();
+
+ if (is_array($current_definition)) {
+ $was_table_name = $table_name;
+ if (!empty($current_definition['was'])) {
+ $was_table_name = $current_definition['was'];
+ }
+ if (!empty($previous_definition[$was_table_name])) {
+ $changes['change'][$was_table_name] = array();
+ if ($was_table_name != $table_name) {
+ $changes['change'][$was_table_name] = array('name' => $table_name);
+ }
+ if (!empty($defined_tables[$was_table_name])) {
+ return $this->raiseError(MDB2_SCHEMA_ERROR_INVALID, null, null,
+ 'the table "'.$was_table_name.
+ '" was specified for more than one table of the database');
+ }
+ $defined_tables[$was_table_name] = true;
+ if (!empty($current_definition['fields']) && is_array($current_definition['fields'])) {
+ $previous_fields = array();
+ if (isset($previous_definition[$was_table_name]['fields'])
+ && is_array($previous_definition[$was_table_name]['fields'])) {
+ $previous_fields = $previous_definition[$was_table_name]['fields'];
+ }
+
+ $change = $this->compareTableFieldsDefinitions($table_name,
+ $current_definition['fields'],
+ $previous_fields);
+
+ if (PEAR::isError($change)) {
+ return $change;
+ }
+ if (!empty($change)) {
+ $changes['change'][$was_table_name] =
+ MDB2_Schema::arrayMergeClobber($changes['change'][$was_table_name], $change);
+ }
+ }
+ if (!empty($current_definition['indexes']) && is_array($current_definition['indexes'])) {
+ $previous_indexes = array();
+ if (isset($previous_definition[$was_table_name]['indexes'])
+ && is_array($previous_definition[$was_table_name]['indexes'])) {
+ $previous_indexes = $previous_definition[$was_table_name]['indexes'];
+ }
+ $change = $this->compareTableIndexesDefinitions($table_name,
+ $current_definition['indexes'],
+ $previous_indexes);
+
+ if (PEAR::isError($change)) {
+ return $change;
+ }
+ if (!empty($change)) {
+ $changes['change'][$was_table_name]['indexes'] = $change;
+ }
+ }
+ if (empty($changes['change'][$was_table_name])) {
+ unset($changes['change'][$was_table_name]);
+ }
+ if (empty($changes['change'])) {
+ unset($changes['change']);
+ }
+ } else {
+ if ($table_name != $was_table_name) {
+ return $this->raiseError(MDB2_SCHEMA_ERROR_INVALID, null, null,
+ 'it was specified a previous table name ("'.$was_table_name.
+ '") for table "'.$table_name.'" that does not exist');
+ }
+ $changes['add'][$table_name] = true;
+ }
+ }
+
+ return $changes;
+ }
+
+ // }}}
+ // {{{ compareSequenceDefinitions()
+
+ /**
+ * Compare a previous definition with the currently parsed definition
+ *
+ * @param string $sequence_name name of the sequence
+ * @param array $current_definition multi dimensional array that contains the current definition
+ * @param array $previous_definition multi dimensional array that contains the previous definition
+ * @param array &$defined_sequences names in the schema
+ *
+ * @return array|MDB2_Error array of changes on success, or a error object
+ * @access public
+ */
+ function compareSequenceDefinitions($sequence_name, $current_definition,
+ $previous_definition, &$defined_sequences)
+ {
+ $changes = array();
+
+ if (is_array($current_definition)) {
+ $was_sequence_name = $sequence_name;
+ if (!empty($previous_definition[$sequence_name])
+ && isset($previous_definition[$sequence_name]['was'])
+ && $previous_definition[$sequence_name]['was'] == $was_sequence_name
+ ) {
+ $was_sequence_name = $sequence_name;
+ } elseif (!empty($current_definition['was'])) {
+ $was_sequence_name = $current_definition['was'];
+ }
+ if (!empty($previous_definition[$was_sequence_name])) {
+ if ($was_sequence_name != $sequence_name) {
+ $changes['change'][$was_sequence_name]['name'] = $sequence_name;
+ }
+
+ if (!empty($defined_sequences[$was_sequence_name])) {
+ return $this->raiseError(MDB2_SCHEMA_ERROR_INVALID, null, null,
+ 'the sequence "'.$was_sequence_name.'" was specified as base'.
+ ' of more than of sequence of the database');
+ }
+
+ $defined_sequences[$was_sequence_name] = true;
+
+ $change = array();
+ if (!empty($current_definition['start'])
+ && isset($previous_definition[$was_sequence_name]['start'])
+ && $current_definition['start'] != $previous_definition[$was_sequence_name]['start']
+ ) {
+ $change['start'] = $previous_definition[$sequence_name]['start'];
+ }
+ if (isset($current_definition['on']['table'])
+ && isset($previous_definition[$was_sequence_name]['on']['table'])
+ && $current_definition['on']['table'] != $previous_definition[$was_sequence_name]['on']['table']
+ && isset($current_definition['on']['field'])
+ && isset($previous_definition[$was_sequence_name]['on']['field'])
+ && $current_definition['on']['field'] != $previous_definition[$was_sequence_name]['on']['field']
+ ) {
+ $change['on'] = $current_definition['on'];
+ }
+ if (!empty($change)) {
+ $changes['change'][$was_sequence_name][$sequence_name] = $change;
+ }
+ } else {
+ if ($sequence_name != $was_sequence_name) {
+ return $this->raiseError(MDB2_SCHEMA_ERROR_INVALID, null, null,
+ 'it was specified a previous sequence name ("'.$was_sequence_name.
+ '") for sequence "'.$sequence_name.'" that does not exist');
+ }
+ $changes['add'][$sequence_name] = true;
+ }
+ }
+ return $changes;
+ }
+ // }}}
+ // {{{ verifyAlterDatabase()
+
+ /**
+ * Verify that the changes requested are supported
+ *
+ * @param array $changes associative array that contains the definition of the changes
+ * that are meant to be applied to the database structure.
+ *
+ * @return bool|MDB2_Error MDB2_OK or error object
+ * @access public
+ */
+ function verifyAlterDatabase($changes)
+ {
+ if (!empty($changes['tables']['change']) && is_array($changes['tables']['change'])) {
+ foreach ($changes['tables']['change'] as $table_name => $table) {
+ if (!empty($table['indexes']) && is_array($table['indexes'])) {
+ if (!$this->db->supports('indexes')) {
+ return $this->raiseError(MDB2_SCHEMA_ERROR_UNSUPPORTED, null, null,
+ 'indexes are not supported');
+ }
+ $table_changes = count($table['indexes']);
+ if (!empty($table['indexes']['add'])) {
+ $table_changes--;
+ }
+ if (!empty($table['indexes']['remove'])) {
+ $table_changes--;
+ }
+ if (!empty($table['indexes']['change'])) {
+ $table_changes--;
+ }
+ if ($table_changes) {
+ return $this->raiseError(MDB2_SCHEMA_ERROR_UNSUPPORTED, null, null,
+ 'index alteration not yet supported: '.implode(', ', array_keys($table['indexes'])));
+ }
+ }
+ unset($table['indexes']);
+ $result = $this->db->manager->alterTable($table_name, $table, true);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+ }
+ }
+ if (!empty($changes['sequences']) && is_array($changes['sequences'])) {
+ if (!$this->db->supports('sequences')) {
+ return $this->raiseError(MDB2_SCHEMA_ERROR_UNSUPPORTED, null, null,
+ 'sequences are not supported');
+ }
+ $sequence_changes = count($changes['sequences']);
+ if (!empty($changes['sequences']['add'])) {
+ $sequence_changes--;
+ }
+ if (!empty($changes['sequences']['remove'])) {
+ $sequence_changes--;
+ }
+ if (!empty($changes['sequences']['change'])) {
+ $sequence_changes--;
+ }
+ if ($sequence_changes) {
+ return $this->raiseError(MDB2_SCHEMA_ERROR_UNSUPPORTED, null, null,
+ 'sequence alteration not yet supported: '.implode(', ', array_keys($changes['sequences'])));
+ }
+ }
+ return MDB2_OK;
+ }
+
+ // }}}
+ // {{{ alterDatabaseIndexes()
+
+ /**
+ * Execute the necessary actions to implement the requested changes
+ * in the indexes inside a database structure.
+ *
+ * @param string $table_name name of the table
+ * @param array $changes associative array that contains the definition of the changes
+ * that are meant to be applied to the database structure.
+ *
+ * @return bool|MDB2_Error MDB2_OK or error object
+ * @access public
+ */
+ function alterDatabaseIndexes($table_name, $changes)
+ {
+ $alterations = 0;
+ if (empty($changes)) {
+ return $alterations;
+ }
+
+ if (!empty($changes['remove']) && is_array($changes['remove'])) {
+ foreach ($changes['remove'] as $index_name => $index) {
+ $this->db->expectError(MDB2_ERROR_NOT_FOUND);
+ if (!empty($index['primary']) || !empty($index['unique'])) {
+ $result = $this->db->manager->dropConstraint($table_name, $index_name, !empty($index['primary']));
+ } else {
+ $result = $this->db->manager->dropIndex($table_name, $index_name);
+ }
+ $this->db->popExpect();
+ if (PEAR::isError($result) && !MDB2::isError($result, MDB2_ERROR_NOT_FOUND)) {
+ return $result;
+ }
+ $alterations++;
+ }
+ }
+ if (!empty($changes['change']) && is_array($changes['change'])) {
+ foreach ($changes['change'] as $index_name => $index) {
+ /**
+ * Drop existing index/constraint first.
+ * Since $changes doesn't tell us whether it's an index or a constraint before the change,
+ * we have to find out and call the appropriate method.
+ */
+ if (in_array($index_name, $this->db->manager->listTableIndexes($table_name))) {
+ $result = $this->db->manager->dropIndex($table_name, $index_name);
+ } elseif (in_array($index_name, $this->db->manager->listTableConstraints($table_name))) {
+ $result = $this->db->manager->dropConstraint($table_name, $index_name);
+ }
+ if (!empty($result) && PEAR::isError($result)) {
+ return $result;
+ }
+
+ if (!empty($index['primary']) || !empty($index['unique'])) {
+ $result = $this->db->manager->createConstraint($table_name, $index_name, $index);
+ } else {
+ $result = $this->db->manager->createIndex($table_name, $index_name, $index);
+ }
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+ $alterations++;
+ }
+ }
+ if (!empty($changes['add']) && is_array($changes['add'])) {
+ foreach ($changes['add'] as $index_name => $index) {
+ if (!empty($index['primary']) || !empty($index['unique'])) {
+ $result = $this->db->manager->createConstraint($table_name, $index_name, $index);
+ } else {
+ $result = $this->db->manager->createIndex($table_name, $index_name, $index);
+ }
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+ $alterations++;
+ }
+ }
+
+ return $alterations;
+ }
+
+ // }}}
+ // {{{ alterDatabaseTables()
+
+ /**
+ * Execute the necessary actions to implement the requested changes
+ * in the tables inside a database structure.
+ *
+ * @param array $current_definition multi dimensional array that contains the current definition
+ * @param array $previous_definition multi dimensional array that contains the previous definition
+ * @param array $changes associative array that contains the definition of the changes
+ * that are meant to be applied to the database structure.
+ *
+ * @return bool|MDB2_Error MDB2_OK or error object
+ * @access public
+ */
+ function alterDatabaseTables($current_definition, $previous_definition, $changes)
+ {
+ /* FIXME: tables marked to be added are initialized by createTable(), others don't */
+ $alterations = 0;
+ if (empty($changes)) {
+ return $alterations;
+ }
+
+ if (!empty($changes['add']) && is_array($changes['add'])) {
+ foreach ($changes['add'] as $table_name => $table) {
+ $result = $this->createTable($table_name, $current_definition[$table_name]);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+ $alterations++;
+ }
+ }
+
+ if ($this->options['drop_obsolete_objects']
+ && !empty($changes['remove'])
+ && is_array($changes['remove'])
+ ) {
+ foreach ($changes['remove'] as $table_name => $table) {
+ $result = $this->db->manager->dropTable($table_name);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+ $alterations++;
+ }
+ }
+
+ if (!empty($changes['change']) && is_array($changes['change'])) {
+ foreach ($changes['change'] as $table_name => $table) {
+ $indexes = array();
+ if (!empty($table['indexes'])) {
+ $indexes = $table['indexes'];
+ unset($table['indexes']);
+ }
+ if (!empty($indexes['remove'])) {
+ $result = $this->alterDatabaseIndexes($table_name, array('remove' => $indexes['remove']));
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+ unset($indexes['remove']);
+ $alterations += $result;
+ }
+ $result = $this->db->manager->alterTable($table_name, $table, false);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+ $alterations++;
+
+ // table may be renamed at this point
+ if (!empty($table['name'])) {
+ $table_name = $table['name'];
+ }
+
+ if (!empty($indexes)) {
+ $result = $this->alterDatabaseIndexes($table_name, $indexes);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+ $alterations += $result;
+ }
+ }
+ }
+
+ return $alterations;
+ }
+
+ // }}}
+ // {{{ alterDatabaseSequences()
+
+ /**
+ * Execute the necessary actions to implement the requested changes
+ * in the sequences inside a database structure.
+ *
+ * @param array $current_definition multi dimensional array that contains the current definition
+ * @param array $previous_definition multi dimensional array that contains the previous definition
+ * @param array $changes associative array that contains the definition of the changes
+ * that are meant to be applied to the database structure.
+ *
+ * @return bool|MDB2_Error MDB2_OK or error object
+ * @access public
+ */
+ function alterDatabaseSequences($current_definition, $previous_definition, $changes)
+ {
+ $alterations = 0;
+ if (empty($changes)) {
+ return $alterations;
+ }
+
+ if (!empty($changes['add']) && is_array($changes['add'])) {
+ foreach ($changes['add'] as $sequence_name => $sequence) {
+ $result = $this->createSequence($sequence_name, $current_definition[$sequence_name]);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+ $alterations++;
+ }
+ }
+
+ if ($this->options['drop_obsolete_objects']
+ && !empty($changes['remove'])
+ && is_array($changes['remove'])
+ ) {
+ foreach ($changes['remove'] as $sequence_name => $sequence) {
+ $result = $this->db->manager->dropSequence($sequence_name);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+ $alterations++;
+ }
+ }
+
+ if (!empty($changes['change']) && is_array($changes['change'])) {
+ foreach ($changes['change'] as $sequence_name => $sequence) {
+ $result = $this->db->manager->dropSequence($previous_definition[$sequence_name]['was']);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+ $result = $this->createSequence($sequence_name, $sequence);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+ $alterations++;
+ }
+ }
+
+ return $alterations;
+ }
+
+ // }}}
+ // {{{ alterDatabase()
+
+ /**
+ * Execute the necessary actions to implement the requested changes
+ * in a database structure.
+ *
+ * @param array $current_definition multi dimensional array that contains the current definition
+ * @param array $previous_definition multi dimensional array that contains the previous definition
+ * @param array $changes associative array that contains the definition of the changes
+ * that are meant to be applied to the database structure.
+ *
+ * @return bool|MDB2_Error MDB2_OK or error object
+ * @access public
+ */
+ function alterDatabase($current_definition, $previous_definition, $changes)
+ {
+ $alterations = 0;
+ if (empty($changes)) {
+ return $alterations;
+ }
+
+ $result = $this->verifyAlterDatabase($changes);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+
+ if (!empty($current_definition['name'])) {
+ $previous_database_name = $this->db->setDatabase($current_definition['name']);
+ }
+
+ if (($support_transactions = $this->db->supports('transactions'))
+ && PEAR::isError($result = $this->db->beginNestedTransaction())
+ ) {
+ return $result;
+ }
+
+ if (!empty($changes['tables']) && !empty($current_definition['tables'])) {
+ $current_tables = isset($current_definition['tables']) ? $current_definition['tables'] : array();
+ $previous_tables = isset($previous_definition['tables']) ? $previous_definition['tables'] : array();
+
+ $result = $this->alterDatabaseTables($current_tables, $previous_tables, $changes['tables']);
+ if (is_numeric($result)) {
+ $alterations += $result;
+ }
+ }
+
+ if (!PEAR::isError($result) && !empty($changes['sequences'])) {
+ $current_sequences = isset($current_definition['sequences']) ? $current_definition['sequences'] : array();
+ $previous_sequences = isset($previous_definition['sequences']) ? $previous_definition['sequences'] : array();
+
+ $result = $this->alterDatabaseSequences($current_sequences, $previous_sequences, $changes['sequences']);
+ if (is_numeric($result)) {
+ $alterations += $result;
+ }
+ }
+
+ if ($support_transactions) {
+ $res = $this->db->completeNestedTransaction();
+ if (PEAR::isError($res)) {
+ $result = $this->raiseError(MDB2_SCHEMA_ERROR, null, null,
+ 'Could not end transaction ('.
+ $res->getMessage().' ('.$res->getUserinfo().'))');
+ }
+ } elseif (PEAR::isError($result) && $alterations) {
+ $result = $this->raiseError(MDB2_SCHEMA_ERROR, null, null,
+ 'the requested database alterations were only partially implemented ('.
+ $result->getMessage().' ('.$result->getUserinfo().'))');
+ }
+
+ if (isset($previous_database_name)) {
+ $this->db->setDatabase($previous_database_name);
+ }
+ return $result;
+ }
+
+ // }}}
+ // {{{ dumpDatabaseChanges()
+
+ /**
+ * Dump the changes between two database definitions.
+ *
+ * @param array $changes associative array that specifies the list of database
+ * definitions changes as returned by the _compareDefinitions
+ * manager class function.
+ *
+ * @return bool|MDB2_Error MDB2_OK or error object
+ * @access public
+ */
+ function dumpDatabaseChanges($changes)
+ {
+ if (!empty($changes['tables'])) {
+ if (!empty($changes['tables']['add']) && is_array($changes['tables']['add'])) {
+ foreach ($changes['tables']['add'] as $table_name => $table) {
+ $this->db->debug("$table_name:", __FUNCTION__);
+ $this->db->debug("\tAdded table '$table_name'", __FUNCTION__);
+ }
+ }
+
+ if (!empty($changes['tables']['remove']) && is_array($changes['tables']['remove'])) {
+ if ($this->options['drop_obsolete_objects']) {
+ foreach ($changes['tables']['remove'] as $table_name => $table) {
+ $this->db->debug("$table_name:", __FUNCTION__);
+ $this->db->debug("\tRemoved table '$table_name'", __FUNCTION__);
+ }
+ } else {
+ foreach ($changes['tables']['remove'] as $table_name => $table) {
+ $this->db->debug("\tObsolete table '$table_name' left as is", __FUNCTION__);
+ }
+ }
+ }
+
+ if (!empty($changes['tables']['change']) && is_array($changes['tables']['change'])) {
+ foreach ($changes['tables']['change'] as $table_name => $table) {
+ if (array_key_exists('name', $table)) {
+ $this->db->debug("\tRenamed table '$table_name' to '".$table['name']."'", __FUNCTION__);
+ }
+ if (!empty($table['add']) && is_array($table['add'])) {
+ foreach ($table['add'] as $field_name => $field) {
+ $this->db->debug("\tAdded field '".$field_name."'", __FUNCTION__);
+ }
+ }
+ if (!empty($table['remove']) && is_array($table['remove'])) {
+ foreach ($table['remove'] as $field_name => $field) {
+ $this->db->debug("\tRemoved field '".$field_name."'", __FUNCTION__);
+ }
+ }
+ if (!empty($table['rename']) && is_array($table['rename'])) {
+ foreach ($table['rename'] as $field_name => $field) {
+ $this->db->debug("\tRenamed field '".$field_name."' to '".$field['name']."'", __FUNCTION__);
+ }
+ }
+ if (!empty($table['change']) && is_array($table['change'])) {
+ foreach ($table['change'] as $field_name => $field) {
+ $field = $field['definition'];
+ if (array_key_exists('type', $field)) {
+ $this->db->debug("\tChanged field '$field_name' type to '".$field['type']."'", __FUNCTION__);
+ }
+
+ if (array_key_exists('unsigned', $field)) {
+ $this->db->debug("\tChanged field '$field_name' type to '".
+ (!empty($field['unsigned']) && $field['unsigned'] ? '' : 'not ')."unsigned'",
+ __FUNCTION__);
+ }
+
+ if (array_key_exists('length', $field)) {
+ $this->db->debug("\tChanged field '$field_name' length to '".
+ (!empty($field['length']) ? $field['length']: 'no length')."'", __FUNCTION__);
+ }
+ if (array_key_exists('default', $field)) {
+ $this->db->debug("\tChanged field '$field_name' default to ".
+ (isset($field['default']) ? "'".$field['default']."'" : 'NULL'), __FUNCTION__);
+ }
+
+ if (array_key_exists('notnull', $field)) {
+ $this->db->debug("\tChanged field '$field_name' notnull to ".
+ (!empty($field['notnull']) && $field['notnull'] ? 'true' : 'false'),
+ __FUNCTION__);
+ }
+ }
+ }
+ if (!empty($table['indexes']) && is_array($table['indexes'])) {
+ if (!empty($table['indexes']['add']) && is_array($table['indexes']['add'])) {
+ foreach ($table['indexes']['add'] as $index_name => $index) {
+ $this->db->debug("\tAdded index '".$index_name.
+ "' of table '$table_name'", __FUNCTION__);
+ }
+ }
+ if (!empty($table['indexes']['remove']) && is_array($table['indexes']['remove'])) {
+ foreach ($table['indexes']['remove'] as $index_name => $index) {
+ $this->db->debug("\tRemoved index '".$index_name.
+ "' of table '$table_name'", __FUNCTION__);
+ }
+ }
+ if (!empty($table['indexes']['change']) && is_array($table['indexes']['change'])) {
+ foreach ($table['indexes']['change'] as $index_name => $index) {
+ if (array_key_exists('name', $index)) {
+ $this->db->debug("\tRenamed index '".$index_name."' to '".$index['name'].
+ "' on table '$table_name'", __FUNCTION__);
+ }
+ if (array_key_exists('unique', $index)) {
+ $this->db->debug("\tChanged index '".$index_name."' unique to '".
+ !empty($index['unique'])."' on table '$table_name'", __FUNCTION__);
+ }
+ if (array_key_exists('primary', $index)) {
+ $this->db->debug("\tChanged index '".$index_name."' primary to '".
+ !empty($index['primary'])."' on table '$table_name'", __FUNCTION__);
+ }
+ if (array_key_exists('change', $index)) {
+ $this->db->debug("\tChanged index '".$index_name.
+ "' on table '$table_name'", __FUNCTION__);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (!empty($changes['sequences'])) {
+ if (!empty($changes['sequences']['add']) && is_array($changes['sequences']['add'])) {
+ foreach ($changes['sequences']['add'] as $sequence_name => $sequence) {
+ $this->db->debug("$sequence_name:", __FUNCTION__);
+ $this->db->debug("\tAdded sequence '$sequence_name'", __FUNCTION__);
+ }
+ }
+ if (!empty($changes['sequences']['remove']) && is_array($changes['sequences']['remove'])) {
+ if ($this->options['drop_obsolete_objects']) {
+ foreach ($changes['sequences']['remove'] as $sequence_name => $sequence) {
+ $this->db->debug("$sequence_name:", __FUNCTION__);
+ $this->db->debug("\tRemoved sequence '$sequence_name'", __FUNCTION__);
+ }
+ } else {
+ foreach ($changes['sequences']['remove'] as $sequence_name => $sequence) {
+ $this->db->debug("\tObsolete sequence '$sequence_name' left as is", __FUNCTION__);
+ }
+ }
+ }
+ if (!empty($changes['sequences']['change']) && is_array($changes['sequences']['change'])) {
+ foreach ($changes['sequences']['change'] as $sequence_name => $sequence) {
+ if (array_key_exists('name', $sequence)) {
+ $this->db->debug("\tRenamed sequence '$sequence_name' to '".
+ $sequence['name']."'", __FUNCTION__);
+ }
+ if (!empty($sequence['change']) && is_array($sequence['change'])) {
+ foreach ($sequence['change'] as $sequence_name => $sequence) {
+ if (array_key_exists('start', $sequence)) {
+ $this->db->debug("\tChanged sequence '$sequence_name' start to '".
+ $sequence['start']."'", __FUNCTION__);
+ }
+ }
+ }
+ }
+ }
+ }
+ return MDB2_OK;
+ }
+
+ // }}}
+ // {{{ dumpDatabase()
+
+ /**
+ * Dump a previously parsed database structure in the Metabase schema
+ * XML based format suitable for the Metabase parser. This function
+ * may optionally dump the database definition with initialization
+ * commands that specify the data that is currently present in the tables.
+ *
+ * @param array $database_definition multi dimensional array that contains the current definition
+ * @param array $arguments associative array that takes pairs of tag
+ * names and values that define dump options.
+ *
array (
+ * 'output_mode' => String
+ * 'file' : dump into a file
+ * default: dump using a function
+ * 'output' => String
+ * depending on the 'Output_Mode'
+ * name of the file
+ * name of the function
+ * 'end_of_line' => String
+ * end of line delimiter that should be used
+ * default: "\n"
+ * );
+ * @param int $dump Int that determines what data to dump
+ * + MDB2_SCHEMA_DUMP_ALL : the entire db
+ * + MDB2_SCHEMA_DUMP_STRUCTURE : only the structure of the db
+ * + MDB2_SCHEMA_DUMP_CONTENT : only the content of the db
+ *
+ * @return bool|MDB2_Error MDB2_OK or error object
+ * @access public
+ */
+ function dumpDatabase($database_definition, $arguments, $dump = MDB2_SCHEMA_DUMP_ALL)
+ {
+ $class_name = $this->options['writer'];
+
+ $result = MDB2::loadClass($class_name, $this->db->getOption('debug'));
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+
+ // get initialization data
+ if (isset($database_definition['tables']) && is_array($database_definition['tables'])
+ && $dump == MDB2_SCHEMA_DUMP_ALL || $dump == MDB2_SCHEMA_DUMP_CONTENT
+ ) {
+ foreach ($database_definition['tables'] as $table_name => $table) {
+ $fields = array();
+ $fieldsq = array();
+ foreach ($table['fields'] as $field_name => $field) {
+ $fields[$field_name] = $field['type'];
+
+ $fieldsq[] = $this->db->quoteIdentifier($field_name, true);
+ }
+
+ $query = 'SELECT '.implode(', ', $fieldsq).' FROM ';
+ $query .= $this->db->quoteIdentifier($table_name, true);
+
+ $data = $this->db->queryAll($query, $fields, MDB2_FETCHMODE_ASSOC);
+
+ if (PEAR::isError($data)) {
+ return $data;
+ }
+
+ if (!empty($data)) {
+ $initialization = array();
+ $lob_buffer_length = $this->db->getOption('lob_buffer_length');
+ foreach ($data as $row) {
+ $rows = array();
+ foreach ($row as $key => $lob) {
+ if (is_resource($lob)) {
+ $value = '';
+ while (!feof($lob)) {
+ $value .= fread($lob, $lob_buffer_length);
+ }
+ $row[$key] = $value;
+ }
+ $rows[] = array('name' => $key, 'group' => array('type' => 'value', 'data' => $row[$key]));
+ }
+ $initialization[] = array('type' => 'insert', 'data' => array('field' => $rows));
+ }
+ $database_definition['tables'][$table_name]['initialization'] = $initialization;
+ }
+ }
+ }
+
+ $writer = new $class_name($this->options['valid_types']);
+ return $writer->dumpDatabase($database_definition, $arguments, $dump);
+ }
+
+ // }}}
+ // {{{ writeInitialization()
+
+ /**
+ * Write initialization and sequences
+ *
+ * @param string|array $data data file or data array
+ * @param string|array $structure structure file or array
+ * @param array $variables associative array that is passed to the argument
+ * of the same name to the parseDatabaseDefinitionFile function. (there third
+ * param)
+ *
+ * @return bool|MDB2_Error MDB2_OK or error object
+ * @access public
+ */
+ function writeInitialization($data, $structure = false, $variables = array())
+ {
+ if ($structure) {
+ $structure = $this->parseDatabaseDefinition($structure, false, $variables);
+ if (PEAR::isError($structure)) {
+ return $structure;
+ }
+ }
+
+ $data = $this->parseDatabaseDefinition($data, false, $variables, false, $structure);
+ if (PEAR::isError($data)) {
+ return $data;
+ }
+
+ $previous_database_name = null;
+ if (!empty($data['name'])) {
+ $previous_database_name = $this->db->setDatabase($data['name']);
+ } elseif (!empty($structure['name'])) {
+ $previous_database_name = $this->db->setDatabase($structure['name']);
+ }
+
+ if (!empty($data['tables']) && is_array($data['tables'])) {
+ foreach ($data['tables'] as $table_name => $table) {
+ if (empty($table['initialization'])) {
+ continue;
+ }
+ $result = $this->initializeTable($table_name, $table);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+ }
+ }
+
+ if (!empty($structure['sequences']) && is_array($structure['sequences'])) {
+ foreach ($structure['sequences'] as $sequence_name => $sequence) {
+ if (isset($data['sequences'][$sequence_name])
+ || !isset($sequence['on']['table'])
+ || !isset($data['tables'][$sequence['on']['table']])
+ ) {
+ continue;
+ }
+ $result = $this->createSequence($sequence_name, $sequence, true);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+ }
+ }
+ if (!empty($data['sequences']) && is_array($data['sequences'])) {
+ foreach ($data['sequences'] as $sequence_name => $sequence) {
+ $result = $this->createSequence($sequence_name, $sequence, true);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+ }
+ }
+
+ if (isset($previous_database_name)) {
+ $this->db->setDatabase($previous_database_name);
+ }
+
+ return MDB2_OK;
+ }
+
+ // }}}
+ // {{{ updateDatabase()
+
+ /**
+ * Compare the correspondent files of two versions of a database schema
+ * definition: the previously installed and the one that defines the schema
+ * that is meant to update the database.
+ * If the specified previous definition file does not exist, this function
+ * will create the database from the definition specified in the current
+ * schema file.
+ * If both files exist, the function assumes that the database was previously
+ * installed based on the previous schema file and will update it by just
+ * applying the changes.
+ * If this function succeeds, the contents of the current schema file are
+ * copied to replace the previous schema file contents. Any subsequent schema
+ * changes should only be done on the file specified by the $current_schema_file
+ * to let this function make a consistent evaluation of the exact changes that
+ * need to be applied.
+ *
+ * @param string|array $current_schema filename or array of the updated database schema definition.
+ * @param string|array $previous_schema filename or array of the previously installed database schema definition.
+ * @param array $variables associative array that is passed to the argument of the same
+ * name to the parseDatabaseDefinitionFile function. (there third param)
+ * @param bool $disable_query determines if the disable_query option should be set to true
+ * for the alterDatabase() or createDatabase() call
+ * @param bool $overwrite_old_schema_file Overwrite?
+ *
+ * @return bool|MDB2_Error MDB2_OK or error object
+ * @access public
+ */
+ function updateDatabase($current_schema, $previous_schema = false,
+ $variables = array(), $disable_query = false,
+ $overwrite_old_schema_file = false)
+ {
+ $current_definition = $this->parseDatabaseDefinition($current_schema, false, $variables,
+ $this->options['fail_on_invalid_names']);
+
+ if (PEAR::isError($current_definition)) {
+ return $current_definition;
+ }
+
+ $previous_definition = false;
+ if ($previous_schema) {
+ $previous_definition = $this->parseDatabaseDefinition($previous_schema, true, $variables,
+ $this->options['fail_on_invalid_names']);
+ if (PEAR::isError($previous_definition)) {
+ return $previous_definition;
+ }
+ }
+
+ if ($previous_definition) {
+ $dbExists = $this->db->databaseExists($current_definition['name']);
+ if (PEAR::isError($dbExists)) {
+ return $dbExists;
+ }
+
+ if (!$dbExists) {
+ return $this->raiseError(MDB2_SCHEMA_ERROR, null, null,
+ 'database to update does not exist: '.$current_definition['name']);
+ }
+
+ $changes = $this->compareDefinitions($current_definition, $previous_definition);
+ if (PEAR::isError($changes)) {
+ return $changes;
+ }
+
+ if (is_array($changes)) {
+ $this->db->setOption('disable_query', $disable_query);
+ $result = $this->alterDatabase($current_definition, $previous_definition, $changes);
+ $this->db->setOption('disable_query', false);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+ $copy = true;
+ if ($this->db->options['debug']) {
+ $result = $this->dumpDatabaseChanges($changes);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+ }
+ }
+ } else {
+ $this->db->setOption('disable_query', $disable_query);
+ $result = $this->createDatabase($current_definition);
+ $this->db->setOption('disable_query', false);
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+ }
+
+ if ($overwrite_old_schema_file
+ && !$disable_query
+ && is_string($previous_schema) && is_string($current_schema)
+ && !copy($current_schema, $previous_schema)) {
+
+ return $this->raiseError(MDB2_SCHEMA_ERROR, null, null,
+ 'Could not copy the new database definition file to the current file');
+ }
+
+ return MDB2_OK;
+ }
+ // }}}
+ // {{{ errorMessage()
+
+ /**
+ * Return a textual error message for a MDB2 error code
+ *
+ * @param int|array $value integer error code, null to get the
+ * current error code-message map,
+ * or an array with a new error code-message map
+ *
+ * @return string error message, or false if the error code was not recognized
+ * @access public
+ */
+ function errorMessage($value = null)
+ {
+ static $errorMessages;
+ if (is_array($value)) {
+ $errorMessages = $value;
+ return MDB2_OK;
+ } elseif (!isset($errorMessages)) {
+ $errorMessages = array(
+ MDB2_SCHEMA_ERROR => 'unknown error',
+ MDB2_SCHEMA_ERROR_PARSE => 'schema parse error',
+ MDB2_SCHEMA_ERROR_VALIDATE => 'schema validation error',
+ MDB2_SCHEMA_ERROR_INVALID => 'invalid',
+ MDB2_SCHEMA_ERROR_UNSUPPORTED => 'not supported',
+ MDB2_SCHEMA_ERROR_WRITER => 'schema writer error',
+ );
+ }
+
+ if (is_null($value)) {
+ return $errorMessages;
+ }
+
+ if (PEAR::isError($value)) {
+ $value = $value->getCode();
+ }
+
+ return !empty($errorMessages[$value]) ?
+ $errorMessages[$value] : $errorMessages[MDB2_SCHEMA_ERROR];
+ }
+
+ // }}}
+ // {{{ raiseError()
+
+ /**
+ * This method is used to communicate an error and invoke error
+ * callbacks etc. Basically a wrapper for PEAR::raiseError
+ * without the message string.
+ *
+ * @param int|PEAR_Error $code integer error code or and PEAR_Error instance
+ * @param int $mode error mode, see PEAR_Error docs
+ * 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 array $options Options, depending on the mode, @see PEAR::setErrorHandling
+ * @param string $userinfo Extra debug information. Defaults to the last
+ * query and native error code.
+ *
+ * @return object a PEAR error object
+ * @access public
+ * @see PEAR_Error
+ */
+ static function &raiseError($code = null, $mode = null, $options = null, $userinfo = null, $dummy1 = null, $dummy2 = null, $dummy3 = false)
+ {
+ $err = PEAR::raiseError(null, $code, $mode, $options,
+ $userinfo, 'MDB2_Schema_Error', true);
+ return $err;
+ }
+
+ // }}}
+ // {{{ isError()
+
+ /**
+ * Tell whether a value is an MDB2_Schema error.
+ *
+ * @param mixed $data the value to test
+ * @param int $code if $data is an error object, return true only if $code is
+ * a string and $db->getMessage() == $code or
+ * $code is an integer and $db->getCode() == $code
+ *
+ * @return bool true if parameter is an error
+ * @access public
+ */
+ static function isError($data, $code = null)
+ {
+ if (is_a($data, 'MDB2_Schema_Error')) {
+ if (is_null($code)) {
+ return true;
+ } elseif (is_string($code)) {
+ return $data->getMessage() === $code;
+ } else {
+ $code = (array)$code;
+ return in_array($data->getCode(), $code);
+ }
+ }
+ return false;
+ }
+
+ // }}}
+}
+
+/**
+ * MDB2_Schema_Error implements a class for reporting portable database error
+ * messages.
+ *
+ * @category Database
+ * @package MDB2_Schema
+ * @author Stig Bakken
+ * @license BSD http://www.opensource.org/licenses/bsd-license.php
+ * @link http://pear.php.net/packages/MDB2_Schema
+ */
+class MDB2_Schema_Error extends PEAR_Error
+{
+ /**
+ * MDB2_Schema_Error constructor.
+ *
+ * @param mixed $code 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
+ *
+ * @access public
+ */
+ function MDB2_Schema_Error($code = MDB2_SCHEMA_ERROR, $mode = PEAR_ERROR_RETURN,
+ $level = E_USER_NOTICE, $debuginfo = null)
+ {
+ $this->PEAR_Error('MDB2_Schema Error: ' . MDB2_Schema::errorMessage($code), $code,
+ $mode, $level, $debuginfo);
+ }
+}
diff -Nru owncloud-1.1+git20110209/3rdparty/MDB2.php owncloud-5.0.4debian/3rdparty/MDB2.php
--- owncloud-1.1+git20110209/3rdparty/MDB2.php 1970-01-01 00:00:00.000000000 +0000
+++ owncloud-5.0.4debian/3rdparty/MDB2.php 2013-04-10 17:29:58.000000000 +0000
@@ -0,0 +1,4587 @@
+ |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+//
+
+/**
+ * @package MDB2
+ * @category Database
+ * @author Lukas Smith
+ */
+
+require_once 'PEAR.php';
+
+// {{{ Error constants
+
+/**
+ * The method mapErrorCode in each MDB2_dbtype implementation maps
+ * native error codes to one of these.
+ *
+ * If you add an error code here, make sure you also add a textual
+ * version of it in MDB2::errorMessage().
+ */
+
+define('MDB2_OK', true);
+define('MDB2_ERROR', -1);
+define('MDB2_ERROR_SYNTAX', -2);
+define('MDB2_ERROR_CONSTRAINT', -3);
+define('MDB2_ERROR_NOT_FOUND', -4);
+define('MDB2_ERROR_ALREADY_EXISTS', -5);
+define('MDB2_ERROR_UNSUPPORTED', -6);
+define('MDB2_ERROR_MISMATCH', -7);
+define('MDB2_ERROR_INVALID', -8);
+define('MDB2_ERROR_NOT_CAPABLE', -9);
+define('MDB2_ERROR_TRUNCATED', -10);
+define('MDB2_ERROR_INVALID_NUMBER', -11);
+define('MDB2_ERROR_INVALID_DATE', -12);
+define('MDB2_ERROR_DIVZERO', -13);
+define('MDB2_ERROR_NODBSELECTED', -14);
+define('MDB2_ERROR_CANNOT_CREATE', -15);
+define('MDB2_ERROR_CANNOT_DELETE', -16);
+define('MDB2_ERROR_CANNOT_DROP', -17);
+define('MDB2_ERROR_NOSUCHTABLE', -18);
+define('MDB2_ERROR_NOSUCHFIELD', -19);
+define('MDB2_ERROR_NEED_MORE_DATA', -20);
+define('MDB2_ERROR_NOT_LOCKED', -21);
+define('MDB2_ERROR_VALUE_COUNT_ON_ROW', -22);
+define('MDB2_ERROR_INVALID_DSN', -23);
+define('MDB2_ERROR_CONNECT_FAILED', -24);
+define('MDB2_ERROR_EXTENSION_NOT_FOUND',-25);
+define('MDB2_ERROR_NOSUCHDB', -26);
+define('MDB2_ERROR_ACCESS_VIOLATION', -27);
+define('MDB2_ERROR_CANNOT_REPLACE', -28);
+define('MDB2_ERROR_CONSTRAINT_NOT_NULL',-29);
+define('MDB2_ERROR_DEADLOCK', -30);
+define('MDB2_ERROR_CANNOT_ALTER', -31);
+define('MDB2_ERROR_MANAGER', -32);
+define('MDB2_ERROR_MANAGER_PARSE', -33);
+define('MDB2_ERROR_LOADMODULE', -34);
+define('MDB2_ERROR_INSUFFICIENT_DATA', -35);
+define('MDB2_ERROR_NO_PERMISSION', -36);
+define('MDB2_ERROR_DISCONNECT_FAILED', -37);
+
+// }}}
+// {{{ Verbose constants
+/**
+ * These are just helper constants to more verbosely express parameters to prepare()
+ */
+
+define('MDB2_PREPARE_MANIP', false);
+define('MDB2_PREPARE_RESULT', null);
+
+// }}}
+// {{{ Fetchmode constants
+
+/**
+ * This is a special constant that tells MDB2 the user hasn't specified
+ * any particular get mode, so the default should be used.
+ */
+define('MDB2_FETCHMODE_DEFAULT', 0);
+
+/**
+ * Column data indexed by numbers, ordered from 0 and up
+ */
+define('MDB2_FETCHMODE_ORDERED', 1);
+
+/**
+ * Column data indexed by column names
+ */
+define('MDB2_FETCHMODE_ASSOC', 2);
+
+/**
+ * Column data as object properties
+ */
+define('MDB2_FETCHMODE_OBJECT', 3);
+
+/**
+ * For multi-dimensional results: normally the first level of arrays
+ * is the row number, and the second level indexed by column number or name.
+ * MDB2_FETCHMODE_FLIPPED switches this order, so the first level of arrays
+ * is the column name, and the second level the row number.
+ */
+define('MDB2_FETCHMODE_FLIPPED', 4);
+
+// }}}
+// {{{ Portability mode constants
+
+/**
+ * Portability: turn off all portability features.
+ * @see MDB2_Driver_Common::setOption()
+ */
+define('MDB2_PORTABILITY_NONE', 0);
+
+/**
+ * Portability: convert names of tables and fields to case defined in the
+ * "field_case" option when using the query*(), fetch*() and tableInfo() methods.
+ * @see MDB2_Driver_Common::setOption()
+ */
+define('MDB2_PORTABILITY_FIX_CASE', 1);
+
+/**
+ * Portability: right trim the data output by query*() and fetch*().
+ * @see MDB2_Driver_Common::setOption()
+ */
+define('MDB2_PORTABILITY_RTRIM', 2);
+
+/**
+ * Portability: force reporting the number of rows deleted.
+ * @see MDB2_Driver_Common::setOption()
+ */
+define('MDB2_PORTABILITY_DELETE_COUNT', 4);
+
+/**
+ * Portability: not needed in MDB2 (just left here for compatibility to DB)
+ * @see MDB2_Driver_Common::setOption()
+ */
+define('MDB2_PORTABILITY_NUMROWS', 8);
+
+/**
+ * Portability: makes certain error messages in certain drivers compatible
+ * with those from other DBMS's.
+ *
+ * + mysql, mysqli: change unique/primary key constraints
+ * MDB2_ERROR_ALREADY_EXISTS -> MDB2_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 MDB2_ERROR_NOSUCHFIELD.
+ *
+ * @see MDB2_Driver_Common::setOption()
+ */
+define('MDB2_PORTABILITY_ERRORS', 16);
+
+/**
+ * Portability: convert empty values to null strings in data output by
+ * query*() and fetch*().
+ * @see MDB2_Driver_Common::setOption()
+ */
+define('MDB2_PORTABILITY_EMPTY_TO_NULL', 32);
+
+/**
+ * Portability: removes database/table qualifiers from associative indexes
+ * @see MDB2_Driver_Common::setOption()
+ */
+define('MDB2_PORTABILITY_FIX_ASSOC_FIELD_NAMES', 64);
+
+/**
+ * Portability: turn on all portability features.
+ * @see MDB2_Driver_Common::setOption()
+ */
+define('MDB2_PORTABILITY_ALL', 127);
+
+// }}}
+// {{{ Globals for class instance tracking
+
+/**
+ * These are global variables that are used to track the various class instances
+ */
+
+$GLOBALS['_MDB2_databases'] = array();
+$GLOBALS['_MDB2_dsninfo_default'] = array(
+ 'phptype' => false,
+ 'dbsyntax' => false,
+ 'username' => false,
+ 'password' => false,
+ 'protocol' => false,
+ 'hostspec' => false,
+ 'port' => false,
+ 'socket' => false,
+ 'database' => false,
+ 'mode' => false,
+);
+
+// }}}
+// {{{ class MDB2
+
+/**
+ * The main 'MDB2' 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 MDB2 is as follows (indentation means inheritance):
+ *
+ * MDB2 The main MDB2 class. This is simply a utility class
+ * with some 'static' methods for creating MDB2 objects as
+ * well as common utility functions for other MDB2 classes.
+ *
+ * MDB2_Driver_Common The base for each MDB2 implementation. Provides default
+ * | implementations (in OO lingo virtual methods) for
+ * | the actual DB implementations as well as a bunch of
+ * | query utility functions.
+ * |
+ * +-MDB2_Driver_mysql The MDB2 implementation for MySQL. Inherits MDB2_Driver_Common.
+ * When calling MDB2::factory or MDB2::connect for MySQL
+ * connections, the object returned is an instance of this
+ * class.
+ * +-MDB2_Driver_pgsql The MDB2 implementation for PostGreSQL. Inherits MDB2_Driver_Common.
+ * When calling MDB2::factory or MDB2::connect for PostGreSQL
+ * connections, the object returned is an instance of this
+ * class.
+ *
+ * @package MDB2
+ * @category Database
+ * @author Lukas Smith
+ */
+class MDB2
+{
+ // {{{ function setOptions($db, $options)
+
+ /**
+ * set option array in an exiting database object
+ *
+ * @param MDB2_Driver_Common MDB2 object
+ * @param array An associative array of option names and their values.
+ *
+ * @return mixed MDB2_OK or a PEAR Error object
+ *
+ * @access public
+ */
+ static function setOptions($db, $options)
+ {
+ if (is_array($options)) {
+ foreach ($options as $option => $value) {
+ $test = $db->setOption($option, $value);
+ if (MDB2::isError($test)) {
+ return $test;
+ }
+ }
+ }
+ return MDB2_OK;
+ }
+
+ // }}}
+ // {{{ function classExists($classname)
+
+ /**
+ * Checks if a class exists without triggering __autoload
+ *
+ * @param string classname
+ *
+ * @return bool true success and false on error
+ * @static
+ * @access public
+ */
+ static function classExists($classname)
+ {
+ return class_exists($classname, false);
+ }
+
+ // }}}
+ // {{{ function loadClass($class_name, $debug)
+
+ /**
+ * Loads a PEAR class.
+ *
+ * @param string classname to load
+ * @param bool if errors should be suppressed
+ *
+ * @return mixed true success or PEAR_Error on failure
+ *
+ * @access public
+ */
+ static function loadClass($class_name, $debug)
+ {
+ if (!MDB2::classExists($class_name)) {
+ $file_name = str_replace('_', DIRECTORY_SEPARATOR, $class_name).'.php';
+ if ($debug) {
+ $include = include_once($file_name);
+ } else {
+ $include = @include_once($file_name);
+ }
+ if (!$include) {
+ if (!MDB2::fileExists($file_name)) {
+ $msg = "unable to find package '$class_name' file '$file_name'";
+ } else {
+ $msg = "unable to load class '$class_name' from file '$file_name'";
+ }
+ $err = MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null, $msg);
+ return $err;
+ }
+ if (!MDB2::classExists($class_name)) {
+ $msg = "unable to load class '$class_name' from file '$file_name'";
+ $err = MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null, $msg);
+ return $err;
+ }
+ }
+ return MDB2_OK;
+ }
+
+ // }}}
+ // {{{ function factory($dsn, $options = false)
+
+ /**
+ * Create a new MDB2 object for the specified database type
+ *
+ * @param mixed 'data source name', see the MDB2::parseDSN
+ * method for a description of the dsn format.
+ * Can also be specified as an array of the
+ * format returned by MDB2::parseDSN.
+ * @param array An associative array of option names and
+ * their values.
+ *
+ * @return mixed a newly created MDB2 object, or false on error
+ *
+ * @access public
+ */
+ static function factory($dsn, $options = false)
+ {
+ $dsninfo = MDB2::parseDSN($dsn);
+ if (empty($dsninfo['phptype'])) {
+ $err = MDB2::raiseError(MDB2_ERROR_NOT_FOUND,
+ null, null, 'no RDBMS driver specified');
+ return $err;
+ }
+ $class_name = 'MDB2_Driver_'.$dsninfo['phptype'];
+
+ $debug = (!empty($options['debug']));
+ $err = MDB2::loadClass($class_name, $debug);
+ if (MDB2::isError($err)) {
+ return $err;
+ }
+
+ $db = new $class_name();
+ $db->setDSN($dsninfo);
+ $err = MDB2::setOptions($db, $options);
+ if (MDB2::isError($err)) {
+ return $err;
+ }
+
+ return $db;
+ }
+
+ // }}}
+ // {{{ function connect($dsn, $options = false)
+
+ /**
+ * Create a new MDB2_Driver_* connection object and connect to the specified
+ * database
+ *
+ * @param mixed $dsn 'data source name', see the MDB2::parseDSN
+ * method for a description of the dsn format.
+ * Can also be specified as an array of the
+ * format returned by MDB2::parseDSN.
+ * @param array $options An associative array of option names and
+ * their values.
+ *
+ * @return mixed a newly created MDB2 connection object, or a MDB2
+ * error object on error
+ *
+ * @access public
+ * @see MDB2::parseDSN
+ */
+ static function connect($dsn, $options = false)
+ {
+ $db = MDB2::factory($dsn, $options);
+ if (MDB2::isError($db)) {
+ return $db;
+ }
+
+ $err = $db->connect();
+ if (MDB2::isError($err)) {
+ $dsn = $db->getDSN('string', 'xxx');
+ $db->disconnect();
+ $err->addUserInfo($dsn);
+ return $err;
+ }
+
+ return $db;
+ }
+
+ // }}}
+ // {{{ function singleton($dsn = null, $options = false)
+
+ /**
+ * Returns a MDB2 connection with the requested DSN.
+ * A new MDB2 connection object is only created if no object with the
+ * requested DSN exists yet.
+ *
+ * @param mixed 'data source name', see the MDB2::parseDSN
+ * method for a description of the dsn format.
+ * Can also be specified as an array of the
+ * format returned by MDB2::parseDSN.
+ * @param array An associative array of option names and
+ * their values.
+ *
+ * @return mixed a newly created MDB2 connection object, or a MDB2
+ * error object on error
+ *
+ * @access public
+ * @see MDB2::parseDSN
+ */
+ static function singleton($dsn = null, $options = false)
+ {
+ if ($dsn) {
+ $dsninfo = MDB2::parseDSN($dsn);
+ $dsninfo = array_merge($GLOBALS['_MDB2_dsninfo_default'], $dsninfo);
+ $keys = array_keys($GLOBALS['_MDB2_databases']);
+ for ($i=0, $j=count($keys); $i<$j; ++$i) {
+ if (isset($GLOBALS['_MDB2_databases'][$keys[$i]])) {
+ $tmp_dsn = $GLOBALS['_MDB2_databases'][$keys[$i]]->getDSN('array');
+ if (count(array_diff_assoc($tmp_dsn, $dsninfo)) == 0) {
+ MDB2::setOptions($GLOBALS['_MDB2_databases'][$keys[$i]], $options);
+ return $GLOBALS['_MDB2_databases'][$keys[$i]];
+ }
+ }
+ }
+ } elseif (is_array($GLOBALS['_MDB2_databases']) && reset($GLOBALS['_MDB2_databases'])) {
+ return $GLOBALS['_MDB2_databases'][key($GLOBALS['_MDB2_databases'])];
+ }
+ $db = MDB2::factory($dsn, $options);
+ return $db;
+ }
+
+ // }}}
+ // {{{ function areEquals()
+
+ /**
+ * It looks like there's a memory leak in array_diff() in PHP 5.1.x,
+ * so use this method instead.
+ * @see http://pear.php.net/bugs/bug.php?id=11790
+ *
+ * @param array $arr1
+ * @param array $arr2
+ * @return boolean
+ */
+ static function areEquals($arr1, $arr2)
+ {
+ if (count($arr1) != count($arr2)) {
+ return false;
+ }
+ foreach (array_keys($arr1) as $k) {
+ if (!array_key_exists($k, $arr2) || $arr1[$k] != $arr2[$k]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // }}}
+ // {{{ function loadFile($file)
+
+ /**
+ * load a file (like 'Date')
+ *
+ * @param string $file name of the file in the MDB2 directory (without '.php')
+ *
+ * @return string name of the file that was included
+ *
+ * @access public
+ */
+ static function loadFile($file)
+ {
+ $file_name = 'MDB2'.DIRECTORY_SEPARATOR.$file.'.php';
+ if (!MDB2::fileExists($file_name)) {
+ return MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+ 'unable to find: '.$file_name);
+ }
+ if (!include_once($file_name)) {
+ return MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+ 'unable to load driver class: '.$file_name);
+ }
+ return $file_name;
+ }
+
+ // }}}
+ // {{{ function apiVersion()
+
+ /**
+ * Return the MDB2 API version
+ *
+ * @return string the MDB2 API version number
+ *
+ * @access public
+ */
+ function apiVersion()
+ {
+ return '@package_version@';
+ }
+
+ // }}}
+ // {{{ function &raiseError($code = null, $mode = null, $options = null, $userinfo = null)
+
+ /**
+ * This method is used to communicate an error and invoke error
+ * callbacks etc. Basically a wrapper for PEAR::raiseError
+ * without the message string.
+ *
+ * @param mixed int error code
+ *
+ * @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.
+ *
+ * @return PEAR_Error instance of a PEAR Error object
+ *
+ * @access private
+ * @see PEAR_Error
+ */
+ public static function &raiseError($code = null,
+ $mode = null,
+ $options = null,
+ $userinfo = null,
+ $dummy1 = null,
+ $dummy2 = null,
+ $dummy3 = false)
+ {
+ $pear = new PEAR;
+ $err = $pear->raiseError(null, $code, $mode, $options, $userinfo, 'MDB2_Error', true);
+ return $err;
+ }
+
+ // }}}
+ // {{{ function isError($data, $code = null)
+
+ /**
+ * Tell whether a value is a MDB2 error.
+ *
+ * @param mixed the value to test
+ * @param int if is an error object, return true
+ * only if $code is a string and
+ * $db->getMessage() == $code or
+ * $code is an integer and $db->getCode() == $code
+ *
+ * @return bool true if parameter is an error
+ *
+ * @access public
+ */
+ static function isError($data, $code = null)
+ {
+ if ($data instanceof MDB2_Error) {
+ if (null === $code) {
+ return true;
+ }
+ if (is_string($code)) {
+ return $data->getMessage() === $code;
+ }
+ return in_array($data->getCode(), (array)$code);
+ }
+ return false;
+ }
+
+ // }}}
+ // {{{ function isConnection($value)
+
+ /**
+ * Tell whether a value is a MDB2 connection
+ *
+ * @param mixed value to test
+ *
+ * @return bool whether $value is a MDB2 connection
+ * @access public
+ */
+ static function isConnection($value)
+ {
+ return ($value instanceof MDB2_Driver_Common);
+ }
+
+ // }}}
+ // {{{ function isResult($value)
+
+ /**
+ * Tell whether a value is a MDB2 result
+ *
+ * @param mixed $value value to test
+ *
+ * @return bool whether $value is a MDB2 result
+ *
+ * @access public
+ */
+ function isResult($value)
+ {
+ return ($value instanceof MDB2_Result);
+ }
+
+ // }}}
+ // {{{ function isResultCommon($value)
+
+ /**
+ * Tell whether a value is a MDB2 result implementing the common interface
+ *
+ * @param mixed $value value to test
+ *
+ * @return bool whether $value is a MDB2 result implementing the common interface
+ *
+ * @access public
+ */
+ static function isResultCommon($value)
+ {
+ return ($value instanceof MDB2_Result_Common);
+ }
+
+ // }}}
+ // {{{ function isStatement($value)
+
+ /**
+ * Tell whether a value is a MDB2 statement interface
+ *
+ * @param mixed value to test
+ *
+ * @return bool whether $value is a MDB2 statement interface
+ *
+ * @access public
+ */
+ function isStatement($value)
+ {
+ return ($value instanceof MDB2_Statement_Common);
+ }
+
+ // }}}
+ // {{{ function errorMessage($value = null)
+
+ /**
+ * Return a textual error message for a MDB2 error code
+ *
+ * @param int|array integer error code,
+ null to get the current error code-message map,
+ or an array with a new error code-message map
+ *
+ * @return string error message, or false if the error code was
+ * not recognized
+ *
+ * @access public
+ */
+ static function errorMessage($value = null)
+ {
+ static $errorMessages;
+
+ if (is_array($value)) {
+ $errorMessages = $value;
+ return MDB2_OK;
+ }
+
+ if (!isset($errorMessages)) {
+ $errorMessages = array(
+ MDB2_OK => 'no error',
+ MDB2_ERROR => 'unknown error',
+ MDB2_ERROR_ALREADY_EXISTS => 'already exists',
+ MDB2_ERROR_CANNOT_CREATE => 'can not create',
+ MDB2_ERROR_CANNOT_ALTER => 'can not alter',
+ MDB2_ERROR_CANNOT_REPLACE => 'can not replace',
+ MDB2_ERROR_CANNOT_DELETE => 'can not delete',
+ MDB2_ERROR_CANNOT_DROP => 'can not drop',
+ MDB2_ERROR_CONSTRAINT => 'constraint violation',
+ MDB2_ERROR_CONSTRAINT_NOT_NULL=> 'null value violates not-null constraint',
+ MDB2_ERROR_DIVZERO => 'division by zero',
+ MDB2_ERROR_INVALID => 'invalid',
+ MDB2_ERROR_INVALID_DATE => 'invalid date or time',
+ MDB2_ERROR_INVALID_NUMBER => 'invalid number',
+ MDB2_ERROR_MISMATCH => 'mismatch',
+ MDB2_ERROR_NODBSELECTED => 'no database selected',
+ MDB2_ERROR_NOSUCHFIELD => 'no such field',
+ MDB2_ERROR_NOSUCHTABLE => 'no such table',
+ MDB2_ERROR_NOT_CAPABLE => 'MDB2 backend not capable',
+ MDB2_ERROR_NOT_FOUND => 'not found',
+ MDB2_ERROR_NOT_LOCKED => 'not locked',
+ MDB2_ERROR_SYNTAX => 'syntax error',
+ MDB2_ERROR_UNSUPPORTED => 'not supported',
+ MDB2_ERROR_VALUE_COUNT_ON_ROW => 'value count on row',
+ MDB2_ERROR_INVALID_DSN => 'invalid DSN',
+ MDB2_ERROR_CONNECT_FAILED => 'connect failed',
+ MDB2_ERROR_NEED_MORE_DATA => 'insufficient data supplied',
+ MDB2_ERROR_EXTENSION_NOT_FOUND=> 'extension not found',
+ MDB2_ERROR_NOSUCHDB => 'no such database',
+ MDB2_ERROR_ACCESS_VIOLATION => 'insufficient permissions',
+ MDB2_ERROR_LOADMODULE => 'error while including on demand module',
+ MDB2_ERROR_TRUNCATED => 'truncated',
+ MDB2_ERROR_DEADLOCK => 'deadlock detected',
+ MDB2_ERROR_NO_PERMISSION => 'no permission',
+ MDB2_ERROR_DISCONNECT_FAILED => 'disconnect failed',
+ );
+ }
+
+ if (null === $value) {
+ return $errorMessages;
+ }
+
+ if (MDB2::isError($value)) {
+ $value = $value->getCode();
+ }
+
+ return isset($errorMessages[$value]) ?
+ $errorMessages[$value] : $errorMessages[MDB2_ERROR];
+ }
+
+ // }}}
+ // {{{ function parseDSN($dsn)
+
+ /**
+ * 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:
+ *
+ * phptype(dbsyntax)://username:password@protocol+hostspec/database?option=8&another=true
+ *
+ *
+ * Most variations are allowed:
+ *
+ * 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
+ *
+ *
+ * @param string 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
+ *
+ * @access public
+ * @author Tomas V.V.Cox
+ */
+ static function parseDSN($dsn)
+ {
+ $parsed = $GLOBALS['_MDB2_dsninfo_default'];
+
+ 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
+
+ // $dsn => proto(proto_opts)/database
+ if (preg_match('|^([^(]+)\((.*?)\)/?(.*?)$|', $dsn, $match)) {
+ $proto = $match[1];
+ $proto_opts = $match[2] ? $match[2] : false;
+ $dsn = $match[3];
+
+ // $dsn => protocol+hostspec/database (old format)
+ } else {
+ if (strpos($dsn, '+') !== false) {
+ list($proto, $dsn) = explode('+', $dsn, 2);
+ }
+ if ( strpos($dsn, '//') === 0
+ && strpos($dsn, '/', 2) !== false
+ && $parsed['phptype'] == 'oci8'
+ ) {
+ //oracle's "Easy Connect" syntax:
+ //"username/password@[//]host[:port][/service_name]"
+ //e.g. "scott/tiger@//mymachine:1521/oracle"
+ $proto_opts = $dsn;
+ $pos = strrpos($proto_opts, '/');
+ $dsn = substr($proto_opts, $pos + 1);
+ $proto_opts = substr($proto_opts, 0, $pos);
+ } elseif (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 (strpos($proto_opts, ':') !== false) {
+ list($proto_opts, $parsed['port']) = explode(':', $proto_opts);
+ }
+ if ($parsed['protocol'] == 'tcp') {
+ $parsed['hostspec'] = $proto_opts;
+ } elseif ($parsed['protocol'] == 'unix') {
+ $parsed['socket'] = $proto_opts;
+ }
+
+ // Get dabase if any
+ // $dsn => database
+ if ($dsn) {
+ // /database
+ if (($pos = strpos($dsn, '?')) === false) {
+ $parsed['database'] = rawurldecode($dsn);
+ // /database?param1=value1¶m2=value2
+ } else {
+ $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 (!array_key_exists($key, $parsed) || false === $parsed[$key]) {
+ // don't allow params overwrite
+ $parsed[$key] = rawurldecode($value);
+ }
+ }
+ }
+ }
+
+ return $parsed;
+ }
+
+ // }}}
+ // {{{ function fileExists($file)
+
+ /**
+ * Checks if a file exists in the include path
+ *
+ * @param string filename
+ *
+ * @return bool true success and false on error
+ *
+ * @access public
+ */
+ static function fileExists($file)
+ {
+ // safe_mode does notwork with is_readable()
+ if (!@ini_get('safe_mode')) {
+ $dirs = explode(PATH_SEPARATOR, ini_get('include_path'));
+ foreach ($dirs as $dir) {
+ if (is_readable($dir . DIRECTORY_SEPARATOR . $file)) {
+ return true;
+ }
+ }
+ } else {
+ $fp = @fopen($file, 'r', true);
+ if (is_resource($fp)) {
+ @fclose($fp);
+ return true;
+ }
+ }
+ return false;
+ }
+ // }}}
+}
+
+// }}}
+// {{{ class MDB2_Error extends PEAR_Error
+
+/**
+ * MDB2_Error implements a class for reporting portable database error
+ * messages.
+ *
+ * @package MDB2
+ * @category Database
+ * @author Stig Bakken
+ */
+class MDB2_Error extends PEAR_Error
+{
+ // {{{ constructor: function MDB2_Error($code = MDB2_ERROR, $mode = PEAR_ERROR_RETURN, $level = E_USER_NOTICE, $debuginfo = null)
+
+ /**
+ * MDB2_Error constructor.
+ *
+ * @param mixed MDB2 error code, or string with error message.
+ * @param int what 'error mode' to operate in
+ * @param int what error level to use for $mode & PEAR_ERROR_TRIGGER
+ * @param mixed additional debug info, such as the last query
+ */
+ function __construct($code = MDB2_ERROR, $mode = PEAR_ERROR_RETURN,
+ $level = E_USER_NOTICE, $debuginfo = null, $dummy = null)
+ {
+ if (null === $code) {
+ $code = MDB2_ERROR;
+ }
+ $this->PEAR_Error('MDB2 Error: '.MDB2::errorMessage($code), $code,
+ $mode, $level, $debuginfo);
+ }
+
+ // }}}
+}
+
+// }}}
+// {{{ class MDB2_Driver_Common extends PEAR
+
+/**
+ * MDB2_Driver_Common: Base class that is extended by each MDB2 driver
+ *
+ * @package MDB2
+ * @category Database
+ * @author Lukas Smith
+ */
+class MDB2_Driver_Common
+{
+ // {{{ Variables (Properties)
+
+ /**
+ * @var MDB2_Driver_Datatype_Common
+ */
+ public $datatype;
+
+ /**
+ * @var MDB2_Extended
+ */
+ public $extended;
+
+ /**
+ * @var MDB2_Driver_Function_Common
+ */
+ public $function;
+
+ /**
+ * @var MDB2_Driver_Manager_Common
+ */
+ public $manager;
+
+ /**
+ * @var MDB2_Driver_Native_Commonn
+ */
+ public $native;
+
+ /**
+ * @var MDB2_Driver_Reverse_Common
+ */
+ public $reverse;
+
+ /**
+ * index of the MDB2 object within the $GLOBALS['_MDB2_databases'] array
+ * @var int
+ * @access public
+ */
+ public $db_index = 0;
+
+ /**
+ * DSN used for the next query
+ * @var array
+ * @access protected
+ */
+ public $dsn = array();
+
+ /**
+ * DSN that was used to create the current connection
+ * @var array
+ * @access protected
+ */
+ public $connected_dsn = array();
+
+ /**
+ * connection resource
+ * @var mixed
+ * @access protected
+ */
+ public $connection = 0;
+
+ /**
+ * if the current opened connection is a persistent connection
+ * @var bool
+ * @access protected
+ */
+ public $opened_persistent;
+
+ /**
+ * the name of the database for the next query
+ * @var string
+ * @access public
+ */
+ public $database_name = '';
+
+ /**
+ * the name of the database currently selected
+ * @var string
+ * @access protected
+ */
+ public $connected_database_name = '';
+
+ /**
+ * server version information
+ * @var string
+ * @access protected
+ */
+ public $connected_server_info = '';
+
+ /**
+ * list of all supported features of the given driver
+ * @var array
+ * @access public
+ */
+ public $supported = array(
+ 'sequences' => false,
+ 'indexes' => false,
+ 'affected_rows' => false,
+ 'summary_functions' => false,
+ 'order_by_text' => false,
+ 'transactions' => false,
+ 'savepoints' => false,
+ 'current_id' => false,
+ 'limit_queries' => false,
+ 'LOBs' => false,
+ 'replace' => false,
+ 'sub_selects' => false,
+ 'triggers' => false,
+ 'auto_increment' => false,
+ 'primary_key' => false,
+ 'result_introspection' => false,
+ 'prepared_statements' => false,
+ 'identifier_quoting' => false,
+ 'pattern_escaping' => false,
+ 'new_link' => false,
+ );
+
+ /**
+ * Array of supported options that can be passed to the MDB2 instance.
+ *
+ * The options can be set during object creation, using
+ * MDB2::connect(), MDB2::factory() or MDB2::singleton(). The options can
+ * also be set after the object is created, using MDB2::setOptions() or
+ * MDB2_Driver_Common::setOption().
+ * The list of available option includes:
+ *
+ *
$options['ssl'] -> boolean: determines if ssl should be used for connections
+ *
$options['field_case'] -> CASE_LOWER|CASE_UPPER: determines what case to force on field/table names
+ *
$options['disable_query'] -> boolean: determines if queries should be executed
+ *
$options['result_class'] -> string: class used for result sets
+ *
$options['buffered_result_class'] -> string: class used for buffered result sets
+ *
$options['result_wrap_class'] -> string: class used to wrap result sets into
+ *
$options['result_buffering'] -> boolean should results be buffered or not?
+ *
$options['fetch_class'] -> string: class to use when fetch mode object is used