Skip to content
Snippets Groups Projects
Select Git revision
  • e560cba76beb918a2c127b931b6d409abd9f03ab
  • master default protected
2 results

filechunking.php

Blame
  • user avatar
    Felix Moeller authored
    This is NoSpaceAfterComma
    6a00a6b9
    History
    filechunking.php 3.63 KiB
    <?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;
    	}
    
    	public function store($index, $data) {
    		$cache = $this->getCache();
    		$name = $this->getPrefix().$index;
    		$cache->set($name, $data);
    	}
    
    	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);
    			$cache->remove($prefix.$i);
    			$count += fwrite($f, $chunk);
    		}
    		return $count;
    	}
    
    	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_Filesystem::normalizePath(OC_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_Filesystem::isValidPath($path)) {
    			$path = OC_Filesystem::getView()->getRelativePath($absolutePath);
    			$exists = OC_Filesystem::file_exists($path);
    			$run = true;
    			if(!$exists) {
    				OC_Hook::emit(
    					OC_Filesystem::CLASSNAME,
    					OC_Filesystem::signal_create,
    					array(
    						OC_Filesystem::signal_param_path => $path,
    						OC_Filesystem::signal_param_run => &$run
    					)
    				);
    			}
    			OC_Hook::emit(
    				OC_Filesystem::CLASSNAME,
    				OC_Filesystem::signal_write,
    				array(
    					OC_Filesystem::signal_param_path => $path,
    					OC_Filesystem::signal_param_run => &$run
    				)
    			);
    			if(!$run) {
    				return false;
    			}
    			$target = OC_Filesystem::fopen($path, 'w');
    			if($target) {
    				$count = $this->assemble($target);
    				fclose($target);
    				if(!$exists) {
    					OC_Hook::emit(
    						OC_Filesystem::CLASSNAME,
    						OC_Filesystem::signal_post_create,
    						array( OC_Filesystem::signal_param_path => $path)
    					);
    				}
    				OC_Hook::emit(
    					OC_Filesystem::CLASSNAME,
    					OC_Filesystem::signal_post_write,
    					array( OC_Filesystem::signal_param_path => $path)
    				);
    				OC_FileProxy::runPostProxies('file_put_contents', $absolutePath, $count);
    				return $count > 0;
    			}else{
    				return false;
    			}
    		}
    	}
    }