diff options
author | Jakob Sack <mail@jakobsack.de> | 2011-03-01 23:20:16 +0100 |
---|---|---|
committer | Jakob Sack <mail@jakobsack.de> | 2011-03-01 23:20:16 +0100 |
commit | 132695ceb1d7ab0e4bfbb141e9e9639111dd25b5 (patch) | |
tree | f53fabcefd89a1e5bbeda9a2c2d2fff6683139d4 /lib | |
parent | 1fd39a52fa750878e7d70fba63c099f252095762 (diff) | |
download | nextcloud-server-132695ceb1d7ab0e4bfbb141e9e9639111dd25b5.tar.gz nextcloud-server-132695ceb1d7ab0e4bfbb141e9e9639111dd25b5.zip |
Start of the refactoring. Commit is quite big because I forgot to use git right from the beginning. Sorry.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/HTTP/WebDAV/Server/Filesystem.php | 760 | ||||
-rw-r--r-- | lib/User/backend.php | 161 | ||||
-rw-r--r-- | lib/User/database.php | 428 | ||||
-rw-r--r-- | lib/appconfig.php | 45 | ||||
-rw-r--r-- | lib/base.php | 807 | ||||
-rw-r--r-- | lib/config.php | 392 | ||||
-rw-r--r-- | lib/connect.php | 300 | ||||
-rw-r--r-- | lib/fileobserver.php | 82 | ||||
-rw-r--r-- | lib/files.php | 399 | ||||
-rw-r--r-- | lib/filestorage.php | 432 | ||||
-rw-r--r-- | lib/filesystem.php | 380 | ||||
-rw-r--r-- | lib/log.php | 78 | ||||
-rw-r--r-- | lib/ocs.php | 592 | ||||
-rw-r--r-- | lib/plugin.php | 381 | ||||
-rw-r--r-- | lib/remotestorage.php | 353 | ||||
-rw-r--r-- | lib/template.php | 197 | ||||
-rw-r--r-- | lib/user.php | 249 |
17 files changed, 6036 insertions, 0 deletions
diff --git a/lib/HTTP/WebDAV/Server/Filesystem.php b/lib/HTTP/WebDAV/Server/Filesystem.php new file mode 100644 index 00000000000..0615c600e07 --- /dev/null +++ b/lib/HTTP/WebDAV/Server/Filesystem.php @@ -0,0 +1,760 @@ +<?php +/* + +----------------------------------------------------------------------+ + | Copyright (c) 2002-2007 Christian Stocker, Hartmut Holzgraefe | + | All rights reserved | + | | + | Redistribution and use in source and binary forms, with or without | + | modification, are permitted provided that the following conditions | + | are met: | + | | + | 1. Redistributions of source code must retain the above copyright | + | notice, this list of conditions and the following disclaimer. | + | 2. 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. | + | 3. The names of the authors may not be used to endorse or promote | + | products derived from this software without specific prior | + | written permission. | + | | + | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | + | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | + | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | + | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | + | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | + | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | + | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | + | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | + | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | + | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | + | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | + | POSSIBILITY OF SUCH DAMAGE. | + +----------------------------------------------------------------------+ + --- modified for ownCloud --- +*/ + require_once("lib/base.php"); + oc_require_once("HTTP/WebDAV/Server.php"); + oc_require_once("System.php"); + + /** + * Filesystem access using WebDAV + * + * @access public + * @author Hartmut Holzgraefe <hartmut@php.net> + * @version @package-version@ + */ + class HTTP_WebDAV_Server_Filesystem extends HTTP_WebDAV_Server + { + /** + * Root directory for WebDAV access + * + * Defaults to webserver document root (set by ServeRequest) + * + * @access private + * @var string + */ + var $base = ""; + + /** + * Serve a webdav request + * + * @access public + * @param string + */ + function ServeRequest($base = false) + { + // special treatment for litmus compliance test + // reply on its identifier header + // not needed for the test itself but eases debugging + if (isset($this->_SERVER['HTTP_X_LITMUS'])) { + error_log("Litmus test ".$this->_SERVER['HTTP_X_LITMUS']); + header("X-Litmus-reply: ".$this->_SERVER['HTTP_X_LITMUS']); + } + + // set root directory, defaults to webserver document root if not set + if ($base) { + $this->base = realpath($base); // TODO throw if not a directory + } else if (!$this->base) { + $this->base = $this->_SERVER['DOCUMENT_ROOT']; + } + + // let the base class do all the work + parent::ServeRequest(); + } + + /** + * No authentication is needed here + * + * @access private + * @param string HTTP Authentication type (Basic, Digest, ...) + * @param string Username + * @param string Password + * @return bool true on successful authentication + */ + function check_auth($type, $user, $pass) + { + return true; + } + + + /** + * PROPFIND method handler + * + * @param array general parameter passing array + * @param array return array for file properties + * @return bool true on success + */ + function PROPFIND(&$options, &$files) + { + // get absolute fs path to requested resource + $fspath = $options["path"]; + + // sanity check + if (!OC_FILESYSTEM::file_exists($fspath)) { + return false; + } + + // prepare property array + $files["files"] = array(); + // store information for the requested path itself + $files["files"][] = $this->fileinfo($options["path"]); + // information for contained resources requested? + if (!empty($options["depth"]) && OC_FILESYSTEM::is_dir($fspath) && OC_FILESYSTEM::is_readable($fspath)) { + // make sure path ends with '/' + $options["path"] = $this->_slashify($options["path"]); + + // try to open directory + $handle = @OC_FILESYSTEM::opendir($fspath); + + if ($handle) { + // ok, now get all its contents + while ($filename = readdir($handle)) { + if ($filename != "." && $filename != "..") { + $files["files"][] = $this->fileinfo($options["path"].$filename); + } + } + // TODO recursion needed if "Depth: infinite" + } + } + + // ok, all done + return true; + } + + /** + * Get properties for a single file/resource + * + * @param string resource path + * @return array resource properties + */ + function fileinfo($path) + { + global $CONFIG_DBTABLEPREFIX; + + // map URI path to filesystem path + $fspath =$path; + + // create result array + $info = array(); + // TODO remove slash append code when base clase is able to do it itself + $info["path"] = OC_FILESYSTEM::is_dir($fspath) ? $this->_slashify($path) : $path; + $info["props"] = array(); + // no special beautified displayname here ... + $info["props"][] = $this->mkprop("displayname", strtoupper($path)); + + // creation and modification time + $info["props"][] = $this->mkprop("creationdate", OC_FILESYSTEM::filectime($fspath)); + $info["props"][] = $this->mkprop("getlastmodified", OC_FILESYSTEM::filemtime($fspath)); + // Microsoft extensions: last access time and 'hidden' status + $info["props"][] = $this->mkprop("lastaccessed", OC_FILESYSTEM::fileatime($fspath)); + $info["props"][] = $this->mkprop("ishidden", ('.' === substr(basename($fspath), 0, 1))); + // type and size (caller already made sure that path exists) + if ( OC_FILESYSTEM::is_dir($fspath)) { + // directory (WebDAV collection) + $info["props"][] = $this->mkprop("resourcetype", "collection"); + $info["props"][] = $this->mkprop("getcontenttype", "httpd/unix-directory"); + } else { + // plain file (WebDAV resource) + $info["props"][] = $this->mkprop("resourcetype", ""); + if ( OC_FILESYSTEM::is_readable($fspath)) { + $info["props"][] = $this->mkprop("getcontenttype", $this->_mimetype($fspath)); + } else { + $info["props"][] = $this->mkprop("getcontenttype", "application/x-non-readable"); + } + $info["props"][] = $this->mkprop("getcontentlength", OC_FILESYSTEM::filesize($fspath)); + } + // get additional properties from database + $query = "SELECT ns, name, value FROM {$CONFIG_DBTABLEPREFIX}properties WHERE path = '$path'"; + $res = OC_DB::select($query); + foreach($res as $row){ + $info["props"][] = $this->mkprop($row["ns"], $row["name"], $row["value"]); + } + return $info; + } + + /** + * try to detect the mime type of a file + * + * @param string file path + * @return string guessed mime type + */ + function _mimetype($fspath) + { + return OC_FILESYSTEM::getMimeType($fspath); + } + + /** + * HEAD method handler + * + * @param array parameter passing array + * @return bool true on success + */ + function HEAD(&$options) + { + // get absolute fs path to requested resource + $fspath = $options["path"]; + + // sanity check + if (! OC_FILESYSTEM::file_exists($fspath)) return false; + + // detect resource type + $options['mimetype'] = $this->_mimetype($fspath); + + // detect modification time + // see rfc2518, section 13.7 + // some clients seem to treat this as a reverse rule + // requiering a Last-Modified header if the getlastmodified header was set + $options['mtime'] = OC_FILESYSTEM::filemtime($fspath); + + // detect resource size + $options['size'] = OC_FILESYSTEM::filesize($fspath); + + return true; + } + + /** + * GET method handler + * + * @param array parameter passing array + * @return bool true on success + */ + function GET(&$options) + { + // get absolute fs path to requested resource) + $fspath = $options["path"]; + // is this a collection? + if (OC_FILESYSTEM::is_dir($fspath)) { + return $this->GetDir($fspath, $options); + } + + // the header output is the same as for HEAD + if (!$this->HEAD($options)) { + return false; + } + + // no need to check result here, it is handled by the base class + $options['stream'] = OC_FILESYSTEM::fopen($fspath, "r"); + + return true; + } + + /** + * GET method handler for directories + * + * This is a very simple mod_index lookalike. + * See RFC 2518, Section 8.4 on GET/HEAD for collections + * + * @param string directory path + * @return void function has to handle HTTP response itself + */ + function GetDir($fspath, &$options) + { + $path = $this->_slashify($options["path"]); + if ($path != $options["path"]) { + header("Location: ".$this->base_uri.$path); + exit; + } + + // fixed width directory column format + $format = "%15s %-19s %-s\n"; + + if (!OC_FILESYSTEM::is_readable($fspath)) { + return false; + } + + $handle = OC_FILESYSTEM::opendir($fspath); + if (!$handle) { + return false; + } + + echo "<html><head><title>Index of ".htmlspecialchars($options['path'])."</title></head>\n"; + + echo "<h1>Index of ".htmlspecialchars($options['path'])."</h1>\n"; + + echo "<pre>"; + printf($format, "Size", "Last modified", "Filename"); + echo "<hr>"; + + while ($filename = readdir($handle)) { + if ($filename != "." && $filename != "..") { + $fullpath = $fspath."/".$filename; + $name = htmlspecialchars($filename); + printf($format, + number_format(filesize($fullpath)), + strftime("%Y-%m-%d %H:%M:%S", filemtime($fullpath)), + "<a href='$name'>$name</a>"); + } + } + + echo "</pre>"; + + closedir($handle); + + echo "</html>\n"; + + exit; + } + + /** + * PUT method handler + * + * @param array parameter passing array + * @return bool true on success + */ + function PUT(&$options) + { + $fspath = $options["path"]; + $dir = dirname($fspath); + if (!OC_FILESYSTEM::file_exists($dir) || !OC_FILESYSTEM::is_dir($dir)) { + return "409 Conflict"; // TODO right status code for both? + } + + $options["new"] = ! OC_FILESYSTEM::file_exists($fspath); + + if ($options["new"] && !OC_FILESYSTEM::is_writeable($dir)) { + return "403 Forbidden"; + } + if (!$options["new"] && !OC_FILESYSTEM::is_writeable($fspath)) { + return "403 Forbidden"; + } + if (!$options["new"] && OC_FILESYSTEM::is_dir($fspath)) { + return "403 Forbidden"; + } + $fp = OC_FILESYSTEM::fopen($fspath, "w"); + + return $fp; + } + + + /** + * MKCOL method handler + * + * @param array general parameter passing array + * @return bool true on success + */ + function MKCOL($options) + { + $path = $options["path"]; + $parent = dirname($path); + $name = basename($path); + if (!OC_FILESYSTEM::file_exists($parent)) { + return "409 Conflict"; + } + + if (!OC_FILESYSTEM::is_dir($parent)) { + return "403 Forbidden"; + } + + if ( OC_FILESYSTEM::file_exists($parent."/".$name) ) { + return "405 Method not allowed"; + } + + if (!empty($this->_SERVER["CONTENT_LENGTH"])) { // no body parsing yet + return "415 Unsupported media type"; + } + + $stat = OC_FILESYSTEM::mkdir($parent."/".$name, 0777); + if (!$stat) { + return "403 Forbidden"; + } + + return ("201 Created"); + } + + + /** + * DELETE method handler + * + * @param array general parameter passing array + * @return bool true on success + */ + function DELETE($options) + { + global $CONFIG_DBTABLEPREFIX; + $path =$options["path"]; + if (!OC_FILESYSTEM::file_exists($path)) { + return "404 Not found"; + } + $lock=self::checkLock($path); + if(is_array($lock)){ + $owner=$options['owner']; + $lockOwner=$lock['owner']; + if($owner==$lockOwner){ + return "423 Locked"; + } + } + if (OC_FILESYSTEM::is_dir($path)) { + $query = "DELETE FROM {$CONFIG_DBTABLEPREFIX}properties WHERE path LIKE '".$this->_slashify($options["path"])."%'"; + OC_DB::query($query); + OC_FILESYSTEM::delTree($path); + } else { + OC_FILESYSTEM::unlink($path); + } + $query = "DELETE FROM {$CONFIG_DBTABLEPREFIX}properties WHERE path = '$options[path]'"; + OC_DB::query($query); + + return "204 No Content"; + } + + + /** + * MOVE method handler + * + * @param array general parameter passing array + * @return bool true on success + */ + function MOVE($options) + { + return $this->COPY($options, true); + } + + /** + * COPY method handler + * + * @param array general parameter passing array + * @return bool true on success + */ + function COPY($options, $del=false) + { + // TODO Property updates still broken (Litmus should detect this?) + global $CONFIG_DBTABLEPREFIX; + + if (!empty($this->_SERVER["CONTENT_LENGTH"])) { // no body parsing yet + return "415 Unsupported media type"; + } + + // no copying to different WebDAV Servers yet + if (isset($options["dest_url"])) { + return "502 bad gateway"; + } + + $source = $options["path"]; + if (!OC_FILESYSTEM::file_exists($source)) { + return "404 Not found"; + } + + if (OC_FILESYSTEM::is_dir($source)) { // resource is a collection + switch ($options["depth"]) { + case "infinity": // valid + break; + case "0": // valid for COPY only + if ($del) { // MOVE? + return "400 Bad request"; + } + break; + case "1": // invalid for both COPY and MOVE + default: + return "400 Bad request"; + } + } + + $dest = $options["dest"]; + $destdir = dirname($dest); + + if (!OC_FILESYSTEM::file_exists($destdir) || !OC_FILESYSTEM::is_dir($destdir)) { + return "409 Conflict"; + } + + + $new = !OC_FILESYSTEM::file_exists($dest); + $existing_col = false; + + if (!$new) { + if ($del && OC_FILESYSTEM::is_dir($dest)) { + if (!$options["overwrite"]) { + return "412 precondition failed"; + } + $dest .= basename($source); + if (OC_FILESYSTEM::file_exists($dest)) { + $options["dest"] .= basename($source); + } else { + $new = true; + $existing_col = true; + } + } + } + + if (!$new) { + if ($options["overwrite"]) { + $stat = $this->DELETE(array("path" => $options["dest"])); + if (($stat{0} != "2") && (substr($stat, 0, 3) != "404")) { + return $stat; + } + } else { + return "412 precondition failed"; + } + } + + if ($del) { + if (!OC_FILESYSTEM::rename($source, $dest)) { + return "500 Internal server error"; + } + $destpath = $this->_unslashify($options["dest"]); + if (is_dir($source)) { + $dpath=OC_DB::escape($destpath); + $path=OC_DB::escape($options["path"]); + $query = "UPDATE {$CONFIG_DBTABLEPREFIX}properties + SET path = REPLACE(path, '$path', '$dpath') + WHERE path LIKE '$path%'"; + OC_DB::query($query); + } + + $query = "UPDATE {$CONFIG_DBTABLEPREFIX}properties + SET path = '$dpath' + WHERE path = '$path'"; + OC_DB::query($query); + } else { + if (OC_FILESYSTEM::is_dir($source)) { + $files = OC_FILESYSTEM::getTree($source); + } else { + $files = array($source); + } + + if (!is_array($files) || empty($files)) { + return "500 Internal server error"; + } + + + foreach ($files as $file) { + if (OC_FILESYSTEM::is_dir($file)) { + $file = $this->_slashify($file); + } + $destfile = str_replace($source, $dest, $file); + + if (OC_FILESYSTEM::is_dir($file)) { + if (!OC_FILESYSTEM::file_exists($destfile)) { + if (!OC_FILESYSTEM::is_writeable(dirname($destfile))) { + return "403 Forbidden"; + } + if (!OC_FILESYSTEM::mkdir($destfile)) { + return "409 Conflict"; + } + } else if (!OC_FILESYSTEM::is_dir($destfile)) { + return "409 Conflict"; + } + } else { + if (!OC_FILESYSTEM::copy($file, $destfile)) { + return "409 Conflict($source) $file --> $destfile ".implode('::',$files); + } + } + } + } + return ($new && !$existing_col) ? "201 Created" : "204 No Content"; + } + + /** + * PROPPATCH method handler + * + * @param array general parameter passing array + * @return bool true on success + */ + function PROPPATCH(&$options) + { + global $prefs, $tab; + global $CONFIG_DBTABLEPREFIX; + + $msg = ""; + $path = $options["path"]; + $dir = dirname($path)."/"; + $base = basename($path); + + foreach ($options["props"] as $key => $prop) { + if ($prop["ns"] == "DAV:") { + $options["props"][$key]['status'] = "403 Forbidden"; + } else { + $path=OC_DB::escape($options['path']); + $name=OC_DB::escape($prop['name']); + $ns=OC_DB::escape($prop['ns']); + $val=OC_DB::escape($prop['val']); + if (isset($prop["val"])) { + $query = "REPLACE INTO {$CONFIG_DBTABLEPREFIX}properties (path,name,ns,value) VALUES('$path','$name','$ns','$val')"; + } else { + $query = "DELETE FROM {$CONFIG_DBTABLEPREFIX}properties WHERE path = '$path' AND name = '$name' AND ns = '$ns'"; + } + OC_DB::query($query); + } + } + + return ""; + } + + + /** + * LOCK method handler + * + * @param array general parameter passing array + * @return bool true on success + */ + function LOCK(&$options) + { + global $CONFIG_DBTABLEPREFIX; + + // get absolute fs path to requested resource + $fspath = $options["path"]; + // TODO recursive locks on directories not supported yet + // makes litmus test "32. lock_collection" fail + if (OC_FILESYSTEM::is_dir($fspath) && !empty($options["depth"])) { + switch($options["depth"]){ + case 'infinity': + $recursion=1; + break; + case '0': + $recursion=0; + break; + } + }else{ + $recursion=0; + } + + $options["timeout"] = time()+300; // 5min. hardcoded + + if (isset($options["update"])) { // Lock Update + $where = "WHERE path = '$options[path]' AND token = '$options[update]'"; + + $query = "SELECT owner, exclusivelock FROM {$CONFIG_DBTABLEPREFIX}locks $where"; + $res = OC_DB::select($query); + + if (is_array($res) and isset($res[0])) { + $row=$res[0]; + $query = "UPDATE `{$CONFIG_DBTABLEPREFIX}locks` SET `expires` = '$options[timeout]', `modified` = ".time()." $where"; + OC_DB::query($query); + + $options['owner'] = $row['owner']; + $options['scope'] = $row["exclusivelock"] ? "exclusive" : "shared"; + $options['type'] = $row["exclusivelock"] ? "write" : "read"; + + return true; + } else {//check for indirect refresh + $query = "SELECT * + FROM {$CONFIG_DBTABLEPREFIX}locks + WHERE recursive = 1 + "; + $res = OC_DB::select($query); + foreach($res as $row){ + if(strpos($options['path'],$row['path'])==0){//are we a child of a folder with an recursive lock + $where = "WHERE path = '$row[path]' AND token = '$options[update]'"; + $query = "UPDATE `{$CONFIG_DBTABLEPREFIX}locks` SET `expires` = '$options[timeout]', `modified` = ".time()." $where"; + OC_DB::query($query); + $options['owner'] = $row['owner']; + $options['scope'] = $row["exclusivelock"] ? "exclusive" : "shared"; + $options['type'] = $row["exclusivelock"] ? "write" : "read"; + return true; + } + } + } + } + + $locktoken=OC_DB::escape($options['locktoken']); + $path=OC_DB::escape($options['path']); + $time=time(); + $owner=OC_DB::escape($options['owner']); + $timeout=OC_DB::escape($options['timeout']); + $exclusive=($options['scope'] === "exclusive" ? "1" : "0"); + $query = "INSERT INTO `{$CONFIG_DBTABLEPREFIX}locks` +(`token`,`path`,`created`,`modified`,`owner`,`expires`,`exclusivelock`,`recursive`) +VALUES ('$locktoken','$path',$time,$time,'$owner','timeout',$exclusive,$recursion)"; + OC_DB::query($query); + $rows=OC_DB::affected_rows(); + if(!OC_FILESYSTEM::file_exists($fspath) and $rows>0) { + return "201 Created"; + } + return OC_DB::affected_rows($rows) ? "200 OK" : "409 Conflict"; + } + + /** + * UNLOCK method handler + * + * @param array general parameter passing array + * @return bool true on success + */ + function UNLOCK(&$options) + { + global $CONFIG_DBTABLEPREFIX; + $query = "DELETE FROM {$CONFIG_DBTABLEPREFIX}locks + WHERE path = '$options[path]' + AND token = '$options[token]'"; + OC_DB::query($query); + + return OC_DB::affected_rows() ? "204 No Content" : "409 Conflict"; + } + + /** + * checkLock() helper + * + * @param string resource path to check for locks + * @return bool true on success + */ + function checkLock($path) + { + global $CONFIG_DBTABLEPREFIX; + + $result = false; + $query = "SELECT * + FROM {$CONFIG_DBTABLEPREFIX}locks + WHERE path = '$path' + "; + $res = OC_DB::select($query); + if (is_array($res) and isset($res[0])) { + $row=$res[0]; + + if ($row) { + $result = array( "type" => "write", + "scope" => $row["exclusivelock"] ? "exclusive" : "shared", + "depth" => 0, + "owner" => $row['owner'], + "token" => $row['token'], + "created" => $row['created'], + "modified" => $row['modified'], + "expires" => $row['expires'], + "recursive" => $row['recursive'] + ); + } + }else{ + //check for recursive locks; + $query = "SELECT * + FROM {$CONFIG_DBTABLEPREFIX}locks + WHERE recursive = 1 + "; + $res = OC_DB::select($query); + foreach($res as $row){ + if(strpos($path,$row['path'])==0){//are we a child of a folder with an recursive lock + $result = array( "type" => "write", + "scope" => $row["exclusivelock"] ? "exclusive" : "shared", + "depth" => 0, + "owner" => $row['owner'], + "token" => $row['token'], + "created" => $row['created'], + "modified" => $row['modified'], + "expires" => $row['expires'], + "recursive" => $row['recursive'] + ); + } + } + } + + return $result; + } +} + +?>
\ No newline at end of file diff --git a/lib/User/backend.php b/lib/User/backend.php new file mode 100644 index 00000000000..a486ea1cbcc --- /dev/null +++ b/lib/User/backend.php @@ -0,0 +1,161 @@ +<?php + +/** +* ownCloud +* +* @author Frank Karlitschek +* @copyright 2010 Frank Karlitschek karlitschek@kde.org +* +* 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/>. +* +*/ + + + +/** + * Base class for user management + * + */ +abstract class OC_USER_BACKEND { + + /** + * Check if the login button is pressed and log the user in + * + */ + abstract public static function loginListener(); + + /** + * Try to create a new user + * + * @param string $username The username of the user to create + * @param string $password The password of the new user + */ + abstract public static function createUser($username, $password); + + /** + * Try to login a user + * + * @param string $username The username of the user to log in + * @param string $password The password of the user + */ + abstract public static function login($username, $password); + + /** + * Check if the logout button is pressed and logout the user + * + */ + abstract public static function logoutListener(); + + /** + * Check if some user is logged in + * + */ + abstract public static function isLoggedIn(); + + /** + * Try to create a new group + * + * @param string $groupName The name of the group to create + */ + abstract public static function createGroup($groupName); + + /** + * Get the ID of a user + * + * @param string $username Name of the user to find the ID + * @param boolean $noCache If false the cache is used to find the ID + */ + abstract public static function getUserId($username, $noCache=false); + + /** + * Get the ID of a group + * + * @param string $groupName Name of the group to find the ID + * @param boolean $noCache If false the cache is used to find the ID + */ + abstract public static function getGroupId($groupName, $noCache=false); + + /** + * Get the name of a group + * + * @param string $groupId ID of the group + * @param boolean $noCache If false the cache is used to find the name of the group + */ + abstract public static function getGroupName($groupId, $noCache=false); + + /** + * Check if a user belongs to a group + * + * @param string $username Name of the user to check + * @param string $groupName Name of the group + */ + abstract public static function inGroup($username, $groupName); + + /** + * Add a user to a group + * + * @param string $username Name of the user to add to group + * @param string $groupName Name of the group in which add the user + */ + abstract public static function addToGroup($username, $groupName); + + /** + * Remove a user from a group + * + * @param string $username Name of the user to remove from group + * @param string $groupName Name of the group from which remove the user + */ + abstract public static function removeFromGroup($username,$groupName); + + /** + * Generate a random password + */ + abstract public static function generatePassword(); + + /** + * Get all groups the user belongs to + * + * @param string $username Name of the user + */ + abstract public static function getUserGroups($username); + + /** + * Set the password of a user + * + * @param string $username User who password will be changed + * @param string $password The new password for the user + */ + abstract public static function setPassword($username, $password); + + /** + * Check if the password of the user is correct + * + * @param string $username Name of the user + * @param string $password Password of the user + */ + abstract public static function checkPassword($username, $password); + + + /** + * get a list of all users + * + */ + abstract public static function getUsers(); + + /** + * get a list of all groups + * + */ + abstract public static function getGroups(); +} diff --git a/lib/User/database.php b/lib/User/database.php new file mode 100644 index 00000000000..defaf7f8f40 --- /dev/null +++ b/lib/User/database.php @@ -0,0 +1,428 @@ +<?php + +/** +* ownCloud +* +* @author Frank Karlitschek +* @copyright 2010 Frank Karlitschek karlitschek@kde.org +* +* 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/>. +* +*/ + +oc_require_once('User/backend.php'); + + + +/** + * Class for user management in a SQL Database (e.g. MySQL, SQLite) + * + */ +class OC_USER_DATABASE extends OC_USER_BACKEND { + static private $userGroupCache=array(); + + /** + * Check if the login button is pressed and log the user in + * + */ + public static function loginListener(){ + if ( isset($_POST['loginbutton']) AND isset($_POST['password']) AND isset($_POST['login']) ) { + if ( OC_USER::login($_POST['login'], $_POST['password']) ) { + echo 1; + OC_LOG::event($_SESSION['username'], 1, ''); + echo 2; + if ( (isset($CONFIG_HTTPFORCESSL) AND $CONFIG_HTTPFORCESSL) + OR (isset($_SERVER['HTTPS']) AND ('on' == $_SERVER['HTTPS'])) ) { + $url = 'https://' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI']; + } else { + $url = 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI']; + } + header("Location: $url"); + die(); + } else { + return('error'); + } + } + return(''); + } + + /** + * Try to create a new user + * + * @param string $username The username of the user to create + * @param string $password The password of the new user + */ + public static function createUser($username, $password) { + self::clearCache(); + global $CONFIG_DBTABLEPREFIX; + // Check if the user already exists + if ( 0 != OC_USER::getUserId($username, true) ) { + return false; + } else { + $usernameClean = strToLower($username); + $password = sha1($password); + $username = OC_DB::escape($username); + $usernameClean = OC_DB::escape($usernameClean); + $query = "INSERT INTO `{$CONFIG_DBTABLEPREFIX}users` (`user_name` ,`user_name_clean` ,`user_password`) " + . "VALUES ('$username', '$usernameClean', '$password')"; + $result = OC_DB::query($query); + return $result ? true : false; + } + } + + /** + * Try to login a user + * + * @param string $username The username of the user to log in + * @param string $password The password of the user + */ + public static function login($username,$password){ + global $CONFIG_DBTABLEPREFIX; + + $password = sha1($password); + $usernameClean = strtolower($username); + $username = OC_DB::escape($username); + $usernameClean = OC_DB::escape($usernameClean); + $query = "SELECT user_id FROM {$CONFIG_DBTABLEPREFIX}users " + . "WHERE user_name_clean = '$usernameClean' AND user_password = '$password' LIMIT 1"; + $result = OC_DB::select($query); + if ( isset($result[0]) AND isset($result[0]['user_id']) ) { + $_SESSION['user_id'] = $result[0]['user_id']; + $_SESSION['username'] = $username; + $_SESSION['username_clean'] = $usernameClean; + return true; + } else { + return false; + } + } + + /** + * Check if the logout button is pressed and logout the user + * + */ + public static function logoutListener() { + global $WEBROOT; + if ( isset($_GET['logoutbutton']) AND isset($_SESSION['username']) ) { + OC_LOG::event($_SESSION['username'], 2, ''); + $_SESSION['user_id'] = false; + $_SESSION['username'] = ''; + $_SESSION['username_clean'] = ''; + + header("location: $WEBROOT"); + } + } + + /** + * Kick the user + * + */ + public static function logout() { + OC_LOG::event($_SESSION['username'], 2, ''); + $_SESSION['user_id'] = false; + $_SESSION['username'] = ''; + $_SESSION['username_clean'] = ''; + } + + /** + * Check if the user is logged in + * + */ + public static function isLoggedIn() { + if ( isset($_SESSION['user_id']) AND $_SESSION['user_id'] ) { + return true; + } else { + return false; + } + } + + /** + * Try to create a new group + * + * @param string $groupName The name of the group to create + */ + public static function createGroup($groupName) { + self::clearCache(); + global $CONFIG_DBTABLEPREFIX; + if (0 == OC_USER::getGroupId($groupName) ) { + $groupName = OC_DB::escape($groupName); + $query = "INSERT INTO `{$CONFIG_DBTABLEPREFIX}groups` (`group_name`) VALUES ('$groupName')"; + $result = OC_DB::query($query); + return $result ? true : false; + } else { + return false; + } + } + + /** + * Get the ID of a user + * + * @param string $username Name of the user to find the ID + * @param boolean $noCache If false the cache is used to find the ID + */ + public static function getUserId($username, $noCache=false) { + global $CONFIG_DBTABLEPREFIX; + + $usernameClean = strToLower($username); + // Try to use cached value to avoid an SQL query + if ( !$noCache AND isset($_SESSION['user_id_cache'][$usernameClean]) ) { + return $_SESSION['user_id_cache'][$usernameClean]; + } + $usernameClean = OC_DB::escape($usernameClean); + $query = "SELECT user_id FROM {$CONFIG_DBTABLEPREFIX}users WHERE user_name_clean = '$usernameClean'"; + $result = OC_DB::select($query); + if ( !is_array($result) ) { + return 0; + } + if ( isset($result[0]) AND isset($result[0]['user_id']) ) { + $_SESSION['user_id_cache'][$usernameClean] = $result[0]['user_id']; + return $result[0]['user_id']; + } else { + return 0; + } + } + + /** + * Get the ID of a group + * + * @param string $groupName Name of the group to find the ID + * @param boolean $noCache If false the cache is used to find the ID + */ + public static function getGroupId($groupName, $noCache=false) { + global $CONFIG_DBTABLEPREFIX; + + // Try to use cached value to avoid an SQL query + if ( !$noCache AND isset($_SESSION['group_id_cache'][$groupName]) ) { + return $_SESSION['group_id_cache'][$groupName]; + } + $groupName = OC_DB::escape($groupName); + $query = "SELECT group_id FROM {$CONFIG_DBTABLEPREFIX}groups WHERE group_name = '$groupName'"; + $result = OC_DB::select($query); + if ( !is_array($result) ) { + return 0; + } + if ( isset($result[0]) AND isset($result[0]['group_id']) ){ + $_SESSION['group_id_cache'][$groupName] = $result[0]['group_id']; + return $result[0]['group_id']; + } else { + return 0; + } + } + + /** + * Get the name of a group + * + * @param string $groupId ID of the group + * @param boolean $noCache If false the cache is used to find the name of the group + */ + public static function getGroupName($groupId, $noCache=false) { + global $CONFIG_DBTABLEPREFIX; + + // Try to use cached value to avoid an sql query + if ( !$noCache AND ($name = array_search($groupId, $_SESSION['group_id_cache'])) ) { + return $name; + } + $groupId = (integer)$groupId; + $query = "SELECT group_name FROM {$CONFIG_DBTABLEPREFIX}groups WHERE group_id = '$groupId' LIMIT 1"; + $result = OC_DB::select($query); + if ( isset($result[0]) AND isset($result[0]['group_name']) ) { + return $result[0]['group_name']; + } else { + return 0; + } + } + + /** + * Check if a user belongs to a group + * + * @param string $username Name of the user to check + * @param string $groupName Name of the group + */ + public static function inGroup($username,$groupName) { + global $CONFIG_DBTABLEPREFIX; + $userId = OC_USER::getUserId($username); + $groupId = OC_USER::getGroupId($groupName); + self::getUserGroups($username); + $groups=self::$userGroupCache[$userId]; + return (array_search($groupId,$groups)!==false); + } + + /** + * Add a user to a group + * + * @param string $username Name of the user to add to group + * @param string $groupName Name of the group in which add the user + */ + public static function addToGroup($username, $groupName) { + global $CONFIG_DBTABLEPREFIX; + self::clearCache(); + if ( !OC_USER::inGroup($username, $groupName) ) { + $userId = OC_USER::getUserId($username,true); + $groupId = OC_USER::getGroupId($groupName,true); + if ( (0 != $groupId) AND (0 != $userId) ) { + $query = "INSERT INTO `{$CONFIG_DBTABLEPREFIX}user_group` (`user_id` ,`group_id`) VALUES ('$userId', '$groupId');"; + $result = OC_DB::query($query); + if ( $result ) { + self::clearCache(); + return true; + } else { + return false; + } + } else { + return false; + } + } else { + return true; + } + } + + /** + * Remove a user from a group + * + * @param string $username Name of the user to remove from group + * @param string $groupName Name of the group from which remove the user + */ + public static function removeFromGroup($username,$groupName){ + global $CONFIG_DBTABLEPREFIX; + self::clearCache(); + if (OC_USER::inGroup($username, $groupName) ) { + $userId = OC_USER::getUserId($username,true); + $groupId = OC_USER::getGroupId($groupName,true); + if ( (0 != $groupId) AND (0 != $userId) ) { + $query="DELETE FROM `{$CONFIG_DBTABLEPREFIX}user_group` WHERE `group_id` =$groupId AND `user_id`=$userId"; + $result = OC_DB::query($query); + if ( $result ) { + self::clearCache(); + return true; + } else { + return false; + } + } + } + return false; + } + + /** + * Generate a random password + */ + public static function generatePassword(){ + return uniqId(); + } + + /** + * Get all groups the user belongs to + * + * @param string $username Name of the user + */ + public static function getUserGroups($username) { + global $CONFIG_DBTABLEPREFIX; + + $userId = OC_USER::getUserId($username); + if(!isset(self::$userGroupCache[$userId])){ + $query = "SELECT group_id FROM {$CONFIG_DBTABLEPREFIX}user_group WHERE user_id = '$userId'"; + $result = OC_DB::select($query); + $groupsId = array(); + if ( is_array($result) ) { + foreach ( $result as $group ) { + $groupId = $group['group_id']; + $groupsId[]=$groupId; + } + } + self::$userGroupCache[$userId]=$groupsId; + return $groupsId; + }else{ + return self::$userGroupCache[$userId]; + } + } + + /** + * Set the password of a user + * + * @param string $username User who password will be changed + * @param string $password The new password for the user + */ + public static function setPassword($username, $password) { + global $CONFIG_DBTABLEPREFIX; + + $password = sha1($password); + $userId = OC_USER::getUserId($username); + $query = "UPDATE {$CONFIG_DBTABLEPREFIX}users SET user_password = '$password' WHERE user_id ='$userId'"; + $result = OC_DB::query($query); + if ( $result ) { + return true; + } else { + return false; + } + } + + /** + * Check if the password of the user is correct + * + * @param string $username Name of the user + * @param string $password Password of the user + */ + public static function checkPassword($username, $password) { + global $CONFIG_DBTABLEPREFIX; + + $password = sha1($password); + $usernameClean = strToLower($username); + $usernameClean = OC_DB::escape($usernameClean); + $username = OC_DB::escape($username); + $query = "SELECT user_id FROM `{$CONFIG_DBTABLEPREFIX}users` " + . "WHERE user_name_clean = '$usernameClean' AND user_password = '$password' LIMIT 1"; + $result = OC_DB::select($query); + if ( isset($result[0]) AND isset($result[0]['user_id']) AND ($result[0]['user_id'] > 0) ) { + return true; + } else { + return false; + } + } + + /** + * get a list of all users + * + */ + public static function getUsers() { + global $CONFIG_DBTABLEPREFIX; + + $query = "SELECT user_name FROM `{$CONFIG_DBTABLEPREFIX}users`"; + $result = OC_DB::select($query); + $users=array(); + foreach($result as $user){ + $users[]=$user['user_name']; + } + return $users; + } + + /** + * get a list of all groups + * + */ + public static function getGroups() { + global $CONFIG_DBTABLEPREFIX; + + $query = "SELECT group_name FROM `{$CONFIG_DBTABLEPREFIX}groups`"; + $result = OC_DB::select($query); + $groups=array(); + foreach($result as $group){ + $groups[]=$group['group_name']; + } + return $groups; + } + + private static function clearCache(){ + self::$userGroupCache=array(); + $_SESSION['user_id_cache']=array(); + $_SESSION['group_id_cache']=array(); + } +} diff --git a/lib/appconfig.php b/lib/appconfig.php new file mode 100644 index 00000000000..f1bccc0a250 --- /dev/null +++ b/lib/appconfig.php @@ -0,0 +1,45 @@ +<?php +class OC_APPCONFIG{ + static public $forms=array(); + + /** + * add a form to the settings page + * @param string name + * @param string url + */ + public static function addForm($name,$url){ + self::$forms[$name]=$url; + } + + /** + * Get the available keys for an application + * @param string application + */ + public static function getKeys( $application ){ + // OC_DB::query( $query); + return array(); + } + + /** + * Get the config value + * @param string application + * @param string key + * @param string default + */ + public static function getValue( $application, $key, $default ){ + // OC_DB::query( $query); + return $default; + } + + /** + * Set the config value + * @param string application + * @param string key + * @param string value + */ + public static function setValue( $application, $name, $url ){ + // OC_DB::query( $query); + return true; + } +} +?> diff --git a/lib/base.php b/lib/base.php new file mode 100644 index 00000000000..4694f826a52 --- /dev/null +++ b/lib/base.php @@ -0,0 +1,807 @@ +<?php +/** +* ownCloud +* +* @author Frank Karlitschek +* @copyright 2010 Frank Karlitschek karlitschek@kde.org +* +* 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/>. +* +*/ + + +// set some stuff +ob_start(); +// error_reporting(E_ALL | E_STRICT); +error_reporting( E_ERROR | E_PARSE | E_WARNING ); // MDB2 gives loads of strict error, disabling for now + +date_default_timezone_set('Europe/Berlin'); +ini_set('arg_separator.output','&'); +ini_set('session.cookie_httponly','1;'); +session_start(); +// calculate the documentroot +$SERVERROOT=substr(__FILE__,0,-13); +$DOCUMENTROOT=realpath($_SERVER['DOCUMENT_ROOT']); +$SERVERROOT=str_replace("\\",'/',$SERVERROOT); +$SUBURI=substr(realpath($_SERVER["SCRIPT_FILENAME"]),strlen($SERVERROOT)); +$WEBROOT=substr($_SERVER["SCRIPT_NAME"],0,strlen($_SERVER["SCRIPT_NAME"])-strlen($SUBURI)); + + + +if($WEBROOT!='' and $WEBROOT[0]!=='/'){ + $WEBROOT='/'.$WEBROOT; +} + +// set the right include path +// set_include_path(get_include_path().PATH_SEPARATOR.$SERVERROOT.PATH_SEPARATOR.$SERVERROOT.'/inc'.PATH_SEPARATOR.$SERVERROOT.'/config'); + +// define default config values +$CONFIG_INSTALLED=false; +$CONFIG_DATADIRECTORY=$SERVERROOT.'/data'; +$CONFIG_BACKUPDIRECTORY=$SERVERROOT.'/backup'; +$CONFIG_HTTPFORCESSL=false; +$CONFIG_ENABLEBACKUP=false; +$CONFIG_DATEFORMAT='j M Y G:i'; +$CONFIG_DBNAME='owncloud'; +$CONFIG_DBTYPE='sqlite'; +$CONFIG_FILESYSTEM=array(); + +// include the generated configfile +@include_once($SERVERROOT.'/config/config.php'); + + +$CONFIG_DATADIRECTORY_ROOT=$CONFIG_DATADIRECTORY;// store this in a seperate variable so we can change the data directory to jail users. +// redirect to https site if configured +if(isset($CONFIG_HTTPFORCESSL) and $CONFIG_HTTPFORCESSL){ + if(!isset($_SERVER['HTTPS']) or $_SERVER['HTTPS'] != 'on') { + $url = "https://". $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI']; + header("Location: $url"); + exit; + } +} + +// load core libs +oc_require_once('files.php'); +oc_require_once('filesystem.php'); +oc_require_once('filestorage.php'); +oc_require_once('fileobserver.php'); +oc_require_once('log.php'); +oc_require_once('config.php'); +oc_require_once('user.php'); +oc_require_once('ocs.php'); +oc_require_once('connect.php'); +oc_require_once('remotestorage.php'); +oc_require_once('plugin.php'); + +OC_PLUGIN::loadPlugins(); + +if(!isset($CONFIG_BACKEND)){ + $CONFIG_BACKEND='database'; +} +OC_USER::setBackend($CONFIG_BACKEND); + +OC_UTIL::setupFS(); + +oc_startup(); + + + +// check if the server is correctly configured for ownCloud +OC_UTIL::checkserver(); + +// listen for login or logout actions +OC_USER::logoutlistener(); +$loginresult=OC_USER::loginlistener(); + +/** + * Class for utility functions + * + */ +class OC_UTIL { + public static $scripts=array(); + public static $styles=array(); + public static $adminpages = array(); + public static $applications = array(); + public static $navigation = array(); + public static $personalmenu = array(); + private static $fsSetup=false; + + public static function setupFS(){// configure the initial filesystem based on the configuration + if(self::$fsSetup){//setting up the filesystem twice can only lead to trouble + return false; + } + global $SERVERROOT; + global $CONFIG_DATADIRECTORY_ROOT; + global $CONFIG_DATADIRECTORY; + global $CONFIG_BACKUPDIRECTORY; + global $CONFIG_ENABLEBACKUP; + global $CONFIG_FILESYSTEM; + if(!is_dir($CONFIG_DATADIRECTORY_ROOT)){ + @mkdir($CONFIG_DATADIRECTORY_ROOT) or die("Can't create data directory ($CONFIG_DATADIRECTORY_ROOT), you can usually fix this by setting the owner of '$SERVERROOT' to the user that the web server uses (www-data for debian/ubuntu)"); + } + if(OC_USER::isLoggedIn()){ //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)); + if($CONFIG_ENABLEBACKUP){ + if(!is_dir($CONFIG_BACKUPDIRECTORY)){ + mkdir($CONFIG_BACKUPDIRECTORY); + } + if(!is_dir($CONFIG_BACKUPDIRECTORY.'/'.$_SESSION['username_clean'])){ + mkdir($CONFIG_BACKUPDIRECTORY.'/'.$_SESSION['username_clean']); + } + $backupStorage=OC_FILESYSTEM::createStorage('local',array('datadir'=>$CONFIG_BACKUPDIRECTORY)); + $backup=new OC_FILEOBSERVER_BACKUP(array('storage'=>$backupStorage)); + $rootStorage->addObserver($backup); + } + OC_FILESYSTEM::mount($rootStorage,'/'); + + $CONFIG_DATADIRECTORY=$CONFIG_DATADIRECTORY_ROOT.'/'.$_SESSION['username_clean']; + if(!is_dir($CONFIG_DATADIRECTORY)){ + mkdir($CONFIG_DATADIRECTORY); + } + + //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('/'.$_SESSION['username_clean']); + self::$fsSetup=true; + } + } + + /** + * get the current installed version of ownCloud + * @return array + */ + public static function getVersion(){ + return array(1,2,0); + } + + /** + * Create an url + * + * @param string $application + * @param string $file + */ + public static function linkTo( $application, $file = null ){ + global $WEBROOT; + if( is_null( $file )){ + $file = $application; + $application = ""; + } + return "$WEBROOT/$application/$file"; + } + + /** + * Create an image link + * + * @param string $application + * @param string $file + */ + public static function imagePath( $application, $file = null ){ + global $WEBROOT; + if( is_null( $file )){ + $file = $application; + $application = ""; + } + return "$WEBROOT/$application/img/$file"; + } + + /** + * add a javascript file + * + * @param url $url + */ + public static function addScript( $application, $file = null ){ + if( is_null( $file )){ + $file = $application; + $application = ""; + } + self::$scripts[] = "$application/js/$file"; + } + + /** + * add a css file + * + * @param url $url + */ + public static function addStyle( $application, $file = null ){ + if( is_null( $file )){ + $file = $application; + $application = ""; + } + self::$styles[] = "$application/css/$file"; + } + + /** + * add an entry to the main navigation + * + * @param array $entry + */ + public static function addNavigationEntry( $entry){ + OC_UTIL::$navigation[] = $entry; + } + + /** + * add administration pages + * + * @param array $entry + */ + public static function addAdminPage( $entry){ + OC_UTIL::$adminpages[] = $entry; + } + + /** + * add application + * + * @param array $entry + */ + public static function addApplication( $entry){ + OC_UTIL::$applications[] = $entry; + } + + /** + * add an entry to the personal menu + * + * @param array $entry + */ + public static function addPersonalMenuEntry( $entry){ + OC_UTIL::$personalmenu[] = $entry; + } + + /** + * check if the current server configuration is suitable for ownCloud + * + */ + public static function checkServer(){ + global $SERVERROOT; + global $CONFIG_DATADIRECTORY_ROOT; + global $CONFIG_BACKUPDIRECTORY; + global $CONFIG_ENABLEBACKUP; + global $CONFIG_INSTALLED; + $error=''; + if(!is_callable('sqlite_open') and !is_callable('mysql_connect')){ + $error.='No database drivers (sqlite or mysql) installed.<br/>'; + } + global $CONFIG_DBTYPE; + global $CONFIG_DBNAME; + if(!stristr(PHP_OS, 'WIN')){ + if($CONFIG_DBTYPE=='sqlite'){ + $file=$SERVERROOT.'/'.$CONFIG_DBNAME; + if(file_exists($file)){ + $prems=substr(decoct(fileperms($file)),-3); + if(substr($prems,2,1)!='0'){ + @chmod($file,0660); + clearstatcache(); + $prems=substr(decoct(fileperms($file)),-3); + if(substr($prems,2,1)!='0'){ + $error.='SQLite database file ('.$file.') is readable from the web<br/>'; + } + } + } + } + $prems=substr(decoct(fileperms($CONFIG_DATADIRECTORY_ROOT)),-3); + if(substr($prems,-1)!='0'){ + chmodr($CONFIG_DATADIRECTORY_ROOT,0770); + clearstatcache(); + $prems=substr(decoct(fileperms($CONFIG_DATADIRECTORY_ROOT)),-3); + if(substr($prems,2,1)!='0'){ + $error.='Data directory ('.$CONFIG_DATADIRECTORY_ROOT.') is readable from the web<br/>'; + } + } + if($CONFIG_ENABLEBACKUP){ + $prems=substr(decoct(fileperms($CONFIG_BACKUPDIRECTORY)),-3); + if(substr($prems,-1)!='0'){ + chmodr($CONFIG_BACKUPDIRECTORY,0770); + clearstatcache(); + $prems=substr(decoct(fileperms($CONFIG_BACKUPDIRECTORY)),-3); + if(substr($prems,2,1)!='0'){ + $error.='Data directory ('.$CONFIG_BACKUPDIRECTORY.') is readable from the web<br/>'; + } + } + } + }else{ + //TODO: premisions checks for windows hosts + } + if($error){ + die($error); + } + } + + /** + * check if we need to use the layout optimized for smaller screen, currently only checks for iPhone/Android + * @return bool + */ + public static function hasSmallScreen(){ + $userAgent=strtolower($_SERVER['HTTP_USER_AGENT']); + if(strpos($userAgent,'android') or strpos($userAgent,'iphone') or strpos($userAgent,'ipod')){//todo, add support for more devices + return true; + } + return false; + } + + /** + * show an icon for a filetype + * + */ + public static function showIcon($filetype){ + global $WEBROOT; + if($filetype=='dir'){ echo('<td><img src="'.$WEBROOT.'/img/icons/folder.png" width="16" height="16"></td>'); + }elseif($filetype=='foo'){ echo('<td>foo</td>'); + }else{ echo('<td><img src="'.$WEBROOT.'/img/icons/other.png" width="16" height="16"></td>'); + } + } +} + + +/** + * Class for database access + * + */ +class OC_DB { + static private $DBConnection=false; + static private $schema=false; + static private $affected=0; + static private $result=false; + /** + * connect to the datbase if not already connected + */ + public static function connect(){ + global $CONFIG_DBNAME; + global $CONFIG_DBHOST; + global $CONFIG_DBUSER; + global $CONFIG_DBPASSWORD; + global $CONFIG_DBTYPE; + global $DOCUMENTROOT; + global $SERVERROOT; + @oc_require_once('MDB2.php'); + if(!self::$DBConnection){ + $options = array( + 'portability' => MDB2_PORTABILITY_ALL, + 'log_line_break' => '<br>', + 'idxname_format' => '%s', + 'debug' => true, + 'quote_identifier' => true, + ); + if($CONFIG_DBTYPE=='sqlite'){ + $dsn = array( + 'phptype' => 'sqlite', + 'database' => $SERVERROOT.'/'.$CONFIG_DBNAME, + 'mode' => '0644', + ); + }elseif($CONFIG_DBTYPE=='mysql'){ + $dsn = array( + 'phptype' => 'mysql', + 'username' => $CONFIG_DBUSER, + 'password' => $CONFIG_DBPASSWORD, + 'hostspec' => $CONFIG_DBHOST, + 'database' => $CONFIG_DBNAME, + ); + }elseif($CONFIG_DBTYPE=='pgsql'){ + $dsn = array( + 'phptype' => 'pgsql', + 'username' => $CONFIG_DBUSER, + 'password' => $CONFIG_DBPASSWORD, + 'hostspec' => $CONFIG_DBHOST, + 'database' => $CONFIG_DBNAME, + ); + } + self::$DBConnection=MDB2::factory($dsn,$options); + + if (PEAR::isError(self::$DBConnection)) { + echo('<b>can not connect to database, using '.$CONFIG_DBTYPE.'. ('.self::$DBConnection->getUserInfo().')</center>'); + $error=self::$DBConnection->getMessage(); + error_log("$error"); + error_log(self::$DBConnection->getUserInfo()); + die($error); + } + self::$DBConnection->setFetchMode(MDB2_FETCHMODE_ASSOC); + } + } + + public static function connectScheme(){ + self::connect(); + @oc_require_once('MDB2/Schema.php'); + if(!self::$schema){ + self::$schema=&MDB2_Schema::factory(self::$DBConnection); + } + } + + /** + * executes a query on the database + * + * @param string $cmd + * @return result-set + */ + static function query($cmd){ + global $CONFIG_DBTYPE; + if(!trim($cmd)){ + return false; + } + OC_DB::connect(); + //fix differences between sql versions + + //differences in escaping of table names (` for mysql) + if($CONFIG_DBTYPE=='sqlite'){ + $cmd=str_replace('`','\'',$cmd); + }elseif($CONFIG_DBTYPE=='pgsql'){ + $cmd=str_replace('`','"',$cmd); + } + $result=self::$DBConnection->exec($cmd); + if (PEAR::isError($result)) { + $entry='DB Error: "'.$result->getMessage().'"<br />'; + $entry.='Offending command was: '.$cmd.'<br />'; + error_log($entry); + die($entry); + }else{ + self::$affected=$result; + } + self::$result=$result; + return $result; + } + + /** + * executes a query on the database and returns the result in an array + * + * @param string $cmd + * @return result-set + */ + static function select($cmd){ + OC_DB::connect(); + global $CONFIG_DBTYPE; + //fix differences between sql versions + + //differences in escaping of table names (` for mysql) + if($CONFIG_DBTYPE=='sqlite'){ + $cmd=str_replace('`','\'',$cmd); + }elseif($CONFIG_DBTYPE=='pgsql'){ + $cmd=str_replace('`','"',$cmd); + } + $result=self::$DBConnection->queryAll($cmd); + if (PEAR::isError($result)){ + $entry='DB Error: "'.$result->getMessage().'"<br />'; + $entry.='Offending command was: '.$cmd.'<br />'; + die($entry); + } + return $result; + } + + /** + * executes multiply queries on the database + * + * @param string $cmd + * @return result-set + */ + static function multiquery($cmd) { + $queries=explode(';',$cmd); + foreach($queries as $query){ + OC_DB::query($query); + } + return true; + } + + + /** + * closing a db connection + * + * @return bool + */ + static function close() { + self::$DBConnection->disconnect(); + self::$DBConnection=false; + } + + + /** + * Returning primarykey if last statement was an insert. + * + * @return primarykey + */ + static function insertid() { + $id=self::$DBConnection->lastInsertID(); + return $id; + } + + /** + * Returning number of rows in a result + * + * @param resultset $result + * @return int + */ + static function numrows($result) { + $result->numRows(); + } + /** + * Returning number of affected rows + * + * @return int + */ + static function affected_rows() { + return self::$affected; + } + + /** + * get a field from the resultset + * + * @param resultset $result + * @param int $i + * @param int $field + * @return unknown + */ + static function result($result, $i, $field) { + $tmp=$result->fetchRow(MDB2_FETCHMODE_ASSOC,$i); + $tmp=$tmp[$field]; + return($tmp); + } + + /** + * get data-array from resultset + * + * @param resultset $result + * @return data + */ + static function fetch_assoc($result){ + return $result->fetchRow(MDB2_FETCHMODE_ASSOC); + } + + /** + * Freeing resultset (performance) + * + * @param unknown_type $result + * @return bool + */ + static function free_result() { + if(self::$result){ + self::$result->free(); + self::$result=false; + } + } + + static public function disconnect(){ + if(self::$DBConnection){ + self::$DBConnection->disconnect(); + self::$DBConnection=false; + } + } + + /** + * escape strings so they can be used in queries + * + * @param string string + * @return string + */ + static function escape($string){ + OC_DB::connect(); + return self::$DBConnection->escape($string); + } + + static function getDbStructure($file){ + OC_DB::connectScheme(); + $definition = self::$schema->getDefinitionFromDatabase(); + $dump_options = array( + 'output_mode' => 'file', + 'output' => $file, + 'end_of_line' => "\n" + ); + self::$schema->dumpDatabase($definition, $dump_options, MDB2_SCHEMA_DUMP_STRUCTURE); + } + + static function createDbFromStructure($file){ + OC_DB::connectScheme(); + global $CONFIG_DBNAME; + global $CONFIG_DBTABLEPREFIX; + $content=file_get_contents($file); + $file2=tempnam(sys_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); + $definition=@self::$schema->parseDatabaseDefinitionFile($file2); + unlink($file2); + if($definition instanceof MDB2_Schema_Error){ + die($definition->getMessage() . ': ' . $definition->getUserInfo()); + } + $ret=@self::$schema->createDatabase($definition); + if($ret instanceof MDB2_Error) { + die ($ret->getMessage() . ': ' . $ret->getUserInfo()); + }else{ + return true; + } + } +} + + +//custom require/include functions because not all hosts allow us to set the include path +function oc_require($file){ + global $SERVERROOT; + global $DOCUMENTROOT; + global $WEBROOT; + global $CONFIG_DBNAME; + global $CONFIG_DBHOST; + global $CONFIG_DBUSER; + global $CONFIG_DBPASSWORD; + global $CONFIG_DBTYPE; + global $CONFIG_DATADIRECTORY; + global $CONFIG_HTTPFORCESSL; + global $CONFIG_DATEFORMAT; + global $CONFIG_INSTALLED; + + if(is_file($file)){ + return require($file); + } + elseif(is_file($SERVERROOT.'/'.$file)){ + return require($SERVERROOT.'/'.$file); + } + elseif(is_file($SERVERROOT.'/lib/'.$file)){ + return require($SERVERROOT.'/lib/'.$file); + } + elseif(is_file($SERVERROOT.'/3dparty/'.$file)){ + return require($SERVERROOT.'/3dparty/'.$file); + } +} + +function oc_require_once($file){ + global $SERVERROOT; + global $DOCUMENTROOT; + global $WEBROOT; + global $CONFIG_DBNAME; + global $CONFIG_DBHOST; + global $CONFIG_DBUSER; + global $CONFIG_DBPASSWORD; + global $CONFIG_DBTYPE; + global $CONFIG_DATADIRECTORY; + global $CONFIG_HTTPFORCESSL; + global $CONFIG_DATEFORMAT; + global $CONFIG_INSTALLED; + + if(is_file($file)){ + return require_once($file); + } + elseif(is_file($SERVERROOT.'/'.$file)){ + return require_once($SERVERROOT.'/'.$file); + } + elseif(is_file($SERVERROOT.'/lib/'.$file)){ + return require_once($SERVERROOT.'/lib/'.$file); + } + elseif(is_file($SERVERROOT.'/3dparty/'.$file)){ + return require_once($SERVERROOT.'/3dparty/'.$file); + } +} + +function oc_include($file){ + global $SERVERROOT; + global $DOCUMENTROOT; + global $WEBROOT; + global $CONFIG_DBNAME; + global $CONFIG_DBHOST; + global $CONFIG_DBUSER; + global $CONFIG_DBPASSWORD; + global $CONFIG_DBTYPE; + global $CONFIG_DATADIRECTORY; + global $CONFIG_HTTPFORCESSL; + global $CONFIG_DATEFORMAT; + global $CONFIG_INSTALLED; + + if(is_file($file)){ + return include($file); + } + elseif(is_file($SERVERROOT.'/'.$file)){ + return include($SERVERROOT.'/'.$file); + } + elseif(is_file($SERVERROOT.'/lib/'.$file)){ + return include($SERVERROOT.'/lib/'.$file); + } + elseif(is_file($SERVERROOT.'/3dparty/'.$file)){ + return include($SERVERROOT.'/3dparty/'.$file); + } +} + +function oc_include_once($file){ + global $SERVERROOT; + global $DOCUMENTROOT; + global $WEBROOT; + global $CONFIG_DBNAME; + global $CONFIG_DBHOST; + global $CONFIG_DBUSER; + global $CONFIG_DBPASSWORD; + global $CONFIG_DBTYPE; + global $CONFIG_DATADIRECTORY; + global $CONFIG_HTTPFORCESSL; + global $CONFIG_DATEFORMAT; + global $CONFIG_INSTALLED; + + if(is_file($file)){ + return include_once($file); + } + elseif(is_file($SERVERROOT.'/'.$file)){ + return include_once($SERVERROOT.'/'.$file); + } + elseif(is_file($SERVERROOT.'/lib/'.$file)){ + return include_once($SERVERROOT.'/lib/'.$file); + } + elseif(is_file($SERVERROOT.'/3dparty/'.$file)){ + return include_once($SERVERROOT.'/3dparty/'.$file); + } +} + +function chmodr($path, $filemode) { +// echo "$path<br/>"; + if (!is_dir($path)) + return chmod($path, $filemode); + $dh = opendir($path); + while (($file = readdir($dh)) !== false) { + if($file != '.' && $file != '..') { + $fullpath = $path.'/'.$file; + if(is_link($fullpath)) + return FALSE; + elseif(!is_dir($fullpath) && !chmod($fullpath, $filemode)) + return FALSE; + elseif(!chmodr($fullpath, $filemode)) + return FALSE; + } + } + closedir($dh); + if(chmod($path, $filemode)) + return TRUE; + else + return FALSE; +} + +function oc_startup(){ + global $SERVERROOT; + global $DOCUMENTROOT; + global $WEBROOT; + global $CONFIG_DBNAME; + global $CONFIG_DBHOST; + global $CONFIG_DBUSER; + global $CONFIG_DBPASSWORD; + global $CONFIG_DBTYPE; + global $CONFIG_DATADIRECTORY; + global $CONFIG_HTTPFORCESSL; + global $CONFIG_DATEFORMAT; + global $CONFIG_INSTALLED; + + // Add the stuff we need always + OC_UTIL::addPersonalMenuEntry( array( "file" => "index.php?logout=1", "name" => "Logout" )); + OC_UTIL::addScript( "jquery-1.5.min" ); + OC_UTIL::addScript( "jquery-ui-1.8.10.custom.min" ); + OC_UTIL::addScript( "js" ); + OC_UTIL::addStyle( "jquery-ui-1.8.10.custom" ); + OC_UTIL::addStyle( "styles" ); + + // Require all appinfo.php + $dir = opendir( $SERVERROOT ); + while( false !== ( $filename = readdir( $dir ))){ + if( substr( $filename, 0, 1 ) != '.' ){ + if( file_exists( "$SERVERROOT/$filename/appinfo.php" )){ + oc_require( "$filename/appinfo.php" ); + } + } + } + closedir( $dir ); + + // Everything done + return true; +} + +?> diff --git a/lib/config.php b/lib/config.php new file mode 100644 index 00000000000..75ddaafc316 --- /dev/null +++ b/lib/config.php @@ -0,0 +1,392 @@ +<?php +class OC_CONFIG{ + static public $forms=array(); + + /** + * add a form to the settings page + * @param string name + * @param string url + */ + public static function addForm($name,$url){ + self::$forms[$name]=$url; + } + + /** + * settings page + * + */ + public static function showSettings(){ + oc_require('templates/settings.php'); + } + + /** + * show the configform + * + */ + public static function showAdminForm(){ + global $CONFIG_ADMINLOGIN; + global $CONFIG_ADMINPASSWORD; + global $CONFIG_DATADIRECTORY; + global $CONFIG_HTTPFORCESSL; + global $CONFIG_DATEFORMAT; + global $CONFIG_DBNAME; + global $CONFIG_DBTABLEPREFIX; + global $CONFIG_INSTALLED; + $allow=false; + if(!$CONFIG_INSTALLED){ + $allow=true; + }elseif(OC_USER::isLoggedIn()){ + if(OC_USER::ingroup($_SESSION['username'],'admin')){ + $allow=true; + } + } + if($allow){ + oc_require('templates/adminform.php'); + } + } + + public static function createUserListener(){ + if(OC_USER::isLoggedIn()){ + if(OC_USER::ingroup($_SESSION['username'],'admin')){ + if(isset($_POST['new_username']) and isset($_POST['new_password'])){ + if(OC_USER::createuser($_POST['new_username'],$_POST['new_password'])){ + return 'user successfully created'; + }else{ + return 'error while trying to create user'; + } + }else{ + return false; + } + }else{ + return false; + } + } + } + + public static function createGroupListener(){ + if(OC_USER::isLoggedIn()){ + if(isset($_POST['creategroup']) and $_POST['creategroup']==1){ + if(OC_USER::creategroup($_POST['groupname'])){ + return 'group successfully created'; + }else{ + return 'error while trying to create group'; + } + }else{ + return false; + } + }else{ + return false; + } + } + + + /** + * listen for configuration changes + * + */ + public static function configListener(){ + if(OC_USER::isLoggedIn()){ + if(isset($_POST['config']) and $_POST['config']==1){ + $error=''; + if(!OC_USER::checkpassword($_SESSION['username'],$_POST['currentpassword'])){ + $error.='wrong password<br />'; + }else{ + if(isset($_POST['changepass']) and $_POST['changepass']==1){ + if(!isset($_POST['password']) or empty($_POST['password'])) $error.='password not set<br />'; + if(!isset($_POST['password2']) or empty($_POST['password2'])) $error.='retype password not set<br />'; + if($_POST['password']<>$_POST['password2'] ) $error.='passwords are not the same<br />'; + if(empty($error)){ + if(!OC_USER::setpassword($_SESSION['username'],$_POST['password'])){ + $error.='error while trying to set password<br />'; + } + } + } + } + return $error; + }else{ + return false; + } + }else{ + return false; + } + } + + /** + * Write the configuration to the `config.php` file + * + * $configuration contains key/value pairs + * - the key is the option name without the 'CONFIG_' prefix + * - the value is a string, a boolean or a number + * + * @param array $configuration is an associative array + */ + protected static function saveConfiguration($configuration) { + global $SERVERROOT; + + $configContent = '<?php'; + foreach ( $configuration as $key => $value ) { + if ( is_string($value) ) { + $configContent .= "\n\$CONFIG_$key = '$value';"; // e.g. $CONFIG_DBTYPE = 'mysql'; + } else if ( is_bool($value) ) { + $value = $value ? 'true' : 'false'; + $configContent .= "\n\$CONFIG_$key = $value;"; // e.g. $CONFIG_INSTALLED = true; + } else if ( is_numeric($value) ) { + $configContent .= "\n\$CONFIG_$key = $value;"; // e.g. $CONFIG_PI = 3.14; + } + } + $configContent .= "\n?>"; + $filename = "$SERVERROOT/config/config.php"; + file_put_contents($filename, $configContent); + } + + /** + * listen for admin configuration changes and write it to the file + *4bd0be1185e76 + */ + public static function writeAdminListener(){ + global $CONFIG_INSTALLED; + $allow=false; + if(!$CONFIG_INSTALLED){ + $allow=true; + }elseif(OC_USER::isLoggedIn()){ + if(OC_USER::ingroup($_SESSION['username'],'admin')){ + $allow=true; + } + } + if($allow){ + global $DOCUMENTROOT; + global $SERVERROOT; + global $WEBROOT; + global $CONFIG_DBHOST; + global $CONFIG_DBNAME; + global $CONFIG_DBTABLEPREFIX; + global $CONFIG_INSTALLED; + global $CONFIG_DBUSER; + global $CONFIG_DBPASSWORD; + global $CONFIG_DBTYPE; + global $CONFIG_ADMINLOGIN; + global $CONFIG_ADMINPASSWORD; + if(isset($_POST['set_config'])){ + //checkdata + $error=''; + $FIRSTRUN=!$CONFIG_INSTALLED; + if(!$FIRSTRUN){ + if(!OC_USER::login($_SESSION['username'],$_POST['currentpassword'])){ + $error.='wrong password<br />'; + } + } + + if((!isset($_POST['adminlogin']) or empty($_POST['adminlogin'])) and $FIRSTRUN) $error.='admin login not set<br />'; + if((!isset($_POST['adminpassword']) or empty($_POST['adminpassword'])) and $FIRSTRUN) $error.='admin password not set<br />'; + if((!isset($_POST['adminpassword2']) or empty($_POST['adminpassword2'])) and $FIRSTRUN) $error.='retype admin password not set<br />'; + if((!isset($_POST['datadirectory']) or empty($_POST['datadirectory'])) and $FIRSTRUN) $error.='data directory not set<br />'; + if(!isset($_POST['dateformat']) or empty($_POST['dateformat'])) $error.='dateformat not set<br />'; + if((!isset($_POST['dbname']) or empty($_POST['dbname'])) and $FIRSTRUN) $error.='databasename not set<br />'; + if($FIRSTRUN and $_POST['adminpassword']<>$_POST['adminpassword2'] ) $error.='admin passwords are not the same<br />'; + $dbtype=(isset($_POST['dbtype']))?$_POST['dbtype']:$CONFIG_DBTYPE; + if($dbtype=='mysql'){ + if(!isset($_POST['dbhost']) or empty($_POST['dbhost'])) $error.='database host not set<br />'; + if(!isset($_POST['dbuser']) or empty($_POST['dbuser'])) $error.='database user not set<br />'; + if($_POST['dbpassword']<>$_POST['dbpassword2'] ) $error.='database passwords are not the same<br />'; + + } + if(isset($_POST['enablebackup']) and $_POST['enablebackup']==1){ + if(!isset($_POST['backupdirectory']) or empty($_POST['backupdirectory'])) $error.='backup directory not set<br />'; + } + if(!$FIRSTRUN){ + if(!isset($_POST['adminpassword']) or empty($_POST['adminpassword'])){ + $_POST['adminpassword']=$CONFIG_ADMINPASSWORD; + } + if(!isset($_POST['dbpassword']) or empty($_POST['dbpassword'])){ + $_POST['dbpassword']=$CONFIG_DBPASSWORD; + } + }else{ + if(!is_dir($_POST['datadirectory'])){ + try{ + mkdir($_POST['datadirectory']); + }catch(Exception $e){ + $error.='error while trying to create data directory<br/>'; + } + } + } + if(empty($error)) { + if($CONFIG_DBTYPE!=$dbtype or $FIRSTRUN){ + //create/fill database + $CONFIG_DBTYPE=$dbtype; + $CONFIG_DBNAME=$_POST['dbname']; + if($dbtype!='sqlite'){ + $CONFIG_DBTABLEPREFIX=$_POST['dbtableprefix']; + $CONFIG_DBHOST=$_POST['dbhost']; + $CONFIG_DBUSER=$_POST['dbuser']; + $CONFIG_DBPASSWORD=$_POST['dbpassword']; + }else{ + $_POST['dbtableprefix']=''; + $CONFIG_DBTABLEPREFIX=''; + } + try{ + if(isset($_POST['createdatabase']) and $CONFIG_DBTYPE!='sqlite'){ + self::createdatabase($_POST['dbadminuser'],$_POST['dbadminpwd']); + } + }catch(Exception $e){ + $error.='error while trying to create the database<br/>'; + } + if($CONFIG_DBTYPE=='sqlite'){ + $f=@fopen($SERVERROOT.'/'.$CONFIG_DBNAME,'a+'); + if(!$f){ + $error.='path of sqlite database not writable by server<br/>'; + } + OC_DB::disconnect(); + unlink($SERVERROOT.'/'.$CONFIG_DBNAME); + } + try{ + if(isset($_POST['filldb'])){ + self::filldatabase(); + } + }catch(Exception $e){ + $error.='error while trying to fill the database<br/>'; + } + if($CONFIG_DBTYPE=='sqlite'){ + OC_DB::disconnect(); + } + } + if($FIRSTRUN){ + if(!OC_USER::createuser($_POST['adminlogin'],$_POST['adminpassword']) && !OC_USER::login($_POST['adminlogin'],$_POST['adminpassword'])){ + $error.='error while trying to create the admin user<br/>'; + } + if(OC_USER::getgroupid('admin',true)==0){ + if(!OC_USER::creategroup('admin')){ + $error.='error while trying to create the admin group<br/>'; + } + } + if(!OC_USER::addtogroup($_POST['adminlogin'],'admin')){ + $error.='error while trying to add the admin user to the admin group<br/>'; + } + } + // Build the configuration array + $config = array(); + $config['INSTALLED'] = true; + $config['DATADIRECTORY'] = $_POST['datadirectory']; + $config['HTTPFORCESSL'] = isset($_POST['forcessl']); + // Backup configuration + $config['ENABLEBACKUP'] = isset($_POST['enablebackup']); + if ( $config['ENABLEBACKUP'] AND (1 == $_POST['enablebackup']) ) + $config['BACKUPDIRECTORY'] = $_POST['backupdirectory']; + $config['DATEFORMAT'] = $_POST['dateformat']; + // DB Configuration + $config['DBTYPE'] = $dbtype; + $config['DBNAME'] = $_POST['dbname']; + $config['DBTABLEPREFIX'] = $_POST['dbtableprefix']; + if ( 'sqlite' != $dbtype ) { + $config['DBHOST'] = $_POST['dbhost']; + $config['DBUSER'] = $_POST['dbuser']; + $config['DBPASSWORD'] = $_POST['dbpassword']; + } + + if( empty($error) ) { + header("Location: $WEBROOT/"); + try { + // Write the configuration array to `/config/config.php` + self::saveConfiguration($config); + } catch ( Exception $e ) { + $error.='error while trying to save the configuration file<br/>'; + return $error; + } + } else { + return $error; + } + } + return($error); + } + } + } + + /** + * Fills the database with the initial tables + * Note: while the AUTO_INCREMENT function is not supported by SQLite + * the same effect can be achieved by accessing the SQLite pseudo-column + * "rowid" + */ + private static function fillDatabase(){ + global $SERVERROOT; + OC_DB::createDBFromStructure($SERVERROOT.'/db_structure.xml'); + } + + /** + * Create the database and user + * @param string adminUser + * @param string adminPwd + * + */ + private static function createDatabase($adminUser,$adminPwd){ + global $CONFIG_DBHOST; + global $CONFIG_DBNAME; + global $CONFIG_DBUSER; + global $CONFIG_DBPWD; + global $CONFIG_DBTYPE; + //we cant user OC_BD functions here because we need to connect as the administrative user. + if($CONFIG_DBTYPE=='mysql'){ + $connection=mysql_connect($CONFIG_DBHOST, $adminUser, $adminPwd); + if(!$connection) { + @ob_end_clean(); + echo('<html><head></head><body bgcolor="#F0F0F0"><br /><br /><center><b>can not connect to database as administrative user.</center></body></html>'); + exit(); + } + $query="SELECT user FROM mysql.user WHERE user='{$_POST['dbuser']}'"; + $result = mysql_query($query,$connection); + if (!$result) { + $entry='DB Error: "'.mysql_error($connection).'"<br />'; + $entry.='Offending command was: '.$query.'<br />'; + echo($entry); + } + if(mysql_num_rows($result)==0){ + $pwd=$_POST['dbpassword']; + //we need to create 2 accounts, one for global use and one for local user. if we don't speccify the local one, + // the anonymous user would take precedence when there is one. + $query="CREATE USER '{$_POST['dbuser']}'@'localhost' IDENTIFIED BY '$pwd'"; + $result = mysql_query($query,$connection); + if (!$result) { + $entry='DB Error: "'.mysql_error($connection).'"<br />'; + $entry.='Offending command was: '.$query.'<br />'; + echo($entry); + } + $query="CREATE USER '{$_POST['dbuser']}'@'%' IDENTIFIED BY '$pwd'"; + $result = mysql_query($query,$connection); + if (!$result) { + $entry='DB Error: "'.mysql_error($connection).'"<br />'; + $entry.='Offending command was: '.$query.'<br />'; + echo($entry); + } + } + $query="CREATE DATABASE IF NOT EXISTS `{$_POST['dbname']}`"; + $result = mysql_query($query,$connection); + if (!$result) { + $entry='DB Error: "'.mysql_error($connection).'"<br />'; + $entry.='Offending command was: '.$query.'<br />'; + echo($entry); + } + $query="GRANT ALL PRIVILEGES ON `{$_POST['dbname']}` . * TO '{$_POST['dbuser']}'"; + $result = mysql_query($query,$connection); + if (!$result) { + $entry='DB Error: "'.mysql_error($connection).'"<br />'; + $entry.='Offending command was: '.$query.'<br />'; + echo($entry); + } + mysql_close($connection); + }elseif($CONFIG_DBTYPE=='pgsql'){ + $connection = pg_connect("user='$adminUser' host='$CONFIG_DBHOST' password='$adminPwd'"); + $query="CREATE USER {$_POST['dbuser']} WITH PASSWORD '{$_POST['dbpassword']}' CREATEDB;"; + $result = pg_exec($connection, $query); + $query="select count(*) from pg_catalog.pg_database where datname = '{$_POST['dbname']}';"; + $result = pg_exec($connection, $query); + if(pg_result($result,0,0)==0){ + $query="CREATE DATABASE {$_POST['dbname']};"; + $result = pg_exec($connection, $query); + $query="ALTER DATABASE {$_POST['dbname']} OWNER TO {$_POST['dbuser']};"; + $result = pg_exec($connection, $query); + } + } + } +} +?> + + diff --git a/lib/connect.php b/lib/connect.php new file mode 100644 index 00000000000..695ae482451 --- /dev/null +++ b/lib/connect.php @@ -0,0 +1,300 @@ +<?php + +/** +* ownCloud +* +* @author Frank Karlitschek +* @copyright 2010 Frank Karlitschek karlitschek@kde.org +* +* 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/>. +* +*/ + +/** + * Class for connecting multiply ownCloud installations + * + */ +class OC_CONNECT{ + static private $clouds=array(); + + static function connect($path,$user,$password){ + $cloud=new OC_REMOTE_CLOUD($path,$user,$password); + if($cloud->connected){ + self::$clouds[$path]=$cloud; + return $cloud; + }else{ + return false; + } + } +} + + +/** + * Class for connection to a remote owncloud installation + * + */ +class OC_REMOTE_CLOUD{ + private $path; + private $connected=false; + private $cookiefile=false; + + /** + * make an api call to the remote cloud + * @param string $action + * @param array parameters + * @param bool assoc when set to true, the result will be parsed as associative array + * + */ + private function apiCall($action,$parameters=false,$assoc=false){ + if(!$this->cookiefile){ + $this->cookiefile=sys_get_temp_dir().'/remoteCloudCookie'.uniqid(); + } + $url=$this->path.='/files/api.php'; + $fields_string="action=$action&"; + if(is_array($parameters)){ + foreach($parameters as $key=>$value){ + $fields_string.=$key.'='.$value.'&'; + } + rtrim($fields_string,'&'); + } + $ch=curl_init(); + curl_setopt($ch,CURLOPT_URL,$url); + curl_setopt($ch,CURLOPT_POST,count($parameters)); + curl_setopt($ch,CURLOPT_POSTFIELDS,$fields_string); + curl_setopt($ch, CURLOPT_COOKIEFILE,$this->cookiefile); + curl_setopt($ch, CURLOPT_COOKIEJAR,$this->cookiefile); + curl_setopt($ch,CURLOPT_RETURNTRANSFER,true); + $result=curl_exec($ch); + $result=trim($result); + $info=curl_getinfo($ch); + $httpCode=$info['http_code']; + curl_close($ch); + if($httpCode==200 or $httpCode==0){ + return json_decode($result,$assoc); + }else{ + return false; + } + } + + public function __construct($path,$user,$password){ + $this->path=$path; + $this->connected=$this->apiCall('login',array('username'=>$user,'password'=>$password)); + } + + /** + * check if we are stull logged in on the remote cloud + * + */ + public function isLoggedIn(){ + if(!$this->connected){ + return false; + } + return $this->apiCall('checklogin'); + } + + public function __get($name){ + switch($name){ + case 'connected': + return $this->connected; + } + } + + /** + * disconnect from the remote cloud + * + */ + public function disconnect(){ + $this->connected=false; + if(is_file($this->cookiefile)){ + unlink($this->cookiefile); + } + $this->cookiefile=false; + } + + /** + * create a new file or directory + * @param string $dir + * @param string $name + * @param string $type + */ + public function newFile($dir,$name,$type){ + if(!$this->connected){ + return false; + } + return $this->apiCall('new',array('dir'=>$dir,'name'=>$name,'type'=>$type),true); + } + + /** + * deletes a file or directory + * @param string $dir + * @param string $file + */ + public function delete($dir,$name){ + if(!$this->connected){ + return false; + } + return $this->apiCall('delete',array('dir'=>$dir,'file'=>$name),true); + } + + /** + * moves a file or directory + * @param string $sorceDir + * @param string $sorceFile + * @param string $targetDir + * @param string $targetFile + */ + public function move($sourceDir,$sourceFile,$targetDir,$targetFile){ + if(!$this->connected){ + return false; + } + return $this->apiCall('move',array('sourcedir'=>$sourceDir,'source'=>$sourceFile,'targetdir'=>$targetDir,'target'=>$targetFile),true); + } + + /** + * copies a file or directory + * @param string $sorceDir + * @param string $sorceFile + * @param string $targetDir + * @param string $targetFile + */ + public function copy($sourceDir,$sourceFile,$targetDir,$targetFile){ + if(!$this->connected){ + return false; + } + return $this->apiCall('copy',array('sourcedir'=>$sourceDir,'source'=>$sourceFile,'targetdir'=>$targetDir,'target'=>$targetFile),true); + } + + /** + * get a file tree + * @param string $dir + */ + public function getTree($dir){ + if(!$this->connected){ + return false; + } + return $this->apiCall('gettree',array('dir'=>$dir),true); + } + + /** + * get the files inside a directory of the remote cloud + * @param string $dir + */ + public function getFiles($dir){ + if(!$this->connected){ + return false; + } + return $this->apiCall('getfiles',array('dir'=>$dir),true); + } + + /** + * get a remove file and save it in a temporary file and return the path of the temporary file + * @param string $dir + * @param string $file + * @return string + */ + public function getFile($dir, $file){ + if(!$this->connected){ + return false; + } + $ch=curl_init(); + if(!$this->cookiefile){ + $this->cookiefile=sys_get_temp_dir().'/remoteCloudCookie'.uniqid(); + } + $tmpfile=tempnam(sys_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); + curl_setopt($ch, CURLOPT_COOKIEFILE,$this->cookiefile); + curl_setopt($ch, CURLOPT_COOKIEJAR,$this->cookiefile); + curl_setopt($ch, CURLOPT_FILE, $fp); + curl_exec($ch); + fclose($fp); + curl_close($ch); + return $tmpfile; + } + + public function sendFile($sourceDir,$sourceFile,$targetDir,$targetFile){ + global $WEBROOT; + $source=$sourceDir.'/'.$sourceFile; + $tmp=OC_FILESYSTEM::toTmpFile($source); + return $this->sendTmpFile($tmp,$targetDir,$targetFile); + } + + public function sendTmpFile($tmp,$targetDir,$targetFile){ + $token=sha1(uniqid().$tmp); + global $WEBROOT; + $file=sys_get_temp_dir().'/'.'remoteCloudFile'.$token; + rename($tmp,$file); + if((isset($CONFIG_HTTPFORCESSL) and $CONFIG_HTTPFORCESSL) or isset($_SERVER['HTTPS']) and $_SERVER['HTTPS'] == 'on') { + $url = "https://". $_SERVER['SERVER_NAME'] . $WEBROOT; + }else{ + $url = "http://". $_SERVER['SERVER_NAME'] . $WEBROOT; + } + return $this->apiCall('pull',array('dir'=>$targetDir,'file'=>$targetFile,'token'=>$token,'source'=>$url),true); + } +} + +function OC_CONNECT_TEST($path,$user,$password){ + echo 'connecting...'; + $remote=OC_CONNECT::connect($path,$user,$password); + if($remote->connected){ + echo 'done<br/>'; + if($remote->isLoggedIn()){ + echo 'logged in, session working<br/>'; + echo 'trying to get remote files...'; + $files=$remote->getFiles(''); + if($files){ + echo count($files).' files found:<br/>'; + foreach($files as $file){ + echo "{$file['type']} {$file['name']}: {$file['size']} bytes<br/>"; + } + echo 'getting file "'.$file['name'].'"...'; + $size=$file['size']; + $file=$remote->getFile('',$file['name']); + if(file_exists($file)){ + $newSize=filesize($file); + if($size!=$newSize){ + echo "fail<br/>Error: $newSize bytes received, $size expected."; + echo '<br/><br/>Recieved file:<br/>'; + readfile($file); + unlink($file); + return; + } + OC_FILESYSTEM::fromTmpFile($file,'/remoteFile'); + echo 'done<br/>'; + echo 'sending file "burning_avatar.png"...'; + $res=$remote->sendFile('','burning_avatar.png','','burning_avatar.png'); + if($res){ + echo 'done<br/>'; + }else{ + echo 'fail<br/>'; + } + }else{ + echo 'fail<br/>'; + } + }else{ + echo 'fail<br/>'; + } + }else{ + echo 'no longer logged in, session fail<br/>'; + } + }else{ + echo 'fail<br/>'; + } + $remote->disconnect(); + die(); +} + + +?> diff --git a/lib/fileobserver.php b/lib/fileobserver.php new file mode 100644 index 00000000000..08a67521f03 --- /dev/null +++ b/lib/fileobserver.php @@ -0,0 +1,82 @@ +<?php + +/** +* ownCloud +* +* @author Frank Karlitschek +* @copyright 2010 Frank Karlitschek karlitschek@kde.org +* +* 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/>. +*/ + +define('OC_FILEACTION_WRITE',2); +define('OC_FILEACTION_READ',4); +define('OC_FILEACTION_DELETE',8); +define('OC_FILEACTION_CREATE',16); +define('OC_FILEACTION_RENAME',32); + +/** + * base class for file observers + */ +class OC_FILEOBSERVER{ + private $mask; + + public function __construct($arguments){} + + public function __get($name){ + switch($name){ + case 'mask': + return $this->mask; + } + } + + public function notify($path,$action){} +} + +/** + * observer that makes automatic backups + */ +class OC_FILEOBSERVER_BACKUP extends OC_FILEOBSERVER{ + private $storage; + + public function __construct($arguments){ + $this->mask=OC_FILEACTION_WRITE+OC_FILEACTION_DELETE+OC_FILEACTION_CREATE+OC_FILEACTION_RENAME; + $this->storage=$arguments['storage']; + } + + public function notify($path,$action,$storage){ + switch($action){ + case OC_FILEACTION_DELETE: + if($storage->is_dir($path)){ + $this->storage->delTree($path); + }else{ + $this->storage->unlink($path); + } + break; + case OC_FILEACTION_CREATE: + if($storage->is_dir($path)){ + $this->storage->mkdir($path); + break; + } + case OC_FILEACTION_WRITE: + $tmpFile=$storage->toTmpFile($path); + $this->storage->fromTmpFile($tmpFile,$path); + break; + case OC_FILEACTION_RENAME: + list($source,$target)=explode('->',$path); + $this->storage->rename($source,$target); + } + } +} +?>
\ No newline at end of file diff --git a/lib/files.php b/lib/files.php new file mode 100644 index 00000000000..bf629a59d44 --- /dev/null +++ b/lib/files.php @@ -0,0 +1,399 @@ +<?php + +/** +* ownCloud +* +* @author Frank Karlitschek +* @copyright 2010 Frank Karlitschek karlitschek@kde.org +* +* 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/>. +* +*/ + +oc_require_once("log.php"); + + +/** + * Class for fileserver access + * + */ +class OC_FILES { + static $tmpFiles=array(); + /** + * show a web GUI filebrowser + * + * @param basedir $basedir + * @param dir $dir + */ + public static function showBrowser($basedir,$dir){ + echo '<div id="content"></div>'; + } + + /** + * get the content of a directory + * @param dir $directory + */ + public static function getDirectoryContent($directory){ + global $CONFIG_DATADIRECTORY; + if(strpos($directory,$CONFIG_DATADIRECTORY)===0){ + $directory=substr($directory,strlen($CONFIG_DATADIRECTORY)); + } + $filesfound=true; + $content=array(); + $dirs=array(); + $file=array(); + $files=array(); + if(OC_FILESYSTEM::is_dir($directory)) { + if ($dh = OC_FILESYSTEM::opendir($directory)) { + while (($filename = readdir($dh)) !== false) { + if($filename<>'.' and $filename<>'..' and substr($filename,0,1)!='.'){ + $file=array(); + $filesfound=true; + $file['name']=$filename; + $file['directory']=$directory; + $stat=OC_FILESYSTEM::stat($directory.'/'.$filename); + $file=array_merge($file,$stat); + $file['mime']=OC_FILES::getMimeType($directory .'/'. $filename); + $file['readable']=OC_FILESYSTEM::is_readable($directory .'/'. $filename); + $file['writeable']=OC_FILESYSTEM::is_writeable($directory .'/'. $filename); + $file['type']=OC_FILESYSTEM::filetype($directory .'/'. $filename); + if($file['type']=='dir'){ + $dirs[$file['name']]=$file; + }else{ + $files[$file['name']]=$file; + } + } + } + closedir($dh); + } + } + ksort($dirs); + ksort($files); + $content=array_merge($dirs,$files); + if($filesfound){ + return $content; + }else{ + return false; + } + } + + + + /** + * return the content of a file or return a zip file containning multiply files + * + * @param dir $dir + * @param file $file + */ + public static function get($dir,$files){ + if(strpos($files,';')){ + $files=explode(';',$files); + } + if(is_array($files)){ + $zip = new ZipArchive(); + $filename = sys_get_temp_dir()."/ownCloud.zip"; + if ($zip->open($filename, ZIPARCHIVE::CREATE)!==TRUE) { + exit("cannot open <$filename>\n"); + } + foreach($files as $file){ + $file=$dir.'/'.$file; + if(OC_FILESYSTEM::is_file($file)){ + $tmpFile=OC_FILESYSTEM::toTmpFile($file); + self::$tmpFiles[]=$tmpFile; + $zip->addFile($tmpFile,basename($file)); + }elseif(OC_FILESYSTEM::is_dir($file)){ + zipAddDir($file,$zip); + } + } + $zip->close(); + }elseif(OC_FILESYSTEM::is_dir($dir.'/'.$files)){ + $zip = new ZipArchive(); + $filename = sys_get_temp_dir()."/ownCloud.zip"; + if ($zip->open($filename, ZIPARCHIVE::CREATE)!==TRUE) { + exit("cannot open <$filename>\n"); + } + $file=$dir.'/'.$files; + zipAddDir($file,$zip); + $zip->close(); + }else{ + $zip=false; + $filename=$dir.'/'.$files; + } + if($zip or OC_FILESYSTEM::is_readable($filename)){ + header('Content-Disposition: attachment; filename="'.basename($filename).'"'); + header('Content-Transfer-Encoding: binary'); + header('Expires: 0'); + header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); + header('Pragma: public'); + if($zip){ + header('Content-Type: application/zip'); + header('Content-Length: ' . filesize($filename)); + }else{ + header('Content-Type: ' . OC_FILESYSTEM::getMimeType($filename)); + header('Content-Length: ' . OC_FILESYSTEM::filesize($filename)); + } + }elseif($zip or !OC_FILESYSTEM::file_exists($filename)){ + header("HTTP/1.0 404 Not Found"); + die('404 Not Found'); + }else{ + header("HTTP/1.0 403 Forbidden"); + die('403 Forbidden'); + } + ob_end_clean(); + OC_LOG::event($_SESSION['username'],3,"$dir/$files"); + if($zip){ + readfile($filename); + unlink($filename); + }else{ + OC_FILESYSTEM::readfile($filename); + } + foreach(self::$tmpFiles as $tmpFile){ + if(file_exists($tmpFile) and is_file($tmpFile)){ + unlink($tmpFile); + } + } + } + + /** + * move a file or folder + * + * @param dir $sourceDir + * @param file $source + * @param dir $targetDir + * @param file $target + */ + public static function move($sourceDir,$source,$targetDir,$target){ + if(OC_USER::isLoggedIn()){ + $targetFile=$targetDir.'/'.$target; + $sourceFile=$sourceDir.'/'.$source; + return OC_FILESYSTEM::rename($sourceFile,$targetFile); + } + } + + /** + * copy a file or folder + * + * @param dir $sourceDir + * @param file $source + * @param dir $targetDir + * @param file $target + */ + public static function copy($sourceDir,$source,$targetDir,$target){ + if(OC_USER::isLoggedIn()){ + $targetFile=$targetDir.'/'.$target; + $sourceFile=$sourceDir.'/'.$source; + return OC_FILESYSTEM::copy($sourceFile,$targetFile); + } + } + + /** + * create a new file or folder + * + * @param dir $dir + * @param file $name + * @param type $type + */ + public static function newFile($dir,$name,$type){ + if(OC_USER::isLoggedIn()){ + $file=$dir.'/'.$name; + if($type=='dir'){ + return OC_FILESYSTEM::mkdir($file); + }elseif($type=='file'){ + $fileHandle=OC_FILESYSTEM::fopen($file, 'w'); + if($fileHandle){ + fclose($fileHandle); + OC_LOG::event($_SESSION['username'],4,"$dir/$name"); + return true; + }else{ + return false; + } + } + } + } + + /** + * deletes a file or folder + * + * @param dir $dir + * @param file $name + */ + public static function delete($dir,$file){ + if(OC_USER::isLoggedIn()){ + $file=$dir.'/'.$file; + if(OC_FILESYSTEM::is_file($file)){ + return OC_FILESYSTEM::unlink($file); + }elseif(OC_FILESYSTEM::is_dir($file)){ + return OC_FILESYSTEM::delTree($file); + } + } + } + + /** + * try to detect the mime type of a file + * + * @param string path + * @return string guessed mime type + */ + static function getMimeType($path){ + return OC_FILESYSTEM::getMimeType($path); + } + + /** + * get a file tree + * + * @param string path + * @return array + */ + static function getTree($path){ + return OC_FILESYSTEM::getTree($path); + } + + /** + * pull a file from a remote server + * @param string source + * @param string token + * @param string dir + * @param string file + * @return string guessed mime type + */ + static function pull($source,$token,$dir,$file){ + $tmpfile=tempnam(sys_get_temp_dir(),'remoteCloudFile'); + $fp=fopen($tmpfile,'w+'); + $url=$source.="/files/pull.php?token=$token"; + $ch=curl_init(); + curl_setopt($ch,CURLOPT_URL,$url); + curl_setopt($ch, CURLOPT_FILE, $fp); + curl_exec($ch); + fclose($fp); + $info=curl_getinfo($ch); + $httpCode=$info['http_code']; + curl_close($ch); + if($httpCode==200 or $httpCode==0){ + OC_FILESYSTEM::fromTmpFile($tmpfile,$dir.'/'.$file); + return true; + }else{ + return false; + } + } +} + +function zipAddDir($dir,$zip,$internalDir=''){ + $dirname=basename($dir); + $zip->addEmptyDir($internalDir.$dirname); + $internalDir.=$dirname.='/'; + $files=OC_FILES::getdirectorycontent($dir); + foreach($files as $file){ + $filename=$file['name']; + $file=$dir.'/'.$filename; + if(OC_FILESYSTEM::is_file($file)){ + $tmpFile=OC_FILESYSTEM::toTmpFile($file); + OC_FILES::$tmpFiles[]=$tmpFile; + $zip->addFile($tmpFile,$internalDir.$filename); + }elseif(OC_FILESYSTEM::is_dir($file)){ + zipAddDir($file,$zip,$internalDir); + } + } +} + +//remove a dir and it's content +function delTree($dir) { + if (!file_exists($dir)) return true; + if (!is_dir($dir) || is_link($dir)) return unlink($dir); + foreach (scandir($dir) as $item) { + if ($item == '.' || $item == '..') continue; + if(is_file($dir.'/'.$item)){ + unlink($dir.'/'.$item); + }elseif(is_dir($dir.'/'.$item)){ + if (!delTree($dir. "/" . $item)){ + return false; + }; + } + } + $return=rmdir($dir); + return $return; +} + +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; + } +} + +function recursive_copy($src,$dst) { + $dir = opendir($src); + @mkdir($dst); + while(false !== ( $file = readdir($dir)) ) { + if (( $file != '.' ) && ( $file != '..' )) { + if ( is_dir($src . '/' . $file) ) { + recursive_copy($src . '/' . $file,$dst . '/' . $file); + } + else { + copy($src . '/' . $file,$dst . '/' . $file); + } + } + } + closedir($dir); +} + +global $FAKEDIRS; +$FAKEDIRS=array(); + +class fakeDirStream{ + private $name; + private $data; + private $index; + + public function dir_opendir($path,$options){ + global $FAKEDIRS; + $url=parse_url($path); + $this->name=substr($path,strlen('fakedir://')); + $this->index=0; + if(isset($FAKEDIRS[$this->name])){ + $this->data=$FAKEDIRS[$this->name]; + }else{ + $this->data=array(); + } + return true; + } + + public function dir_readdir(){ + if($this->index>=count($this->data)){ + return false; + } + $filename=$this->data[$this->index]; + $this->index++; + return $filename; + } + + public function dir_closedir() { + $this->data=false; + $this->name=''; + return true; + } + + public function dir_rewinddir() { + $this->index=0; + return true; + } +} +stream_wrapper_register("fakedir", "fakeDirStream"); +?>
\ No newline at end of file diff --git a/lib/filestorage.php b/lib/filestorage.php new file mode 100644 index 00000000000..06ce26f0d23 --- /dev/null +++ b/lib/filestorage.php @@ -0,0 +1,432 @@ +<?php + +/** +* ownCloud +* +* @author Frank Karlitschek +* @copyright 2010 Frank Karlitschek karlitschek@kde.org +* +* 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/>. +*/ + +/** + * Privde a common interface to all different storage options + */ +class OC_FILESTORAGE{ + private $observers=array(); + /** + * add an observer to the list + * @param OC_FILEOBERSER observer + */ + public function addObserver($observer){ + $this->observers[]=$observer; + } + /** + * notify the observers about an action + * @param int action a combination of OC_FILEACTION_WRITE and OC_FILEACTION_READ + * @param string path relative path of the file + */ + public function notifyObservers($path,$action){ + foreach($this->observers as $observer){ + if($observer->mask & $action){ + $observer->notify($path,$action,$this); + } + } + } + + public function __construct($parameters){} + public function mkdir($path){} + public function rmdir($path){} + public function opendir($path){} + public function is_dir($path){} + public function is_file($path){} + public function stat($path){} + public function filetype($path){} + public function filesize($path){} + public function is_readable($path){} + public function is_writeable($path){} + public function file_exists($path){} + public function readfile($path){} + public function filectime($path){} + public function filemtime($path){} + public function fileatime($path){} + public function file_get_contents($path){} + public function file_put_contents($path,$data){} + public function unlink($path){} + public function rename($path1,$path2){} + public function copy($path1,$path2){} + public function fopen($path,$mode){} + public function toTmpFile($path){}//copy the file to a temporary file, used for cross-storage file actions + public function fromTmpFile($tmpPath,$path){}//copy a file from a temporary file, used for cross-storage file actions + public function getMimeType($path){} + public function delTree($path){} + public function find($path){} + public function getTree($path){} +} + + +OC_FILESYSTEM::registerStorageType('local','OC_FILESTORAGE_LOCAL',array('datadir'=>'string')); +/** + * for local filestore, we only have to map the paths + */ +class OC_FILESTORAGE_LOCAL extends OC_FILESTORAGE{ + private $datadir; + public function __construct($arguments){ + $this->datadir=$arguments['datadir']; + if(substr($this->datadir,-1)!=='/'){ + $this->datadir.='/'; + } + } + public function mkdir($path){ + if($return=mkdir($this->datadir.$path)){ + $this->notifyObservers($path,OC_FILEACTION_CREATE); + } + return $return; + } + public function rmdir($path){ + if($return=rmdir($this->datadir.$path)){ + $this->notifyObservers($path,OC_FILEACTION_DELETE); + } + return $return; + } + public function opendir($path){ + if($return=opendir($this->datadir.$path)){ + $this->notifyObservers($path,OC_FILEACTION_READ); + } + return $return; + } + public function is_dir($path){ + return (is_dir($this->datadir.$path) or substr($path,-1)=='/'); + } + public function is_file($path){ + return is_file($this->datadir.$path); + } + public function stat($path){ + return stat($this->datadir.$path); + } + public function filetype($path){ + $filetype=filetype($this->datadir.$path); + if($filetype=='link'){ + $filetype=filetype(readlink($this->datadir.$path)); + } + return $filetype; + } + public function filesize($path){ + return filesize($this->datadir.$path); + } + public function is_readable($path){ + return is_readable($this->datadir.$path); + } + public function is_writeable($path){ + return is_writeable($this->datadir.$path); + } + public function file_exists($path){ + return file_exists($this->datadir.$path); + } + public function readfile($path){ + if($return=readfile($this->datadir.$path)){ + $this->notifyObservers($path,OC_FILEACTION_READ); + } + return $return; + } + public function filectime($path){ + return filectime($this->datadir.$path); + } + public function filemtime($path){ + return filemtime($this->datadir.$path); + } + public function fileatime($path){ + return fileatime($this->datadir.$path); + } + public function file_get_contents($path){ + if($return=file_get_contents($this->datadir.$path)){ + $this->notifyObservers($path,OC_FILEACTION_READ); + } + return $return; + } + public function file_put_contents($path,$data){ + if($return=file_put_contents($this->datadir.$path,$data)){ + $this->notifyObservers($path,OC_FILEACTION_WRITE); + } + } + public function unlink($path){ + if($return=unlink($this->datadir.$path)){ + $this->notifyObservers($path,OC_FILEACTION_DELETE); + } + return $return; + } + public function rename($path1,$path2){ + if($return=rename($this->datadir.$path1,$this->datadir.$path2)){ + $this->notifyObservers($path1.'->'.$path2,OC_FILEACTION_RENAME); + } + return $return; + } + public function copy($path1,$path2){ + if($this->is_dir($path2)){ + if(!$this->file_exists($path2)){ + $this->mkdir($path2); + } + $source=substr($path1,strrpos($path1,'/')+1); + $path2.=$source; + } + if($return=copy($this->datadir.$path1,$this->datadir.$path2)){ + $this->notifyObservers($path2,OC_FILEACTION_CREATE); + } + return $return; + } + public function fopen($path,$mode){ + if($return=fopen($this->datadir.$path,$mode)){ + switch($mode){ + case 'r': + $this->notifyObservers($path,OC_FILEACTION_READ); + break; + case 'r+': + case 'w+': + case 'x+': + case 'a+': + $this->notifyObservers($path,OC_FILEACTION_READ | OC_FILEACTION_WRITE); + break; + case 'w': + case 'x': + case 'a': + $this->notifyObservers($path,OC_FILEACTION_WRITE); + break; + } + } + return $return; + } + + public function getMimeType($fspath){ + if($this->is_readable($fspath)){ + if (@is_dir($this->datadir.$fspath)) { + // directories are easy + return "httpd/unix-directory"; + }elseif (function_exists('finfo_open') and function_exists('finfo_file') and $finfo=finfo_open(FILEINFO_MIME)){ + $mimeType =strtolower(finfo_file($finfo,$this->datadir.$fspath)); + $mimeType=substr($mimeType,0,strpos($mimeType,';')); + finfo_close($finfo); + return $mimeType; + } else if (function_exists("mime_content_type")) { + // use mime magic extension if available + $mime_type = mime_content_type($this->datadir.$fspath); + } else if (self::canExecute("file")) { + // it looks like we have a 'file' command, + // lets see it it does have mime support + $fp = popen("file -i -b '{$this->datadir}$fspath' 2>/dev/null", "r"); + $reply = fgets($fp); + pclose($fp); + + //trim the character set from the end of the response + $mime_type=substr($reply,0,strrpos($reply,' ')); + } + if (empty($mime_type)) { + // Fallback solution: try to guess the type by the file extension + // TODO: add more ... + switch (strtolower(strrchr(basename($fspath), "."))) { + case '.css': + $mime_type = 'text/css'; + break; + case '.flac': + $mime_type = 'audio/flac'; + break; + case '.gif': + $mime_type = 'image/gif'; + break; + case '.gzip': + case '.gz': + $mime_type = 'application/x-gzip'; + break; + case '.htm': + case '.html': + $mime_type = 'text/html'; + break; + case '.jpeg': + case '.jpg': + $mime_type = 'image/jpeg'; + break; + case '.js': + $mime_type = 'application/x-javascript'; + break; + case '.oga': + case '.ogg': + $mime_type = 'audio/ogg'; + break; + case '.ogv': + $mime_type = 'video/ogg'; + break; + case '.pdf': + $mime_type = 'application/pdf'; + break; + case '.png': + $mime_type = 'image/png'; + break; + case '.svg': + $mime_type = 'image/svg+xml'; + break; + case '.tar': + $mime_type = 'application/x-tar'; + break; + case '.tgz': + $mime_type = 'application/x-compressed'; + break; + case '.tif': + case '.tiff': + $mime_type = 'image/tiff'; + break; + case '.txt': + $mime_type = 'text/plain'; + break; + case '.zip': + $mime_type = 'application/zip'; + break; + default: + $mime_type = 'application/octet-stream'; + break; + } + } + + return $mime_type; + } + } + + /** + * detect if a given program is found in the search PATH + * + * helper function used by _mimetype() to detect if the + * external 'file' utility is available + * + * @param string program name + * @param string optional search path, defaults to $PATH + * @return bool true if executable program found in path + */ + private function canExecute($name, $path = false) + { + // path defaults to PATH from environment if not set + if ($path === false) { + $path = getenv("PATH"); + } + + // check method depends on operating system + if (!strncmp(PHP_OS, "WIN", 3)) { + // on Windows an appropriate COM or EXE file needs to exist + $exts = array(".exe", ".com"); + $check_fn = "file_exists"; + } else { + // anywhere else we look for an executable file of that name + $exts = array(""); + $check_fn = "is_executable"; + } + + // Default check will be done with $path directories : + $dirs = explode(PATH_SEPARATOR, $path); + + // WARNING : We have to check if open_basedir is enabled : + $obd = ini_get('open_basedir'); + + if($obd != "none") + $obd_values = explode(PATH_SEPARATOR, $obd); + + if(count($obd_values) > 0) + { + // open_basedir is in effect ! + // We need to check if the program is in one of these dirs : + $dirs = $obd_values; + } + + foreach($dirs as $dir) + { + foreach($exts as $ext) + { + if($check_fn("$dir/$name".$ext)) + return true; + } + } + + return false; + } + + public function toTmpFile($path){ + $tmpFolder=sys_get_temp_dir(); + $filename=tempnam($tmpFolder,'OC_TEMP_FILE_'.substr($path,strrpos($path,'.'))); + if(copy($this->datadir.$path,$filename)){ + $this->notifyObservers($path,OC_FILEACTION_READ); + return $filename; + }else{ + return false; + } + } + + public function fromTmpFile($tmpFile,$path){ + if(rename($tmpFile,$this->datadir.$path)){ + $this->notifyObservers($path,OC_FILEACTION_CREATE); + return true; + }else{ + return false; + } + } + + public function delTree($dir) { + $dirRelative=$dir; + $dir=$this->datadir.$dir; + if (!file_exists($dir)) return true; + if (!is_dir($dir) || is_link($dir)) return unlink($dir); + foreach (scandir($dir) as $item) { + if ($item == '.' || $item == '..') continue; + if(is_file($dir.'/'.$item)){ + if(unlink($dir.'/'.$item)){ + $this->notifyObservers($dir.'/'.$item,OC_FILEACTION_DELETE); + } + }elseif(is_dir($dir.'/'.$item)){ + if (!$this->delTree($dirRelative. "/" . $item)){ + return false; + }; + } + } + if($return=rmdir($dir)){ + $this->notifyObservers($dir,OC_FILEACTION_DELETE); + } + return $return; + } + + public function find($path){ + $return=System::find($this->datadir.$path); + foreach($return as &$file){ + $file=str_replace($file,$this->datadir,''); + } + return $return; + } + + public function getTree($dir) { + if(substr($dir,-1,1)=='/'){ + $dir=substr($dir,0,-1); + } + $tree=array(); + $tree[]=$dir; + $dirRelative=$dir; + $dir=$this->datadir.$dir; + if (!file_exists($dir)) return true; + foreach (scandir($dir) as $item) { + if ($item == '.' || $item == '..') continue; + if(is_file($dir.'/'.$item)){ + $tree[]=$dirRelative.'/'.$item; + }elseif(is_dir($dir.'/'.$item)){ + if ($subTree=$this->getTree($dirRelative. "/" . $item)){ + $tree=array_merge($tree,$subTree); + } + } + } + return $tree; + } +} +?>
\ No newline at end of file diff --git a/lib/filesystem.php b/lib/filesystem.php new file mode 100644 index 00000000000..26a0066aa74 --- /dev/null +++ b/lib/filesystem.php @@ -0,0 +1,380 @@ +<?php + +/** +* ownCloud +* +* @author Frank Karlitschek +* @copyright 2010 Frank Karlitschek karlitschek@kde.org +* +* 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/>. +* +*/ + + +/** + * Class for abstraction of filesystem functions + * This class won't call any filesystem functions for itself but but will pass them to the correct OC_FILESTORAGE object + * this class should also handle all the file premission related stuff + */ +class OC_FILESYSTEM{ + static private $storages=array(); + static private $fakeRoot=''; + static private $storageTypes=array(); + + + /** + * register a storage type + * @param string type + * @param string classname + * @param array arguments an associative array in the form of name=>type (eg array('datadir'=>'string')) + */ + static public function registerStorageType($type,$classname,$arguments){ + self::$storageTypes[$type]=array('type'=>$type,'classname'=>$classname,'arguments'=>$arguments); + } + + /** + * check if the filesystem supports a specific storagetype + * @param string type + * @return bool + */ + static public function hasStorageType($type){ + return isset(self::$storageTypes[$type]); + } + + /** + * get the list of names of storagetypes that the filesystem supports + * @return array + */ + static public function getStorageTypeNames(){ + return array_keys(self::$storageTypes); + } + + /** + * create a new storage of a specific type + * @param string type + * @param array arguments + * @return OC_FILESTORAGE + */ + static public function createStorage($type,$arguments){ + if(!self::hasStorageType($type)){ + return false; + } + $className=self::$storageTypes[$type]['classname']; + if(class_exists($className)){ + return new $className($arguments); + }else{ + return false; + } + } + + /** + * change the root to a fake toor + * @param string fakeRoot + * @return bool + */ + static public function chroot($fakeRoot){ + if($fakeRoot[0]!=='/'){ + $fakeRoot='/'.$fakeRoot; + } + self::$fakeRoot=$fakeRoot; + } + + /** + * get the part of the path relative to the mountpoint of the storage it's stored in + * @param string path + * @return bool + */ + static public function getInternalPath($path){ + $mountPoint=self::getMountPoint($path); + $path=self::$fakeRoot.$path; + $internalPath=substr($path,strlen($mountPoint)); + return $internalPath; + } + + /** + * 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){ + if(substr($mountpoint,0,1)!=='/'){ + $mountpoint='/'.$mountpoint; + } + self::$storages[self::$fakeRoot.$mountpoint]=$storage; + } + + /** + * get the storage object for a path + * @param string path + * @return OC_FILESTORAGE + */ + static private function getStorage($path){ + $mountpoint=self::getMountPoint($path); + if($mountpoint){ + return self::$storages[$mountpoint]; + } + } + + /** + * get the mountpoint of the storage object for a path + ( note: because a storage is not always mounted inside the fakeroot, the returned mountpoint is relative to the absolute root of the filesystem and doesn't take the chroot into account + * + * @param string path + * @return string + */ + static private function getMountPoint($path){ + if(!$path){ + $path='/'; + } + if(substr($path,0,1)!=='/'){ + $path='/'.$path; + } + if(substr($path,-1)!=='/'){ + $path=$path.'/'; + } + $path=self::$fakeRoot.$path; + $foundMountPoint=''; + foreach(self::$storages as $mountpoint=>$storage){ + if(substr($mountpoint,-1)!=='/'){ + $mountpoint=$mountpoint.'/'; + } + if($mountpoint==$path){ + return $mountpoint; + } + if(strpos($path,$mountpoint)===0 and strlen($mountpoint)>strlen($foundMountPoint)){ + $foundMountPoint=$mountpoint; + } + } + return $foundMountPoint; + } + + static public function mkdir($path){ + $parent=substr($path,0,strrpos($path,'/')); + if(self::canWrite($parent) and $storage=self::getStorage($path)){ + return $storage->mkdir(self::getInternalPath($path)); + } + } + static public function rmdir($path){ + if(self::canWrite($path) and $storage=self::getStorage($path)){ + return $storage->rmdir(self::getInternalPath($path)); + } + } + static public function opendir($path){ + if(self::canRead($path) and $storage=self::getStorage($path)){ + return $storage->opendir(self::getInternalPath($path)); + } + } + static public function is_dir($path){ + if($path=='/'){ + return true; + } + if(self::canRead($path) and $storage=self::getStorage($path)){ + return $storage->is_dir(self::getInternalPath($path)); + } + } + static public function is_file($path){ + if($path=='/'){ + return false; + } + if(self::canRead($path) and $storage=self::getStorage($path)){ + return $storage->is_file(self::getInternalPath($path)); + } + } + static public function stat($path){ + if(self::canRead($path) and $storage=self::getStorage($path)){ + return $storage->stat(self::getInternalPath($path)); + } + } + static public function filetype($path){ + if(self::canRead($path) and $storage=self::getStorage($path)){ + return $storage->filetype(self::getInternalPath($path)); + } + } + static public function filesize($path){ + if(self::canRead($path) and $storage=self::getStorage($path)){ + return $storage->filesize(self::getInternalPath($path)); + } + } + static public function readfile($path){ + if(self::canRead($path) and $storage=self::getStorage($path)){ + return $storage->readfile(self::getInternalPath($path)); + } + } + static public function is_readable($path){ + if(self::canRead($path) and $storage=self::getStorage($path)){ + return $storage->is_readable(self::getInternalPath($path)); + } + return false; + } + static public function is_writeable($path){ + if(self::canWrite($path) and $storage=self::getStorage($path)){ + return $storage->is_writeable(self::getInternalPath($path)); + } + return false; + } + static public function file_exists($path){ + if($path=='/'){ + return true; + } + if(self::canWrite($path) and $storage=self::getStorage($path)){ + return $storage->file_exists(self::getInternalPath($path)); + } + return false; + } + static public function filectime($path){ + if($storage=self::getStorage($path)){ + return $storage->filectime(self::getInternalPath($path)); + } + } + static public function filemtime($path){ + if($storage=self::getStorage($path)){ + return $storage->filemtime(self::getInternalPath($path)); + } + } + static public function fileatime($path){ + if($storage=self::getStorage($path)){ + return $storage->fileatime(self::getInternalPath($path)); + } + } + static public function file_get_contents($path){ + if(self::canRead($path) and $storage=self::getStorage($path)){ + return $storage->file_get_contents(self::getInternalPath($path)); + } + } + static public function file_put_contents($path,$data){ + if(self::canWrite($path) and $storage=self::getStorage($path)){ + return $storage->file_put_contents(self::getInternalPath($path),$data); + } + } + static public function unlink($path){ + if(self::canWrite($path) and $storage=self::getStorage($path)){ + return $storage->unlink(self::getInternalPath($path)); + } + } + static public function rename($path1,$path2){ + if(self::canWrite($path1) and self::canWrite($path2)){ + $mp1=self::getMountPoint($path1); + $mp2=self::getMountPoint($path2); + if($mp1==$mp2){ + if($storage=self::getStorage($path1)){ + return $storage->rename(self::getInternalPath($path1),self::getInternalPath($path2)); + } + }elseif($storage1=self::getStorage($path1) and $storage2=self::getStorage($path2)){ + $tmpFile=$storage1->toTmpFile(self::getInternalPath($path1)); + $result=$storage2->fromTmpFile(self::getInternalPath($path2)); + $storage1->unlink(self::getInternalPath($path1)); + return $result; + } + } + } + static public function copy($path1,$path2){ + if(self::canRead($path1) and self::canWrite($path2)){ + $mp1=self::getMountPoint($path1); + $mp2=self::getMountPoint($path2); + if($mp1==$mp2){ + if($storage=self::getStorage($path1)){ + return $storage->copy(self::getInternalPath($path1),self::getInternalPath($path2)); + } + }elseif($storage1=self::getStorage($path1) and $storage2=self::getStorage($path2)){ + $tmpFile=$storage1->toTmpFile(self::getInternalPath($path1)); + return $storage2->fromTmpFile(self::getInternalPath($path2)); + } + } + } + static public function fopen($path,$mode){ + $allowed=((strpos($path,'r')===false and strpos($path,'r+')!==false and self::canRead) or self::canWrite($path)); + if($allowed){ + if($storage=self::getStorage($path)){ + return $storage->fopen(self::getInternalPath($path),$mode); + } + } + } + static public function toTmpFile($path){ + if(self::canRead($path) and $storage=self::getStorage($path)){ + return $storage->toTmpFile(self::getInternalPath($path)); + } + } + static public function fromTmpFile($tmpFile,$path){ + if(self::canWrite($path) and $storage=self::getStorage($path)){ + return $storage->fromTmpFile($tmpFile,self::getInternalPath($path)); + } + } + static public function getMimeType($path){ + if(self::canRead($path) and $storage=self::getStorage($path)){ + return $storage->getMimeType(self::getInternalPath($path)); + } + } + static public function delTree($path){ + if(self::canWrite($path) and $storage=self::getStorage($path)){ + return $storage->delTree(self::getInternalPath($path)); + } + } + static public function find($path){ + if($storage=self::getStorage($path)){ + $mp=self::getMountPoint($path); + $return=$storage->find(self::getInternalPath($path)); + foreach($return as &$file){ + $file=$mp.$file; + } + } + return $return; + } + static public function getTree($path){ + if(self::canRead($path) and $storage=self::getStorage($path)){ + $mp=self::getMountPoint($path); + $return=$storage->getTree(self::getInternalPath($path)); + foreach($return as &$file){ + if(substr($file,0,1)=='/'){ + $file=substr($file,1); + } + $file=$mp.$file; + $file=substr($file,strlen(self::$fakeRoot)); + if($file === '' || $file === false){ + $file = '/'; + } + } + return $return; + } + } +} +?> diff --git a/lib/log.php b/lib/log.php new file mode 100644 index 00000000000..f2f935b466b --- /dev/null +++ b/lib/log.php @@ -0,0 +1,78 @@ +<?php + +/** +* ownCloud +* +* @author Frank Karlitschek +* @copyright 2010 Frank Karlitschek karlitschek@kde.org +* +* 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/>. +* +*/ + + +/** + * Class for logging features + * + */ +class OC_LOG { + + /** + * array to define different log types + * + */ + public static $TYPE = array ( + 1=>'login', + 2=>'logout', + 3=>'read', + 4=>'write' ); + + + /** + * log an event + * + * @param username $user + * @param type $type + * @param message $message + */ + public static function event($user,$type,$message){ + global $CONFIG_DBTABLEPREFIX; + $result = OC_DB::query('INSERT INTO `' . $CONFIG_DBTABLEPREFIX . 'log` (`timestamp`,`user`,`type`,`message`) VALUES ('.time().',\''.addslashes($user).'\','.addslashes($type).',\''.addslashes($message).'\');'); + } + + + /** + * get log entries + */ + public static function get(){ + global $CONFIG_DATEFORMAT; + global $CONFIG_DBTABLEPREFIX; + + $result; + + if(OC_USER::ingroup($_SESSION['username_clean'],'admin')){ + $result = OC_DB::select('select `timestamp`,`user`,`type`,`message` from '.$CONFIG_DBTABLEPREFIX.'log order by timestamp desc limit 20'); + } + else{ + $user=$_SESSION['username_clean']; + $result = OC_DB::select('select `timestamp`,`user`,`type`,`message` from '.$CONFIG_DBTABLEPREFIX.'log where user=\''.$user.'\' order by timestamp desc limit 20'); + } + + return $result; + } +} + + + +?> diff --git a/lib/ocs.php b/lib/ocs.php new file mode 100644 index 00000000000..08b4b79ae91 --- /dev/null +++ b/lib/ocs.php @@ -0,0 +1,592 @@ +<?php + +/** +* ownCloud +* +* @author Frank Karlitschek +* @copyright 2010 Frank Karlitschek karlitschek@kde.org +* +* 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/>. +* +*/ + + + +/** + * Class to handle open collaboration services API requests + * + */ +class OC_OCS { + + /** + * reads input date from get/post/cookies and converts the date to a special data-type + * + * @param variable $key + * @param variable-type $type + * @param priority $getpriority + * @param default $default + * @return data + */ + public static function readData($key,$type='raw',$getpriority=false,$default='') { + if($getpriority) { + if(isset($_GET[$key])) { + $data=$_GET[$key]; + } elseif(isset($_POST[$key])) { + $data=$_POST[$key]; + } else { + if($default=='') { + if(($type=='int') or ($type=='float')) $data=0; else $data=''; + } else { + $data=$default; + } + } + } else { + if(isset($_POST[$key])) { + $data=$_POST[$key]; + } elseif(isset($_GET[$key])) { + $data=$_GET[$key]; + } elseif(isset($_COOKIE[$key])) { + $data=$_COOKIE[$key]; + } else { + if($default=='') { + if(($type=='int') or ($type=='float')) $data=0; else $data=''; + } else { + $data=$default; + } + } + } + + if($type=='raw') return($data); + elseif($type=='text') return(addslashes(strip_tags($data))); + elseif($type=='int') { $data = (int) $data; return($data); } + elseif($type=='float') { $data = (float) $data; return($data); } + elseif($type=='array') { $data = $data; return($data); } + } + + + /** + main function to handle the REST request + **/ + public static function handle() { + + // overwrite the 404 error page returncode + header("HTTP/1.0 200 OK"); + + + if($_SERVER['REQUEST_METHOD'] == 'GET') { + $method='get'; + }elseif($_SERVER['REQUEST_METHOD'] == 'PUT') { + $method='put'; + parse_str(file_get_contents("php://input"),$put_vars); + }elseif($_SERVER['REQUEST_METHOD'] == 'POST') { + $method='post'; + }else{ + echo('internal server error: method not supported'); + exit(); + } + + // preprocess url + $url=$_SERVER['REQUEST_URI']; + if(substr($url,(strlen($url)-1))<>'/') $url.='/'; + $ex=explode('/',$url); + $paracount=count($ex); + + // eventhandler + // CONFIG + // apiconfig - GET - CONFIG + if(($method=='get') and (strtolower($ex[$paracount-3])=='v1.php') and (strtolower($ex[$paracount-2])=='config')){ + $format=OC_OCS::readdata('format','text'); + OC_OCS::apiconfig($format); + + // PERSON + // personcheck - POST - PERSON/CHECK + }elseif(($method=='post') and (strtolower($ex[$paracount-4])=='v1.php') and (strtolower($ex[$paracount-3])=='person') and (strtolower($ex[$paracount-2])=='check')){ + $format=OC_OCS::readdata('format','text'); + $login=OC_OCS::readdata('login','text'); + $passwd=OC_OCS::readdata('password','text'); + OC_OCS::personcheck($format,$login,$passwd); + + // ACTIVITY + // activityget - GET ACTIVITY page,pagesize als urlparameter + }elseif(($method=='get') and (strtolower($ex[$paracount-3])=='v1.php')and (strtolower($ex[$paracount-2])=='activity')){ + $format=OC_OCS::readdata('format','text'); + $page=OC_OCS::readdata('page','int'); + $pagesize=OC_OCS::readdata('pagesize','int'); + if($pagesize<1 or $pagesize>100) $pagesize=10; + OC_OCS::activityget($format,$page,$pagesize); + + // activityput - POST ACTIVITY + }elseif(($method=='post') and (strtolower($ex[$paracount-3])=='v1.php')and (strtolower($ex[$paracount-2])=='activity')){ + $format=OC_OCS::readdata('format','text'); + $message=OC_OCS::readdata('message','text'); + OC_OCS::activityput($format,$message); + + // PRIVATEDATA + // get - GET DATA + }elseif(($method=='get') and (strtolower($ex[$paracount-4])=='v1.php')and (strtolower($ex[$paracount-2])=='getattribute')){ + $format=OC_OCS::readdata('format','text'); + OC_OCS::privateDataGet($format); + + }elseif(($method=='get') and (strtolower($ex[$paracount-5])=='v1.php')and (strtolower($ex[$paracount-3])=='getattribute')){ + $format=OC_OCS::readdata('format','text'); + $app=$ex[$paracount-2]; + OC_OCS::privateDataGet($format, $app); + }elseif(($method=='get') and (strtolower($ex[$paracount-6])=='v1.php')and (strtolower($ex[$paracount-4])=='getattribute')){ + $format=OC_OCS::readdata('format','text'); + $key=$ex[$paracount-2]; + $app=$ex[$paracount-3]; + OC_OCS::privateDataGet($format, $app,$key); + + // set - POST DATA + }elseif(($method=='post') and (strtolower($ex[$paracount-6])=='v1.php')and (strtolower($ex[$paracount-4])=='setattribute')){ + $format=OC_OCS::readdata('format','text'); + $key=$ex[$paracount-2]; + $app=$ex[$paracount-3]; + $value=OC_OCS::readdata('value','text'); + OC_OCS::privatedataset($format, $app, $key, $value); + // delete - POST DATA + }elseif(($method=='post') and (strtolower($ex[$paracount-6])=='v1.php')and (strtolower($ex[$paracount-4])=='deleteattribute')){ + $format=OC_OCS::readdata('format','text'); + $key=$ex[$paracount-2]; + $app=$ex[$paracount-3]; + OC_OCS::privatedatadelete($format, $app, $key); + + }else{ + $format=OC_OCS::readdata('format','text'); + $txt='Invalid query, please check the syntax. API specifications are here: http://www.freedesktop.org/wiki/Specifications/open-collaboration-services. DEBUG OUTPUT:'."\n"; + $txt.=OC_OCS::getdebugoutput(); + echo(OC_OCS::generatexml($format,'failed',999,$txt)); + } + exit(); + } + + /** + * generated some debug information to make it easier to find faild API calls + * @return debug data string + */ + private static function getDebugOutput() { + $txt=''; + $txt.="debug output:\n"; + if(isset($_SERVER['REQUEST_METHOD'])) $txt.='http request method: '.$_SERVER['REQUEST_METHOD']."\n"; + if(isset($_SERVER['REQUEST_URI'])) $txt.='http request uri: '.$_SERVER['REQUEST_URI']."\n"; + if(isset($_GET)) foreach($_GET as $key=>$value) $txt.='get parameter: '.$key.'->'.$value."\n"; + if(isset($_POST)) foreach($_POST as $key=>$value) $txt.='post parameter: '.$key.'->'.$value."\n"; + return($txt); + } + + /** + * checks if the user is authenticated + * checks the IP whitlist, apikeys and login/password combination + * if $forceuser is true and the authentication failed it returns an 401 http response. + * if $forceuser is false and authentification fails it returns an empty username string + * @param bool $forceuser + * @return username string + */ + private static function checkPassword($forceuser=true) { + //valid user account ? + if(isset($_SERVER['PHP_AUTH_USER'])) $authuser=$_SERVER['PHP_AUTH_USER']; else $authuser=''; + if(isset($_SERVER['PHP_AUTH_PW'])) $authpw=$_SERVER['PHP_AUTH_PW']; else $authpw=''; + + if(empty($authuser)) { + if($forceuser){ + header('WWW-Authenticate: Basic realm="your valid user account or api key"'); + header('HTTP/1.0 401 Unauthorized'); + exit; + }else{ + $identifieduser=''; + } + }else{ + if(!OC_USER::login($authuser,$authpw)){ + if($forceuser){ + header('WWW-Authenticate: Basic realm="your valid user account or api key"'); + header('HTTP/1.0 401 Unauthorized'); + exit; + }else{ + $identifieduser=''; + } + }else{ + $identifieduser=$authuser; + } + } + + return($identifieduser); + } + + + /** + * generates the xml or json response for the API call from an multidimenional data array. + * @param string $format + * @param string $status + * @param string $statuscode + * @param string $message + * @param array $data + * @param string $tag + * @param string $tagattribute + * @param int $dimension + * @param int $itemscount + * @param int $itemsperpage + * @return string xml/json + */ + private static function generateXml($format,$status,$statuscode,$message,$data=array(),$tag='',$tagattribute='',$dimension=-1,$itemscount='',$itemsperpage='') { + if($format=='json') { + + $json=array(); + $json['status']=$status; + $json['statuscode']=$statuscode; + $json['message']=$message; + $json['totalitems']=$itemscount; + $json['itemsperpage']=$itemsperpage; + $json['data']=$data; + return(json_encode($json)); + + + }else{ + $txt=''; + $writer = xmlwriter_open_memory(); + xmlwriter_set_indent( $writer, 2 ); + xmlwriter_start_document($writer ); + xmlwriter_start_element($writer,'ocs'); + xmlwriter_start_element($writer,'meta'); + xmlwriter_write_element($writer,'status',$status); + xmlwriter_write_element($writer,'statuscode',$statuscode); + xmlwriter_write_element($writer,'message',$message); + if($itemscount<>'') xmlwriter_write_element($writer,'totalitems',$itemscount); + if(!empty($itemsperpage)) xmlwriter_write_element($writer,'itemsperpage',$itemsperpage); + xmlwriter_end_element($writer); + if($dimension=='0') { + // 0 dimensions + xmlwriter_write_element($writer,'data',$data); + + }elseif($dimension=='1') { + xmlwriter_start_element($writer,'data'); + foreach($data as $key=>$entry) { + xmlwriter_write_element($writer,$key,$entry); + } + xmlwriter_end_element($writer); + + }elseif($dimension=='2') { + xmlwriter_start_element($writer,'data'); + foreach($data as $entry) { + xmlwriter_start_element($writer,$tag); + if(!empty($tagattribute)) { + xmlwriter_write_attribute($writer,'details',$tagattribute); + } + foreach($entry as $key=>$value) { + if(is_array($value)){ + foreach($value as $k=>$v) { + xmlwriter_write_element($writer,$k,$v); + } + } else { + xmlwriter_write_element($writer,$key,$value); + } + } + xmlwriter_end_element($writer); + } + xmlwriter_end_element($writer); + + }elseif($dimension=='3') { + xmlwriter_start_element($writer,'data'); + foreach($data as $entrykey=>$entry) { + xmlwriter_start_element($writer,$tag); + if(!empty($tagattribute)) { + xmlwriter_write_attribute($writer,'details',$tagattribute); + } + foreach($entry as $key=>$value) { + if(is_array($value)){ + xmlwriter_start_element($writer,$entrykey); + foreach($value as $k=>$v) { + xmlwriter_write_element($writer,$k,$v); + } + xmlwriter_end_element($writer); + } else { + xmlwriter_write_element($writer,$key,$value); + } + } + xmlwriter_end_element($writer); + } + xmlwriter_end_element($writer); + }elseif($dimension=='dynamic') { + xmlwriter_start_element($writer,'data'); + OC_OCS::toxml($writer,$data,'comment'); + xmlwriter_end_element($writer); + } + + xmlwriter_end_element($writer); + + xmlwriter_end_document( $writer ); + $txt.=xmlwriter_output_memory( $writer ); + unset($writer); + return($txt); + } + } + + public static function toXml($writer,$data,$node) { + foreach($data as $key => $value) { + if (is_numeric($key)) { + $key = $node; + } + if (is_array($value)){ + xmlwriter_start_element($writer,$key); + OC_OCS::toxml($writer,$value,$node); + xmlwriter_end_element($writer); + }else{ + xmlwriter_write_element($writer,$key,$value); + } + + } + } + + + + + /** + * return the config data of this server + * @param string $format + * @return string xml/json + */ + private static function apiConfig($format) { + $user=OC_OCS::checkpassword(false); + $url=substr($_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME'],0,-11).''; + + $xml['version']='1.5'; + $xml['website']='ownCloud'; + $xml['host']=$_SERVER['HTTP_HOST']; + $xml['contact']=''; + $xml['ssl']='false'; + echo(OC_OCS::generatexml($format,'ok',100,'',$xml,'config','',1)); + } + + + /** + * check if the provided login/apikey/password is valid + * @param string $format + * @param string $login + * @param string $passwd + * @return string xml/json + */ + private static function personCheck($format,$login,$passwd) { + if($login<>''){ + if(OC_USER::login($login,$passwd)){ + $xml['person']['personid']=$login; + echo(OC_OCS::generatexml($format,'ok',100,'',$xml,'person','check',2)); + }else{ + echo(OC_OCS::generatexml($format,'failed',102,'login not valid')); + } + }else{ + echo(OC_OCS::generatexml($format,'failed',101,'please specify all mandatory fields')); + } + } + + + + // ACTIVITY API ############################################# + + /** + * get my activities + * @param string $format + * @param string $page + * @param string $pagesize + * @return string xml/json + */ + private static function activityGet($format,$page,$pagesize) { + global $CONFIG_DBTABLEPREFIX; + + $user=OC_OCS::checkpassword(); + + $result = OC_DB::query("select count(*) as co from {$CONFIG_DBTABLEPREFIX}log"); + $entry=$result->fetchRow(); + $totalcount=$entry['co']; + OC_DB::free_result($result); + + $result = OC_DB::select("select id,timestamp,user,type,message from {$CONFIG_DBTABLEPREFIX}log order by timestamp desc limit " . ($page*$pagesize) . ",$pagesize"); + $itemscount=count($result); + + $url='http://'.substr($_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME'],0,-11).''; + $xml=array(); + foreach($result as $i=>$log) { + $xml[$i]['id']=$log['id']; + $xml[$i]['personid']=$log['user']; + $xml[$i]['firstname']=$log['user']; + $xml[$i]['lastname']=''; + $xml[$i]['profilepage']=$url; + + $pic=$url.'/img/owncloud-icon.png'; + $xml[$i]['avatarpic']=$pic; + + $xml[$i]['timestamp']=date('c',$log['timestamp']); + $xml[$i]['type']=1; + $xml[$i]['message']=OC_LOG::$TYPE[$log['type']].' '.strip_tags($log['message']); + $xml[$i]['link']=$url; + } + + $txt=OC_OCS::generatexml($format,'ok',100,'',$xml,'activity','full',2,$totalcount,$pagesize); + echo($txt); + } + + /** + * submit a activity + * @param string $format + * @param string $message + * @return string xml/json + */ + private static function activityPut($format,$message) { + // not implemented in ownCloud + $user=OC_OCS::checkpassword(); + echo(OC_OCS::generatexml($format,'ok',100,'')); + } + + // PRIVATEDATA API ############################################# + + /** + * get private data and create the xml for ocs + * @param string $format + * @param string $app + * @param string $key + * @return string xml/json + */ + private static function privateDataGet($format,$app="",$key="") { + $user=OC_OCS::checkpassword(); + $result=OC_OCS::getData($user,$app,$key); + $xml=array(); + foreach($result as $i=>$log) { + $xml[$i]['key']=$log['key']; + $xml[$i]['app']=$log['app']; + $xml[$i]['value']=$log['value']; + $xml[$i]['timestamp']=$log['timestamp']; + } + + + $txt=OC_OCS::generatexml($format, 'ok', 100, '', $xml, 'privatedata', 'full', 2, count($xml), 0);//TODO: replace 'privatedata' with 'attribute' once a new libattice has been released that works with it + echo($txt); + } + + /** + * set private data referenced by $key to $value and generate the xml for ocs + * @param string $format + * @param string $app + * @param string $key + * @param string $value + * @return string xml/json + */ + private static function privateDataSet($format, $app, $key, $value) { + $user=OC_OCS::checkpassword(); + if(OC_OCS::setData($user,$app,$key,$value)){ + echo(OC_OCS::generatexml($format,'ok',100,'')); + } + } + + /** + * delete private data referenced by $key and generate the xml for ocs + * @param string $format + * @param string $app + * @param string $key + * @return string xml/json + */ + private static function privateDataDelete($format, $app, $key) { + if($key=="" or $app==""){ + return; //key and app are NOT optional here + } + $user=OC_OCS::checkpassword(); + if(OC_OCS::deleteData($user,$app,$key)){ + echo(OC_OCS::generatexml($format,'ok',100,'')); + } + } + + /** + * get private data + * @param string $user + * @param string $app + * @param string $key + * @return array + */ + public static function getData($user,$app="",$key="") { + global $CONFIG_DBTABLEPREFIX; + $user=OC_DB::escape($user); + $key=OC_DB::escape($key); + $app=OC_DB::escape($app); + $key="$user::$key";//ugly hack for the sake of keeping database scheme compatibiliy + if($app){ + if (!trim($key)) { + $result = OC_DB::select("select app, `key`,value,`timestamp` from {$CONFIG_DBTABLEPREFIX}privatedata where app='$app' order by `timestamp` desc"); + } else { + $result = OC_DB::select("select app, `key`,value,`timestamp` from {$CONFIG_DBTABLEPREFIX}privatedata where app='$app' and `key` ='$key' order by `timestamp` desc"); + } + }else{ + if (!trim($key)) { + $result = OC_DB::select("select app, `key`,value,`timestamp` from {$CONFIG_DBTABLEPREFIX}privatedata order by `timestamp` desc"); + } else { + $result = OC_DB::select("select app, `key`,value,`timestamp` from {$CONFIG_DBTABLEPREFIX}privatedata where `key` ='$key' order by `timestamp` desc"); + } + } + return $result; + } + + /** + * set private data referenced by $key to $value + * @param string $user + * @param string $app + * @param string $key + * @param string $value + * @return bool + */ + public static function setData($user, $app, $key, $value) { + global $CONFIG_DBTABLEPREFIX; + $app=OC_DB::escape($app); + $key=OC_DB::escape($key); + $user=OC_DB::escape($user); + $value=OC_DB::escape($value); + $key="$user::$key";//ugly hack for the sake of keeping database scheme compatibiliy + //TODO: prepared statements, locking tables, fancy stuff, error checking/handling + $result=OC_DB::select("select count(*) as co from {$CONFIG_DBTABLEPREFIX}privatedata where `key` = '$key' and app = '$app'"); + $totalcount=$result[0]['co']; + if ($totalcount != 0) { + $result = OC_DB::query("update {$CONFIG_DBTABLEPREFIX}privatedata set value='$value', `timestamp` = now() where `key` = '$key' and app = '$app'"); + } else { + $result = OC_DB::query("insert into {$CONFIG_DBTABLEPREFIX}privatedata(app, `key`, value, `timestamp`) values('$app', '$key', '$value', now())"); + } + if (PEAR::isError($result)){ + $entry='DB Error: "'.$result->getMessage().'"<br />'; + error_log($entry); + return false; + }else{ + return true; + } + } + + /** + * delete private data referenced by $key + * @param string $user + * @param string $app + * @param string $key + * @return string xml/json + */ + public static function deleteData($user, $app, $key) { + global $CONFIG_DBTABLEPREFIX; + $app=OC_DB::escape($app); + $key=OC_DB::escape($key); + $user=OC_DB::escape($user); + $key="$user::$key";//ugly hack for the sake of keeping database scheme compatibiliy + //TODO: prepared statements, locking tables, fancy stuff, error checking/handling + $result = OC_DB::query("delete from {$CONFIG_DBTABLEPREFIX}privatedata where `key` = '$key' and app = '$app'"); + if (PEAR::isError($result)){ + $entry='DB Error: "'.$result->getMessage().'"<br />'; + error_log($entry); + return false; + }else{ + return true; + } + } +} + +?> diff --git a/lib/plugin.php b/lib/plugin.php new file mode 100644 index 00000000000..0cec329ea35 --- /dev/null +++ b/lib/plugin.php @@ -0,0 +1,381 @@ +<?php + +/** +* ownCloud +* +* @author Frank Karlitschek +* @copyright 2010 Frank Karlitschek karlitschek@kde.org +* +* 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/>. +* +*/ + +class OC_PLUGIN{ + static private $blacklist=array(); + + /** + * load the plugin with the given id + * @param string id + * @return bool + */ + static public function load($id){ + global $SERVERROOT; + $data=self::getPluginData($id); + if($data){ + if(isset($data['info']['require'])){ + $minVersion=explode('.',$data['info']['require']); + $version=OC_UTIL::getVersion(); + $roundTo=count($minVersion); + while(count($version)>$roundTo){ + if($version[count($version)-1]>=50){ + $version[count($version)-2]++; + } + unset($version[count($version)-1]); + } + for($i=0;$i<count($minVersion);$i++){ + if($version[$i]<$minVersion[$i]){ + return false; + } + } + } + //check for uninstalled db's + if(isset($data['install']) and isset($data['install']['database'])){ + foreach($data['install']['database'] as $db){ + if(!$data['install']['database_installed'][$db]){ + self::installDB($id); + break; + } + } + } + + if(isset($data['runtime'])){ + foreach($data['runtime'] as $include){ + include($SERVERROOT.'/plugins/'.$id.'/'.$include); + } + } + } + return false; + } + + /** + * Get a list of all installed plugins + */ + public static function listPlugins() { + global $SERVERROOT; + $plugins = array(); + $fd = opendir($SERVERROOT . '/plugins'); + while ( false !== ($filename = readdir($fd)) ) { + if ( $filename<>'.' AND $filename<>'..' AND ('.' != substr($filename, 0, 1))) { + if(file_exists($SERVERROOT . '/plugins/'.$filename.'/plugin.xml')){ + $plugins[]=$filename; + } + } + } + closedir($fd); + return $plugins; + } + + /** + * Load all plugins that aren't blacklisted + */ + public static function loadPlugins() { + global $CONFIG_INSTALLED; + if($CONFIG_INSTALLED){ + global $SERVERROOT; + $plugins = self::listPlugins(); + $blacklist=self::loadBlacklist(); + foreach($plugins as $plugin){ + if (array_search($plugin,$blacklist)===false) { + self::load($plugin); + } + } + } + } + + /** + * load the blacklist from blacklist.txt + * @return array + */ + public static function loadBlacklist(){ + global $SERVERROOT; + if(count(self::$blacklist)>0){ + return self::$blacklist; + } + $blacklist=array(); + if(is_file($SERVERROOT.'/plugins/blacklist.txt')){ + $file=file_get_contents($SERVERROOT.'/plugins/blacklist.txt'); + $lines=explode("\n",$file); + foreach($lines as $line){ + $id=trim($line); + if($id!='' and is_dir($SERVERROOT.'/plugins/'.$id)){ + $blacklist[]=$id; + } + } + } + self::$blacklist=$blacklist; + return $blacklist; + } + + /** + * save a blacklist to blacklist.txt + * @param array blacklist + */ + private static function saveBlacklist($blacklist){ + global $SERVERROOT; + $file=''; + foreach($blacklist as $item){ + $file.="$item\n"; + } + self::$blacklist=$blacklist; + file_put_contents($SERVERROOT.'/plugins/blacklist.txt',$file); + } + + /** + * add a plugin to the blacklist + * @param string id + */ + public static function addToBlacklist($id){ + $blacklist=self::loadBlacklist(); + if(array_search($id,$blacklist)===false){ + $blacklist[]=$id; + self::$blacklist=$blacklist; + self::saveBlacklist($blacklist); + } + } + + /** + * remove a plugin to the blacklist + * @param string id + */ + public static function removeFromBlacklist($id){ + $blacklist=self::loadBlacklist(); + $index=array_search($id,$blacklist); + if($index!==false){ + unset($blacklist[$index]); + self::$blacklist=$blacklist; + self::saveBlacklist($blacklist); + } + } + + /** + * Load data from the plugin.xml of a plugin, either identified by the plugin or the path of the plugin.xml file + * @param string id + * @return array + */ + public static function getPluginData($id){ + global $SERVERROOT; + if(is_file($id)){ + $file=$id; + }else{ + if(!is_dir($SERVERROOT.'/plugins/'.$id) or !is_file($SERVERROOT.'/plugins/'.$id.'/plugin.xml')){ + return false; + }else{ + $file=$SERVERROOT.'/plugins/'.$id.'/plugin.xml'; + } + } + $data=array(); + $plugin=new DOMDocument(); + $plugin->load($file); + $data['version']=$plugin->documentElement->getAttribute('version'); + $info=$plugin->getElementsByTagName('info'); + if($info->length>0){ + $info=$info->item(0); + $data['info']=array(); + foreach($info->childNodes as $child){ + if($child->nodeType==XML_ELEMENT_NODE){ + $data['info'][$child->tagName]=$child->textContent; + } + } + } + $runtime=$plugin->getElementsByTagName('runtime'); + if($runtime->length>0){ + $runtime=$runtime->item(0); + $data['runtime']=array(); + foreach($runtime->childNodes as $child){ + if($child->nodeType==XML_ELEMENT_NODE and $child->tagName=='include'){ + $data['runtime'][]=$child->textContent; + } + } + } + $install=$plugin->getElementsByTagName('install'); + if($install->length>0){ + $install=$install->item(0); + $data['install']=array(); + foreach($install->childNodes as $child){ + if($child->nodeType==XML_ELEMENT_NODE){ + $data['install']['include']=array(); + $data['install']['dialog']=array(); + $data['install']['database']=array(); + switch($child->tagName){ + case 'include': + $data['install']['include'][]=$child->textContent; + break; + case 'dialog': + $data['install']['dialog'][]=$child->textContent; + break; + case 'database': + $data['install']['database'][]=$child->textContent; + $data['install']['database_installed'][$child->textContent]=($child->hasAttribute('installed') and $child->getAttribute('installed')=='true')?true:false; + break; + } + } + } + } + $uninstall=$plugin->getElementsByTagName('uninstall'); + if($uninstall->length>0){ + $uninstall=$uninstall->item(0); + $data['uninstall']=array(); + foreach($uninstall->childNodes as $child){ + if($child->nodeType==XML_ELEMENT_NODE){ + $data['uninstall']['include']=array(); + $data['uninstall']['dialog']=array(); + switch($child->tagName){ + case 'include': + $data['uninstall']['include'][]=$child->textContent; + break; + case 'dialog': + $data['uninstall']['dialog'][]=$child->textContent; + break; + } + } + } + } + return $data; + } + + + /** + * Save data to the plugin.xml of a plugin, either identified by the plugin or the path of the plugin.xml file + * @param string id + * @param array data the plugin data in the same structure as returned by getPluginData + * @return bool + */ + public static function savePluginData($id,$data){ + global $SERVERROOT; + if(is_file($id)){ + $file=$id; + } + if(!is_dir($SERVERROOT.'/plugins/'.$id) or !is_file($SERVERROOT.'/plugins/'.$id.'/plugin.xml')){ + return false; + }else{ + $file=$SERVERROOT.'/plugins/'.$id.'/plugin.xml'; + } + $plugin=new DOMDocument(); + $pluginNode=$plugin->createElement('plugin'); + $pluginNode->setAttribute('version',$data['version']); + $plugin->appendChild($pluginNode); + $info=$plugin->createElement('info'); + foreach($data['info'] as $name=>$value){ + $node=$plugin->createElement($name); + $node->appendChild($plugin->createTextNode($value)); + $info->appendChild($node); + } + $pluginNode->appendChild($info); + if(isset($data['runtime'])){ + $runtime=$plugin->createElement('runtime'); + foreach($data['runtime'] as $include){ + $node=$plugin->createElement('include'); + $node->appendChild($plugin->createTextNode($include)); + $runtime->appendChild($node); + } + $pluginNode->appendChild($runtime); + } + if(isset($data['install'])){ + $install=$plugin->createElement('install'); + foreach($data['install']['include'] as $include){ + $node=$plugin->createElement('include'); + $node->appendChild($plugin->createTextNode($include)); + $install->appendChild($node); + } + foreach($data['install']['dialog'] as $dialog){ + $node=$plugin->createElement('dialog'); + $node->appendChild($plugin->createTextNode($dialog)); + $install->appendChild($node); + } + foreach($data['install']['database'] as $database){ + $node=$plugin->createElement('database'); + $node->appendChild($plugin->createTextNode($database)); + if($data['install']['database_installed'][$database]){ + $node->setAttribute('installed','true'); + } + $install->appendChild($node); + } + $pluginNode->appendChild($install); + } + if(isset($data['uninstall'])){ + $uninstall=$plugin->createElement('uninstall'); + foreach($data['uninstall']['include'] as $include){ + $node=$plugin->createElement('include'); + $node->appendChild($plugin->createTextNode($include)); + $uninstall->appendChild($node); + } + foreach($data['uninstall']['dialog'] as $dialog){ + $node=$plugin->createElement('dialog'); + $node->appendChild($plugin->createTextNode($dialog)); + $uninstall->appendChild($node); + } + $pluginNode->appendChild($uninstall); + } + $plugin->save($file); + } + + /** + * install the databases of a plugin + * @param string id + * @return bool + */ + public static function installDB($id){ + global $SERVERROOT; + $data=OC_PLUGIN::getPluginData($id); + foreach($data['install']['database'] as $db){ + if (!$data['install']['database_installed'][$db]){ + $file=$SERVERROOT.'/plugins/'.$id.'/'.$db; + OC_DB::createDbFromStructure($file); + $data['install']['database_installed'][$db]=true; + } + } + self::savePluginData($id,$data); + return true; + } + + public static function installPlugin($path){ + global $SERVERROOT; + if(is_file($path)){ + $zip = new ZipArchive; + if($zip->open($path)===TRUE){ + $folder=sys_get_temp_dir().'/OC_PLUGIN_INSTALL/'; + mkdir($folder); + $zip->extractTo($folder); + if(is_file($folder.'/plugin.xml')){ + $pluginData=self::getPluginData($folder.'/plugin.xml'); + if(array_search($pluginData['info']['id'],self::listPlugins())===false){ + if(isset($pluginData['install'])){ + foreach($pluginData['install']['database'] as $db){ + OC_DB::createDbFromStructure($folder.'/'.$db); + $pluginData['install']['database_installed'][$db]=true; + } + foreach($pluginData['install']['include'] as $include){ + include($folder.'/'.$include); + } + } + recursive_copy($folder,$SERVERROOT.'/plugins/'.$pluginData['info']['id']); + self::savePluginData($SERVERROOT.'/plugins/'.$pluginData['info']['id'].'/plugin.xml',$pluginData); + } + } + delTree($folder); + } + } + } +} +?> diff --git a/lib/remotestorage.php b/lib/remotestorage.php new file mode 100644 index 00000000000..ed90cf1fdaf --- /dev/null +++ b/lib/remotestorage.php @@ -0,0 +1,353 @@ +<?php + +/** +* ownCloud +* +* @author Frank Karlitschek +* @copyright 2010 Frank Karlitschek karlitschek@kde.org +* +* 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/>. +* +*/ + + +class OC_FILESTORAGE_REMOTE extends OC_FILESTORAGE{ + private $url; + private $username; + private $password; + private $remote=false; + private $statCache; + private $statCacheDir=false; + private $changed=array(); + + private function cacheDir($dir){ + if($this->statCacheDir!=$dir or $this->statCacheDir===false){ + $this->statCache=$this->remote->getFiles($dir); + $keys=array_keys($this->statCache); + $this->statCacheDir=$dir; + } + } + + public function __construct($arguments){ + $this->url=$arguments['url']; + $this->username=$arguments['username']; + $this->password=$arguments['password']; + } + private function connect(){ + if($this->remote===false){ + $this->remote=OC_CONNECT::connect($this->url,$this->username,$this->password); + } + } + public function mkdir($path){ + $this->connect(); + $parent=dirname($path); + $name=substr($path,strlen($parent)+1); + $return=$this->remote->newFile($parent,$name,'dir'); + if($return){ + $this->notifyObservers($path,OC_FILEACTION_CREATE); + } + return $return; + } + public function rmdir($path){ + $this->connect(); + $parent=dirname($path); + $name=substr($path,strlen($parent)+1); + $return=$this->remote->delete($parent,$name); + if($return){ + $this->notifyObservers($path,OC_FILEACTION_DELETE); + } + return $return; + } + public function opendir($path){ + $this->connect(); + $this->cacheDir($path); + $dirs=array_keys($this->statCache); + $id=uniqid(); + global $FAKEDIRS; + $FAKEDIRS[$id]=$dirs; + if($return=opendir("fakedir://$id")){ + $this->notifyObservers($path,OC_FILEACTION_READ); + } + return $return; + } + public function is_dir($path){ + $this->connect(); + $parent=dirname($path); + $name=substr($path,strlen($parent)+1); + $this->cacheDir($path); + if($path=='' or $path=='/'){ + return true; + } + if(!isset($this->statCache[$name])){ + return false; + } + return ($this->statCache[$name]['type'=='dir']); + } + public function is_file($path){ + $this->connect(); + $parent=dirname($path); + $name=substr($path,strlen($parent)+1); + $this->cacheDir($parent); + if(!isset($this->statCache[$name])){ + return false; + } + return ($this->statCache[$name]['type'!='dir']); + } + public function stat($path){ + $this->connect(); + $parent=dirname($path); + $name=substr($path,strlen($parent)+1); + $this->cacheDir($parent); + if(!isset($this->statCache[$name])){ + return $false; + } + return $this->statCache[$name]; + } + public function filetype($path){ + $this->connect(); + $parent=dirname($path); + $name=substr($path,strlen($parent)+1); + $this->cacheDir($parent); + if(!isset($this->statCache[$name])){ + return false; + } + return $this->statCache[$name]['type']; + } + public function filesize($path){ + $this->connect(); + $parent=dirname($path); + $name=substr($path,strlen($parent)+1); + $this->cacheDir($parent); + if(!isset($this->statCache[$name])){ + return $false; + } + return $this->statCache[$name]['size']; + } + public function is_readable($path){ + $this->connect(); + $parent=dirname($path); + $name=substr($path,strlen($parent)+1); + $this->cacheDir($parent); + if(!isset($this->statCache[$name])){ + return false; + } + return $this->statCache[$name]['readable']; + } + public function is_writeable($path){ + $this->connect(); + $parent=dirname($path); + $name=substr($path,strlen($parent)+1); + $this->cacheDir($parent); + if(!isset($this->statCache[$name])){ + return false; + } + return $this->statCache[$name]['writeable']; + } + public function file_exists($path){ + $this->connect(); + $parent=dirname($path); + $name=substr($path,strlen($parent)+1); + $this->cacheDir($parent); + return isset($this->statCache[$name]); + } + public function readfile($path){ + $this->connect(); + $parent=dirname($path); + $name=substr($path,strlen($parent)+1); + $file=$this->remote->getFile($parent,$name); + readfile($file); + unlink($file); + } + public function filectime($path){ + $this->connect(); + $parent=dirname($path); + $name=substr($path,strlen($parent)+1); + $this->cacheDir($parent); + if(!isset($this->statCache[$name])){ + return false; + } + return $this->statCache[$name]['ctime']; + } + public function filemtime($path){ + $this->connect(); + $parent=dirname($path); + $name=substr($path,strlen($parent)+1); + $this->cacheDir($parent); + if(!isset($this->statCache[$name])){ + return false; + } + return $this->statCache[$name]['mtime']; + } + public function fileatime($path){ + $this->connect(); + $parent=dirname($path); + $name=substr($path,strlen($parent)+1); + $this->cacheDir($parent); + if(!isset($this->statCache[$name])){ + return false; + } + return $this->statCache[$name]['atime']; + } + public function file_get_contents($path){ + $this->connect(); + $parent=dirname($path); + $name=substr($path,strlen($parent)+1); + $file=$this->remote->getFile($parent,$name); + file_get_contents($file); + unlink($file); + } + public function file_put_contents($path,$data){ + $this->connect(); + $parent=dirname($path); + $name=substr($path,strlen($parent)+1); + $file=$this->remote->getFile($parent,$name); + $file=tempnam(sys_get_temp_dir(),'oc_'); + file_put_contents($file,$data); + if($return=$this->remote->sendTmpFile($file,$parent,$name)){ + $this->notifyObservers($path,OC_FILEACTION_WRITE); + } + } + public function unlink($path){ + $this->connect(); + $parent=dirname($path); + $name=substr($path,strlen($parent)+1); + if($return=$this->remote->delete($paren,$name)){ + $this->notifyObservers($path,OC_FILEACTION_DELETE); + } + return $return; + } + public function rename($path1,$path2){ + $this->connect(); + $parent1=dirname($path1); + $name1=substr($path1,strlen($parent1)+1); + $parent2=dirname($path2); + $name2=substr($path2,strlen($parent2)+1); + if($return=$this->remote->move($parent1,$name1,$parent2,$name2)){ + $this->notifyObservers($path1.'->'.$path2,OC_FILEACTION_RENAME); + } + return $return; + } + public function copy($path1,$path2){ + $this->connect(); + $parent1=dirname($path1); + $name1=substr($path1,strlen($parent1)+1); + $parent2=dirname($path2); + $name2=substr($path2,strlen($parent2)+1); + if($return=$this->copy->rename($parent1,$name1,$parent2,$name2)){ + $this->notifyObservers($path1.'->'.$path2,OC_FILEACTION_RENAME); + } + return $return; + } + public function fopen($path,$mode){ + $this->connect(); + $changed=false; + $parent=dirname($path); + $name=substr($path,strlen($parent)+1); + $file=$this->remote->getFile($parent,$name); + if($return=fopen($file,$mode)){ + switch($mode){ + case 'r': + $this->notifyObservers($path,OC_FILEACTION_READ); + break; + case 'r+': + case 'w+': + case 'x+': + case 'a+': + $this->notifyObservers($path,OC_FILEACTION_READ | OC_FILEACTION_WRITE); + $this->changed[]=array('dir'=>$parent,'file'=>$name,'tmp'=>$file); + break; + case 'w': + case 'x': + case 'a': + $this->notifyObservers($path,OC_FILEACTION_WRITE); + $this->changed[]=array('dir'=>$parent,'file'=>$name,'tmp'=>$file); + break; + } + } + return $return; + } + + public function getMimeType($path){ + $this->connect(); + $parent=dirname($path); + $name=substr($path,strlen($parent)+1); + if(substr($name,0,1)=='/'){ + $name=substr($name,1); + } + $this->cacheDir($parent); + if(!isset($this->statCache[$name])){ + return false; + } + return $this->statCache[$name]['mime']; + } + + public function toTmpFile($path){ + $this->connect(); + $parent=dirname($path); + $name=substr($path,strlen($parent)+1); + if(substr($name,0,1)=='/'){ + $name=substr($name,1); + } + $filename=$this->remote->getFile($parent,$name); + if($filename){ + $this->notifyObservers($path,OC_FILEACTION_READ); + return $filename; + }else{ + return false; + } + } + + public function fromTmpFile($tmpFile,$path){ + $this->connect(); + $parent=dirname($path); + $name=substr($path,strlen($parent)+1); + if($this->remote->sendTmpFile($tmpFile,$parent,$name)){ + $this->notifyObservers($path,OC_FILEACTION_CREATE); + return true; + }else{ + return false; + } + } + + public function delTree($dir) { + $this->connect(); + $parent=dirname($dir); + $name=substr($dir,strlen($parent)+1); + $return=$this->remote->delete($parent,$name); + if($return=rmdir($dir)){ + $this->notifyObservers($dir,OC_FILEACTION_DELETE); + } + return $return; + } + + public function find($path){ + return $this->getTree($path); + } + + public function getTree($dir) { + $this->connect(); + if($return=$this->remote->getTree($dir)){ + $this->notifyObservers($dir,OC_FILEACTION_READ); + } + return $return; + } + + public function __destruct(){ + foreach($this->changed as $changed){ + $this->remote->sendTmpFile($changed['tmp'],$changed['dir'],$changed['file']); + } + } +} + +?> diff --git a/lib/template.php b/lib/template.php new file mode 100644 index 00000000000..0541d55b124 --- /dev/null +++ b/lib/template.php @@ -0,0 +1,197 @@ +<?php + +/** +* ownCloud +* +* @author Frank Karlitschek +* @copyright 2010 Frank Karlitschek karlitschek@kde.org +* +* 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/>. +* +*/ + +oc_require_once( "Smarty/Smarty.class.php" ); + +/** + * + */ +function oc_template_helper_link_to( $params, $smarty ){ + $app = ""; + if( isset( $params["app"] )) + { + $app = $params["app"]; + } + $file = $params["file"]; + return OC_UTIL::linkTo( $app, $file ); +} + +/** + * + */ +function oc_template_helper_image_path( $params, $smarty ){ + $app = ""; + if( isset( $params["app"] )) + { + $app = $params["app"]; + } + $file = $params["file"]; + return OC_UTIL::imagePath( $app, $file ); +} + +class OC_TEMPLATE{ + private $renderas; // Create a full page? + private $name; // name of the template + private $application; // template Application + private $smarty; // The smarty object + + public function __construct( $application, $name, $renderas = "" ){ + // Global vars we need + global $SERVERROOT; + + $template_dir = "$SERVERROOT/templates/"; + // Get the right template folder + if( $application != "core" ){ + $template_dir = "$SERVERROOT/$application/templates/"; + } + + // Set the OC-defaults for Smarty + $smarty = new Smarty(); + $smarty->left_delimiter = "[%"; + $smarty->right_delimiter = "%]"; + $smarty->template_dir = $template_dir; + $smarty->compile_dir = "$template_dir/_c"; + $smarty->registerPlugin( "function", "linkto", "oc_template_helper_link_to"); + $smarty->registerPlugin( "function", "imagepath", "oc_template_helper_image_path"); + + // Templates have the ending .tmpl + $name = "$name.tmpl"; + // Set the private data + $this->renderas = $renderas; + $this->application = $application; + $this->name = $name; + $this->smarty = $smarty; + } + + public function assign( $a, $b = null ){ + $this->smarty->assign( $a, $b ); + } + + public function append( $a, $b = null ){ + $this->smarty->append( $a, $b ); + } + + public function printPage() + { + $data = $this->fetchPage(); + if( $data === false ) + { + return false; + } + else + { + print $data; + return true; + } + } + + public function fetchPage() + { + // global Data we need + global $WEBROOT; + $data = $this->smarty->fetch( $this->name ); + + if( $this->renderas ) + { + // Decide which page we show + if( $this->renderas == "user" ) + { + $page = new OC_TEMPLATE( "core", "layout.user" ); + // Add menu data + } + elseif( $this->renderas == "admin" ) + { + $page = new OC_TEMPLATE( "core", "layout.admin" ); + // Add menu data + } + else + { + $page = new OC_TEMPLATE( "core", "layout.guest" ); + // Add data if required + } + + // Add the css and js files + foreach(OC_UTIL::$scripts as $script){ + $page->append( "jsfiles", "$WEBROOT/$script.js" ); + } + foreach(OC_UTIL::$styles as $style){ + $page->append( "cssfiles", "$WEBROOT/$style.css" ); + } + + // Add navigation entry and personal menu + $page->assign( "navigation", OC_UTIL::$navigation ); + $page->assign( "personalmenu", OC_UTIL::$personalmenu ); + + // Add css files and js files + $page->assign( "content", $data ); + return $page->fetchPage(); + } + else + { + return $data; + } + } + public function __destruct(){ + } + + /** + * @brief Shortcut to print a simple page for users + * @param $application The application we render the template for + * @param $name Name of the template + * @param $parameters Parameters for the template + * @returns true/false + */ + public static function printUserPage( $application, $name, $parameters = array() ){ + $content = new OC_TEMPLATE( $application, $name, "user" ); + $content->assign( $parameters ); + return $content->printPage(); + } + + /** + * @brief Shortcut to print a simple page for admins + * @param $application The application we render the template for + * @param $name Name of the template + * @param $parameters Parameters for the template + * @returns true/false + */ + public static function printAdminPage( $application, $name, $parameters = array() ){ + $content = new OC_TEMPLATE( $application, $name, "admin" ); + $content->assign( $parameters ); + return $content->printPage(); + } + + /** + * @brief Shortcut to print a simple page for guests + * @param $application The application we render the template for + * @param $name Name of the template + * @param $parameters Parameters for the template + * @returns true/false + */ + public static function printGuestPage( $application, $name, $parameters = array() ){ + $content = new OC_TEMPLATE( $application, $name, "guest" ); + $content->assign( $parameters ); + return $content->printPage(); + } +} + +?> diff --git a/lib/user.php b/lib/user.php new file mode 100644 index 00000000000..431d0bfc359 --- /dev/null +++ b/lib/user.php @@ -0,0 +1,249 @@ +<?php + +/** +* ownCloud +* +* @author Frank Karlitschek +* @copyright 2010 Frank Karlitschek karlitschek@kde.org +* +* 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/>. +* +*/ + + + + +if ( !$CONFIG_INSTALLED ) { + $_SESSION['user_id'] = false; + $_SESSION['username'] = ''; + $_SESSION['username_clean'] = ''; +} + +//cache the userid's an groupid's +if ( !isset($_SESSION['user_id_cache']) ) { + $_SESSION['user_id_cache'] = array(); +} +if ( !isset($_SESSION['group_id_cache']) ) { + $_SESSION['group_id_cache'] = array(); +} + + + + +/** + * Class for User Management + * + */ +class OC_USER { + + // The backend used for user management + private static $_backend; + + /** + * Set the User Authentication Module + * + * @param string $backend The backend to use for user managment + */ + public static function setBackend($backend='database') { + if ( (null === $backend) OR (!is_string($backend)) ) { + $backend = 'database'; + } + + switch ( $backend ) { + case 'database': + case 'mysql': + case 'sqlite': + oc_require_once('User/database.php'); + self::$_backend = new OC_USER_DATABASE(); + break; + default: + $className = 'OC_USER_' . strToUpper($backend); + self::$_backend = new $className(); + break; + } + } + + /** + * Check if the login button is pressed and log the user in + * + */ + public static function loginListener() { + return self::$_backend->loginListener(); + } + + /** + * Try to create a new user + * + * @param string $username The username of the user to create + * @param string $password The password of the new user + */ + public static function createUser($username, $password) { + return self::$_backend->createUser($username, $password); + } + + /** + * Try to login a user + * + * @param string $username The username of the user to log in + * @param string $password The password of the user + */ + public static function login($username, $password) { + return self::$_backend->login($username, $password); + } + + /** + * Check if the logout button is pressed and logout the user + * + */ + public static function logoutListener() { + return self::$_backend->logoutListener(); + } + + /** + * Kick the user + * + */ + public static function logout() { + return self::$_backend->logout(); + } + + /** + * Check if the user is logged in + * + */ + public static function isLoggedIn() { + return self::$_backend->isLoggedIn(); + } + + /** + * Try to create a new group + * + * @param string $groupName The name of the group to create + */ + public static function createGroup($groupName) { + return self::$_backend->createGroup($groupName); + } + + /** + * Get the ID of a user + * + * @param string $username Name of the user to find the ID + * @param boolean $noCache If false the cache is used to find the ID + */ + public static function getUserId($username, $noCache=false) { + return self::$_backend->getUserId($username, $noCache); + } + + /** + * Get the ID of a group + * + * @param string $groupName Name of the group to find the ID + * @param boolean $noCache If false the cache is used to find the ID + */ + public static function getGroupId($groupName, $noCache=false) { + return self::$_backend->getGroupId($groupName, $noCache); + } + + /** + * Get the name of a group + * + * @param string $groupId ID of the group + * @param boolean $noCache If false the cache is used to find the name of the group + */ + public static function getGroupName($groupId, $noCache=false) { + return self::$_backend->getGroupName($groupId, $noCache); + } + + /** + * Check if a user belongs to a group + * + * @param string $username Name of the user to check + * @param string $groupName Name of the group + */ + public static function inGroup($username, $groupName) { + return self::$_backend->inGroup($username, $groupName); + } + + /** + * Add a user to a group + * + * @param string $username Name of the user to add to group + * @param string $groupName Name of the group in which add the user + */ + public static function addToGroup($username, $groupName) { + return self::$_backend->addToGroup($username, $groupName); + } + + /** + * Remove a user from a group + * + * @param string $username Name of the user to remove from group + * @param string $groupName Name of the group from which remove the user + */ + public static function removeFromGroup($username,$groupName){ + return self::$_backend->removeFromGroup($username, $groupName); + } + + /** + * Generate a random password + */ + public static function generatePassword() { + return substr(md5(uniqId().time()),0,10); + } + + /** + * Get all groups the user belongs to + * + * @param string $username Name of the user + */ + public static function getUserGroups($username) { + return self::$_backend->getUserGroups($username); + } + + /** + * Set the password of a user + * + * @param string $username User who password will be changed + * @param string $password The new password for the user + */ + public static function setPassword($username, $password) { + return self::$_backend->setPassword($username, $password); + } + + /** + * Check if the password of the user is correct + * + * @param string $username Name of the user + * @param string $password Password of the user + */ + public static function checkPassword($username, $password) { + return self::$_backend->checkPassword($username, $password); + } + + /** + * get a list of all users + * + */ + public static function getUsers() { + return self::$_backend->getUsers(); + } + + /** + * get a list of all groups + * + */ + public static function getGroups() { + return self::$_backend->getGroups(); + } +} |