Passed
Push — master ( 7799ee...fb64fd )
by Roeland
19:38 queued 09:40
created
lib/private/Files/Stream/SeekableHttpStream.php 1 patch
Indentation   +161 added lines, -161 removed lines patch added patch discarded remove patch
@@ -28,165 +28,165 @@
 block discarded – undo
28 28
  * A stream wrapper that uses http range requests to provide a seekable stream for http reading
29 29
  */
30 30
 class SeekableHttpStream implements File {
31
-	private const PROTOCOL = 'httpseek';
32
-
33
-	private static $registered = false;
34
-
35
-	/**
36
-	 * Registers the stream wrapper using the `httpseek://` url scheme
37
-	 * $return void
38
-	 */
39
-	private static function registerIfNeeded() {
40
-		if (!self::$registered) {
41
-			stream_wrapper_register(
42
-				self::PROTOCOL,
43
-				self::class
44
-			);
45
-			self::$registered = true;
46
-		}
47
-	}
48
-
49
-	/**
50
-	 * Open a readonly-seekable http stream
51
-	 *
52
-	 * The provided callback will be called with byte range and should return an http stream for the requested range
53
-	 *
54
-	 * @param callable $callback
55
-	 * @return false|resource
56
-	 */
57
-	public static function open(callable $callback) {
58
-		$context = stream_context_create([
59
-			SeekableHttpStream::PROTOCOL => [
60
-				'callback' => $callback
61
-			],
62
-		]);
63
-
64
-		SeekableHttpStream::registerIfNeeded();
65
-		return fopen(SeekableHttpStream::PROTOCOL . '://', 'r', false, $context);
66
-	}
67
-
68
-	/** @var resource */
69
-	public $context;
70
-
71
-	/** @var callable */
72
-	private $openCallback;
73
-
74
-	/** @var resource */
75
-	private $current;
76
-	/** @var int */
77
-	private $offset = 0;
78
-
79
-	private function reconnect(int $start) {
80
-		$range = $start . '-';
81
-		if ($this->current != null) {
82
-			fclose($this->current);
83
-		}
84
-
85
-		$this->current = ($this->openCallback)($range);
86
-
87
-		if ($this->current === false) {
88
-			return false;
89
-		}
90
-
91
-		$responseHead = stream_get_meta_data($this->current)['wrapper_data'];
92
-		$rangeHeaders = array_values(array_filter($responseHead, function ($v) {
93
-			return preg_match('#^content-range:#i', $v) === 1;
94
-		}));
95
-		if (!$rangeHeaders) {
96
-			return false;
97
-		}
98
-		$contentRange = $rangeHeaders[0];
99
-
100
-		$content = trim(explode(':', $contentRange)[1]);
101
-		$range = trim(explode(' ', $content)[1]);
102
-		$begin = intval(explode('-', $range)[0]);
103
-
104
-		if ($begin !== $start) {
105
-			return false;
106
-		}
107
-
108
-		$this->offset = $begin;
109
-
110
-		return true;
111
-	}
112
-
113
-	public function stream_open($path, $mode, $options, &$opened_path) {
114
-		$options = stream_context_get_options($this->context)[self::PROTOCOL];
115
-		$this->openCallback = $options['callback'];
116
-
117
-		return $this->reconnect(0);
118
-	}
119
-
120
-	public function stream_read($count) {
121
-		if (!$this->current) {
122
-			return false;
123
-		}
124
-		$ret = fread($this->current, $count);
125
-		$this->offset += strlen($ret);
126
-		return $ret;
127
-	}
128
-
129
-	public function stream_seek($offset, $whence = SEEK_SET) {
130
-		switch ($whence) {
131
-			case SEEK_SET:
132
-				if ($offset === $this->offset) {
133
-					return true;
134
-				}
135
-				return $this->reconnect($offset);
136
-			case SEEK_CUR:
137
-				if ($offset === 0) {
138
-					return true;
139
-				}
140
-				return $this->reconnect($this->offset + $offset);
141
-			case SEEK_END:
142
-				return false;
143
-		}
144
-		return false;
145
-	}
146
-
147
-	public function stream_tell() {
148
-		return $this->offset;
149
-	}
150
-
151
-	public function stream_stat() {
152
-		if (is_resource($this->current)) {
153
-			return fstat($this->current);
154
-		} else {
155
-			return false;
156
-		}
157
-	}
158
-
159
-	public function stream_eof() {
160
-		if (is_resource($this->current)) {
161
-			return feof($this->current);
162
-		} else {
163
-			return true;
164
-		}
165
-	}
166
-
167
-	public function stream_close() {
168
-		if (is_resource($this->current)) {
169
-			fclose($this->current);
170
-		}
171
-	}
172
-
173
-	public function stream_write($data) {
174
-		return false;
175
-	}
176
-
177
-	public function stream_set_option($option, $arg1, $arg2) {
178
-		return false;
179
-	}
180
-
181
-	public function stream_truncate($size) {
182
-		return false;
183
-	}
184
-
185
-	public function stream_lock($operation) {
186
-		return false;
187
-	}
188
-
189
-	public function stream_flush() {
190
-		return; //noop because readonly stream
191
-	}
31
+    private const PROTOCOL = 'httpseek';
32
+
33
+    private static $registered = false;
34
+
35
+    /**
36
+     * Registers the stream wrapper using the `httpseek://` url scheme
37
+     * $return void
38
+     */
39
+    private static function registerIfNeeded() {
40
+        if (!self::$registered) {
41
+            stream_wrapper_register(
42
+                self::PROTOCOL,
43
+                self::class
44
+            );
45
+            self::$registered = true;
46
+        }
47
+    }
48
+
49
+    /**
50
+     * Open a readonly-seekable http stream
51
+     *
52
+     * The provided callback will be called with byte range and should return an http stream for the requested range
53
+     *
54
+     * @param callable $callback
55
+     * @return false|resource
56
+     */
57
+    public static function open(callable $callback) {
58
+        $context = stream_context_create([
59
+            SeekableHttpStream::PROTOCOL => [
60
+                'callback' => $callback
61
+            ],
62
+        ]);
63
+
64
+        SeekableHttpStream::registerIfNeeded();
65
+        return fopen(SeekableHttpStream::PROTOCOL . '://', 'r', false, $context);
66
+    }
67
+
68
+    /** @var resource */
69
+    public $context;
70
+
71
+    /** @var callable */
72
+    private $openCallback;
73
+
74
+    /** @var resource */
75
+    private $current;
76
+    /** @var int */
77
+    private $offset = 0;
78
+
79
+    private function reconnect(int $start) {
80
+        $range = $start . '-';
81
+        if ($this->current != null) {
82
+            fclose($this->current);
83
+        }
84
+
85
+        $this->current = ($this->openCallback)($range);
86
+
87
+        if ($this->current === false) {
88
+            return false;
89
+        }
90
+
91
+        $responseHead = stream_get_meta_data($this->current)['wrapper_data'];
92
+        $rangeHeaders = array_values(array_filter($responseHead, function ($v) {
93
+            return preg_match('#^content-range:#i', $v) === 1;
94
+        }));
95
+        if (!$rangeHeaders) {
96
+            return false;
97
+        }
98
+        $contentRange = $rangeHeaders[0];
99
+
100
+        $content = trim(explode(':', $contentRange)[1]);
101
+        $range = trim(explode(' ', $content)[1]);
102
+        $begin = intval(explode('-', $range)[0]);
103
+
104
+        if ($begin !== $start) {
105
+            return false;
106
+        }
107
+
108
+        $this->offset = $begin;
109
+
110
+        return true;
111
+    }
112
+
113
+    public function stream_open($path, $mode, $options, &$opened_path) {
114
+        $options = stream_context_get_options($this->context)[self::PROTOCOL];
115
+        $this->openCallback = $options['callback'];
116
+
117
+        return $this->reconnect(0);
118
+    }
119
+
120
+    public function stream_read($count) {
121
+        if (!$this->current) {
122
+            return false;
123
+        }
124
+        $ret = fread($this->current, $count);
125
+        $this->offset += strlen($ret);
126
+        return $ret;
127
+    }
128
+
129
+    public function stream_seek($offset, $whence = SEEK_SET) {
130
+        switch ($whence) {
131
+            case SEEK_SET:
132
+                if ($offset === $this->offset) {
133
+                    return true;
134
+                }
135
+                return $this->reconnect($offset);
136
+            case SEEK_CUR:
137
+                if ($offset === 0) {
138
+                    return true;
139
+                }
140
+                return $this->reconnect($this->offset + $offset);
141
+            case SEEK_END:
142
+                return false;
143
+        }
144
+        return false;
145
+    }
146
+
147
+    public function stream_tell() {
148
+        return $this->offset;
149
+    }
150
+
151
+    public function stream_stat() {
152
+        if (is_resource($this->current)) {
153
+            return fstat($this->current);
154
+        } else {
155
+            return false;
156
+        }
157
+    }
158
+
159
+    public function stream_eof() {
160
+        if (is_resource($this->current)) {
161
+            return feof($this->current);
162
+        } else {
163
+            return true;
164
+        }
165
+    }
166
+
167
+    public function stream_close() {
168
+        if (is_resource($this->current)) {
169
+            fclose($this->current);
170
+        }
171
+    }
172
+
173
+    public function stream_write($data) {
174
+        return false;
175
+    }
176
+
177
+    public function stream_set_option($option, $arg1, $arg2) {
178
+        return false;
179
+    }
180
+
181
+    public function stream_truncate($size) {
182
+        return false;
183
+    }
184
+
185
+    public function stream_lock($operation) {
186
+        return false;
187
+    }
188
+
189
+    public function stream_flush() {
190
+        return; //noop because readonly stream
191
+    }
192 192
 }
Please login to merge, or discard this patch.