filechunking.php 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. <?php
  2. /**
  3. * Copyright (c) 2012 Bart Visscher <bartv@thisnet.nl>
  4. * This file is licensed under the Affero General Public License version 3 or
  5. * later.
  6. * See the COPYING-README file.
  7. */
  8. class OC_FileChunking {
  9. protected $info;
  10. protected $cache;
  11. static public function decodeName($name) {
  12. preg_match('/(?P<name>.*)-chunking-(?P<transferid>\d+)-(?P<chunkcount>\d+)-(?P<index>\d+)/', $name, $matches);
  13. return $matches;
  14. }
  15. public function __construct($info) {
  16. $this->info = $info;
  17. }
  18. public function getPrefix() {
  19. $name = $this->info['name'];
  20. $transferid = $this->info['transferid'];
  21. return $name.'-chunking-'.$transferid.'-';
  22. }
  23. protected function getCache() {
  24. if (!isset($this->cache)) {
  25. $this->cache = new OC_Cache_File();
  26. }
  27. return $this->cache;
  28. }
  29. public function store($index, $data) {
  30. $cache = $this->getCache();
  31. $name = $this->getPrefix().$index;
  32. $cache->set($name, $data);
  33. }
  34. public function isComplete() {
  35. $prefix = $this->getPrefix();
  36. $parts = 0;
  37. $cache = $this->getCache();
  38. for($i=0; $i < $this->info['chunkcount']; $i++) {
  39. if ($cache->hasKey($prefix.$i)) {
  40. $parts ++;
  41. }
  42. }
  43. return $parts == $this->info['chunkcount'];
  44. }
  45. public function assemble($f) {
  46. $cache = $this->getCache();
  47. $prefix = $this->getPrefix();
  48. $count = 0;
  49. for($i=0; $i < $this->info['chunkcount']; $i++) {
  50. $chunk = $cache->get($prefix.$i);
  51. $cache->remove($prefix.$i);
  52. $count += fwrite($f, $chunk);
  53. }
  54. return $count;
  55. }
  56. public function signature_split($orgfile, $input) {
  57. $info = unpack('n', fread($input, 2));
  58. $blocksize = $info[1];
  59. $this->info['transferid'] = mt_rand();
  60. $count = 0;
  61. $needed = array();
  62. $cache = $this->getCache();
  63. $prefix = $this->getPrefix();
  64. while (!feof($orgfile)) {
  65. $new_md5 = fread($input, 16);
  66. if (feof($input)) {
  67. break;
  68. }
  69. $data = fread($orgfile, $blocksize);
  70. $org_md5 = md5($data, true);
  71. if ($org_md5 == $new_md5) {
  72. $cache->set($prefix.$count, $data);
  73. } else {
  74. $needed[] = $count;
  75. }
  76. $count++;
  77. }
  78. return array(
  79. 'transferid' => $this->info['transferid'],
  80. 'needed' => $needed,
  81. 'count' => $count,
  82. );
  83. }
  84. public function file_assemble($path) {
  85. $absolutePath = \OC\Files\Filesystem::normalizePath(\OC\Files\Filesystem::getView()->getAbsolutePath($path));
  86. $data = '';
  87. // use file_put_contents as method because that best matches what this function does
  88. if (OC_FileProxy::runPreProxies('file_put_contents', $absolutePath, $data)
  89. && \OC\Files\Filesystem::isValidPath($path)) {
  90. $path = \OC\Files\Filesystem::getView()->getRelativePath($absolutePath);
  91. $exists = \OC\Files\Filesystem::file_exists($path);
  92. $run = true;
  93. if(!$exists) {
  94. OC_Hook::emit(
  95. \OC\Files\Filesystem::CLASSNAME,
  96. \OC\Files\Filesystem::signal_create,
  97. array(
  98. \OC\Files\Filesystem::signal_param_path => $path,
  99. \OC\Files\Filesystem::signal_param_run => &$run
  100. )
  101. );
  102. }
  103. OC_Hook::emit(
  104. \OC\Files\Filesystem::CLASSNAME,
  105. \OC\Files\Filesystem::signal_write,
  106. array(
  107. \OC\Files\Filesystem::signal_param_path => $path,
  108. \OC\Files\Filesystem::signal_param_run => &$run
  109. )
  110. );
  111. if(!$run) {
  112. return false;
  113. }
  114. $target = \OC\Files\Filesystem::fopen($path, 'w');
  115. if($target) {
  116. $count = $this->assemble($target);
  117. fclose($target);
  118. if(!$exists) {
  119. OC_Hook::emit(
  120. \OC\Files\Filesystem::CLASSNAME,
  121. \OC\Files\Filesystem::signal_post_create,
  122. array( \OC\Files\Filesystem::signal_param_path => $path)
  123. );
  124. }
  125. OC_Hook::emit(
  126. \OC\Files\Filesystem::CLASSNAME,
  127. \OC\Files\Filesystem::signal_post_write,
  128. array( \OC\Files\Filesystem::signal_param_path => $path)
  129. );
  130. OC_FileProxy::runPostProxies('file_put_contents', $absolutePath, $count);
  131. return $count > 0;
  132. }else{
  133. return false;
  134. }
  135. }
  136. }
  137. }