--- /dev/null
+ <?php
+ /**
+ * Copyright (c) 2012 Bart Visscher <bartv@thisnet.nl>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+ namespace OC\Cache;
+
+ class File {
+ protected $storage;
+ protected function getStorage() {
+ if (isset($this->storage)) {
+ return $this->storage;
+ }
+ if(\OC_User::isLoggedIn()) {
+ \OC\Files\Filesystem::initMountPoints(\OC_User::getUser());
+ $subdir = 'cache';
+ $view = new \OC\Files\View('/' . \OC_User::getUser());
+ if(!$view->file_exists($subdir)) {
+ $view->mkdir($subdir);
+ }
+ $this->storage = new \OC\Files\View('/' . \OC_User::getUser().'/'.$subdir);
+ return $this->storage;
+ }else{
+ \OC_Log::write('core', 'Can\'t get cache storage, user not logged in', \OC_Log::ERROR);
+ return false;
+ }
+ }
+
+ public function get($key) {
+ $result = null;
+ $proxyStatus = \OC_FileProxy::$enabled;
+ \OC_FileProxy::$enabled = false;
+ if ($this->hasKey($key)) {
+ $storage = $this->getStorage();
+ $result = $storage->file_get_contents($key);
+ }
+ \OC_FileProxy::$enabled = $proxyStatus;
+ return $result;
+ }
+
++ /**
++ * Returns the size of the stored/cached data
++ *
++ * @param $key
++ * @return int
++ */
++ public function size($key) {
++ $result = 0;
++ $proxyStatus = \OC_FileProxy::$enabled;
++ \OC_FileProxy::$enabled = false;
++ if ($this->hasKey($key)) {
++ $storage = $this->getStorage();
++ $result = $storage->filesize($key);
++ }
++ \OC_FileProxy::$enabled = $proxyStatus;
++ return $result;
++ }
++
+ public function set($key, $value, $ttl=0) {
+ $storage = $this->getStorage();
+ $result = false;
+ $proxyStatus = \OC_FileProxy::$enabled;
+ \OC_FileProxy::$enabled = false;
+ if ($storage and $storage->file_put_contents($key, $value)) {
+ if ($ttl === 0) {
+ $ttl = 86400; // 60*60*24
+ }
+ $result = $storage->touch($key, time() + $ttl);
+ }
+ \OC_FileProxy::$enabled = $proxyStatus;
+ return $result;
+ }
+
+ public function hasKey($key) {
+ $storage = $this->getStorage();
+ if ($storage && $storage->is_file($key)) {
+ $mtime = $storage->filemtime($key);
+ if ($mtime < time()) {
+ $storage->unlink($key);
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public function remove($key) {
+ $storage = $this->getStorage();
+ if(!$storage) {
+ return false;
+ }
+ return $storage->unlink($key);
+ }
+
+ public function clear($prefix='') {
+ $storage = $this->getStorage();
+ if($storage and $storage->is_dir('/')) {
+ $dh=$storage->opendir('/');
+ if(is_resource($dh)) {
+ while (($file = readdir($dh)) !== false) {
+ if($file!='.' and $file!='..' and ($prefix==='' || strpos($file, $prefix) === 0)) {
+ $storage->unlink('/'.$file);
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ public function gc() {
+ $storage = $this->getStorage();
+ if($storage and $storage->is_dir('/')) {
+ $now = time();
+ $dh=$storage->opendir('/');
+ if(!is_resource($dh)) {
+ return null;
+ }
+ while (($file = readdir($dh)) !== false) {
+ if($file!='.' and $file!='..') {
+ $mtime = $storage->filemtime('/'.$file);
+ if ($mtime < $now) {
+ $storage->unlink('/'.$file);
+ }
+ }
+ }
+ }
+ }
+
+ public static function loginListener() {
+ $c = new self();
+ $c->gc();
+ }
+ }
--- /dev/null
-
+ <?php
+
+ /**
+ * ownCloud
+ *
+ * @author Jakob Sack
+ * @copyright 2011 Jakob Sack kde@jakobsack.de
+ *
+ * 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_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sabre_DAV_ICollection, Sabre_DAV_IQuota {
+
+ /**
+ * Creates a new file in the directory
+ *
+ * Data will either be supplied as a stream resource, or in certain cases
+ * as a string. Keep in mind that you may have to support either.
+ *
+ * After succesful creation of the file, you may choose to return the ETag
+ * of the new file here.
+ *
+ * The returned ETag must be surrounded by double-quotes (The quotes should
+ * be part of the actual string).
+ *
+ * If you cannot accurately determine the ETag, you should not return it.
+ * If you don't store the file exactly as-is (you're transforming it
+ * somehow) you should also not return an ETag.
+ *
+ * This means that if a subsequent GET to this new file does not exactly
+ * return the same contents of what was submitted here, you are strongly
+ * recommended to omit the ETag.
+ *
+ * @param string $name Name of the file
+ * @param resource|string $data Initial payload
+ * @throws Sabre_DAV_Exception_Forbidden
+ * @return null|string
+ */
+ public function createFile($name, $data = null) {
+
+ if (!\OC\Files\Filesystem::isCreatable($this->path)) {
+ throw new \Sabre_DAV_Exception_Forbidden();
+ }
+
+ $path = $this->path . '/' . $name;
+ $node = new OC_Connector_Sabre_File($path);
+ return $node->put($data);
+ }
+
+ /**
+ * Creates a new subdirectory
+ *
+ * @param string $name
+ * @throws Sabre_DAV_Exception_Forbidden
+ * @return void
+ */
+ public function createDirectory($name) {
+
+ if (!\OC\Files\Filesystem::isCreatable($this->path)) {
+ throw new \Sabre_DAV_Exception_Forbidden();
+ }
+
+ $newPath = $this->path . '/' . $name;
+ if(!\OC\Files\Filesystem::mkdir($newPath)) {
+ throw new Sabre_DAV_Exception_Forbidden('Could not create directory '.$newPath);
+ }
+
+ }
+
+ /**
+ * Returns a specific child node, referenced by its name
+ *
+ * @param string $name
+ * @throws Sabre_DAV_Exception_FileNotFound
+ * @return Sabre_DAV_INode
+ */
+ public function getChild($name, $info = null) {
+
+ $path = $this->path . '/' . $name;
+ if (is_null($info)) {
+ $info = \OC\Files\Filesystem::getFileInfo($path);
+ }
+
+ if (!$info) {
+ throw new Sabre_DAV_Exception_NotFound('File with name ' . $path . ' could not be located');
+ }
+
+ if ($info['mimetype'] == 'httpd/unix-directory') {
+ $node = new OC_Connector_Sabre_Directory($path);
+ } else {
+ $node = new OC_Connector_Sabre_File($path);
+ }
+
+ $node->setFileinfoCache($info);
+ return $node;
+ }
+
+ /**
+ * Returns an array with all the child nodes
+ *
+ * @return Sabre_DAV_INode[]
+ */
+ public function getChildren() {
+
+ $folder_content = \OC\Files\Filesystem::getDirectoryContent($this->path);
+ $paths = array();
+ foreach($folder_content as $info) {
+ $paths[] = $this->path.'/'.$info['name'];
+ $properties[$this->path.'/'.$info['name']][self::GETETAG_PROPERTYNAME] = '"' . $info['etag'] . '"';
+ }
+ if(count($paths)>0) {
+ //
+ // the number of arguments within IN conditions are limited in most databases
+ // we chunk $paths into arrays of 200 items each to meet this criteria
+ //
+ $chunks = array_chunk($paths, 200, false);
+ foreach ($chunks as $pack) {
+ $placeholders = join(',', array_fill(0, count($pack), '?'));
+ $query = OC_DB::prepare( 'SELECT * FROM `*PREFIX*properties`'
+ .' WHERE `userid` = ?' . ' AND `propertypath` IN ('.$placeholders.')' );
+ array_unshift($pack, OC_User::getUser()); // prepend userid
+ $result = $query->execute( $pack );
+ while($row = $result->fetchRow()) {
+ $propertypath = $row['propertypath'];
+ $propertyname = $row['propertyname'];
+ $propertyvalue = $row['propertyvalue'];
+ if($propertyname !== self::GETETAG_PROPERTYNAME) {
+ $properties[$propertypath][$propertyname] = $propertyvalue;
+ }
+ }
+ }
+ }
+
+ $nodes = array();
+ foreach($folder_content as $info) {
+ $node = $this->getChild($info['name'], $info);
+ $node->setPropertyCache($properties[$this->path.'/'.$info['name']]);
+ $nodes[] = $node;
+ }
+ return $nodes;
+ }
+
+ /**
+ * Checks if a child exists.
+ *
+ * @param string $name
+ * @return bool
+ */
+ public function childExists($name) {
+
+ $path = $this->path . '/' . $name;
+ return \OC\Files\Filesystem::file_exists($path);
+
+ }
+
+ /**
+ * Deletes all files in this directory, and then itself
+ *
+ * @return void
+ * @throws Sabre_DAV_Exception_Forbidden
+ */
+ public function delete() {
+
+ if (!\OC\Files\Filesystem::isDeletable($this->path)) {
+ throw new \Sabre_DAV_Exception_Forbidden();
+ }
+ if ($this->path != "/Shared") {
+ \OC\Files\Filesystem::rmdir($this->path);
+ }
+
+ }
+
+ /**
+ * Returns available diskspace information
+ *
+ * @return array
+ */
+ public function getQuotaInfo() {
+ $storageInfo = OC_Helper::getStorageInfo($this->path);
+ return array(
+ $storageInfo['used'],
+ $storageInfo['free']
+ );
+
+ }
+
+ /**
+ * Returns a list of properties for this nodes.;
+ *
+ * The properties list is a list of propertynames the client requested,
+ * encoded as xmlnamespace#tagName, for example:
+ * http://www.example.org/namespace#author
+ * If the array is empty, all properties should be returned
+ *
+ * @param array $properties
+ * @return array
+ */
+ public function getProperties($properties) {
+ $props = parent::getProperties($properties);
+ if (in_array(self::GETETAG_PROPERTYNAME, $properties) && !isset($props[self::GETETAG_PROPERTYNAME])) {
+ $props[self::GETETAG_PROPERTYNAME] = $this->getETagPropertyForPath($this->path);
+ }
+ return $props;
+ }
++
+ }
--- /dev/null
- $cache->remove($prefix.$i);
+ <?php
+ /**
+ * Copyright (c) 2012 Bart Visscher <bartv@thisnet.nl>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+
+ class OC_FileChunking {
+ protected $info;
+ protected $cache;
+
+ static public function decodeName($name) {
+ preg_match('/(?P<name>.*)-chunking-(?P<transferid>\d+)-(?P<chunkcount>\d+)-(?P<index>\d+)/', $name, $matches);
+ return $matches;
+ }
+
+ public function __construct($info) {
+ $this->info = $info;
+ }
+
+ public function getPrefix() {
+ $name = $this->info['name'];
+ $transferid = $this->info['transferid'];
+
+ return $name.'-chunking-'.$transferid.'-';
+ }
+
+ protected function getCache() {
+ if (!isset($this->cache)) {
+ $this->cache = new \OC\Cache\File();
+ }
+ return $this->cache;
+ }
+
++ /**
++ * Stores the given $data under the given $key - the number of stored bytes is returned
++ *
++ * @param $index
++ * @param $data
++ * @return int
++ */
+ public function store($index, $data) {
+ $cache = $this->getCache();
+ $name = $this->getPrefix().$index;
+ $cache->set($name, $data);
++
++ return $cache->size($name);
+ }
+
+ public function isComplete() {
+ $prefix = $this->getPrefix();
+ $parts = 0;
+ $cache = $this->getCache();
+ for($i=0; $i < $this->info['chunkcount']; $i++) {
+ if ($cache->hasKey($prefix.$i)) {
+ $parts ++;
+ }
+ }
+ return $parts == $this->info['chunkcount'];
+ }
+
+ public function assemble($f) {
+ $cache = $this->getCache();
+ $prefix = $this->getPrefix();
+ $count = 0;
+ for($i=0; $i < $this->info['chunkcount']; $i++) {
+ $chunk = $cache->get($prefix.$i);
+ $count += fwrite($f, $chunk);
+ }
++
++ $this->cleanup();
+ return $count;
+ }
+
++ /**
++ * Removes all chunks which belong to this transmission
++ */
++ public function cleanup() {
++ $cache = $this->getCache();
++ $prefix = $this->getPrefix();
++ for($i=0; $i < $this->info['chunkcount']; $i++) {
++ $cache->remove($prefix.$i);
++ }
++ }
++
+ public function signature_split($orgfile, $input) {
+ $info = unpack('n', fread($input, 2));
+ $blocksize = $info[1];
+ $this->info['transferid'] = mt_rand();
+ $count = 0;
+ $needed = array();
+ $cache = $this->getCache();
+ $prefix = $this->getPrefix();
+ while (!feof($orgfile)) {
+ $new_md5 = fread($input, 16);
+ if (feof($input)) {
+ break;
+ }
+ $data = fread($orgfile, $blocksize);
+ $org_md5 = md5($data, true);
+ if ($org_md5 == $new_md5) {
+ $cache->set($prefix.$count, $data);
+ } else {
+ $needed[] = $count;
+ }
+ $count++;
+ }
+ return array(
+ 'transferid' => $this->info['transferid'],
+ 'needed' => $needed,
+ 'count' => $count,
+ );
+ }
+
+ public function file_assemble($path) {
+ $absolutePath = \OC\Files\Filesystem::normalizePath(\OC\Files\Filesystem::getView()->getAbsolutePath($path));
+ $data = '';
+ // use file_put_contents as method because that best matches what this function does
+ if (OC_FileProxy::runPreProxies('file_put_contents', $absolutePath, $data)
+ && \OC\Files\Filesystem::isValidPath($path)) {
+ $path = \OC\Files\Filesystem::getView()->getRelativePath($absolutePath);
+ $exists = \OC\Files\Filesystem::file_exists($path);
+ $run = true;
+ if(!$exists) {
+ OC_Hook::emit(
+ \OC\Files\Filesystem::CLASSNAME,
+ \OC\Files\Filesystem::signal_create,
+ array(
+ \OC\Files\Filesystem::signal_param_path => $path,
+ \OC\Files\Filesystem::signal_param_run => &$run
+ )
+ );
+ }
+ OC_Hook::emit(
+ \OC\Files\Filesystem::CLASSNAME,
+ \OC\Files\Filesystem::signal_write,
+ array(
+ \OC\Files\Filesystem::signal_param_path => $path,
+ \OC\Files\Filesystem::signal_param_run => &$run
+ )
+ );
+ if(!$run) {
+ return false;
+ }
+ $target = \OC\Files\Filesystem::fopen($path, 'w');
+ if($target) {
+ $count = $this->assemble($target);
+ fclose($target);
+ if(!$exists) {
+ OC_Hook::emit(
+ \OC\Files\Filesystem::CLASSNAME,
+ \OC\Files\Filesystem::signal_post_create,
+ array( \OC\Files\Filesystem::signal_param_path => $path)
+ );
+ }
+ OC_Hook::emit(
+ \OC\Files\Filesystem::CLASSNAME,
+ \OC\Files\Filesystem::signal_post_write,
+ array( \OC\Files\Filesystem::signal_param_path => $path)
+ );
+ OC_FileProxy::runPostProxies('file_put_contents', $absolutePath, $count);
+ return $count > 0;
+ }else{
+ return false;
+ }
+ }
+ }
+ }