iGusev /
torrent
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | |||
| 3 | namespace League\Torrent; |
||
| 4 | |||
| 5 | use League\Torrent\Helper\Decoder; |
||
| 6 | use League\Torrent\Helper\Encoder; |
||
| 7 | use League\Torrent\Helper\FileSystem; |
||
| 8 | |||
| 9 | /** |
||
| 10 | * Class Torrent |
||
| 11 | * |
||
| 12 | * @package League\Torrent |
||
| 13 | */ |
||
| 14 | class Torrent |
||
| 15 | { |
||
| 16 | /** |
||
| 17 | * Optional comment |
||
| 18 | * |
||
| 19 | * @var string |
||
| 20 | */ |
||
| 21 | public $comment; |
||
| 22 | |||
| 23 | /** |
||
| 24 | * |
||
| 25 | * @var string |
||
| 26 | */ |
||
| 27 | public $announce; |
||
| 28 | |||
| 29 | /** |
||
| 30 | * |
||
| 31 | * @var string |
||
| 32 | */ |
||
| 33 | protected $createdBy; |
||
| 34 | |||
| 35 | /** |
||
| 36 | * |
||
| 37 | * @var int |
||
| 38 | */ |
||
| 39 | protected $creationDate; |
||
| 40 | |||
| 41 | /** |
||
| 42 | * Info about the file(s) in the torrent |
||
| 43 | * |
||
| 44 | * @var array |
||
| 45 | */ |
||
| 46 | public $info; |
||
| 47 | |||
| 48 | /** |
||
| 49 | * @param null $data |
||
| 50 | * @param array $meta |
||
| 51 | * @param int $piece_length |
||
| 52 | * |
||
| 53 | * @throws Exception |
||
| 54 | */ |
||
| 55 | public function __construct($data = null, $meta = array(), $piece_length = 256) |
||
| 56 | { |
||
| 57 | if (is_null($data)) { |
||
| 58 | return false; |
||
|
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||
| 59 | } |
||
| 60 | if ($piece_length < 32 || $piece_length > 4096) { |
||
| 61 | throw new Exception('Invalid piece lenth, must be between 32 and 4096'); |
||
| 62 | } |
||
| 63 | if ($this->build($data, $piece_length * 1024)) { |
||
| 64 | $this->touch(); |
||
| 65 | } else { |
||
| 66 | $meta = array_merge($meta, Decoder::decode($data)); |
||
| 67 | } |
||
| 68 | foreach ($meta as $key => $value) { |
||
| 69 | $this->{$key} = $value; |
||
| 70 | } |
||
| 71 | } |
||
| 72 | |||
| 73 | public static function createFromTorrentFile($filename, $meta = array()) |
||
| 74 | { |
||
| 75 | return self::setMeta(new self(), file_get_contents($filename), $meta); |
||
| 76 | } |
||
| 77 | |||
| 78 | public static function createFromUrl($url, $meta = array()) |
||
| 79 | { |
||
| 80 | if (!FileSystem::url_exists($url)) { |
||
| 81 | throw new \InvalidArgumentException('Url is not valud'); |
||
| 82 | } |
||
| 83 | |||
| 84 | return self::setMeta(new self(), FileSystem::downloadTorrent($url), $meta); |
||
| 85 | } |
||
| 86 | |||
| 87 | public static function createFromFilesList(array $list, $meta = array()) |
||
| 88 | { |
||
| 89 | $instance = new self; |
||
| 90 | if ($instance->build($list, 256 * 1024)) { |
||
| 91 | $instance->touch(); |
||
| 92 | } |
||
| 93 | |||
| 94 | return self::setMeta($instance, '', $meta); |
||
| 95 | } |
||
| 96 | |||
| 97 | public static function setMeta($instance, $data = '', $meta = array()) |
||
| 98 | { |
||
| 99 | if (strlen($data)) { |
||
| 100 | $meta = array_merge($meta, (array) Decoder::decodeData($data)); |
||
| 101 | } |
||
| 102 | |||
| 103 | foreach ($meta as $key => $value) { |
||
| 104 | $instance->{$key} = $value; |
||
| 105 | } |
||
| 106 | |||
| 107 | return $instance; |
||
| 108 | } |
||
| 109 | |||
| 110 | /** |
||
| 111 | * @return string |
||
| 112 | */ |
||
| 113 | public function __toString() |
||
| 114 | { |
||
| 115 | return Encoder::encode(get_object_vars($this)); |
||
| 116 | } |
||
| 117 | |||
| 118 | /** |
||
| 119 | * @param null $announce |
||
| 120 | * |
||
| 121 | * @return array|mixed|null|string |
||
| 122 | */ |
||
| 123 | public function announce($announce = null) |
||
| 124 | { |
||
| 125 | if (is_null($announce)) { |
||
| 126 | return !isset($this->{'announce-list'}) ? |
||
| 127 | isset($this->announce) ? $this->announce : null : |
||
| 128 | $this->{'announce-list'}; |
||
| 129 | } |
||
| 130 | $this->touch(); |
||
| 131 | if (is_string($announce) && isset($this->announce)) { |
||
| 132 | return $this->{'announce-list'} = self::announce_list(isset($this->{'announce-list'}) ? $this->{'announce-list'} : $this->announce, |
||
| 133 | $announce); |
||
|
0 ignored issues
–
show
$announce is of type string, but the function expects a array.
It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: function acceptsInteger($int) { }
$x = '123'; // string "123"
// Instead of
acceptsInteger($x);
// we recommend to use
acceptsInteger((integer) $x);
Loading history...
|
|||
| 134 | } |
||
| 135 | unset($this->{'announce-list'}); |
||
| 136 | if (is_array($announce) || is_object($announce)) { |
||
| 137 | if (($this->announce = self::first_announce($announce)) && count($announce) > 1) { |
||
| 138 | return $this->{'announce-list'} = self::announce_list($announce); |
||
| 139 | } else { |
||
| 140 | return $this->announce; |
||
| 141 | } |
||
| 142 | } |
||
| 143 | if (!isset($this->announce) && $announce) { |
||
| 144 | return $this->announce = (string) $announce; |
||
| 145 | } |
||
| 146 | unset($this->announce); |
||
| 147 | } |
||
| 148 | |||
| 149 | /** |
||
| 150 | * |
||
| 151 | * @return null|string |
||
| 152 | */ |
||
| 153 | public function getComment() |
||
| 154 | { |
||
| 155 | return $this->comment; |
||
| 156 | } |
||
| 157 | |||
| 158 | /** |
||
| 159 | * @param null $comment |
||
| 160 | * |
||
| 161 | */ |
||
| 162 | public function setComment($comment) |
||
| 163 | { |
||
| 164 | $this->touch($this->comment = (string) $comment); |
||
| 165 | } |
||
| 166 | |||
| 167 | /** |
||
| 168 | * |
||
| 169 | * @return string|null |
||
| 170 | */ |
||
| 171 | public function getName() |
||
| 172 | { |
||
| 173 | return isset($this->info['name']) ? $this->info['name'] : null; |
||
| 174 | } |
||
| 175 | |||
| 176 | /** |
||
| 177 | * @param string $name |
||
| 178 | * |
||
| 179 | * @return null|string |
||
| 180 | */ |
||
| 181 | public function setName($name) |
||
| 182 | { |
||
| 183 | $this->touch($this->info['name'] = (string) $name); |
||
| 184 | } |
||
| 185 | |||
| 186 | /** |
||
| 187 | * @param null $private |
||
| 188 | * |
||
| 189 | * @return bool|null |
||
| 190 | */ |
||
| 191 | public function isPrivate($private = null) |
||
| 192 | { |
||
| 193 | return is_null($private) ? |
||
| 194 | !empty($this->info['private']) : |
||
| 195 | $this->touch($this->info['private'] = $private ? 1 : 0); |
||
| 196 | } |
||
| 197 | |||
| 198 | /** |
||
| 199 | * @param null $urls |
||
| 200 | * |
||
| 201 | * @return null |
||
| 202 | */ |
||
| 203 | public function urlList($urls = null) |
||
| 204 | { |
||
| 205 | return is_null($urls) ? |
||
| 206 | isset($this->{'url-list'}) ? $this->{'url-list'} : null : |
||
| 207 | $this->touch($this->{'url-list'} = is_string($urls) ? $urls : (array) $urls); |
||
| 208 | } |
||
| 209 | |||
| 210 | /** |
||
| 211 | * @param null $urls |
||
| 212 | * |
||
| 213 | * @return null |
||
| 214 | */ |
||
| 215 | public function httpSeeds($urls = null) |
||
| 216 | { |
||
| 217 | return is_null($urls) ? |
||
| 218 | isset($this->httpseeds) ? $this->httpseeds : null : |
||
|
0 ignored issues
–
show
The property
httpseeds does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
Loading history...
|
|||
| 219 | $this->touch($this->httpseeds = (array) $urls); |
||
| 220 | } |
||
| 221 | |||
| 222 | /** |
||
| 223 | * @return null |
||
| 224 | */ |
||
| 225 | public function piece_length() |
||
| 226 | { |
||
| 227 | return isset($this->info['piece length']) ? |
||
| 228 | $this->info['piece length'] : |
||
| 229 | null; |
||
| 230 | } |
||
| 231 | |||
| 232 | /** |
||
| 233 | * @return null|string |
||
| 234 | */ |
||
| 235 | public function hash_info() |
||
| 236 | { |
||
| 237 | return isset($this->info) ? sha1(Encoder::encode($this->info)) : null; |
||
| 238 | } |
||
| 239 | |||
| 240 | /** |
||
| 241 | * |
||
| 242 | * @return array |
||
| 243 | */ |
||
| 244 | public function content() |
||
| 245 | { |
||
| 246 | $files = array(); |
||
| 247 | if ($this->isOneFile()) { |
||
| 248 | $files[$this->info['name']] = $this->info['length']; |
||
| 249 | |||
| 250 | } else { |
||
| 251 | foreach ((array) $this->info['files'] as $file) { |
||
| 252 | $files[FileSystem::path($file['path'], $this->info['name'])] = $file['length']; |
||
| 253 | } |
||
| 254 | } |
||
| 255 | |||
| 256 | return $files; |
||
| 257 | } |
||
| 258 | |||
| 259 | |||
| 260 | private function isOneFile() |
||
| 261 | { |
||
| 262 | return isset($this->info['length'], $this->info['name']); |
||
| 263 | } |
||
| 264 | |||
| 265 | /** |
||
| 266 | * @return array |
||
| 267 | */ |
||
| 268 | public function offset() |
||
| 269 | { |
||
| 270 | $files = array(); |
||
| 271 | $size = 0; |
||
| 272 | if ($this->isOneFile()) { |
||
| 273 | $files[$this->info['name']] = array( |
||
| 274 | 'startpiece' => 0, |
||
| 275 | 'offset' => 0, |
||
| 276 | 'size' => $this->info['length'], |
||
| 277 | 'endpiece' => floor($this->info['length'] / $this->info['piece length']) |
||
| 278 | ); |
||
| 279 | } else { |
||
| 280 | foreach ((array) $this->info['files'] as $file) { |
||
| 281 | $files[FileSystem::path($file['path'], $this->info['name'])] = array( |
||
| 282 | 'startpiece' => floor($size / $this->info['piece length']), |
||
| 283 | 'offset' => fmod($size, $this->info['piece length']), |
||
| 284 | 'size' => $size += $file['length'], |
||
| 285 | 'endpiece' => floor($size / $this->info['piece length']) |
||
| 286 | ); |
||
| 287 | } |
||
| 288 | } |
||
| 289 | |||
| 290 | return $files; |
||
| 291 | } |
||
| 292 | |||
| 293 | /** |
||
| 294 | * |
||
| 295 | * @return int |
||
| 296 | */ |
||
| 297 | public function getSize() |
||
| 298 | { |
||
| 299 | $size = 0; |
||
| 300 | |||
| 301 | if ($this->isOneFile()) { |
||
| 302 | return $this->info['length']; |
||
| 303 | } else { |
||
| 304 | foreach ((array) $this->info['files'] as $file) { |
||
| 305 | $size += $file['length']; |
||
| 306 | } |
||
| 307 | } |
||
| 308 | |||
| 309 | return $size; |
||
| 310 | } |
||
| 311 | |||
| 312 | |||
| 313 | /** |
||
| 314 | * @param null $announce |
||
| 315 | * @param null $hash_info |
||
| 316 | * @param int $timeout |
||
| 317 | * |
||
| 318 | * @return array|bool |
||
| 319 | * |
||
| 320 | * @throws Exception |
||
| 321 | */ |
||
| 322 | public function scrape($announce = null, $hash_info = null, $timeout = FileSystem::timeout) |
||
| 323 | { |
||
| 324 | $packed_hash = urlencode(pack('H*', $hash_info ? $hash_info : $this->hash_info())); |
||
| 325 | $handles = $scrape = array(); |
||
| 326 | if (!function_exists('curl_multi_init')) { |
||
| 327 | throw new Exception('Install CURL with "curl_multi_init" enabled'); |
||
| 328 | } |
||
| 329 | $curl = curl_multi_init(); |
||
| 330 | foreach ((array) ($announce ? $announce : $this->announce()) as $tier) { |
||
| 331 | foreach ((array) $tier as $tracker) { |
||
| 332 | $tracker = str_ireplace(array('udp://', '/announce', ':80/'), array( |
||
| 333 | 'http://', |
||
| 334 | '/scrape', |
||
| 335 | '/' |
||
| 336 | ), $tracker); |
||
| 337 | if (isset($handles[$tracker])) { |
||
| 338 | continue; |
||
| 339 | } |
||
| 340 | $handles[$tracker] = curl_init($tracker . '?info_hash=' . $packed_hash); |
||
| 341 | curl_setopt($handles[$tracker], CURLOPT_RETURNTRANSFER, true); |
||
| 342 | curl_setopt($handles[$tracker], CURLOPT_TIMEOUT, $timeout); |
||
| 343 | curl_multi_add_handle($curl, $handles[$tracker]); |
||
| 344 | } |
||
| 345 | } |
||
| 346 | do { |
||
| 347 | while (($state = curl_multi_exec($curl, $running)) == CURLM_CALL_MULTI_PERFORM) { |
||
| 348 | ; |
||
| 349 | } |
||
| 350 | if ($state != CURLM_OK) { |
||
| 351 | continue; |
||
| 352 | } |
||
| 353 | while ($done = curl_multi_info_read($curl)) { |
||
| 354 | $info = curl_getinfo($done['handle']); |
||
| 355 | $tracker = explode('?', $info['url'], 2); |
||
| 356 | $tracker = array_shift($tracker); |
||
| 357 | if (empty($info['http_code'])) { |
||
| 358 | $scrape[$tracker] = 'Tracker request timeout (' . $timeout . 's)'; |
||
| 359 | continue; |
||
| 360 | } elseif ($info['http_code'] != 200) { |
||
| 361 | $scrape[$tracker] = 'Tracker request failed (' . $info['http_code'] . ' code)'; |
||
| 362 | continue; |
||
| 363 | } |
||
| 364 | $data = curl_multi_getcontent($done['handle']); |
||
| 365 | $stats = Decoder::decodeData($data); |
||
| 366 | curl_multi_remove_handle($curl, $done['handle']); |
||
| 367 | $scrape[$tracker] = empty($stats['files']) ? |
||
| 368 | 'Empty scrape data' : |
||
| 369 | array_shift($stats['files']) + (empty($stats['flags']) ? array() : $stats['flags']); |
||
| 370 | } |
||
| 371 | } while ($running); |
||
| 372 | curl_multi_close($curl); |
||
| 373 | return $scrape; |
||
| 374 | } |
||
| 375 | |||
| 376 | /** |
||
| 377 | * @param string $filename |
||
| 378 | * |
||
| 379 | * @return string |
||
| 380 | */ |
||
| 381 | public function saveToFile($filename = null) |
||
| 382 | { |
||
| 383 | return file_put_contents($filename, Encoder::encode(get_object_vars($this))); |
||
| 384 | } |
||
| 385 | |||
| 386 | /** |
||
| 387 | * |
||
| 388 | * @return string |
||
| 389 | */ |
||
| 390 | public function save() |
||
| 391 | { |
||
| 392 | return file_put_contents($this->info['name'] . '.torrent', Encoder::encode(get_object_vars($this))); |
||
| 393 | } |
||
| 394 | |||
| 395 | /** |
||
| 396 | * @param bool $html |
||
| 397 | * |
||
| 398 | * @return string |
||
| 399 | */ |
||
| 400 | public function magnet($html = true) |
||
| 401 | { |
||
| 402 | $ampersand = $html ? '&' : '&'; |
||
| 403 | return sprintf( |
||
| 404 | 'magnet:?xt=urn:btih:%2$s%1$sdn=%3$s%1$sxl=%4$d%1$str=%5$s', |
||
| 405 | $ampersand, |
||
| 406 | $this->hash_info(), |
||
| 407 | urlencode($this->getName()), |
||
| 408 | $this->getSize(), |
||
| 409 | implode($ampersand . 'tr=', FileSystem::untier($this->announce())) |
||
| 410 | ); |
||
| 411 | } |
||
| 412 | |||
| 413 | |||
| 414 | /** |
||
| 415 | * @param $data |
||
| 416 | * @param integer $piece_length |
||
| 417 | * |
||
| 418 | * @return array|bool |
||
| 419 | */ |
||
| 420 | protected function build($data, $piece_length) |
||
| 421 | { |
||
| 422 | if (is_null($data)) { |
||
| 423 | return false; |
||
| 424 | } elseif (is_array($data) && FileSystem::is_list($data)) { |
||
| 425 | return $this->info = $this->files($data, $piece_length); |
||
| 426 | } elseif (is_dir($data)) { |
||
| 427 | return $this->info = $this->folder($data, $piece_length); |
||
| 428 | } elseif ( |
||
| 429 | (is_file($data) && !FileSystem::isTorrent(file_get_contents($data))) |
||
| 430 | || (FileSystem::url_exists($data) && !FileSystem::isTorrent(FileSystem::downloadTorrent($data))) |
||
| 431 | ) { |
||
| 432 | return $this->info = $this->file($data, $piece_length); |
||
| 433 | } |
||
| 434 | |||
| 435 | return false; |
||
| 436 | } |
||
| 437 | |||
| 438 | /** |
||
| 439 | * @param null $void |
||
| 440 | * |
||
| 441 | * @return null |
||
| 442 | */ |
||
| 443 | protected function touch($void = null) |
||
| 444 | { |
||
| 445 | $this->createdBy = 'League\Torrent Class - http://github.com/iGusev/torrent'; |
||
| 446 | $this->creationDate = time(); |
||
| 447 | return $void; |
||
| 448 | } |
||
| 449 | |||
| 450 | /** |
||
| 451 | * @param $announce |
||
| 452 | * @param array $merge |
||
| 453 | * |
||
| 454 | * @return array |
||
| 455 | */ |
||
| 456 | protected static function announce_list($announce, $merge = array()) |
||
| 457 | { |
||
| 458 | return array_map(create_function('$a', 'return (array) $a;'), array_merge((array) $announce, (array) $merge)); |
||
| 459 | } |
||
| 460 | |||
| 461 | /** |
||
| 462 | * @param $announce |
||
| 463 | * |
||
| 464 | * @return array|mixed |
||
| 465 | */ |
||
| 466 | protected static function first_announce($announce) |
||
| 467 | { |
||
| 468 | while (is_array($announce)) { |
||
| 469 | $announce = reset($announce); |
||
| 470 | } |
||
| 471 | return $announce; |
||
| 472 | } |
||
| 473 | |||
| 474 | /** |
||
| 475 | * @param $handle |
||
| 476 | * @param $piece_length |
||
| 477 | * @param bool $last |
||
| 478 | * |
||
| 479 | * @return bool|string |
||
| 480 | * |
||
| 481 | * @throws Exception |
||
| 482 | */ |
||
| 483 | private function pieces($handle, $piece_length, $last = true) |
||
| 484 | { |
||
| 485 | static $piece, $length; |
||
| 486 | if (empty($length)) { |
||
| 487 | $length = $piece_length; |
||
| 488 | } |
||
| 489 | $pieces = null; |
||
| 490 | while (!feof($handle)) { |
||
| 491 | if (($length = strlen($piece .= fread($handle, $length))) == $piece_length) { |
||
| 492 | $pieces .= FileSystem::pack($piece); |
||
| 493 | } elseif (($length = $piece_length - $length) < 0) { |
||
| 494 | throw new Exception('Invalid piece length!'); |
||
| 495 | } |
||
| 496 | } |
||
| 497 | fclose($handle); |
||
| 498 | return $pieces . ($last && $piece ? FileSystem::pack($piece) : null); |
||
| 499 | } |
||
| 500 | |||
| 501 | /** |
||
| 502 | * @param $file |
||
| 503 | * @param $piece_length |
||
| 504 | * |
||
| 505 | * @return array|bool |
||
| 506 | */ |
||
| 507 | protected function file($file, $piece_length) |
||
| 508 | { |
||
| 509 | |||
| 510 | if (FileSystem::is_url($file)) { |
||
| 511 | $this->urlList($file); |
||
| 512 | } |
||
| 513 | $path = explode(DIRECTORY_SEPARATOR, $file); |
||
| 514 | return array( |
||
| 515 | 'length' => FileSystem::filesize($file), |
||
| 516 | 'name' => end($path), |
||
| 517 | 'piece length' => $piece_length, |
||
| 518 | 'pieces' => $this->pieces(self::fopen($file), $piece_length) |
||
| 519 | ); |
||
| 520 | } |
||
| 521 | |||
| 522 | /** |
||
| 523 | * @param $files |
||
| 524 | * @param $piece_length |
||
| 525 | * |
||
| 526 | * @return array |
||
| 527 | * |
||
| 528 | * @throws Exception |
||
| 529 | */ |
||
| 530 | protected function files($files, $piece_length) |
||
| 531 | { |
||
| 532 | if (!FileSystem::is_url(current($files))) { |
||
| 533 | $files = array_map('realpath', $files); |
||
| 534 | } |
||
| 535 | sort($files); |
||
| 536 | usort($files, |
||
| 537 | create_function('$a,$b', 'return strrpos($a,DIRECTORY_SEPARATOR)-strrpos($b,DIRECTORY_SEPARATOR);')); |
||
| 538 | $first = current($files); |
||
| 539 | $root = dirname($first); |
||
| 540 | if ($url = FileSystem::is_url($first)) { |
||
| 541 | $this->urlList(dirname($root) . DIRECTORY_SEPARATOR); |
||
| 542 | } |
||
| 543 | $path = explode(DIRECTORY_SEPARATOR, dirname($url ? $first : realpath($first))); |
||
| 544 | $pieces = null; |
||
| 545 | $info_files = array(); |
||
| 546 | $count = count($files) - 1; |
||
| 547 | foreach ($files as $i => $file) { |
||
| 548 | if ($path != array_intersect_assoc($file_path = explode(DIRECTORY_SEPARATOR, $file), $path)) { |
||
| 549 | throw new Exception('Files must be in the same folder: "' . $file . '" discarded'); |
||
| 550 | } |
||
| 551 | $pieces .= $this->pieces(self::fopen($file), $piece_length, $count == $i); |
||
| 552 | $info_files[] = array( |
||
| 553 | 'length' => FileSystem::filesize($file), |
||
| 554 | 'path' => array_values(array_diff($file_path, $path)) |
||
| 555 | ); |
||
| 556 | } |
||
| 557 | return array( |
||
| 558 | 'files' => $info_files, |
||
| 559 | 'name' => end($path), |
||
| 560 | 'piece length' => $piece_length, |
||
| 561 | 'pieces' => $pieces |
||
| 562 | ); |
||
| 563 | } |
||
| 564 | |||
| 565 | /** |
||
| 566 | * @param $dir |
||
| 567 | * @param $piece_length |
||
| 568 | * |
||
| 569 | * @return array |
||
| 570 | */ |
||
| 571 | protected function folder($dir, $piece_length) |
||
| 572 | { |
||
| 573 | return $this->files(FileSystem::scandir($dir), $piece_length); |
||
| 574 | } |
||
| 575 | |||
| 576 | /** |
||
| 577 | * @param $filename |
||
| 578 | * |
||
| 579 | * @return bool|resource |
||
| 580 | * |
||
| 581 | * @throws Exception |
||
| 582 | */ |
||
| 583 | public static function fopen($filename) |
||
| 584 | { |
||
| 585 | if (!$handle = fopen($filename, 'r')) { |
||
| 586 | throw new Exception('Failed to open file: "' . $filename . '"'); |
||
| 587 | } |
||
| 588 | |||
| 589 | return $handle; |
||
| 590 | } |
||
| 591 | |||
| 592 | |||
| 593 | } |
||
| 594 |