diff options
author | Robin Appelman <icewind@owncloud.com> | 2012-01-30 16:39:51 +0400 |
---|---|---|
committer | Robin Appelman <icewind@owncloud.com> | 2012-01-30 16:39:51 +0400 |
commit | 686590bd3a510efc0cf2752a3d0fd48d536f787d (patch) | |
tree | 662fef8f57ee4c0511e949cc559ac24e33ed51d2 /lib | |
parent | 40ba508874f0e87d2d6709fa6d13107c5a49972b (diff) | |
parent | 039bbfde2d2e1efc90fa9828811566ea1f328722 (diff) |
merge master into stable
Diffstat (limited to 'lib')
-rw-r--r-- | lib/MDB2/Driver/Datatype/sqlite3.php | 65 | ||||
-rw-r--r-- | lib/MDB2/Driver/Function/sqlite3.php | 64 | ||||
-rw-r--r-- | lib/MDB2/Driver/Manager/sqlite3.php | 154 | ||||
-rw-r--r-- | lib/MDB2/Driver/Native/sqlite3.php | 64 | ||||
-rw-r--r-- | lib/MDB2/Driver/Reverse/sqlite3.php | 81 | ||||
-rw-r--r-- | lib/MDB2/Driver/sqlite3.php | 64 | ||||
-rw-r--r-- | lib/app.php | 54 | ||||
-rw-r--r-- | lib/appconfig.php | 2 | ||||
-rw-r--r-- | lib/base.php | 110 | ||||
-rw-r--r-- | lib/config.php | 3 | ||||
-rw-r--r-- | lib/db.php | 447 | ||||
-rw-r--r-- | lib/files.php | 25 | ||||
-rw-r--r-- | lib/filestorage/local.php | 21 | ||||
-rw-r--r-- | lib/filestorage/remote.php | 2 | ||||
-rw-r--r-- | lib/filesystem.php | 212 | ||||
-rw-r--r-- | lib/helper.php | 33 | ||||
-rw-r--r-- | lib/hook.php | 2 | ||||
-rw-r--r-- | lib/image.php | 557 | ||||
-rw-r--r-- | lib/installer.php | 24 | ||||
-rw-r--r-- | lib/l10n.php | 16 | ||||
-rw-r--r-- | lib/log.php | 74 | ||||
-rw-r--r-- | lib/mimetypes.fixlist.php | 14 | ||||
-rw-r--r-- | lib/ocsclient.php | 29 | ||||
-rw-r--r-- | lib/preferences.php | 1 | ||||
-rw-r--r-- | lib/remote/cloud.php | 8 | ||||
-rw-r--r-- | lib/setup.php | 74 | ||||
-rw-r--r-- | lib/template.php | 27 | ||||
-rw-r--r-- | lib/updater.php | 11 | ||||
-rw-r--r-- | lib/user.php | 5 | ||||
-rw-r--r-- | lib/util.php | 67 | ||||
-rw-r--r-- | lib/vobject.php | 207 |
31 files changed, 1846 insertions, 671 deletions
diff --git a/lib/MDB2/Driver/Datatype/sqlite3.php b/lib/MDB2/Driver/Datatype/sqlite3.php index 378d5540cbe..d74badbe4f1 100644 --- a/lib/MDB2/Driver/Datatype/sqlite3.php +++ b/lib/MDB2/Driver/Datatype/sqlite3.php @@ -1,49 +1,24 @@ <?php -// vim: set et ts=4 sw=4 fdm=marker: -// +----------------------------------------------------------------------+ -// | PHP version 5 | -// +----------------------------------------------------------------------+ -// | Copyright (c) 2011 Robin Appelman | -// | All rights reserved. | -// +----------------------------------------------------------------------+ -// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB | -// | API as well as database abstraction for PHP applications. | -// | This LICENSE is in the BSD license style. | -// | | -// | 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. | -// | | -// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, | -// | Lukas Smith nor the names of his contributors may be used to endorse | -// | or promote products derived from this software without specific prior| -// | written permission. | -// | | -// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | -// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | -// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | -// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | -// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | -// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | -// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS| -// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | -// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | -// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY| -// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | -// | POSSIBILITY OF SUCH DAMAGE. | -// +----------------------------------------------------------------------+ -// | Author: Robin Appelman <icewind1991@gmail.com | -// +----------------------------------------------------------------------+ -// -// $Id: sqlite.php,v 1.67 2008/02/22 19:58:06 quipo Exp $ -// +/** + * ownCloud + * + * @author Robin Appelman + * @copyright 2011 Robin Appelman icewind1991@gmail.com + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + */ require_once('MDB2/Driver/Datatype/Common.php'); diff --git a/lib/MDB2/Driver/Function/sqlite3.php b/lib/MDB2/Driver/Function/sqlite3.php index 0d6b329f0ad..a013aea165a 100644 --- a/lib/MDB2/Driver/Function/sqlite3.php +++ b/lib/MDB2/Driver/Function/sqlite3.php @@ -1,48 +1,24 @@ <?php -// vim: set et ts=4 sw=4 fdm=marker: -// +----------------------------------------------------------------------+ -// | PHP versions 5 | -// +----------------------------------------------------------------------+ -// | Copyright (c) 2011 Robin Appelman | -// | All rights reserved. | -// +----------------------------------------------------------------------+ -// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB | -// | API as well as database abstraction for PHP applications. | -// | This LICENSE is in the BSD license style. | -// | | -// | 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. | -// | | -// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, | -// | Lukas Smith nor the names of his contributors may be used to endorse | -// | or promote products derived from this software without specific prior| -// | written permission. | -// | | -// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | -// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | -// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | -// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | -// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | -// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | -// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS| -// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | -// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | -// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY| -// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | -// | POSSIBILITY OF SUCH DAMAGE. | -// +----------------------------------------------------------------------+ -// | Author: Robin Appelman <icewind1991@gmail.com> | -// +----------------------------------------------------------------------+ -// -// +/** + * ownCloud + * + * @author Robin Appelman + * @copyright 2011 Robin Appelman icewind1991@gmail.com + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + */ require_once('MDB2/Driver/Function/Common.php'); diff --git a/lib/MDB2/Driver/Manager/sqlite3.php b/lib/MDB2/Driver/Manager/sqlite3.php index eabbb72b3c2..8f4e1312eb8 100644 --- a/lib/MDB2/Driver/Manager/sqlite3.php +++ b/lib/MDB2/Driver/Manager/sqlite3.php @@ -1,48 +1,24 @@ <?php -// vim: set et ts=4 sw=4 fdm=marker: -// +----------------------------------------------------------------------+ -// | PHP versions 5 | -// +----------------------------------------------------------------------+ -// | Copyright (c) 2011 Robin Appelman | -// | All rights reserved. | -// +----------------------------------------------------------------------+ -// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB | -// | API as well as database abstraction for PHP applications. | -// | This LICENSE is in the BSD license style. | -// | | -// | 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. | -// | | -// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, | -// | Lukas Smith nor the names of his contributors may be used to endorse | -// | or promote products derived from this software without specific prior| -// | written permission. | -// | | -// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | -// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | -// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | -// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | -// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | -// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | -// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS| -// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | -// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | -// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY| -// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | -// | POSSIBILITY OF SUCH DAMAGE. | -// +----------------------------------------------------------------------+ -// | Author: Robin Appelman <icewind1991@gmail.com> | -// +----------------------------------------------------------------------+ -// -// +/** + * ownCloud + * + * @author Robin Appelman + * @copyright 2011 Robin Appelman icewind1991@gmail.com + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + */ require_once('MDB2/Driver/Manager/Common.php'); @@ -192,9 +168,6 @@ class MDB2_Driver_Manager_sqlite3 extends MDB2_Driver_Manager_Common if (PEAR::isError($query_fields)) { return $query_fields; } - if (!empty($options['primary'])) { - $query_fields.= ', PRIMARY KEY ('.implode(', ', array_keys($options['primary'])).')'; - } if (!empty($options['foreign_keys'])) { foreach ($options['foreign_keys'] as $fkname => $fkdef) { if (empty($fkdef)) { @@ -558,9 +531,26 @@ class MDB2_Driver_Manager_sqlite3 extends MDB2_Driver_Manager_Common return MDB2_OK; } + if (empty($changes['remove']) and empty($changes['rename']) and empty($changes['change']) ){//if only rename or add changes are required, we can use ALTER TABLE + $query = ''; + if (!empty($changes['name'])) { + $change_name = $db->quoteIdentifier($changes['name'], true); + $query = 'RENAME TO ' . $change_name; + $db->exec("ALTER TABLE $name $query"); + } + + if (!empty($changes['add']) && is_array($changes['add'])) { + foreach ($changes['add'] as $field_name => $field) { + $query= 'ADD ' . $db->getDeclaration($field['type'], $field_name, $field); + $db->exec("ALTER TABLE $name $query"); + } + } + return MDB2_OK; + } + $db->loadModule('Reverse', null, true); - // actually sqlite 2.x supports no ALTER TABLE at all .. so we emulate it + // for other operations we need to emulate them with sqlite3 $fields = $db->manager->listTableFields($name); if (PEAR::isError($fields)) { return $fields; @@ -660,44 +650,54 @@ class MDB2_Driver_Manager_sqlite3 extends MDB2_Driver_Manager_Common } } + //rename the old table so we can create the new one + $db->exec("ALTER TABLE $name RENAME TO __$name"); $data = null; - if (!empty($select_fields)) { - $query = 'SELECT '.implode(', ', $select_fields).' FROM '.$db->quoteIdentifier($name, true); - $data = $db->queryAll($query, null, MDB2_FETCHMODE_ORDERED); - } - $result = $this->dropTable($name); - if (PEAR::isError($result)) { - return $result; - } $result = $this->createTable($name_new, $fields, $options); if (PEAR::isError($result)) { return $result; } - foreach ($indexes as $index => $definition) { - $this->createIndex($name_new, $index, $definition); - } + //these seem to only give errors - foreach ($constraints as $constraint => $definition) { - $this->createConstraint($name_new, $constraint, $definition); - } +// foreach ($indexes as $index => $definition) { +// $this->createIndex($name_new, $index, $definition); +// } - if (!empty($select_fields) && !empty($data)) { - $query = 'INSERT INTO '.$db->quoteIdentifier($name_new, true); - $query.= '('.implode(', ', array_slice(array_keys($fields), 0, count($select_fields))).')'; - $query.=' VALUES (?'.str_repeat(', ?', (count($select_fields) - 1)).')'; - $stmt =$db->prepare($query, null, MDB2_PREPARE_MANIP); - if (PEAR::isError($stmt)) { - return $stmt; - } - foreach ($data as $row) { - $result = $stmt->execute($row); - if (PEAR::isError($result)) { - return $result; - } - } +// foreach ($constraints as $constraint => $definition) { +// $this->createConstraint($name_new, $constraint, $definition); +// } + + //fill the new table with data from the old one + if (!empty($select_fields)) { + $query = 'INSERT INTO '.$db->quoteIdentifier($name_new, true); + $query.= '('.implode(', ', array_slice(array_keys($fields), 0, count($select_fields))).')'; + $query .= ' SELECT '.implode(', ', $select_fields).' FROM '.$db->quoteIdentifier('__'.$name, true); + $db->exec($query); + } + +// if (!empty($select_fields) && !empty($data)) { +// $query = 'INSERT INTO '.$db->quoteIdentifier($name_new, true); +// $query.= '('.implode(', ', array_slice(array_keys($fields), 0, count($select_fields))).')'; +// $query.=' VALUES (?'.str_repeat(', ?', (count($select_fields) - 1)).')'; +// $stmt =$db->prepare($query, null, MDB2_PREPARE_MANIP); +// if (PEAR::isError($stmt)) { +// return $stmt; +// } +// foreach ($data as $row) { +// $result = $stmt->execute($row); +// if (PEAR::isError($result)) { +// return $result; +// } +// } +// } + + //remove the old table + $result = $this->dropTable('__'.$name); + if (PEAR::isError($result)) { + return $result; } return MDB2_OK; } @@ -822,7 +822,7 @@ class MDB2_Driver_Manager_sqlite3 extends MDB2_Driver_Manager_Common return $db; } - $query = "SELECT name FROM sqlite_master WHERE type='table' AND sql NOT NULL ORDER BY name"; + $query = "SELECT name FROM sqlite_master WHERE type='table' AND sql NOT NULL AND name!='sqlite_sequence' ORDER BY name"; $table_names = $db->queryCol($query); if (PEAR::isError($table_names)) { return $table_names; diff --git a/lib/MDB2/Driver/Native/sqlite3.php b/lib/MDB2/Driver/Native/sqlite3.php index 81dc67dea65..de650107238 100644 --- a/lib/MDB2/Driver/Native/sqlite3.php +++ b/lib/MDB2/Driver/Native/sqlite3.php @@ -1,48 +1,24 @@ <?php -// vim: set et ts=4 sw=4 fdm=marker: -// +----------------------------------------------------------------------+ -// | PHP versions 5 | -// +----------------------------------------------------------------------+ -// | Copyright (c) 2011 Robin Appelman | -// | All rights reserved. | -// +----------------------------------------------------------------------+ -// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB | -// | API as well as database abstraction for PHP applications. | -// | This LICENSE is in the BSD license style. | -// | | -// | 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. | -// | | -// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, | -// | Lukas Smith nor the names of his contributors may be used to endorse | -// | or promote products derived from this software without specific prior| -// | written permission. | -// | | -// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | -// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | -// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | -// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | -// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | -// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | -// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS| -// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | -// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | -// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY| -// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | -// | POSSIBILITY OF SUCH DAMAGE. | -// +----------------------------------------------------------------------+ -// | Author: Robin Appelman <icewind1991@gmail.com> | -// +----------------------------------------------------------------------+ -// -// +/** + * ownCloud + * + * @author Robin Appelman + * @copyright 2011 Robin Appelman icewind1991@gmail.com + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + */ require_once 'MDB2/Driver/Native/Common.php'; /** diff --git a/lib/MDB2/Driver/Reverse/sqlite3.php b/lib/MDB2/Driver/Reverse/sqlite3.php index d488977b158..33e5b590268 100644 --- a/lib/MDB2/Driver/Reverse/sqlite3.php +++ b/lib/MDB2/Driver/Reverse/sqlite3.php @@ -1,48 +1,24 @@ <?php -// vim: set et ts=4 sw=4 fdm=marker: -// +----------------------------------------------------------------------+ -// | PHP versions 5 | -// +----------------------------------------------------------------------+ -// | Copyright (c) 2011 Robin Appelman | -// | All rights reserved. | -// +----------------------------------------------------------------------+ -// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB | -// | API as well as database abstraction for PHP applications. | -// | This LICENSE is in the BSD license style. | -// | | -// | 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. | -// | | -// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, | -// | Lukas Smith nor the names of his contributors may be used to endorse | -// | or promote products derived from this software without specific prior| -// | written permission. | -// | | -// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | -// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | -// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | -// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | -// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | -// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | -// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS| -// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | -// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | -// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY| -// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | -// | POSSIBILITY OF SUCH DAMAGE. | -// +----------------------------------------------------------------------+ -// | Author: Robin Appelman <icewind1991@gmail.com> | -// +----------------------------------------------------------------------+ -// -// +/** + * ownCloud + * + * @author Robin Appelman + * @copyright 2011 Robin Appelman icewind1991@gmail.com + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + */ require_once('MDB2/Driver/Reverse/Common.php'); @@ -93,7 +69,7 @@ class MDB2_Driver_Reverse_sqlite3 extends MDB2_Driver_Reverse_Common return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, 'unexpected empty table column definition list', __FUNCTION__); } - $regexp = '/^\s*([^\s]+) +(CHAR|VARCHAR|VARCHAR2|TEXT|BOOLEAN|SMALLINT|INT|INTEGER|DECIMAL|BIGINT|DOUBLE|FLOAT|DATETIME|DATE|TIME|LONGTEXT|LONGBLOB)( ?\(([1-9][0-9]*)(:([1-9][0-9]*))?\))?( NULL| NOT NULL)?( UNSIGNED)?( NULL| NOT NULL)?( PRIMARY KEY)?( DEFAULT (\'[^\']*\'|[^ ]+))?( NULL| NOT NULL)?( PRIMARY KEY)?(\s*\-\-.*)?$/i'; + $regexp = '/^\s*([^\s]+) +(CHAR|VARCHAR|VARCHAR2|TEXT|BOOLEAN|SMALLINT|INT|INTEGER|DECIMAL|BIGINT|DOUBLE|FLOAT|DATETIME|DATE|TIME|LONGTEXT|LONGBLOB)( ?\(([1-9][0-9]*)(:([1-9][0-9]*))?\))?( NULL| NOT NULL)?( UNSIGNED)?( NULL| NOT NULL)?( PRIMARY KEY)?( AUTOINCREMENT)?( DEFAULT (\'[^\']*\'|[^ ]+))?( NULL| NOT NULL)?( PRIMARY KEY)?(\s*\-\-.*)?$/i'; $regexp2 = '/^\s*([^ ]+) +(PRIMARY|UNIQUE|CHECK)$/i'; for ($i=0, $j=0; $i<$count; ++$i) { if (!preg_match($regexp, trim($column_sql[$i]), $matches)) { @@ -114,11 +90,16 @@ class MDB2_Driver_Reverse_sqlite3 extends MDB2_Driver_Reverse_Common if (isset($matches[8]) && strlen($matches[8])) { $columns[$j]['unsigned'] = true; } - if (isset($matches[9]) && strlen($matches[9])) { + if (isset($matches[10]) && strlen($matches[10])) { + $columns[$j]['autoincrement'] = true; + $columns[$j]['notnull']=true; + } + if (isset($matches[10]) && strlen($matches[10])) { $columns[$j]['autoincrement'] = true; + $columns[$j]['notnull']=true; } - if (isset($matches[12]) && strlen($matches[12])) { - $default = $matches[12]; + if (isset($matches[13]) && strlen($matches[13])) { + $default = $matches[13]; if (strlen($default) && $default[0]=="'") { $default = str_replace("''", "'", substr($default, 1, strlen($default)-2)); } @@ -131,8 +112,8 @@ class MDB2_Driver_Reverse_sqlite3 extends MDB2_Driver_Reverse_Common $columns[$j]['notnull'] = ($matches[7] === ' NOT NULL'); } else if (isset($matches[9]) && strlen($matches[9])) { $columns[$j]['notnull'] = ($matches[9] === ' NOT NULL'); - } else if (isset($matches[13]) && strlen($matches[13])) { - $columns[$j]['notnull'] = ($matches[13] === ' NOT NULL'); + } else if (isset($matches[14]) && strlen($matches[14])) { + $columns[$j]['notnull'] = ($matches[14] === ' NOT NULL'); } ++$j; } diff --git a/lib/MDB2/Driver/sqlite3.php b/lib/MDB2/Driver/sqlite3.php index a41aeed4850..e42d36176c4 100644 --- a/lib/MDB2/Driver/sqlite3.php +++ b/lib/MDB2/Driver/sqlite3.php @@ -1,48 +1,24 @@ <?php -// vim: set et ts=4 sw=4 fdm=marker: -// +----------------------------------------------------------------------+ -// | PHP versions 5 | -// +----------------------------------------------------------------------+ -// | Copyright (c) 2011 Robin Appelman | -// | All rights reserved. | -// +----------------------------------------------------------------------+ -// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB | -// | API as well as database abstraction for PHP applications. | -// | This LICENSE is in the BSD license style. | -// | | -// | 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. | -// | | -// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, | -// | Lukas Smith nor the names of his contributors may be used to endorse | -// | or promote products derived from this software without specific prior| -// | written permission. | -// | | -// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | -// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | -// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | -// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | -// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | -// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | -// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS| -// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | -// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | -// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY| -// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | -// | POSSIBILITY OF SUCH DAMAGE. | -// +----------------------------------------------------------------------+ -// | Author: Robin Appelman <icewind1991@gmail.com> | -// +----------------------------------------------------------------------+ -// -// +/** + * ownCloud + * + * @author Robin Appelman + * @copyright 2011 Robin Appelman icewind1991@gmail.com + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + */ /** * MDB2 SQLite3 driver diff --git a/lib/app.php b/lib/app.php index b9eea483a55..37a99823e3d 100644 --- a/lib/app.php +++ b/lib/app.php @@ -94,19 +94,28 @@ class OC_App{ */ public static function enable( $app ){ if(!OC_Installer::isInstalled($app)){ - OC_Installer::installShippedApp($app); + // check if app is a shipped app or not. OCS apps have an integer as id, shipped apps use a string + if(!is_numeric($app)){ + OC_Installer::installShippedApp($app); + }else{ + $download=OC_OCSClient::getApplicationDownload($app,1); + if(isset($download['downloadlink']) and $download['downloadlink']<>'') { + $app=OC_Installer::installApp(array('source'=>'http','href'=>$download['downloadlink'])); + } + } } OC_Appconfig::setValue( $app, 'enabled', 'yes' ); } /** - * @brief enables an app + * @brief disables an app * @param $app app * @returns true/false * - * This function set an app as enabled in appconfig. + * This function set an app as disabled in appconfig. */ public static function disable( $app ){ + // check if app is a shiped app or not. if not delete OC_Appconfig::setValue( $app, 'enabled', 'no' ); } @@ -222,11 +231,10 @@ class OC_App{ $settings[] = array( "id" => "core_users", "order" => 2, "href" => OC_Helper::linkTo( "settings", "users.php" ), "name" => $l->t("Users"), "icon" => OC_Helper::imagePath( "settings", "users.svg" )); // admin apps menu $settings[] = array( "id" => "core_apps", "order" => 3, "href" => OC_Helper::linkTo( "settings", "apps.php?installed" ), "name" => $l->t("Apps"), "icon" => OC_Helper::imagePath( "settings", "apps.svg" )); + // admin log menu + $settings[] = array( "id" => "core_log", "order" => 4, "href" => OC_Helper::linkTo( "settings", "log.php" ), "name" => $l->t("Log"), "icon" => OC_Helper::imagePath( "settings", "log.svg" )); - // if there're some admin forms - if(!empty(self::$adminForms)) - // admins menu - $settings[]=array( "id" => "admin", "order" => 1000, "href" => OC_Helper::linkTo( "settings", "admin.php" ), "name" => $l->t("Admin"), "icon" => OC_Helper::imagePath( "settings", "admin.svg" )); + $settings[]=array( "id" => "admin", "order" => 1000, "href" => OC_Helper::linkTo( "settings", "admin.php" ), "name" => $l->t("Admin"), "icon" => OC_Helper::imagePath( "settings", "admin.svg" )); } } @@ -363,4 +371,36 @@ class OC_App{ } return $apps; } + + /** + * check if any apps need updating and update those + */ + public static function updateApps(){ + // The rest comes here + $apps = OC_Appconfig::getApps(); + foreach( $apps as $app ){ + $installedVersion=OC_Appconfig::getValue($app,'installed_version'); + $appInfo=OC_App::getAppInfo($app); + if (isset($appInfo['version'])) { + $currentVersion=$appInfo['version']; + if (version_compare($currentVersion, $installedVersion, '>')) { + OC_App::updateApp($app); + OC_Appconfig::setValue($app,'installed_version',$appInfo['version']); + } + } + } + } + + /** + * update the database for the app and call the update script + * @param string appid + */ + public static function updateApp($appid){ + if(file_exists(OC::$SERVERROOT.'/apps/'.$appid.'/appinfo/database.xml')){ + OC_DB::updateDbFromStructure(OC::$SERVERROOT.'/apps/'.$appid.'/appinfo/database.xml'); + } + if(file_exists(OC::$SERVERROOT.'/apps/'.$appid.'/appinfo/update.php')){ + include OC::$SERVERROOT.'/apps/'.$appid.'/appinfo/update.php'; + } + } } diff --git a/lib/appconfig.php b/lib/appconfig.php index f43ef141732..2b5cef59adc 100644 --- a/lib/appconfig.php +++ b/lib/appconfig.php @@ -47,7 +47,7 @@ class OC_Appconfig{ */ public static function getApps(){ // No magic in here! - $query = OC_DB::prepare( 'SELECT DISTINCT( appid ) FROM *PREFIX*appconfig' ); + $query = OC_DB::prepare( 'SELECT DISTINCT appid FROM *PREFIX*appconfig' ); $result = $query->execute(); $apps = array(); diff --git a/lib/base.php b/lib/base.php index ade4d889631..ab7cb2990ed 100644 --- a/lib/base.php +++ b/lib/base.php @@ -70,6 +70,31 @@ class OC{ } } + /** + * autodetects the formfactor of the used device + * default -> the normal desktop browser interface + * mobile -> interface for smartphones + * tablet -> interface for tablets + * standalone -> the default interface but without header, footer and sidebar. just the application. useful to ue just a specific app on the desktop in a standalone window. + */ + public static function detectFormfactor(){ + // please add more useragent strings for other devices + if(isset($_SERVER['HTTP_USER_AGENT'])){ + if(stripos($_SERVER['HTTP_USER_AGENT'],'ipad')>0) { + $mode='tablet'; + }elseif(stripos($_SERVER['HTTP_USER_AGENT'],'iphone')>0){ + $mode='mobile'; + }elseif((stripos($_SERVER['HTTP_USER_AGENT'],'N9')>0) and (stripos($_SERVER['HTTP_USER_AGENT'],'nokia')>0)){ + $mode='mobile'; + }else{ + $mode='default'; + } + }else{ + $mode='default'; + } + return($mode); + } + public static function init(){ // register autoloader spl_autoload_register(array('OC','autoload')); @@ -77,6 +102,9 @@ class OC{ // set some stuff //ob_start(); error_reporting(E_ALL | E_STRICT); + if (defined('DEBUG') && DEBUG){ + ini_set('display_errors', 1); + } date_default_timezone_set('Europe/Berlin'); ini_set('arg_separator.output','&'); @@ -89,6 +117,14 @@ class OC{ $_SERVER['PHP_AUTH_PW'] = strip_tags($password); } + //set http auth headers for apache+php-cgi work around if variable gets renamed by apache + if (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION']) && preg_match('/Basic\s+(.*)$/i', $_SERVER['REDIRECT_HTTP_AUTHORIZATION'], $matches)) + { + list($name, $password) = explode(':', base64_decode($matches[1])); + $_SERVER['PHP_AUTH_USER'] = strip_tags($name); + $_SERVER['PHP_AUTH_PW'] = strip_tags($password); + } + // calculate the documentroot OC::$DOCUMENTROOT=realpath($_SERVER['DOCUMENT_ROOT']); OC::$SERVERROOT=str_replace("\\",'/',substr(__FILE__,0,-13)); @@ -116,12 +152,37 @@ class OC{ } } + if(OC_Config::getValue('installed', false)){ + $installedVersion=OC_Config::getValue('version','0.0.0'); + $currentVersion=implode('.',OC_Util::getVersion()); + if (version_compare($currentVersion, $installedVersion, '>')) { + $result=OC_DB::updateDbFromStructure(OC::$SERVERROOT.'/db_structure.xml'); + if(!$result){ + echo 'Error while upgrading the database'; + die(); + } + OC_Config::setValue('version',implode('.',OC_Util::getVersion())); + } + + OC_App::updateApps(); + } + ini_set('session.cookie_httponly','1;'); session_start(); + // if the formfactor is not yet autodetected do the autodetection now. For possible forfactors check the detectFormfactor documentation + if(!isset($_SESSION['formfactor'])){ + $_SESSION['formfactor']=OC::detectFormfactor(); + } + // allow manual override via GET parameter + if(isset($_GET['formfactor'])){ + $_SESSION['formfactor']=$_GET['formfactor']; + } + + // Add the stuff we need always OC_Util::addScript( "jquery-1.6.4.min" ); - OC_Util::addScript( "jquery-ui-1.8.14.custom.min" ); + OC_Util::addScript( "jquery-ui-1.8.16.custom.min" ); OC_Util::addScript( "jquery-showpassword" ); OC_Util::addScript( "jquery.infieldlabel.min" ); OC_Util::addScript( "jquery-tipsy" ); @@ -130,7 +191,7 @@ class OC{ OC_Util::addScript('search','result'); OC_Util::addStyle( "styles" ); OC_Util::addStyle( "multiselect" ); - OC_Util::addStyle( "jquery-ui-1.8.14.custom" ); + OC_Util::addStyle( "jquery-ui-1.8.16.custom" ); OC_Util::addStyle( "jquery-tipsy" ); $errors=OC_Util::checkServer(); @@ -154,13 +215,6 @@ class OC{ OC_User::useBackend( OC_Config::getValue( "userbackend", "database" )); OC_Group::setBackend( OC_Config::getValue( "groupbackend", "database" )); - // Load Apps - // This includes plugins for users and filesystems as well - global $RUNTIME_NOAPPS; - if(!$RUNTIME_NOAPPS ){ - OC_App::loadApps(); - } - // Was in required file ... put it here OC_Filesystem::registerStorageType('local','OC_Filestorage_Local',array('datadir'=>'string')); @@ -170,6 +224,13 @@ class OC{ OC_Util::setupFS(); } + // Load Apps + // This includes plugins for users and filesystems as well + global $RUNTIME_NOAPPS; + if(!$RUNTIME_NOAPPS ){ + OC_App::loadApps(); + } + // Last part: connect some hooks OC_HOOK::connect('OC_User', 'post_createUser', 'OC_Connector_Sabre_Principal', 'addPrincipal'); OC_HOOK::connect('OC_User', 'post_deleteUser', 'OC_Connector_Sabre_Principal', 'deletePrincipal'); @@ -184,23 +245,26 @@ if( !isset( $RUNTIME_NOAPPS )){ $RUNTIME_NOAPPS = false; } -OC::init(); - -if(!function_exists('sys_get_temp_dir')) { - function sys_get_temp_dir() { - if( $temp=getenv('TMP') ) return $temp; - if( $temp=getenv('TEMP') ) return $temp; - if( $temp=getenv('TMPDIR') ) return $temp; - $temp=tempnam(__FILE__,''); - if (file_exists($temp)) { - unlink($temp); - return dirname($temp); - } - return null; - } +if(!function_exists('get_temp_dir')) { + function get_temp_dir() { + if( $temp=ini_get('upload_tmp_dir') ) return $temp; + if( $temp=getenv('TMP') ) return $temp; + if( $temp=getenv('TEMP') ) return $temp; + if( $temp=getenv('TMPDIR') ) return $temp; + $temp=tempnam(__FILE__,''); + if (file_exists($temp)) { + unlink($temp); + return dirname($temp); + } + return null; + } } +OC::init(); + require_once('fakedirstream.php'); + + // FROM search.php new OC_Search_Provider_File(); diff --git a/lib/config.php b/lib/config.php index 3aa69327f56..8d03271b3ea 100644 --- a/lib/config.php +++ b/lib/config.php @@ -94,7 +94,6 @@ class OC_Config{ // Write changes self::writeData(); - return true; } @@ -175,7 +174,7 @@ class OC_Config{ $result=@file_put_contents( OC::$SERVERROOT."/config/config.php", $content ); if(!$result) { $tmpl = new OC_Template( '', 'error', 'guest' ); - $tmpl->assign('errors',array(1=>array('error'=>"Can't write into config directory 'config'",'hint'=>"You can usually fix this by setting the owner of 'config' to the user that the web server uses (".OC_Util::checkWebserverUser().")"))); + $tmpl->assign('errors',array(1=>array('error'=>"Can't write into config directory 'config'",'hint'=>"You can usually fix this by giving the webserver use write access to the config directory in owncloud"))); $tmpl->printPage(); exit; } diff --git a/lib/db.php b/lib/db.php index 7ba08cb48d9..4860651b323 100644 --- a/lib/db.php +++ b/lib/db.php @@ -25,7 +25,13 @@ * MDB2 with some adaptions. */ class OC_DB { - static private $DBConnection=false; + const BACKEND_PDO=0; + const BACKEND_MDB2=1; + + static private $connection; //the prefered connection to use, either PDO or MDB2 + static private $backend=null; + static private $MDB2=false; + static private $PDO=false; static private $schema=false; static private $affected=0; static private $result=false; @@ -36,107 +42,164 @@ class OC_DB { * * Connects to the database as specified in config.php */ - static public function connect(){ + public static function connect($backend=null){ + if(self::$connection){ + return; + } + if(is_null($backend)){ + $backend=self::BACKEND_MDB2; + if(class_exists('PDO') && OC_Config::getValue('installed', false)){//check if we can use PDO, else use MDB2 (instalation always needs to be done my mdb2) + $type = OC_Config::getValue( "dbtype", "sqlite" ); + if($type=='sqlite3') $type='sqlite'; + $drivers=PDO::getAvailableDrivers(); + if(array_search($type,$drivers)!==false){ + $backend=self::BACKEND_PDO; + } + } + } + if($backend==self::BACKEND_PDO){ + self::connectPDO(); + self::$connection=self::$PDO; + self::$backend=self::BACKEND_PDO; + }else{ + self::connectMDB2(); + self::$connection=self::$MDB2; + self::$backend=self::BACKEND_MDB2; + } + } + + /** + * connect to the database using pdo + */ + public static function connectPDO(){ + if(self::$connection){ + if(self::$backend==self::BACKEND_MDB2){ + self::disconnect(); + }else{ + return; + } + } + // The global data we need + $name = OC_Config::getValue( "dbname", "owncloud" ); + $host = OC_Config::getValue( "dbhost", "" ); + $user = OC_Config::getValue( "dbuser", "" ); + $pass = OC_Config::getValue( "dbpassword", "" ); + $type = OC_Config::getValue( "dbtype", "sqlite" ); + $datadir=OC_Config::getValue( "datadirectory", OC::$SERVERROOT.'/data' ); + + // do nothing if the connection already has been established + if(!self::$PDO){ + // Add the dsn according to the database type + switch($type){ + case 'sqlite': + $dsn='sqlite2:'.$datadir.'/'.$name.'.db'; + break; + case 'sqlite3': + $dsn='sqlite:'.$datadir.'/'.$name.'.db'; + break; + case 'mysql': + $dsn='mysql:dbname='.$name.';host='.$host; + break; + case 'pgsql': + $dsn='pgsql:dbname='.$name.';host='.$host; + break; + } + try{ + self::$PDO=new PDO($dsn,$user,$pass); + }catch(PDOException $e){ + echo( '<b>can not connect to database, using '.$type.'. ('.$e->getMessage().')</center>'); + die(); + } + // We always, really always want associative arrays + self::$PDO->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE,PDO::FETCH_ASSOC); + self::$PDO->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION); + } + return true; + } + + /** + * connect to the database using mdb2 + */ + public static function connectMDB2(){ + if(self::$connection){ + if(self::$backend==self::BACKEND_PDO){ + self::disconnect(); + }else{ + return; + } + } // The global data we need - $CONFIG_DBNAME = OC_Config::getValue( "dbname", "owncloud" );; - $CONFIG_DBHOST = OC_Config::getValue( "dbhost", "" );; - $CONFIG_DBUSER = OC_Config::getValue( "dbuser", "" );; - $CONFIG_DBPASSWORD = OC_Config::getValue( "dbpassword", "" );; - $CONFIG_DBTYPE = OC_Config::getValue( "dbtype", "sqlite" );; - $datadir=OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" ); + $name = OC_Config::getValue( "dbname", "owncloud" ); + $host = OC_Config::getValue( "dbhost", "" ); + $user = OC_Config::getValue( "dbuser", "" ); + $pass = OC_Config::getValue( "dbpassword", "" ); + $type = OC_Config::getValue( "dbtype", "sqlite" ); + $SERVERROOT=OC::$SERVERROOT; + $datadir=OC_Config::getValue( "datadirectory", "$SERVERROOT/data" ); // do nothing if the connection already has been established - if(!self::$DBConnection){ + if(!self::$MDB2){ // Require MDB2.php (not required in the head of the file so we only load it when needed) require_once('MDB2.php'); // Prepare options array $options = array( - 'portability' => MDB2_PORTABILITY_ALL, + 'portability' => MDB2_PORTABILITY_ALL & (!MDB2_PORTABILITY_FIX_CASE), 'log_line_break' => '<br>', 'idxname_format' => '%s', 'debug' => true, 'quote_identifier' => true ); // Add the dsn according to the database type - if( $CONFIG_DBTYPE == 'sqlite' or $CONFIG_DBTYPE == 'sqlite3' ){ - // sqlite - $dsn = array( - 'phptype' => $CONFIG_DBTYPE, - 'database' => "$datadir/$CONFIG_DBNAME.db", - 'mode' => '0644' ); - } - elseif( $CONFIG_DBTYPE == 'mysql' ){ - // MySQL - $dsn = array( - 'phptype' => 'mysql', - 'username' => $CONFIG_DBUSER, - 'password' => $CONFIG_DBPASSWORD, - 'hostspec' => $CONFIG_DBHOST, - 'database' => $CONFIG_DBNAME ); + switch($type){ + case 'sqlite': + case 'sqlite3': + $dsn = array( + 'phptype' => $type, + 'database' => "$datadir/$name.db", + 'mode' => '0644' + ); + break; + case 'mysql': + $dsn = array( + 'phptype' => 'mysql', + 'username' => $user, + 'password' => $pass, + 'hostspec' => $host, + 'database' => $name + ); + break; + case 'pgsql': + $dsn = array( + 'phptype' => 'pgsql', + 'username' => $user, + 'password' => $pass, + 'hostspec' => $host, + 'database' => $name + ); + break; } - elseif( $CONFIG_DBTYPE == 'pgsql' ){ - // PostgreSQL - $dsn = array( - 'phptype' => 'pgsql', - 'username' => $CONFIG_DBUSER, - 'password' => $CONFIG_DBPASSWORD, - 'hostspec' => $CONFIG_DBHOST, - 'database' => $CONFIG_DBNAME ); - } - + // Try to establish connection - self::$DBConnection = MDB2::factory( $dsn, $options ); - + self::$MDB2 = MDB2::factory( $dsn, $options ); + // Die if we could not connect - if( PEAR::isError( self::$DBConnection )){ - echo( '<b>can not connect to database, using '.$CONFIG_DBTYPE.'. ('.self::$DBConnection->getUserInfo().')</center>'); - $error = self::$DBConnection->getMessage(); - if(defined("DEBUG") && DEBUG) {error_log( $error);} - if(defined("DEBUG") && DEBUG) {error_log( self::$DBConnection->getUserInfo());} + if( PEAR::isError( self::$MDB2 )){ + echo( '<b>can not connect to database, using '.$type.'. ('.self::$MDB2->getUserInfo().')</center>'); + OC_Log::write('core',self::$MDB2->getUserInfo(),OC_Log::FATAL); + OC_Log::write('core',self::$MDB2->getMessage(),OC_Log::FATAL); die( $error ); } - + // We always, really always want associative arrays - self::$DBConnection->setFetchMode(MDB2_FETCHMODE_ASSOC); - - //we need to function module for query pre-procesing - self::$DBConnection->loadModule('Function'); + self::$MDB2->setFetchMode(MDB2_FETCHMODE_ASSOC); } - + // we are done. great! return true; } /** - * @brief SQL query - * @param $query Query string - * @returns result as MDB2_Result - * - * SQL query via MDB2 query() - */ - static public function query( $query ){ - // Optimize the query - $query = self::processQuery( $query ); - - self::connect(); - //fix differences between sql versions - - // return the result - $result = self::$DBConnection->exec( $query ); - - // Die if we have an error (error means: bad query, not 0 results!) - if( PEAR::isError($result)) { - $entry = 'DB Error: "'.$result->getMessage().'"<br />'; - $entry .= 'Offending command was: '.$query.'<br />'; - if(defined("DEBUG") && DEBUG) {error_log( $entry );} - die( $entry ); - } - - return $result; - } - - /** * @brief Prepare a SQL query * @param $query Query string * @returns prepared SQL query @@ -149,21 +212,33 @@ class OC_DB { self::connect(); // return the result - $result = self::$DBConnection->prepare( $query ); - - // Die if we have an error (error means: bad query, not 0 results!) - if( PEAR::isError($result)) { - $entry = 'DB Error: "'.$result->getMessage().'"<br />'; - $entry .= 'Offending command was: '.$query.'<br />'; - if(defined("DEBUG") && DEBUG) {error_log( $entry );} - die( $entry ); + if(self::$backend==self::BACKEND_MDB2){ + $result = self::$connection->prepare( $query ); + + // Die if we have an error (error means: bad query, not 0 results!) + if( PEAR::isError($result)) { + $entry = 'DB Error: "'.$result->getMessage().'"<br />'; + $entry .= 'Offending command was: '.$query.'<br />'; + OC_Log::write('core',$entry,OC_Log::FATAL); + die( $entry ); + } + }else{ + try{ + $result=self::$connection->prepare($query); + }catch(PDOException $e){ + $entry = 'DB Error: "'.$e->getMessage().'"<br />'; + $entry .= 'Offending command was: '.$query.'<br />'; + OC_Log::write('core',$entry,OC_Log::FATAL); + die( $entry ); + } + $result=new PDOStatementWrapper($result); } - return $result; } /** * @brief gets last value of autoincrement + * @param $table string The optional table name (will replace *PREFIX*) and add sequence suffix * @returns id * * MDB2 lastInsertID() @@ -171,9 +246,14 @@ class OC_DB { * Call this method right after the insert command or other functions may * cause trouble! */ - public static function insertid(){ + public static function insertid($table=null){ self::connect(); - return self::$DBConnection->lastInsertID(); + if($table !== null){ + $prefix = OC_Config::getValue( "dbtableprefix", "oc_" ); + $suffix = OC_Config::getValue( "dbsequencesuffix", "_id_seq" ); + $table = str_replace( '*PREFIX*', $prefix, $table ); + } + return self::$connection->lastInsertId($table.$suffix); } /** @@ -184,34 +264,26 @@ class OC_DB { */ public static function disconnect(){ // Cut connection if required - if(self::$DBConnection){ - self::$DBConnection->disconnect(); - self::$DBConnection=false; + if(self::$connection){ + if(self::$backend==self::BACKEND_MDB2){ + self::$connection->disconnect(); + } + self::$connection=false; + self::$MDB2=false; + self::$PDO=false; } return true; } /** - * @brief Escapes bad characters - * @param $string string with dangerous characters - * @returns escaped string - * - * MDB2 escape() - */ - public static function escape( $string ){ - self::connect(); - return self::$DBConnection->escape( $string ); - } - - /** * @brief saves database scheme to xml file * @param $file name of file * @returns true/false * * TODO: write more documentation */ - public static function getDbStructure( $file ){ + public static function getDbStructure( $file ,$mode=MDB2_SCHEMA_DUMP_STRUCTURE){ self::connectScheme(); // write the scheme @@ -221,7 +293,7 @@ class OC_DB { 'output' => $file, 'end_of_line' => "\n" ); - self::$schema->dumpDatabase( $definition, $dump_options, MDB2_SCHEMA_DUMP_STRUCTURE ); + self::$schema->dumpDatabase( $definition, $dump_options, $mode ); return true; } @@ -244,10 +316,10 @@ class OC_DB { $content = file_get_contents( $file ); // Make changes and save them to a temporary file - $file2 = tempnam( sys_get_temp_dir(), 'oc_db_scheme_' ); + $file2 = tempnam( get_temp_dir(), 'oc_db_scheme_' ); $content = str_replace( '*dbname*', $CONFIG_DBNAME, $content ); $content = str_replace( '*dbprefix*', $CONFIG_DBTABLEPREFIX, $content ); - if( $CONFIG_DBTYPE == 'pgsql' ){ //mysql support it too but sqlite don't + if( $CONFIG_DBTYPE == 'pgsql' ){ //mysql support it too but sqlite doesn't $content = str_replace( '<default>0000-00-00 00:00:00</default>', '<default>CURRENT_TIMESTAMP</default>', $content ); } file_put_contents( $file2, $content ); @@ -274,6 +346,47 @@ class OC_DB { return true; } + + /** + * @brief update the database scheme + * @param $file file to read structure from + */ + public static function updateDbFromStructure($file){ + $CONFIG_DBTABLEPREFIX = OC_Config::getValue( "dbtableprefix", "oc_" ); + $CONFIG_DBTYPE = OC_Config::getValue( "dbtype", "sqlite" ); + + self::connectScheme(); + + // read file + $content = file_get_contents( $file ); + + $previousSchema = self::$schema->getDefinitionFromDatabase(); + if (PEAR::isError($previousSchema)) { + $error = $previousSchema->getMessage(); + OC_Log::write('core','Failed to get existing database structure for upgrading ('.$error.')',OC_Log::FATAL); + return false; + } + + // Make changes and save them to a temporary file + $file2 = tempnam( get_temp_dir(), 'oc_db_scheme_' ); + $content = str_replace( '*dbname*', $previousSchema['name'], $content ); + $content = str_replace( '*dbprefix*', $CONFIG_DBTABLEPREFIX, $content ); + if( $CONFIG_DBTYPE == 'pgsql' ){ //mysql support it too but sqlite doesn't + $content = str_replace( '<default>0000-00-00 00:00:00</default>', '<default>CURRENT_TIMESTAMP</default>', $content ); + } + file_put_contents( $file2, $content ); + $op = self::$schema->updateDatabase($file2, $previousSchema, array(), false); + + // Delete our temporary file + unlink( $file2 ); + + if (PEAR::isError($op)) { + $error = $op->getMessage(); + OC_Log::write('core','Failed to update database structure ('.$error.')',OC_Log::FATAL); + return false; + } + return true; + } /** * @brief connects to a MDB2 database scheme @@ -282,13 +395,15 @@ class OC_DB { * Connects to a MDB2 database scheme */ private static function connectScheme(){ - // We need a database connection - self::connect(); + // We need a mdb2 database connection + self::connectMDB2(); + self::$MDB2->loadModule('Manager'); + self::$MDB2->loadModule('Reverse'); // Connect if this did not happen before if(!self::$schema){ require_once('MDB2/Schema.php'); - self::$schema=MDB2_Schema::factory(self::$DBConnection); + self::$schema=MDB2_Schema::factory(self::$MDB2); } return true; @@ -305,23 +420,25 @@ class OC_DB { private static function processQuery( $query ){ self::connect(); // We need Database type and table prefix - $CONFIG_DBTYPE = OC_Config::getValue( "dbtype", "sqlite" ); - $CONFIG_DBTABLEPREFIX = OC_Config::getValue( "dbtableprefix", "oc_" ); - - // differences is getting the current timestamp - $query = str_replace( 'NOW()', self::$DBConnection->now(), $query ); - $query = str_replace( 'now()', self::$DBConnection->now(), $query ); + $type = OC_Config::getValue( "dbtype", "sqlite" ); + $prefix = OC_Config::getValue( "dbtableprefix", "oc_" ); // differences in escaping of table names ('`' for mysql) and getting the current timestamp - if( $CONFIG_DBTYPE == 'sqlite' || $CONFIG_DBTYPE == 'sqlite3' ){ + if( $type == 'sqlite' || $type == 'sqlite3' ){ $query = str_replace( '`', '\'', $query ); - } - elseif( $CONFIG_DBTYPE == 'pgsql' ){ + $query = str_replace( 'NOW()', 'datetime(\'now\')', $query ); + $query = str_replace( 'now()', 'datetime(\'now\')', $query ); + }elseif( $type == 'mysql' ){ + $query = str_replace( 'NOW()', 'CURRENT_TIMESTAMP', $query ); + $query = str_replace( 'now()', 'CURRENT_TIMESTAMP', $query ); + }elseif( $type == 'pgsql' ){ $query = str_replace( '`', '"', $query ); + $query = str_replace( 'NOW()', 'CURRENT_TIMESTAMP', $query ); + $query = str_replace( 'now()', 'CURRENT_TIMESTAMP', $query ); } // replace table name prefix - $query = str_replace( '*PREFIX*', $CONFIG_DBTABLEPREFIX, $query ); + $query = str_replace( '*PREFIX*', $prefix, $query ); return $query; } @@ -331,9 +448,9 @@ class OC_DB { * @param string $tableNamme the table to drop */ public static function dropTable($tableName){ - self::connect(); - self::$DBConnection->loadModule('Manager'); - self::$DBConnection->dropTable($tableName); + self::connectMDB2(); + self::$MDB2->loadModule('Manager'); + self::$MDB2->dropTable($tableName); } /** @@ -349,7 +466,7 @@ class OC_DB { $content = file_get_contents( $file ); // Make changes and save them to a temporary file - $file2 = tempnam( sys_get_temp_dir(), 'oc_db_scheme_' ); + $file2 = tempnam( get_temp_dir(), 'oc_db_scheme_' ); $content = str_replace( '*dbname*', $CONFIG_DBNAME, $content ); $content = str_replace( '*dbprefix*', $CONFIG_DBTABLEPREFIX, $content ); file_put_contents( $file2, $content ); @@ -365,37 +482,85 @@ class OC_DB { } /** - * Start a transaction or set a savepoint. - * @param string $savePoint (optional) name of the savepoint to set + * Start a transaction */ - public static function beginTransaction($savePoint=''){ + public static function beginTransaction(){ self::connect(); - if (!self::$DBConnection->supports('transactions')) { + if (self::$backend=self::BACKEND_MDB2 && !self::$connection->supports('transactions')) { return false; } - if($savePoint && !self::$DBConnection->supports('savepoints')){ - return false; - } - if($savePoint){ - self::$DBConnection->beginTransaction($savePoint); - }else{ - self::$DBConnection->beginTransaction(); - } + self::$connection->beginTransaction(); } /** - * Commit the database changes done during a transaction that is in progress or release a savepoint. - * @param string $savePoint (optional) name of the savepoint to commit + * Commit the database changes done during a transaction that is in progress */ public static function commit($savePoint=''){ self::connect(); - if(!self::$DBConnection->inTransaction()){ + if(!self::$connection->inTransaction()){ return false; } - if($savePoint){ - self::$DBConnection->commit($savePoint); + self::$connection->commit(); + } +} + +/** + * small wrapper around PDOStatement to make it behave ,more like an MDB2 Statement + */ +class PDOStatementWrapper{ + private $statement=null; + private $lastArguments=array(); + + public function __construct($statement){ + $this->statement=$statement; + } + + /** + * make execute return the result instead of a bool + */ + public function execute($input=array()){ + $this->lastArguments=$input; + if(count($input)>0){ + $this->statement->execute($input); + }else{ + $this->statement->execute(); + } + return $this; + } + + /** + * provide numRows + */ + public function numRows(){ + $regex = '/^SELECT\s+(?:ALL\s+|DISTINCT\s+)?(?:.*?)\s+FROM\s+(.*)$/i'; + if (preg_match($regex, $this->statement->queryString, $output) > 0) { + $query = OC_DB::prepare("SELECT COUNT(*) FROM {$output[1]}", PDO::FETCH_NUM); + return $query->execute($this->lastArguments)->fetchColumn(); }else{ - self::$DBConnection->commit(); + return $this->statement->rowCount(); } } + + /** + * provide an alias for fetch + */ + public function fetchRow(){ + return $this->statement->fetch(); + } + + /** + * pass all other function directly to the PDOStatement + */ + public function __call($name,$arguments){ + return call_user_func_array(array($this->statement,$name),$arguments); + } + + /** + * Provide a simple fetchOne. + * fetch single column from the next row + * @param int $colnum the column number to fetch + */ + public function fetchOne($colnum = 0){ + return $this->statement->fetchColumn($colnum); + } } diff --git a/lib/files.php b/lib/files.php index 631726bf9b5..9ae5320ad1d 100644 --- a/lib/files.php +++ b/lib/files.php @@ -91,7 +91,7 @@ class OC_Files { if(is_array($files)){ $zip = new ZipArchive(); - $filename = sys_get_temp_dir()."/ownCloud.zip"; + $filename = get_temp_dir()."/ownCloud.zip"; if ($zip->open($filename, ZIPARCHIVE::CREATE)!==TRUE) { exit("cannot open <$filename>\n"); } @@ -108,7 +108,7 @@ class OC_Files { $zip->close(); }elseif(OC_Filesystem::is_dir($dir.'/'.$files)){ $zip = new ZipArchive(); - $filename = sys_get_temp_dir()."/ownCloud.zip"; + $filename = get_temp_dir()."/ownCloud.zip"; if ($zip->open($filename, ZIPARCHIVE::CREATE)!==TRUE) { exit("cannot open <$filename>\n"); } @@ -183,8 +183,8 @@ class OC_Files { */ public static function move($sourceDir,$source,$targetDir,$target){ if(OC_User::isLoggedIn()){ - $targetFile=$targetDir.'/'.$target; - $sourceFile=$sourceDir.'/'.$source; + $targetFile=self::normalizePath($targetDir.'/'.$target); + $sourceFile=self::normalizePath($sourceDir.'/'.$source); return OC_Filesystem::rename($sourceFile,$targetFile); } } @@ -271,7 +271,7 @@ class OC_Files { * @return string guessed mime type */ static function pull($source,$token,$dir,$file){ - $tmpfile=tempnam(sys_get_temp_dir(),'remoteCloudFile'); + $tmpfile=tempnam(get_temp_dir(),'remoteCloudFile'); $fp=fopen($tmpfile,'w+'); $url=$source.="/files/pull.php?token=$token"; $ch=curl_init(); @@ -305,4 +305,19 @@ class OC_Files { $content.= "Options -Indexes\n"; @file_put_contents(OC::$SERVERROOT.'/.htaccess', $content); //supress errors in case we don't have permissions for it } + + /** + * normalize a path, removing any double, add leading /, etc + * @param string $path + * @return string + */ + static public function normalizePath($path){ + $path='/'.$path; + $old=''; + while($old!=$path){//replace any multiplicity of slashes with a single one + $old=$path; + $path=str_replace('//','/',$path); + } + return $path; + } } diff --git a/lib/filestorage/local.php b/lib/filestorage/local.php index d1fe87ec4c2..e846aa420e4 100644 --- a/lib/filestorage/local.php +++ b/lib/filestorage/local.php @@ -38,7 +38,7 @@ class OC_Filestorage_Local extends OC_Filestorage{ public function filetype($path){ $filetype=filetype($this->datadir.$path); if($filetype=='link'){ - $filetype=filetype(readlink($this->datadir.$path)); + $filetype=filetype(realpath($this->datadir.$path)); } return $filetype; } @@ -53,7 +53,7 @@ class OC_Filestorage_Local extends OC_Filestorage{ return is_readable($this->datadir.$path); } public function is_writeable($path){ - return is_writeable($this->datadir.$path); + return is_writable($this->datadir.$path); } public function file_exists($path){ return file_exists($this->datadir.$path); @@ -84,6 +84,11 @@ class OC_Filestorage_Local extends OC_Filestorage{ return $return; } public function rename($path1,$path2){ + if(! $this->file_exists($path1)){ + OC_Log::write('core','unable to rename, file does not exists : '.$path1,OC_Log::ERROR); + return false; + } + if($return=rename($this->datadir.$path1,$this->datadir.$path2)){ $this->clearFolderSizeCache($path1); $this->clearFolderSizeCache($path2); @@ -127,6 +132,13 @@ class OC_Filestorage_Local extends OC_Filestorage{ public function getMimeType($fspath){ if($this->is_readable($fspath)){ $mimeType='application/octet-stream'; + if ($mimeType=='application/octet-stream') { + self::$mimetypes = include('mimetypes.fixlist.php'); + $extention=strtolower(strrchr(basename($fspath), ".")); + $extention=substr($extention,1);//remove leading . + $mimeType=(isset(self::$mimetypes[$extention]))?self::$mimetypes[$extention]:'application/octet-stream'; + + } if (@is_dir($this->datadir.$fspath)) { // directories are easy return "httpd/unix-directory"; @@ -153,7 +165,7 @@ class OC_Filestorage_Local extends OC_Filestorage{ } if ($mimeType=='application/octet-stream') { // Fallback solution: (try to guess the type by the file extension - if(!self::$mimetypes){ + if(!self::$mimetypes || self::$mimetypes != include('mimetypes.list.php')){ self::$mimetypes=include('mimetypes.list.php'); } $extention=strtolower(strrchr(basename($fspath), ".")); @@ -165,7 +177,7 @@ class OC_Filestorage_Local extends OC_Filestorage{ } public function toTmpFile($path){ - $tmpFolder=sys_get_temp_dir(); + $tmpFolder=get_temp_dir(); $filename=tempnam($tmpFolder,'OC_TEMP_FILE_'.substr($path,strrpos($path,'.'))); $fileStats = stat($this->datadir.$path); if(copy($this->datadir.$path,$filename)){ @@ -199,7 +211,6 @@ class OC_Filestorage_Local extends OC_Filestorage{ } private function delTree($dir) { - if(defined("DEBUG") && DEBUG) {error_log('del'.$dir);} $dirRelative=$dir; $dir=$this->datadir.$dir; if (!file_exists($dir)) return true; diff --git a/lib/filestorage/remote.php b/lib/filestorage/remote.php index fb14c4121a2..88bdbca481c 100644 --- a/lib/filestorage/remote.php +++ b/lib/filestorage/remote.php @@ -211,7 +211,7 @@ class OC_Filestorage_Remote extends OC_Filestorage{ $parent=dirname($path); $name=substr($path,strlen($parent)+1); $file=$this->remote->getFile($parent,$name); - $file=tempnam(sys_get_temp_dir(),'oc_'); + $file=tempnam(get_temp_dir(),'oc_'); file_put_contents($file,$data); if($return=$this->remote->sendTmpFile($file,$parent,$name)){ $this->notifyObservers($path,OC_FILEACTION_WRITE); diff --git a/lib/filesystem.php b/lib/filesystem.php index 3d0c92e622e..bd953deb210 100644 --- a/lib/filesystem.php +++ b/lib/filesystem.php @@ -44,10 +44,96 @@ */ class OC_Filesystem{ static private $storages=array(); + static private $mounts=array(); static private $fakeRoot=''; static private $storageTypes=array(); + + /** + * classname which used for hooks handling + * used as signalclass in OC_Hooks::emit() + */ + const CLASSNAME = 'OC_Filesystem'; + + /** + * signalname emited before file renaming + * @param oldpath + * @param newpath + */ + const signal_rename = 'rename'; + + /** + * signal emited after file renaming + * @param oldpath + * @param newpath + */ + const signal_post_rename = 'post_rename'; + /** + * signal emited before file/dir creation + * @param path + * @param run changing this flag to false in hook handler will cancel event + */ + const signal_create = 'create'; + + /** + * signal emited after file/dir creation + * @param path + * @param run changing this flag to false in hook handler will cancel event + */ + const signal_post_create = 'post_create'; + + /** + * signal emits before file/dir copy + * @param oldpath + * @param newpath + * @param run changing this flag to false in hook handler will cancel event + */ + const signal_copy = 'copy'; + + /** + * signal emits after file/dir copy + * @param oldpath + * @param newpath + */ + const signal_post_copy = 'post_copy'; + + /** + * signal emits before file/dir save + * @param path + * @param run changing this flag to false in hook handler will cancel event + */ + const signal_write = 'write'; + + /** + * signal emits after file/dir save + * @param path + */ + const signal_post_write = 'post_write'; + /** + * signal emits when reading file/dir + * @param path + */ + const signal_read = 'read'; + + /** + * signal emits when removing file/dir + * @param path + */ + const signal_delete = 'delete'; + + /** + * parameters definitions for signals + */ + const signal_param_path = 'path'; + const signal_param_oldpath = 'oldpath'; + const signal_param_newpath = 'newpath'; + + /** + * run - changing this flag to false in hook handler will cancel event + */ + const signal_param_run = 'run'; + /** * register a storage type * @param string type @@ -91,7 +177,7 @@ class OC_Filesystem{ * @param array arguments * @return OC_Filestorage */ - static public function createStorage($type,$arguments){ + static private function createStorage($type,$arguments){ if(!self::hasStorageType($type)){ return false; } @@ -130,44 +216,26 @@ class OC_Filesystem{ } /** - * check if the current users has the right premissions to read a file - * @param string path - * @return bool - */ - static private function canRead($path){ - if(substr($path,0,1)!=='/'){ - $path='/'.$path; - } - if(strstr($path,'/../') || strrchr($path, '/') === '/..' ){ - return false; - } - return true;//dummy untill premissions are correctly implemented, also the correcty value because for now users are locked in their seperate data dir and can read/write everything in there - } - /** - * check if the current users has the right premissions to write a file - * @param string path - * @return bool - */ - static private function canWrite($path){ - if(substr($path,0,1)!=='/'){ - $path='/'.$path; - } - if(strstr($path,'/../') || strrchr($path, '/') === '/..' ){ - return false; - } - return true;//dummy untill premissions are correctly implemented, also the correcty value because for now users are locked in their seperate data dir and can read/write everything in there - } - - /** * mount an OC_Filestorage in our virtual filesystem * @param OC_Filestorage storage * @param string mountpoint */ - static public function mount($storage,$mountpoint){ + static public function mount($type,$arguments,$mountpoint){ if(substr($mountpoint,0,1)!=='/'){ $mountpoint='/'.$mountpoint; } - self::$storages[self::$fakeRoot.$mountpoint]=$storage; + self::$mounts[$mountpoint]=array('type'=>$type,'arguments'=>$arguments); + } + + /** + * create all storage backends mounted in the filesystem + */ + static private function mountAll(){ + foreach(self::$mounts as $mountPoint=>$mount){ + if(!isset(self::$storages[$mountPoint])){ + self::$storages[$mountPoint]=self::createStorage($mount['type'],$mount['arguments']); + } + } } /** @@ -178,6 +246,10 @@ class OC_Filesystem{ static public function getStorage($path){ $mountpoint=self::getMountPoint($path); if($mountpoint){ + if(!isset(self::$storages[$mountpoint])){ + $mount=self::$mounts[$mountpoint]; + self::$storages[$mountpoint]=self::createStorage($mount['type'],$mount['arguments']); + } return self::$storages[$mountpoint]; } } @@ -201,7 +273,7 @@ class OC_Filesystem{ } $path=self::$fakeRoot.$path; $foundMountPoint=''; - foreach(self::$storages as $mountpoint=>$storage){ + foreach(self::$mounts as $mountpoint=>$storage){ if(substr($mountpoint,-1)!=='/'){ $mountpoint=$mountpoint.'/'; } @@ -223,11 +295,26 @@ class OC_Filesystem{ */ static public function getLocalFile($path){ $parent=substr($path,0,strrpos($path,'/')); - if(self::canRead($parent) and $storage=self::getStorage($path)){ + if(self::isValidPath($parent) and $storage=self::getStorage($path)){ return $storage->getLocalFile(self::getInternalPath($path)); } } + /** + * check if the requested path is valid + * @param string path + * @return bool + */ + static public function isValidPath($path){ + if(substr($path,0,1)!=='/'){ + $path='/'.$path; + } + if(strstr($path,'/../') || strrchr($path, '/') === '/..' ){ + return false; + } + return true; + } + static public function mkdir($path){ return self::basicOperation('mkdir',$path,array('create','write')); } @@ -292,9 +379,9 @@ class OC_Filesystem{ return self::basicOperation('unlink',$path,array('delete')); } static public function rename($path1,$path2){ - if(OC_FileProxy::runPreProxies('rename',$path1,$path2) and self::canWrite($path1) and self::canWrite($path2)){ + if(OC_FileProxy::runPreProxies('rename',$path1,$path2) and self::is_writeable($path1) and self::isValidPath($path2)){ $run=true; - OC_Hook::emit( 'OC_Filesystem', 'rename', array( 'oldpath' => $path1 ,'newpath'=>$path2, 'run' => &$run)); + OC_Hook::emit( self::CLASSNAME, self::signal_rename, array( self::signal_param_oldpath => $path1 , self::signal_param_newpath=>$path2, self::signal_param_run => &$run)); if($run){ $mp1=self::getMountPoint($path1); $mp2=self::getMountPoint($path2); @@ -307,21 +394,21 @@ class OC_Filesystem{ $result=$storage2->fromTmpFile($tmpFile,self::getInternalPath($path2)); $storage1->unlink(self::getInternalPath($path1)); } - OC_Hook::emit( 'OC_Filesystem', 'post_rename', array( 'oldpath' => $path1, 'newpath'=>$path2)); + OC_Hook::emit( self::CLASSNAME, self::signal_post_rename, array( self::signal_param_oldpath => $path1, self::signal_param_newpath=>$path2)); return $result; } } } static public function copy($path1,$path2){ - if(OC_FileProxy::runPreProxies('copy',$path1,$path2) and self::canRead($path1) and self::canWrite($path2)){ + if(OC_FileProxy::runPreProxies('copy',$path1,$path2) and self::is_readable($path1) and self::isValidPath($path2)){ $run=true; - OC_Hook::emit( 'OC_Filesystem', 'copy', array( 'oldpath' => $path1 ,'newpath'=>$path2, 'run' => &$run)); + OC_Hook::emit( self::CLASSNAME, self::signal_copy, array( self::signal_param_oldpath => $path1 , self::signal_param_newpath=>$path2, self::signal_param_run => &$run)); $exists=self::file_exists($path2); if($run and !$exists){ - OC_Hook::emit( 'OC_Filesystem', 'create', array( 'path' => $path2, 'run' => &$run)); + OC_Hook::emit( self::CLASSNAME, self::signal_create, array( self::signal_param_path => $path2, self::signal_param_run => &$run)); } if($run){ - OC_Hook::emit( 'OC_Filesystem', 'write', array( 'path' => $path2, 'run' => &$run)); + OC_Hook::emit( self::CLASSNAME, self::signal_write, array( self::signal_param_path => $path2, self::signal_param_run => &$run)); } if($run){ $mp1=self::getMountPoint($path1); @@ -334,11 +421,11 @@ class OC_Filesystem{ $tmpFile=$storage1->toTmpFile(self::getInternalPath($path1)); $result=$storage2->fromTmpFile($tmpFile,self::getInternalPath($path2)); } - OC_Hook::emit( 'OC_Filesystem', 'post_copy', array( 'oldpath' => $path1 ,'newpath'=>$path2)); + OC_Hook::emit( self::CLASSNAME, self::signal_post_copy, array( self::signal_param_oldpath => $path1 , self::signal_param_newpath=>$path2)); if(!$exists){ - OC_Hook::emit( 'OC_Filesystem', 'post_create', array( 'path' => $path2)); + OC_Hook::emit( self::CLASSNAME, self::signal_post_create, array( self::signal_param_path => $path2)); } - OC_Hook::emit( 'OC_Filesystem', 'post_write', array( 'path' => $path2)); + OC_Hook::emit( self::CLASSNAME, self::signal_post_write, array( self::signal_param_path => $path2)); return $result; } } @@ -368,47 +455,47 @@ class OC_Filesystem{ return self::basicOperation('fopen',$path,$hooks,$mode); } static public function toTmpFile($path){ - if(OC_FileProxy::runPreProxies('toTmpFile',$path) and self::canRead($path) and $storage=self::getStorage($path)){ - OC_Hook::emit( 'OC_Filesystem', 'read', array( 'path' => $path)); + if(OC_FileProxy::runPreProxies('toTmpFile',$path) and self::isValidPath($path) and $storage=self::getStorage($path)){ + OC_Hook::emit( self::CLASSNAME, self::signal_read, array( self::signal_param_path => $path)); return $storage->toTmpFile(self::getInternalPath($path)); } } static public function fromTmpFile($tmpFile,$path){ - if(OC_FileProxy::runPreProxies('copy',$tmpFile,$path) and self::canWrite($path) and $storage=self::getStorage($path)){ + if(OC_FileProxy::runPreProxies('copy',$tmpFile,$path) and self::isValidPath($path) and $storage=self::getStorage($path)){ $run=true; $exists=self::file_exists($path); if(!$exists){ - OC_Hook::emit( 'OC_Filesystem', 'create', array( 'path' => $path, 'run' => &$run)); + OC_Hook::emit( self::CLASSNAME, self::signal_create, array( self::signal_param_path => $path, self::signal_param_run => &$run)); } if($run){ - OC_Hook::emit( 'OC_Filesystem', 'write', array( 'path' => $path, 'run' => &$run)); + OC_Hook::emit( self::CLASSNAME, self::signal_write, array( self::signal_param_path => $path, self::signal_param_run => &$run)); } if($run){ $result=$storage->fromTmpFile($tmpFile,self::getInternalPath($path)); if(!$exists){ - OC_Hook::emit( 'OC_Filesystem', 'post_create', array( 'path' => $path)); + OC_Hook::emit( self::CLASSNAME, self::signal_post_create, array( self::signal_param_path => $path)); } - OC_Hook::emit( 'OC_Filesystem', 'post_write', array( 'path' => $path)); + OC_Hook::emit( self::CLASSNAME, self::signal_post_write, array( self::signal_param_path => $path)); return $result; } } } static public function fromUploadedFile($tmpFile,$path){ - if(OC_FileProxy::runPreProxies('fromUploadedFile',$tmpFile,$path) and self::canWrite($path) and $storage=self::getStorage($path)){ + if(OC_FileProxy::runPreProxies('fromUploadedFile',$tmpFile,$path) and self::isValidPath($path) and $storage=self::getStorage($path)){ $run=true; $exists=self::file_exists($path); if(!$exists){ - OC_Hook::emit( 'OC_Filesystem', 'create', array( 'path' => $path, 'run' => &$run)); + OC_Hook::emit( self::CLASSNAME, self::signal_create, array( self::signal_param_path => $path, self::signal_param_run => &$run)); } if($run){ - OC_Hook::emit( 'OC_Filesystem', 'write', array( 'path' => $path, 'run' => &$run)); + OC_Hook::emit( self::CLASSNAME, self::signal_write, array( self::signal_param_path => $path, self::signal_param_run => &$run)); } if($run){ $result=$storage->fromUploadedFile($tmpFile,self::getInternalPath($path)); if(!$exists){ - OC_Hook::emit( 'OC_Filesystem', 'post_create', array( 'path' => $path)); + OC_Hook::emit( self::CLASSNAME, self::signal_post_create, array( self::signal_param_path => $path)); } - OC_Hook::emit( 'OC_Filesystem', 'post_write', array( 'path' => $path)); + OC_Hook::emit( self::CLASSNAME, self::signal_post_write, array( self::signal_param_path => $path)); return $result; } } @@ -425,6 +512,7 @@ class OC_Filesystem{ } static public function search($query){ + self::mountAll(); $files=array(); $fakeRoot=self::$fakeRoot; $fakeRootLength=strlen($fakeRoot); @@ -443,6 +531,10 @@ class OC_Filesystem{ return $files; } + + static public function update_session_file_hash($sessionname,$sessionvalue){ + $_SESSION[$sessionname] = $sessionvalue; + } /** * abstraction for running most basic operations @@ -453,14 +545,14 @@ class OC_Filesystem{ * @return mixed */ private static function basicOperation($operation,$path,$hooks=array(),$extraParam=null){ - if(OC_FileProxy::runPreProxies($operation,$path, $extraParam) and self::canRead($path) and $storage=self::getStorage($path)){ + if(OC_FileProxy::runPreProxies($operation,$path, $extraParam) and self::isValidPath($path) and $storage=self::getStorage($path)){ $interalPath=self::getInternalPath($path); $run=true; foreach($hooks as $hook){ if($hook!='read'){ - OC_Hook::emit( 'OC_Filesystem', $hook, array( 'path' => $path, 'run' => &$run)); + OC_Hook::emit( self::CLASSNAME, $hook, array( self::signal_param_path => $path, self::signal_param_run => &$run)); }else{ - OC_Hook::emit( 'OC_Filesystem', $hook, array( 'path' => $path)); + OC_Hook::emit( self::CLASSNAME, $hook, array( self::signal_param_path => $path)); } } if($run){ @@ -472,7 +564,7 @@ class OC_Filesystem{ $result=OC_FileProxy::runPostProxies($operation,$path,$result); foreach($hooks as $hook){ if($hook!='read'){ - OC_Hook::emit( 'OC_Filesystem', 'post_'.$hook, array( 'path' => $path)); + OC_Hook::emit( self::CLASSNAME, 'post_'.$hook, array( self::signal_param_path => $path)); } } return $result; diff --git a/lib/helper.php b/lib/helper.php index c2a81ba3306..4d1219d78d4 100644 --- a/lib/helper.php +++ b/lib/helper.php @@ -56,7 +56,7 @@ class OC_Helper { if($absolute){ // Checking if the request was made through HTTPS. The last in line is for IIS - $protocol = isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS']) && ($_SERVER['HTTPS']!='off'); + $protocol = isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) && ($_SERVER['HTTPS']!='off'); $urlLinkTo = ($protocol?'https':'http') . '://' . $_SERVER['HTTP_HOST'] . $urlLinkTo; } @@ -96,6 +96,12 @@ class OC_Helper { * Returns the path to the image of this file type. */ public static function mimetypeIcon( $mimetype ){ + $alias=array('application/xml'=>'code/xml'); +// echo $mimetype; + if(isset($alias[$mimetype])){ + $mimetype=$alias[$mimetype]; +// echo $mimetype; + } // Replace slash with a minus $mimetype = str_replace( "/", "-", $mimetype ); @@ -154,24 +160,25 @@ class OC_Helper { */ public static function computerFileSize( $str ){ $bytes = 0; + $str=strtolower($str); $bytes_array = array( - 'B' => 1, - 'K' => 1024, - 'KB' => 1024, - 'MB' => 1024 * 1024, - 'M' => 1024 * 1024, - 'GB' => 1024 * 1024 * 1024, - 'G' => 1024 * 1024 * 1024, - 'TB' => 1024 * 1024 * 1024 * 1024, - 'T' => 1024 * 1024 * 1024 * 1024, - 'PB' => 1024 * 1024 * 1024 * 1024 * 1024, - 'P' => 1024 * 1024 * 1024 * 1024 * 1024, + 'b' => 1, + 'k' => 1024, + 'kb' => 1024, + 'mb' => 1024 * 1024, + 'm' => 1024 * 1024, + 'gb' => 1024 * 1024 * 1024, + 'g' => 1024 * 1024 * 1024, + 'tb' => 1024 * 1024 * 1024 * 1024, + 't' => 1024 * 1024 * 1024 * 1024, + 'pb' => 1024 * 1024 * 1024 * 1024 * 1024, + 'p' => 1024 * 1024 * 1024 * 1024 * 1024, ); $bytes = floatval($str); - if (preg_match('#([KMGTP]?B?)$#si', $str, $matches) && !empty($bytes_array[$matches[1]])) { + if (preg_match('#([kmgtp]?b?)$#si', $str, $matches) && !empty($bytes_array[$matches[1]])) { $bytes *= $bytes_array[$matches[1]]; } diff --git a/lib/hook.php b/lib/hook.php index b069a7da6c0..83a16106bf0 100644 --- a/lib/hook.php +++ b/lib/hook.php @@ -20,7 +20,7 @@ class OC_Hook{ * TODO: write example */ static public function connect( $signalclass, $signalname, $slotclass, $slotname ){ - // Cerate the data structure + // Create the data structure if( !array_key_exists( $signalclass, self::$registered )){ self::$registered[$signalclass] = array(); } diff --git a/lib/image.php b/lib/image.php new file mode 100644 index 00000000000..6de3ed9104d --- /dev/null +++ b/lib/image.php @@ -0,0 +1,557 @@ +<?php + +/** +* ownCloud +* +* @author Thomas Tanghus +* @copyright 2011 Thomas Tanghus <thomas@tanghus.net> +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE +* License as published by the Free Software Foundation; either +* version 3 of the License, or any later version. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU AFFERO GENERAL PUBLIC LICENSE for more details. +* +* You should have received a copy of the GNU Affero General Public +* License along with this library. If not, see <http://www.gnu.org/licenses/>. +* +*/ + +//From user comments at http://dk2.php.net/manual/en/function.exif-imagetype.php +if ( ! function_exists( 'exif_imagetype' ) ) { + function exif_imagetype ( $filename ) { + if ( ( list($width, $height, $type, $attr) = getimagesize( $filename ) ) !== false ) { + return $type; + } + return false; + } +} + +function ellipsis($str, $maxlen) { + if (strlen($str) > $maxlen) { + $characters = floor($maxlen / 2); + return substr($str, 0, $characters) . '...' . substr($str, -1 * $characters); + } + return $str; +} + +/** + * Class for basic image manipulation + * + */ +class OC_Image { + static private $resource = false; // tmp resource. + static private $destroy = false; // if the resource is created withing the object. + static private $imagetype = IMAGETYPE_PNG; // Default to png if file type isn't evident. + static private $filepath = null; + /** + * @brief Constructor. + * @param $imageref The path to a local file, a base64 encoded string or a resource created by an imagecreate* function. + * If a resource is passed it is the job of the caller to destroy it using imagedestroy($var) + * @returns bool False on error + */ + function __construct($imageref = null) { + //OC_Log::write('core','OC_Image::__construct, start', OC_Log::DEBUG); + if(!extension_loaded('gd') || !function_exists('gd_info')) { + //if(!function_exists('imagecreatefromjpeg')) { + OC_Log::write('core','OC_Image::__construct, GD module not installed', OC_Log::ERROR); + return false; + } + if(!is_null($imageref)) { + self::load($imageref); + } + } + + /** + * @brief Destructor. + */ + function __destruct() { + if(is_resource(self::$resource) && self::$destroy) { + imagedestroy(self::$resource); // Why does this issue a warning. + } + } + + /** + * @brief Determine whether the object contains an image resource. + * @returns bool + */ + public function valid() { // apparently you can't name a method 'empty'... + $ret = is_resource(self::$resource); + return $ret; + } + + /** + * @brief Returns the MIME type of the image or an empty string if no image is loaded. + * @returns int + */ + public function mimeType() { + return is_resource(self::$resource) ? image_type_to_mime_type(self::$imagetype) : ''; + } + + /** + * @brief Returns the width of the image or -1 if no image is loaded. + * @returns int + */ + public function width() { + return is_resource(self::$resource) ? imagesx(self::$resource) : -1; + } + + /** + * @brief Returns the height of the image or -1 if no image is loaded. + * @returns int + */ + public function height() { + return is_resource(self::$resource) ? imagesy(self::$resource) : -1; + } + + /** + * @brief Outputs the image. + * @returns bool + */ + public function show() { + return $this->_output(); + } + + /** + * @brief Saves the image. + * @returns bool + */ + + public function save($filepath=null) { + if($filepath === null && self::$filepath === null) { + OC_Log::write('core','OC_Image::save. save() called with no path.', OC_Log::ERROR); + return false; + } elseif($filepath === null && $this->filepath !== null) { + $filepath = $this->filepath; + } + return $this->_output($filepath, true); + } + + /** + * @brief Outputs/saves the image. + */ + private function _output($filepath=null, $really=false) { + if($really === false) { + header('Content-Type: '.self::mimeType()); + $filepath = null; // Just being cautious ;-) + } else { + if(!is_writable(dirname($filepath))) { + OC_Log::write('core','OC_Image::_output. Directory \''.dirname($filepath).'\' is not writable.', OC_Log::ERROR); + return false; + } elseif(is_writable(dirname($filepath)) && file_exists($filepath) && !is_writable($filepath)) { + OC_Log::write('core','OC_Image::_output. File \''.$filepath.'\' is not writable.', OC_Log::ERROR); + return false; + } + } + $retval = false; + switch(self::$imagetype) { + case IMAGETYPE_GIF: + $retval = imagegif(self::$resource, $filepath); + break; + case IMAGETYPE_JPEG: + $retval = imagejpeg(self::$resource, $filepath); + break; + case IMAGETYPE_PNG: + $retval = imagepng(self::$resource, $filepath); + break; + case IMAGETYPE_XBM: + $retval = imagexbm(self::$resource, $filepath); + break; + case IMAGETYPE_WBMP: + case IMAGETYPE_BMP: + $retval = imagewbmp(self::$resource, $filepath); + break; + default: + $retval = imagepng(self::$resource, $filepath); + } + return $retval; + } + + /** + * @brief Prints the image when called as $image(). + */ + public function __invoke() { + return self::show(); + } + + /** + * @returns Returns the image resource in any. + */ + public function resource() { + return self::$resource; + } + + /** + * @returns Returns a base64 encoded string suitable for embedding in a VCard. + */ + function __toString() { + ob_start(); + $res = imagepng(self::$resource); + if (!$res) { + OC_Log::write('core','OC_Image::_string. Error writing image',OC_Log::ERROR); + } + return base64_encode(ob_get_clean()); + } + + /** + * (I'm open for suggestions on better method name ;) + * @brief Fixes orientation based on EXIF data. + * @returns bool. + */ + public function fixOrientation() { + if(!is_callable('exif_read_data')){ + OC_Log::write('core','OC_Image::fixOrientation() Exif module not enabled.', OC_Log::DEBUG); + return false; + } + if(!is_resource(self::$resource)) { + OC_Log::write('core','OC_Image::fixOrientation() No image loaded.', OC_Log::DEBUG); + return false; + } + if(is_null(self::$filepath) || !is_readable(self::$filepath)) { + OC_Log::write('core','OC_Image::fixOrientation() No readable file path set.', OC_Log::DEBUG); + return false; + } + $exif = exif_read_data(self::$filepath, 'IFD0'); + if(!$exif) { + return false; + } + if(!isset($exif['Orientation'])) { + return true; // Nothing to fix + } + $o = $exif['Orientation']; + OC_Log::write('core','OC_Image::fixOrientation() Orientation: '.$o, OC_Log::DEBUG); + $rotate = 0; + $flip = false; + switch($o) { + case 1: + $rotate = 0; + $flip = false; + break; + case 2: // Not tested + $rotate = 0; + $flip = true; + break; + case 3: + $rotate = 180; + $flip = false; + break; + case 4: // Not tested + $rotate = 180; + $flip = true; + break; + case 5: // Not tested + $rotate = 90; + $flip = true; + break; + case 6: + //$rotate = 90; + $rotate = 270; + $flip = false; + break; + case 7: // Not tested + $rotate = 270; + $flip = true; + break; + case 8: + $rotate = 270; + $flip = false; + break; + } + if($rotate) { + $res = imagerotate(self::$resource, $rotate, -1); + if($res) { + if(imagealphablending($res, true)) { + if(imagesavealpha($res, true)) { + self::$resource = $res; + return true; + } else { + OC_Log::write('core','OC_Image::fixOrientation() Error during alphasaving.', OC_Log::DEBUG); + return false; + } + } else { + OC_Log::write('core','OC_Image::fixOrientation() Error during alphablending.', OC_Log::DEBUG); + return false; + } + } else { + OC_Log::write('core','OC_Image::fixOrientation() Error during oriention fixing.', OC_Log::DEBUG); + return false; + } + } + } + + /** + * @brief Loads an image from a local file, a base64 encoded string or a resource created by an imagecreate* function. + * @param $imageref The path to a local file, a base64 encoded string or a resource created by an imagecreate* function. + * If a resource is passed it is the job of the caller to destroy it using imagedestroy($var) + * @returns An image resource or false on error + */ + public function load($imageref) { + if(self::loadFromFile($imageref) !== false) { + return self::$resource; + } elseif(self::loadFromBase64($imageref) !== false) { + return self::$resource; + } elseif(self::loadFromData($imageref) !== false) { + return self::$resource; + } elseif(self::loadFromResource($imageref) !== false) { + return self::$resource; + } else { + OC_Log::write('core','OC_Image::load, couldn\'t load anything. Giving up!', OC_Log::DEBUG); + return false; + } + } + + /** + * @brief Loads an image from a local file. + * @param $imageref The path to a local file. + * @returns An image resource or false on error + */ + public function loadFromFile($imagepath=false) { + if(!is_file($imagepath) || !file_exists($imagepath) || !is_readable($imagepath)) { + // Debug output disabled because this method is tried before loadFromBase64? + OC_Log::write('core','OC_Image::loadFromFile, couldn\'t load: '.ellipsis($imagepath, 50), OC_Log::DEBUG); + return false; + } + $itype = exif_imagetype($imagepath); + switch($itype) { + case IMAGETYPE_GIF: + if (imagetypes() & IMG_GIF) { + self::$resource = imagecreatefromgif($imagepath); + } else { + OC_Log::write('core','OC_Image::loadFromFile, GIF images not supported: '.$imagepath, OC_Log::DEBUG); + } + break; + case IMAGETYPE_JPEG: + if (imagetypes() & IMG_JPG) { + self::$resource = imagecreatefromjpeg($imagepath); + } else { + OC_Log::write('core','OC_Image::loadFromFile, JPG images not supported: '.$imagepath, OC_Log::DEBUG); + } + break; + case IMAGETYPE_PNG: + if (imagetypes() & IMG_PNG) { + self::$resource = imagecreatefrompng($imagepath); + } else { + OC_Log::write('core','OC_Image::loadFromFile, PNG images not supported: '.$imagepath, OC_Log::DEBUG); + } + break; + case IMAGETYPE_XBM: + if (imagetypes() & IMG_XPM) { + self::$resource = imagecreatefromxbm($imagepath); + } else { + OC_Log::write('core','OC_Image::loadFromFile, XBM/XPM images not supported: '.$imagepath, OC_Log::DEBUG); + } + break; + case IMAGETYPE_WBMP: + case IMAGETYPE_BMP: + if (imagetypes() & IMG_WBMP) { + self::$resource = imagecreatefromwbmp($imagepath); + } else { + OC_Log::write('core','OC_Image::loadFromFile, (W)BMP images not supported: '.$imagepath, OC_Log::DEBUG); + } + break; + /* + case IMAGETYPE_TIFF_II: // (intel byte order) + break; + case IMAGETYPE_TIFF_MM: // (motorola byte order) + break; + case IMAGETYPE_JPC: + break; + case IMAGETYPE_JP2: + break; + case IMAGETYPE_JPX: + break; + case IMAGETYPE_JB2: + break; + case IMAGETYPE_SWC: + break; + case IMAGETYPE_IFF: + break; + case IMAGETYPE_ICO: + break; + case IMAGETYPE_SWF: + break; + case IMAGETYPE_PSD: + break; + */ + default: + self::$resource = imagecreatefromstring(file_get_contents($imagepath)); + $itype = IMAGETYPE_PNG; + OC_Log::write('core','OC_Image::loadFromFile, Default', OC_Log::DEBUG); + break; + } + if($this->valid()) { + self::$imagetype = $itype; + self::$filepath = $imagepath; + self::$destroy = true; + } + return self::$resource; + } + + /** + * @brief Loads an image from a string of data. + * @param $str A string of image data as read from a file. + * @returns An image resource or false on error + */ + public function loadFromData($str) { + if(is_resource($str)) { + return false; + } + self::$resource = imagecreatefromstring($str); + if(!self::$resource) { + OC_Log::write('core','OC_Image::loadFromData, couldn\'t load', OC_Log::DEBUG); + return false; + } + self::$destroy = true; + return self::$resource; + } + + /** + * @brief Loads an image from a base64 encoded string. + * @param $str A string base64 encoded string of image data. + * @returns An image resource or false on error + */ + public function loadFromBase64($str) { + if(!is_string($str)) { + return false; + } + $data = base64_decode($str); + if($data) { // try to load from string data + self::$resource = imagecreatefromstring($data); + if(!self::$resource) { + OC_Log::write('core','OC_Image::loadFromBase64, couldn\'t load', OC_Log::DEBUG); + return false; + } + self::$destroy = true; + return self::$resource; + } else { + return false; + } + } + + /** + * @brief Checks if image resource is valid and assigns it to self::$resource. + * @param $res An image resource. + * @returns An image resource or false on error + */ + public function loadFromResource($res) { + if(!is_resource($res)) { + return false; + } + self::$resource = $res; + } + + /** + * @brief Resizes the image preserving ratio. + * @param $maxsize The maximum size of either the width or height. + * @returns bool + */ + public function resize($maxsize) { + if(!self::$resource) { + OC_Log::write('core','OC_Image::resize, No image loaded', OC_Log::ERROR); + return false; + } + $width_orig=imageSX(self::$resource); + $height_orig=imageSY(self::$resource); + $ratio_orig = $width_orig/$height_orig; + + if ($ratio_orig > 1) { + $new_height = round($maxsize/$ratio_orig); + $new_width = $maxsize; + } else { + $new_width = round($maxsize*$ratio_orig); + $new_height = $maxsize; + } + + $process = imagecreatetruecolor(round($new_width), round($new_height)); + if ($process == false) { + OC_Log::write('core','OC_Image::resize. Error creating true color image',OC_Log::ERROR); + imagedestroy($process); + return false; + } + + imagecopyresampled($process, self::$resource, 0, 0, 0, 0, $new_width, $new_height, $width_orig, $height_orig); + if ($process == false) { + OC_Log::write('core','OC_Image::resize. Error resampling process image '.$new_width.'x'.$new_height,OC_Log::ERROR); + imagedestroy($process); + return false; + } + self::$resource = $process; + return true; + } + + /** + * @brief Crops the image to the middle square. If the image is already square it just returns. + * @returns bool for success or failure + */ + public function centerCrop() { + if(!self::$resource) { + OC_Log::write('core','OC_Image::centerCrop, No image loaded', OC_Log::ERROR); + return false; + } + $width_orig=imageSX(self::$resource); + $height_orig=imageSY(self::$resource); + if($width_orig === $height_orig) { + return true; + } + $ratio_orig = $width_orig/$height_orig; + $width = $height = min($width_orig, $height_orig); + + if ($ratio_orig > 1) { + $x = ($width_orig/2) - ($width/2); + $y = 0; + } else { + $y = ($height_orig/2) - ($height/2); + $x = 0; + } + $process = imagecreatetruecolor($width, $height); + if ($process == false) { + OC_Log::write('core','OC_Image::centerCrop. Error creating true color image',OC_Log::ERROR); + imagedestroy($process); + return false; + } + imagecopyresampled($process, self::$resource, 0, 0, $x, $y, $width, $height, $width, $height); + if ($process == false) { + OC_Log::write('core','OC_Image::centerCrop. Error resampling process image '.$width.'x'.$height,OC_Log::ERROR); + imagedestroy($process); + return false; + } + self::$resource = $process; + return true; + } + + /** + * @brief Crops the image from point $x$y with dimension $wx$h. + * @param $x Horizontal position + * @param $y Vertical position + * @param $w Width + * @param $h Hight + * @returns bool for success or failure + */ + public function crop($x, $y, $w, $h) { + if(!self::$resource) { + OC_Log::write('core','OC_Image::crop, No image loaded', OC_Log::ERROR); + return false; + } + $width_orig=imageSX(self::$resource); + $height_orig=imageSY(self::$resource); + //OC_Log::write('core','OC_Image::crop. Original size: '.$width_orig.'x'.$height_orig, OC_Log::DEBUG); + $process = imagecreatetruecolor($w, $h); + if ($process == false) { + OC_Log::write('core','OC_Image::crop. Error creating true color image',OC_Log::ERROR); + imagedestroy($process); + return false; + } + imagecopyresampled($process, self::$resource, 0, 0, $x, $y, $w, $h, $w, $h); + if ($process == false) { + OC_Log::write('core','OC_Image::crop. Error resampling process image '.$w.'x'.$h,OC_Log::ERROR); + imagedestroy($process); + return false; + } + self::$resource = $process; + return true; + } +} diff --git a/lib/installer.php b/lib/installer.php index 0febb2cab46..b2f817e702f 100644 --- a/lib/installer.php +++ b/lib/installer.php @@ -56,28 +56,28 @@ class OC_Installer{ */ public static function installApp( $data = array()){ if(!isset($data['source'])){ - if(defined("DEBUG") && DEBUG) {error_log("No source specified when installing app");} + OC_Log::write('core','No source specified when installing app',OC_Log::ERROR); return false; } //download the file if necesary if($data['source']=='http'){ - $path=tempnam(sys_get_temp_dir(),'oc_installer_'); + $path=tempnam(get_temp_dir(),'oc_installer_'); if(!isset($data['href'])){ - if(defined("DEBUG") && DEBUG) {error_log("No href specified when installing app from http");} + OC_Log::write('core','No href specified when installing app from http',OC_Log::ERROR); return false; } copy($data['href'],$path); }else{ if(!isset($data['path'])){ - if(defined("DEBUG") && DEBUG) {error_log("No path specified when installing app from local file");} + OC_Log::write('core','No path specified when installing app from local file',OC_Log::ERROR); return false; } $path=$data['path']; } //extract the archive in a temporary folder - $extractDir=tempnam(sys_get_temp_dir(),'oc_installer_uncompressed_'); + $extractDir=tempnam(get_temp_dir(),'oc_installer_uncompressed_'); unlink($extractDir); mkdir($extractDir); $zip = new ZipArchive; @@ -85,7 +85,7 @@ class OC_Installer{ $zip->extractTo($extractDir); $zip->close(); } else { - if(defined("DEBUG") && DEBUG) {error_log("Failed to open archive when installing app");} + OC_Log::write('core','Failed to open archive when installing app',OC_Log::ERROR); OC_Helper::rmdirr($extractDir); if($data['source']=='http'){ unlink($path); @@ -95,7 +95,7 @@ class OC_Installer{ //load the info.xml file of the app if(!is_file($extractDir.'/appinfo/info.xml')){ - if(defined("DEBUG") && DEBUG) {error_log("App does not provide an info.xml file");} + OC_Log::write('core','App does not provide an info.xml file',OC_Log::ERROR); OC_Helper::rmdirr($extractDir); if($data['source']=='http'){ unlink($path); @@ -107,7 +107,7 @@ class OC_Installer{ //check if an app with the same id is already installed if(self::isInstalled( $info['id'] )){ - if(defined("DEBUG") && DEBUG) {error_log("App already installed");} + OC_Log::write('core','App already installed',OC_Log::WARN); OC_Helper::rmdirr($extractDir); if($data['source']=='http'){ unlink($path); @@ -117,7 +117,7 @@ class OC_Installer{ //check if the destination directory already exists if(is_dir($basedir)){ - if(defined("DEBUG") && DEBUG) {error_log("App's directory already exists");} + OC_Log::write('core','App directory already exists',OC_Log::WARN); OC_Helper::rmdirr($extractDir); if($data['source']=='http'){ unlink($path); @@ -131,7 +131,7 @@ class OC_Installer{ //copy the app to the correct place if(!mkdir($basedir)){ - if(defined("DEBUG") && DEBUG) {error_log('Can\'t create app folder ('.$basedir.')');} + OC_Log::write('core','Can\'t create app folder ('.$basedir.')',OC_Log::ERROR); OC_Helper::rmdirr($extractDir); if($data['source']=='http'){ unlink($path); @@ -152,14 +152,14 @@ class OC_Installer{ } //run appinfo/install.php - if(!isset($data['noinstall']) or $data['noinstall']==false and is_file($basedir.'/appinfo/install.php')){ + if((!isset($data['noinstall']) or $data['noinstall']==false) and file_exists($basedir.'/appinfo/install.php')){ include($basedir.'/appinfo/install.php'); } //set the installed version OC_Appconfig::setValue($info['id'],'installed_version',$info['version']); OC_Appconfig::setValue($info['id'],'enabled','no'); - return true; + return $info['id']; } /** diff --git a/lib/l10n.php b/lib/l10n.php index 54331d44ae4..a5544eb3a27 100644 --- a/lib/l10n.php +++ b/lib/l10n.php @@ -110,6 +110,22 @@ class OC_L10N{ } /** + * @brief Translating + * @param $textArray The text array we need a translation for + * @returns Translation or the same text + * + * Returns the translation. If no translation is found, $textArray will be + * returned. + */ + public function tA($textArray){ + $result = array(); + foreach($textArray as $key => $text){ + $result[$key] = $this->t($text); + } + return $result; + } + + /** * @brief getTranslations * @returns Fetch all translations * diff --git a/lib/log.php b/lib/log.php new file mode 100644 index 00000000000..446ddd48848 --- /dev/null +++ b/lib/log.php @@ -0,0 +1,74 @@ +<?php +/** + * ownCloud + * + * @author Robin Appelman + * @copyright 2011 Robin Appelman icewind1991@gmail.com + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + */ + +/** + *logging utilities + * + * Log is saved at data/owncloud.log (on default) + */ + +class OC_Log{ + const DEBUG=0; + const INFO=1; + const WARN=2; + const ERROR=3; + const FATAL=4; + + /** + * write a message in the log + * @param string $app + * @param string $message + * @param int level + */ + public static function write($app,$message,$level){ + $minLevel=OC_Config::getValue( "loglevel", 2 ); + if($level>=$minLevel){ + $datadir=OC_Config::getValue( "datadirectory", OC::$SERVERROOT.'/data' ); + $logFile=OC_Config::getValue( "logfile", $datadir.'/owncloud.log' ); + $entry=array('app'=>$app,'message'=>$message,'level'=>$level,'time'=>time()); + $fh=fopen($logFile,'a'); + fwrite($fh,json_encode($entry)."\n"); + fclose($fh); + } + } + + public static function getEntries(){ + $datadir=OC_Config::getValue( "datadirectory", OC::$SERVERROOT.'/data' ); + $logFile=OC_Config::getValue( "logfile", $datadir.'/owncloud.log' ); + $entries=array(); + if(!file_exists($logFile)){ + return array(); + } + $fh=fopen($logFile,'r'); + if($fh === false){ // Unable to read log file! + return array(); + } + while(!feof($fh)){ + $line=fgets($fh); + if($line){ + $entries[]=json_decode($line); + } + } + fclose($fh); + return $entries; + } +} diff --git a/lib/mimetypes.fixlist.php b/lib/mimetypes.fixlist.php new file mode 100644 index 00000000000..1c6acbc4438 --- /dev/null +++ b/lib/mimetypes.fixlist.php @@ -0,0 +1,14 @@ +<?php +return array( + 'ics'=>'text/calendar', + 'ical'=>'text/calendar', + 'js'=>'application/javascript', + 'odt'=>'application/vnd.oasis.opendocument.text', + 'ods'=>'application/vnd.oasis.opendocument.spreadsheet', + 'odg'=>'application/vnd.oasis.opendocument.graphics', + 'odp'=>'application/vnd.oasis.opendocument.presentation', + 'pl'=>'text/x-script.perl', + 'py'=>'text/x-script.phyton', + 'vcf' => 'text/vcard', + 'vcard' => 'text/vcard' +); diff --git a/lib/ocsclient.php b/lib/ocsclient.php index 654c5e0527b..9d5932fb720 100644 --- a/lib/ocsclient.php +++ b/lib/ocsclient.php @@ -108,6 +108,7 @@ class OC_OCSClient{ $xml=@file_get_contents($url); if($xml==FALSE){ + OC_Log::write('core','Unable to parse OCS content',OC_Log::FATAL); return NULL; } $data=simplexml_load_string($xml); @@ -129,6 +130,33 @@ class OC_OCSClient{ return $app; } + /** + * @brief Get the download url for an application from the OCS server + * @returns array with application data + * + * This function returns an download url for an applications from the OCS server + */ + public static function getApplicationDownload($id,$item){ + $url='http://api.apps.owncloud.com/v1/content/download/'.urlencode($id).'/'.urlencode($item); + + $xml=@file_get_contents($url); + if($xml==FALSE){ + OC_Log::write('core','Unable to parse OCS content',OC_Log::FATAL); + return NULL; + } + $data=simplexml_load_string($xml); + + $tmp=$data->data->content; + $app=array(); + if(isset($tmp->downloadlink)) { + $app['downloadlink']=$tmp->downloadlink; + }else{ + $app['downloadlink']=''; + } + return $app; + } + + /** * @brief Get all the knowledgebase entries from the OCS server * @returns array with q and a data @@ -143,6 +171,7 @@ class OC_OCSClient{ $kbe=array(); $xml=@file_get_contents($url); if($xml==FALSE){ + OC_Log::write('core','Unable to parse knowledgebase content',OC_Log::FATAL); return NULL; } $data=simplexml_load_string($xml); diff --git a/lib/preferences.php b/lib/preferences.php index 6d8aa17afd5..75201f455ba 100644 --- a/lib/preferences.php +++ b/lib/preferences.php @@ -140,7 +140,6 @@ class OC_Preferences{ // Check if the key does exist $query = OC_DB::prepare( 'SELECT configvalue FROM *PREFIX*preferences WHERE userid = ? AND appid = ? AND configkey = ?' ); $values=$query->execute(array($user,$app,$key))->fetchAll(); - if(defined("DEBUG") && DEBUG) {error_log(print_r($values,true));} $exists=(count($values)>0); if( !$exists ){ diff --git a/lib/remote/cloud.php b/lib/remote/cloud.php index 75d60155d06..a9c74e8bf5f 100644 --- a/lib/remote/cloud.php +++ b/lib/remote/cloud.php @@ -17,7 +17,7 @@ class OC_REMOTE_CLOUD{ */ private function apiCall($action,$parameters=false,$assoc=false){ if(!$this->cookiefile){ - $this->cookiefile=sys_get_temp_dir().'/remoteCloudCookie'.uniqid(); + $this->cookiefile=get_temp_dir().'/remoteCloudCookie'.uniqid(); } $url=$this->path.='/files/api.php'; $fields_string="action=$action&"; @@ -168,9 +168,9 @@ class OC_REMOTE_CLOUD{ } $ch=curl_init(); if(!$this->cookiefile){ - $this->cookiefile=sys_get_temp_dir().'/remoteCloudCookie'.uniqid(); + $this->cookiefile=get_temp_dir().'/remoteCloudCookie'.uniqid(); } - $tmpfile=tempnam(sys_get_temp_dir(),'remoteCloudFile'); + $tmpfile=tempnam(get_temp_dir(),'remoteCloudFile'); $fp=fopen($tmpfile,'w+'); $url=$this->path.="/files/api.php?action=get&dir=$dir&file=$file"; curl_setopt($ch,CURLOPT_URL,$url); @@ -191,7 +191,7 @@ class OC_REMOTE_CLOUD{ public function sendTmpFile($tmp,$targetDir,$targetFile){ $token=sha1(uniqid().$tmp); - $file=sys_get_temp_dir().'/'.'remoteCloudFile'.$token; + $file=get_temp_dir().'/'.'remoteCloudFile'.$token; rename($tmp,$file); if( OC_Config::getValue( "forcessl", false ) or isset($_SERVER['HTTPS']) and $_SERVER['HTTPS'] == 'on') { $url = "https://". $_SERVER['SERVER_NAME'] . OC::$WEBROOT; diff --git a/lib/setup.php b/lib/setup.php index 36ee966c556..30a91b4681b 100644 --- a/lib/setup.php +++ b/lib/setup.php @@ -84,7 +84,7 @@ class OC_Setup { $dbpass = $options['dbpass']; $dbname = $options['dbname']; $dbhost = $options['dbhost']; - $dbtableprefix = $options['dbtableprefix']; + $dbtableprefix = isset($options['dbtableprefix']) ? $options['dbtableprefix'] : 'oc_'; OC_Config::setValue('dbname', $dbname); OC_Config::setValue('dbhost', $dbhost); OC_Config::setValue('dbtableprefix', $dbtableprefix); @@ -98,35 +98,45 @@ class OC_Setup { ); } else { + $oldUser=OC_Config::getValue('dbuser', false); + $oldPassword=OC_Config::getValue('dbpassword', false); + $query="SELECT user FROM mysql.user WHERE user='$dbuser'"; //this should be enough to check for admin rights in mysql if(mysql_query($query, $connection)) { //use the admin login data for the new database user //add prefix to the mysql user name to prevent collissions - $dbusername=substr('oc_mysql_'.$username,0,16); - //hash the password so we don't need to store the admin config in the config file - $dbpassword=md5(time().$password); - - self::createDBUser($dbusername, $dbpassword, $connection); - - OC_Config::setValue('dbuser', $dbusername); - OC_Config::setValue('dbpassword', $dbpassword); + $dbusername=substr('oc_'.$username,0,16); + if($dbusername!=$oldUser){ + //hash the password so we don't need to store the admin config in the config file + $dbpassword=md5(time().$password); + + self::createDBUser($dbusername, $dbpassword, $connection); + + OC_Config::setValue('dbuser', $dbusername); + OC_Config::setValue('dbpassword', $dbpassword); + } //create the database self::createDatabase($dbname, $dbusername, $connection); } else { - OC_Config::setValue('dbuser', $dbuser); - OC_Config::setValue('dbpassword', $dbpass); + if($dbuser!=$oldUser){ + OC_Config::setValue('dbuser', $dbuser); + OC_Config::setValue('dbpassword', $dbpass); + } //create the database self::createDatabase($dbname, $dbuser, $connection); } //fill the database if needed - $query="SELECT * FROM $dbname.{$dbtableprefix}users"; + $query="select count(*) from information_schema.tables where table_schema='$dbname' AND table_name = '{$dbtableprefix}users';"; $result = mysql_query($query,$connection); - if(!$result) { + if($result){ + $row=mysql_fetch_row($result); + } + if(!$result or $row[0]==0) { OC_DB::createDbFromStructure('db_structure.xml'); } mysql_close($connection); @@ -160,8 +170,8 @@ class OC_Setup { //add prefix to the postgresql user name to prevent collissions $dbusername='oc_'.$username; - //hash the password so we don't need to store the admin config in the config file - $dbpassword=md5(time().$password); + //create a new password so we don't need to store the admin config in the config file + $dbpassword=md5(time()); self::pg_createDBUser($dbusername, $dbpassword, $connection); @@ -179,13 +189,29 @@ class OC_Setup { self::pg_createDatabase($dbname, $dbuser, $connection); } - //fill the database if needed - $query = "SELECT relname FROM pg_class WHERE relname='{$dbtableprefix}users' limit 1"; - $result = pg_query($connection, $query); - if(!$result) { - OC_DB::createDbFromStructure('db_structure.xml'); - } + // the connection to dbname=postgres is not needed anymore pg_close($connection); + + // connect to the ownCloud database (dbname=$dbname) an check if it needs to be filled + $dbuser = OC_CONFIG::getValue('dbuser'); + $dbpass = OC_CONFIG::getValue('dbpassword'); + $connection_string = "host=$dbhost dbname=$dbname user=$dbuser password=$dbpass"; + $connection = @pg_connect($connection_string); + if(!$connection) { + $error[] = array( + 'error' => 'PostgreSQL username and/or password not valid', + 'hint' => 'You need to enter either an existing account or the administrator.' + ); + } else { + $query = "select count(*) FROM pg_class WHERE relname='{$dbtableprefix}users' limit 1"; + $result = pg_query($connection, $query); + if($result) { + $row = pg_fetch_row($result); + } + if(!$result or $row[0]==0) { + OC_DB::createDbFromStructure('db_structure.xml'); + } + } } } else { @@ -221,7 +247,7 @@ class OC_Setup { } public static function createDatabase($name,$user,$connection) { - //we cant user OC_BD functions here because we need to connect as the administrative user. + //we cant use OC_BD functions here because we need to connect as the administrative user. $query = "CREATE DATABASE IF NOT EXISTS `$name`"; $result = mysql_query($query, $connection); if(!$result) { @@ -243,7 +269,7 @@ class OC_Setup { } public static function pg_createDatabase($name,$user,$connection) { - //we cant user OC_BD functions here because we need to connect as the administrative user. + //we cant use OC_BD functions here because we need to connect as the administrative user. $query = "CREATE DATABASE $name OWNER $user"; $result = pg_query($connection, $query); if(!$result) { @@ -275,7 +301,7 @@ class OC_Setup { $content.= "php_value post_max_size 512M\n"; $content.= "SetEnv htaccessWorking true\n"; $content.= "</IfModule>\n"; - $content.= "<IfModule !mod_php5.c>\n"; + $content.= "<IfModule mod_rewrite.c>\n"; $content.= "RewriteEngine on\n"; $content.= "RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization},last]\n"; $content.= "</IfModule>\n"; diff --git a/lib/template.php b/lib/template.php index 440b62003e7..881d2a27b1e 100644 --- a/lib/template.php +++ b/lib/template.php @@ -98,6 +98,33 @@ function relative_modified_date($timestamp) { else { return $l->t('years ago'); } } +function html_select_options($options, $selected, $params=array()) { + if (!is_array($selected)){ + $selected=array($selected); + } + if (isset($params['combine']) && $params['combine']){ + $options = array_combine($options, $options); + } + $value_name = $label_name = false; + if (isset($params['value'])){ + $value_name = $params['value']; + } + if (isset($params['label'])){ + $label_name = $params['label']; + } + $html = ''; + foreach($options as $value => $label){ + if ($value_name && is_array($label)){ + $value = $label[$value_name]; + } + if ($label_name && is_array($label)){ + $label = $label[$label_name]; + } + $select = in_array($value, $selected) ? ' selected="selected"' : ''; + $html .= '<option value="' . $value . '"' . $select . '>' . $label . '</option>'."\n"; + } + return $html; +} /** * This class provides the templates for owncloud. diff --git a/lib/updater.php b/lib/updater.php index e4db719a62c..e992e4dcf11 100644 --- a/lib/updater.php +++ b/lib/updater.php @@ -52,13 +52,9 @@ class OC_Updater{ $tmp['url'] = $data->url; $tmp['web'] = $data->web; - return $tmp; - } - - public static function ShowUpdatingHint(){ $data=OC_Updater::check(); if(isset($data['version']) and $data['version']<>'') { @@ -67,10 +63,8 @@ class OC_Updater{ $txt='Your ownCloud is up to date'; } return($txt); - } - /** * do ownCloud update */ @@ -83,9 +77,4 @@ class OC_Updater{ //update version in config } - } - - - -?> diff --git a/lib/user.php b/lib/user.php index 241d9aa8b10..34f44f572e0 100644 --- a/lib/user.php +++ b/lib/user.php @@ -120,7 +120,7 @@ class OC_User { return false; } // No empty username - if( !$uid ){ + if(trim($uid) == ''){ return false; } // Check if user already exists @@ -169,7 +169,8 @@ class OC_User { foreach( OC_Group::getUserGroups( $uid ) as $i ){ OC_Group::removeFromGroup( $uid, $i ); } - + // Delete the user's keys in preferences + OC_Preferences::deleteUser($uid); // Emit and exit OC_Hook::emit( "OC_User", "post_deleteUser", array( "uid" => $uid )); return true; diff --git a/lib/util.php b/lib/util.php index 2b2238f9220..2fba1206bff 100644 --- a/lib/util.php +++ b/lib/util.php @@ -24,7 +24,7 @@ class OC_Util { $success=@mkdir($CONFIG_DATADIRECTORY_ROOT); if(!$success) { $tmpl = new OC_Template( '', 'error', 'guest' ); - $tmpl->assign('errors',array(1=>array('error'=>"Can't create data directory (".$CONFIG_DATADIRECTORY_ROOT.")",'hint'=>"You can usually fix this by setting the owner of '".OC::$SERVERROOT."' to the user that the web server uses (".OC_Util::checkWebserverUser().")"))); + $tmpl->assign('errors',array(1=>array('error'=>"Can't create data directory (".$CONFIG_DATADIRECTORY_ROOT.")",'hint'=>"You can usually fix this by giving the webserver write access to the ownCloud directory '".OC::$SERVERROOT."' "))); $tmpl->printPage(); exit; } @@ -36,42 +36,14 @@ class OC_Util { } if( $user != "" ){ //if we aren't logged in, there is no use to set up the filesystem - //first set up the local "root" storage and the backupstorage if needed - $rootStorage=OC_Filesystem::createStorage('local',array('datadir'=>$CONFIG_DATADIRECTORY_ROOT)); -// if( OC_Config::getValue( "enablebackup", false )){ -// // This creates the Directorys recursively -// if(!is_dir( "$CONFIG_BACKUPDIRECTORY/$user/$root" )){ -// mkdir( "$CONFIG_BACKUPDIRECTORY/$user/$root", 0755, true ); -// } -// $backupStorage=OC_Filesystem::createStorage('local',array('datadir'=>$CONFIG_BACKUPDIRECTORY)); -// $backup=new OC_FILEOBSERVER_BACKUP(array('storage'=>$backupStorage)); -// $rootStorage->addObserver($backup); -// } - OC_Filesystem::mount($rootStorage,'/'); - - // TODO add this storage provider in a proper way - $sharedStorage = OC_Filesystem::createStorage('shared',array('datadir'=>'/'.OC_User::getUser().'/files/Shared')); - OC_Filesystem::mount($sharedStorage,'/'.OC_User::getUser().'/files/Shared/'); + //first set up the local "root" storage + OC_Filesystem::mount('local',array('datadir'=>$CONFIG_DATADIRECTORY_ROOT),'/'); OC::$CONFIG_DATADIRECTORY = $CONFIG_DATADIRECTORY_ROOT."/$user/$root"; if( !is_dir( OC::$CONFIG_DATADIRECTORY )){ mkdir( OC::$CONFIG_DATADIRECTORY, 0755, true ); } -// TODO: find a cool way for doing this -// //set up the other storages according to the system settings -// foreach($CONFIG_FILESYSTEM as $storageConfig){ -// if(OC_Filesystem::hasStorageType($storageConfig['type'])){ -// $arguments=$storageConfig; -// unset($arguments['type']); -// unset($arguments['mountpoint']); -// $storage=OC_Filesystem::createStorage($storageConfig['type'],$arguments); -// if($storage){ -// OC_Filesystem::mount($storage,$storageConfig['mountpoint']); -// } -// } -// } - //jail the user into his "home" directory OC_Filesystem::chroot("/$user/$root"); $quotaProxy=new OC_FileProxy_Quota(); @@ -90,7 +62,7 @@ class OC_Util { * @return array */ public static function getVersion(){ - return array(2,00,1); + return array(3,00,0); } /** @@ -98,7 +70,7 @@ class OC_Util { * @return string */ public static function getVersionString(){ - return '2'; + return '3'; } /** @@ -153,7 +125,7 @@ class OC_Util { */ public static function formatDate( $timestamp,$dateOnly=false){ if(isset($_SESSION['timezone'])){//adjust to clients timezone if we know it - $systemTimeZone = intval(exec('date +%z')); + $systemTimeZone = intval(date('O')); $systemTimeZone=(round($systemTimeZone/100,0)*60)+($systemTimeZone%100); $clientTimeZone=$_SESSION['timezone']*60; $offset=$clientTimeZone-$systemTimeZone; @@ -203,15 +175,14 @@ class OC_Util { $errors=array(); //check for database drivers - if(!is_callable('sqlite_open') and !is_callable('mysql_connect')){ - $errors[]=array('error'=>'No database drivers (sqlite or mysql) installed.<br/>','hint'=>'');//TODO: sane hint + if(!(is_callable('sqlite_open') or class_exists('SQLite3')) and !is_callable('mysql_connect') and !is_callable('pg_connect')){ + $errors[]=array('error'=>'No database drivers (sqlite, mysql, or postgresql) installed.<br/>','hint'=>'');//TODO: sane hint } $CONFIG_DBTYPE = OC_Config::getValue( "dbtype", "sqlite" ); $CONFIG_DBNAME = OC_Config::getValue( "dbname", "owncloud" ); - $serverUser=OC_Util::checkWebserverUser(); //common hint for all file permissons error messages - $permissionsHint="Permissions can usually be fixed by setting the owner of the file or directory to the user the web server runs as ($serverUser)"; + $permissionsHint="Permissions can usually be fixed by giving the webserver write access to the ownCloud directory"; //check for correct file permissions if(!stristr(PHP_OS, 'WIN')){ @@ -255,6 +226,10 @@ class OC_Util { $errors[]=array('error'=>'PHP module ctype is not installed.<br/>','hint'=>'Please ask your server administrator to install the module.'); } + if(file_exists(OC::$SERVERROOT."/config/config.php") and !is_writeable(OC::$SERVERROOT."/config/config.php")){ + $errors[]=array('error'=>"Can't write into config directory 'config'",'hint'=>"You can usually fix this by giving the webserver use write access to the config directory in owncloud"); + } + return $errors; } @@ -267,22 +242,6 @@ class OC_Util { OC_Template::printGuestPage("", "login", $parameters); } - /** - * Try to get the username the httpd server runs on, used in hints - */ - public static function checkWebserverUser(){ - $stat=stat($_SERVER['DOCUMENT_ROOT']); - if(is_callable('posix_getpwuid')){ - $serverUser=posix_getpwuid($stat['uid']); - $serverUser='\''.$serverUser['name'].'\''; - }elseif(exec('whoami')){ - $serverUser=exec('whoami'); - }else{ - $serverUser='\'www-data\' for ubuntu/debian'; //TODO: try to detect the distro and give a guess based on that - } - return $serverUser; - } - /** * Check if the app is enabled, send json error msg if not diff --git a/lib/vobject.php b/lib/vobject.php new file mode 100644 index 00000000000..e3479fc6d36 --- /dev/null +++ b/lib/vobject.php @@ -0,0 +1,207 @@ +<?php +/** + * ownCloud + * + * @author Bart Visscher + * @copyright 2011 Bart Visscher bartv@thisnet.nl + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + */ + +/** + * This class provides a streamlined interface to the Sabre VObject classes + */ +class OC_VObject{ + /** @var Sabre_VObject_Component */ + protected $vobject; + + /** + * @returns Sabre_VObject_Component + */ + public function getVObject(){ + return $this->vobject; + } + + /** + * @brief Parses the VObject + * @param string VObject as string + * @returns Sabre_VObject or null + */ + public static function parse($data){ + try { + Sabre_VObject_Reader::$elementMap['LAST-MODIFIED'] = 'Sabre_VObject_Element_DateTime'; + $vobject = Sabre_VObject_Reader::read($data); + if ($vobject instanceof Sabre_VObject_Component){ + $vobject = new OC_VObject($vobject); + } + return $vobject; + } catch (Exception $e) { + OC_Log::write('vobject', $e->getMessage(), OC_Log::ERROR); + return null; + } + } + + /** + * @brief Escapes semicolons + * @param string $value + * @return string + */ + public static function escapeSemicolons($value){ + foreach($value as &$i ){ + $i = implode("\\\\;", explode(';', $i)); + } + return implode(';',$value); + } + + /** + * @brief Creates an array out of a multivalue property + * @param string $value + * @return array + */ + public static function unescapeSemicolons($value){ + $array = explode(';',$value); + for($i=0;$i<count($array);$i++){ + if(substr($array[$i],-2,2)=="\\\\"){ + if(isset($array[$i+1])){ + $array[$i] = substr($array[$i],0,count($array[$i])-2).';'.$array[$i+1]; + unset($array[$i+1]); + } + else{ + $array[$i] = substr($array[$i],0,count($array[$i])-2).';'; + } + $i = $i - 1; + } + } + return $array; + } + + /** + * Constuctor + * @param Sabre_VObject_Component or string + */ + public function __construct($vobject_or_name){ + if (is_object($vobject_or_name)){ + $this->vobject = $vobject_or_name; + } else { + $this->vobject = new Sabre_VObject_Component($vobject_or_name); + } + } + + public function add($item, $itemValue = null){ + if ($item instanceof OC_VObject){ + $item = $item->getVObject(); + } + $this->vobject->add($item, $itemValue); + } + + /** + * @brief Add property to vobject + * @param object $name of property + * @param object $value of property + * @param object $parameters of property + * @returns Sabre_VObject_Property newly created + */ + public function addProperty($name, $value, $parameters=array()){ + if(is_array($value)){ + $value = OC_VObject::escapeSemicolons($value); + } + $property = new Sabre_VObject_Property( $name, $value ); + foreach($parameters as $name => $value){ + $property->parameters[] = new Sabre_VObject_Parameter($name, $value); + } + + $this->vobject->add($property); + return $property; + } + + public function setUID(){ + $uid = substr(md5(rand().time()),0,10); + $this->vobject->add('UID',$uid); + } + + public function setString($name, $string){ + if ($string != ''){ + $string = strtr($string, array("\r\n"=>"\n")); + $this->vobject->__set($name, $string); + }else{ + $this->vobject->__unset($name); + } + } + + /** + * Sets or unsets the Date and Time for a property. + * When $datetime is set to 'now', use the current time + * When $datetime is null, unset the property + * + * @param string property name + * @param DateTime $datetime + * @param int $dateType + * @return void + */ + public function setDateTime($name, $datetime, $dateType=Sabre_VObject_Element_DateTime::LOCALTZ){ + if ($datetime == 'now'){ + $datetime = new DateTime(); + } + if ($datetime instanceof DateTime){ + $datetime_element = new Sabre_VObject_Element_DateTime($name); + $datetime_element->setDateTime($datetime, $dateType); + $this->vobject->__set($name, $datetime_element); + }else{ + $this->vobject->__unset($name); + } + } + + public function getAsString($name){ + return $this->vobject->__isset($name) ? + $this->vobject->__get($name)->value : + ''; + } + + public function getAsArray($name){ + $values = array(); + if ($this->vobject->__isset($name)){ + $values = explode(',', $this->getAsString($name)); + $values = array_map('trim', $values); + } + return $values; + } + + public function &__get($name){ + if ($name == 'children'){ + return $this->vobject->children; + } + $return = $this->vobject->__get($name); + if ($return instanceof Sabre_VObject_Component){ + $return = new OC_VObject($return); + } + return $return; + } + + public function __set($name, $value){ + return $this->vobject->__set($name, $value); + } + + public function __unset($name){ + return $this->vobject->__unset($name); + } + + public function __isset($name){ + return $this->vobject->__isset($name); + } + + public function __call($function,$arguments){ + return call_user_func_array(array($this->vobject, $function), $arguments); + } +} |