Blame view

sources/apps/documents/lib/download/range.php 2.31 KB
d1bafeea1   Kload   [fix] Upgrade to ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
  <?php
  /**
   * ownCloud - Documents App
   *
   * @author Victor Dubiniuk
   * @copyright 2013 Victor Dubiniuk victor.dubiniuk@gmail.com
   *
   * This file is licensed under the Affero General Public License version 3 or
   * later.
   */
  
  namespace OCA\Documents;
  
  /**
   * Class processing range HTTP request (partial download)
   */
  class Download_Range extends \OCA\Documents\Download {
  
  	// Start of the range
  	protected $start;
  	// End of the range
  	protected $end;
  
  	/**
  	 * Build download model to serve HTTP_RANGE
  	 * @param type $view - filesystem view
  	 * @param type $filepath - path to the file relative to this view root
  	 */
  	public function __construct($owner, $filepath){
  		$this->view = $this->getView($owner);
  		$this->filepath = $filepath;
  	}
  
  	/**
  	 * Send the requested parts of the file
  	 */
  	public function sendResponse(){
  		if (!preg_match('/^bytes=\d*-\d*(,\d*-\d*)*$/', $_SERVER['HTTP_RANGE'])){
  			$this->sendNotSatisfiable();
  		}
  	
  		$mimetype = $this->getMimeType();
  		$content = $this->view->file_get_contents($this->filepath);
  		$data = Filter::read($content, $mimetype);
  		$size = strlen($data['content']);
  		
  		$ranges = explode(',', substr($_SERVER['HTTP_RANGE'], 6));
  		foreach ($ranges as $range){
  			$parts = explode('-', $range);
  
  			if ($parts[0]==='' && $parts[1]=='') {
  				$this->sendNotSatisfiable();
  			}
  			if ($parts[0]==='') {
  				$start = $size - $parts[1];
  				$end = $size - 1;
  			}
  			else {
  				$start = $parts[0];
  				$end = ($parts[1]==='') ? $size - 1 : $parts[1];
  			}
  
  			if ($start > $end){
  				$this->sendNotSatisfiable();
  			}
  
  			$buffer = substr($data['content'], $start,  $end - $start);
  			$md5Sum = md5($buffer);
  
  			// send the headers and data 
  			header("Content-Length: " . ($end - $start));
  			header("Content-md5: " . $md5Sum);
  			header("Accept-Ranges: bytes");
  			header('Content-Range: bytes ' . $start . '-' . ($end) . '/' . $size);
  			header("Connection: close");
  			header("Content-type: " . $data['mimetype']);
  			header('Content-Disposition: attachment; filename=' . $this->getFilename());
  			\OC_Util::obEnd();
  			echo $buffer;
  			flush();
  		}
  	}
  
  	/**
  	 * Send 416 if we can't satisfy the requested ranges
  	 */
  	protected function sendNotSatisfiable(){
  		header('HTTP/1.1 416 Requested Range Not Satisfiable');
  		header('Content-Range: bytes */' . $this->getFilesize()); // Required in 416.
  		exit;
  	}
  }