Changeset 84
- Timestamp:
- 12.06.2008 11:52:16 (7 months ago)
- Files:
-
- 1 added
- 10 modified
- 2 copied
-
tags/2.2.0 (copied) (copied from trunk2)
-
tags/2.2.0/package2.xml (copied) (copied from trunk2/package2.xml)
-
trunk/File/Bittorrent/Decode.php (modified) (20 diffs)
-
trunk/File/Bittorrent/Encode.php (modified) (4 diffs)
-
trunk/File/Bittorrent/Exception.php (added)
-
trunk/File/Bittorrent/MakeTorrent.php (modified) (18 diffs)
-
trunk/Tests/FileBittorrent.php (modified) (2 diffs)
-
trunk/example.php (modified) (2 diffs)
-
trunk/example_mktorrent.php (modified) (1 diff)
-
trunk/infohash.php (modified) (1 diff)
-
trunk/package2.xml (modified) (1 diff)
-
trunk/scrape.php (modified) (2 diffs)
-
trunk/torrentinfo.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/File/Bittorrent/Decode.php
r76 r84 48 48 */ 49 49 require_once 'PEAR.php'; 50 require_once 'PHP/Compat.php';51 50 require_once 'File/Bittorrent/Encode.php'; 52 53 /** 54 * Load replacement functions 55 */ 56 PHP_Compat::loadFunction('file_get_contents'); 51 require_once 'File/Bittorrent/Exception.php'; 57 52 58 53 /** … … 81 76 * @var string Name of the torrent 82 77 */ 83 var$name = '';78 protected $name = ''; 84 79 85 80 /** 86 81 * @var string Filename of the torrent 87 82 */ 88 var$filename = '';83 protected $filename = ''; 89 84 90 85 /** 91 86 * @var string Comment 92 87 */ 93 var$comment = '';88 protected $comment = ''; 94 89 95 90 /** 96 91 * @var int Creation date as unix timestamp 97 92 */ 98 var$date = 0;93 protected $date = 0; 99 94 100 95 /** 101 96 * @var array Files in the torrent 102 97 */ 103 var$files = array();98 protected $files = array(); 104 99 105 100 /** 106 101 * @var int Size of of the full torrent (after download) 107 102 */ 108 var$size = 0;103 protected $size = 0; 109 104 110 105 /** 111 106 * @var string Signature of the software which created the torrent 112 107 */ 113 var$created_by = '';108 protected $created_by = ''; 114 109 115 110 /** 116 111 * @var string tracker (the tracker the torrent has been received from) 117 112 */ 118 var$announce = '';113 protected $announce = ''; 119 114 120 115 /** 121 116 * @var array List of known trackers for the torrent 122 117 */ 123 var$announce_list = array();118 protected $announce_list = array(); 124 119 125 120 /** 126 121 * @var string Source string 127 * @access private 128 */ 129 var $_source = ''; 122 */ 123 protected $source = ''; 130 124 131 125 /** 132 126 * @var int Source length 133 * @access private 134 */ 135 var $_source_length = 0; 127 */ 128 protected $source_length = 0; 136 129 137 130 /** 138 131 * @var int Current position of the string 139 * @access private 140 */ 141 var $_position = 0; 132 */ 133 protected $position = 0; 142 134 143 135 /** 144 136 * @var string Info hash 145 137 */ 146 var $info_hash; 147 148 /** 149 * @var mixed The last error object or null if no error has occurred. 150 */ 151 var $last_error; 138 protected $info_hash; 152 139 153 140 /** 154 141 * @var array Decoded data from File_Bittorrent_Decode::decodeFile() 155 142 */ 156 var$decoded = array();143 protected $decoded = array(); 157 144 158 145 /** … … 161 148 * @param string 162 149 * @return mixed 150 * @throws File_Bittorrent_Exception if decoded data contains trailing garbage 163 151 */ 164 152 function decode($str) 165 153 { 166 $this->_source = $str; 167 $this->_position = 0; 168 $this->_source_length = strlen($this->_source); 169 $result = $this->_bdecode(); 170 if ($this->_position < $this->_source_length) { 171 $this->last_error = PEAR::raiseError('File_Bittorrent_Decode::decode() - Trailing garbage in file.'); 172 return false; 154 $this->source = $str; 155 $this->position = 0; 156 $this->source_length = strlen($this->source); 157 $result = $this->bdecode(); 158 if ($this->position < $this->source_length) { 159 throw new File_Bittorrent_Exception('Trailing garbage in file.', File_Bittorrent_Exception::decode); 173 160 } 174 161 return $result; … … 180 167 * @param string Filename 181 168 * @return mixed Returns an arrayon success or false on error 169 * @throws File_Bittorrent_Exception if no file given or bencoded data is corrupt 182 170 */ 183 171 function decodeFile($file) … … 185 173 // Check file 186 174 if (!is_file($file)) { 187 $this->last_error = PEAR::raiseError('File_Bittorrent_Decode::decode() - Not a file.', null, null, "Given filename '$file' is not a valid file."); 188 return false; 175 throw new File_Bittorrent_Exception('Given filename \'' . $file . '\' is not a valid file.', File_Bittorrent_Exception::source); 189 176 } 190 177 … … 199 186 $this->announce = ''; 200 187 $this->announce_list = array(); 201 $this-> _position = 0;188 $this->position = 0; 202 189 $this->info_hash = ''; 203 190 204 191 // Decode .torrent 205 $this-> _source = file_get_contents($file);206 $this-> _source_length = strlen($this->_source);207 $this->decoded = $this-> _bdecode();192 $this->source = file_get_contents($file); 193 $this->source_length = strlen($this->source); 194 $this->decoded = $this->bdecode(); 208 195 if (!is_array($this->decoded)) { 209 $this->last_error = PEAR::raiseError('File_Bittorrent_Decode::decode() - Corrupted bencoded data.', null, null, "Failed to decode data from file '$file'."); 210 return false; 196 throw new File_Bittorrent_Exception('Corrupted bencoded data. Failed to decode data from file \'$file\'.', File_Bittorrent_Exception::decode); 211 197 } 212 198 … … 281 267 'announce' => $this->announce, 282 268 'announce_list' => $this->announce_list, 269 'info_hash' => $this->info_hash, 283 270 ); 284 271 } … … 287 274 * Decode a BEncoded String 288 275 * 289 * @access private290 276 * @return mixed Returns the representation of the data in the BEncoded string or false on error 291 277 */ 292 function _bdecode()293 { 294 switch ($this-> _getChar()) {278 protected function bdecode() 279 { 280 switch ($this->getChar()) { 295 281 case 'i': 296 $this-> _position++;297 return $this-> _decode_int();282 $this->position++; 283 return $this->decode_int(); 298 284 break; 299 285 case 'l': 300 $this-> _position++;301 return $this-> _decode_list();286 $this->position++; 287 return $this->decode_list(); 302 288 break; 303 289 case 'd': 304 $this-> _position++;305 return $this-> _decode_dict();290 $this->position++; 291 return $this->decode_dict(); 306 292 break; 307 293 default: 308 return $this-> _decode_string();294 return $this->decode_string(); 309 295 } 310 296 } … … 318 304 * would bEncode to d3:key5:value7:Monduna3:com3:bit:8:Torrents6:numberi7ee 319 305 * 320 * @access private321 306 * @return array 322 */ 323 function _decode_dict() 307 * @throws File_Bittorrent_Exception if bencoded dictionary contains invalid data 308 */ 309 protected function decode_dict() 324 310 { 325 311 $return = array(); 326 312 $ended = false; 327 313 $lastkey = NULL; 328 while ($char = $this-> _getChar()) {314 while ($char = $this->getChar()) { 329 315 if ($char == 'e') { 330 316 $ended = true; … … 332 318 } 333 319 if (!ctype_digit($char)) { 334 $this->last_error = PEAR::raiseError('File_Bittorrent_Decode::_decode_dict() - Invalid dictionary key.'); 335 $return = false; 336 break; 337 } 338 $key = $this->_decode_string(); 320 throw new File_Bittorrent_Exception('Invalid dictionary key.', File_Bittorrent_Exception::decode); 321 } 322 $key = $this->decode_string(); 339 323 if (isset($return[$key])) { 340 $this->last_error = PEAR::raiseError('File_Bittorrent_Decode::_decode_dict() - Duplicate dictionary key.'); 341 $return = false; 342 break; 324 throw new File_Bittorrent_Exception('Duplicate dictionary key.', File_Bittorrent_Exception::decode); 343 325 } 344 326 if ($key < $lastkey) { 345 $this->last_error = PEAR::raiseError('File_Bittorrent_Decode::_decode_dict() - Missorted dictionary key.'); 346 $return = false; 347 break; 348 } 349 $val = $this->_bdecode(); 327 throw new File_Bittorrent_Exception('Missorted dictionary key.', File_Bittorrent_Exception::decode); 328 } 329 $val = $this->bdecode(); 350 330 if ($val === false) { 351 $this->last_error = PEAR::raiseError('File_Bittorrent_Decode::_decode_dict() - Invalid value.'); 352 $return = false; 353 break; 331 throw new File_Bittorrent_Exception('Invalid value.', File_Bittorrent_Exception::decode); 354 332 } 355 333 $return[$key] = $val; … … 357 335 } 358 336 if (!$ended) { 359 $this->last_error = PEAR::raiseError('File_Bittorrent_Decode::_decode_dict() - Unterminated dictionary.'); 360 $return = false; 361 } 362 $this->_position++; 337 throw new File_Bittorrent_Exception('Unterminated dictionary.', File_Bittorrent_Exception::decode); 338 } 339 $this->position++; 363 340 return $return; 364 341 } … … 371 348 * would bEncode to 11:BitTorrents. 372 349 * 373 * @access private374 350 * @return string|false 375 */ 376 function _decode_string() 351 * @throws File_Bittorrent_Exception if bencoded data is invalid 352 */ 353 protected function decode_string() 377 354 { 378 355 // Check for bad leading zero 379 if (substr($this->_source, $this->_position, 1) == '0' and 380 substr($this->_source, $this->_position + 1, 1) != ':') { 381 $this->last_error = PEAR::raiseError('File_Bittorrent_Decode::_decode_string() - Leading zero in string length.'); 382 return false; 356 if (substr($this->source, $this->position, 1) == '0' and 357 substr($this->source, $this->position + 1, 1) != ':') { 358 throw new File_Bittorrent_Exception('Leading zero in string length.', File_Bittorrent_Exception::decode); 383 359 } 384 360 // Find position of colon 385 361 // Supress error message if colon is not found which may be caused by a corrupted or wrong encoded string 386 if (!$pos_colon = @strpos($this->_source, ':', $this->_position)) { 387 $this->last_error = PEAR::raiseError('File_Bittorrent_Decode::_decode_string() - Colon not found.'); 388 return false; 362 if (!$pos_colon = @strpos($this->source, ':', $this->position)) { 363 throw new File_Bittorrent_Exception('Colon not found.', File_Bittorrent_Exception::decode); 389 364 } 390 365 // Get length of string 391 $str_length = intval(substr($this->_source, $this->_position, $pos_colon)); 392 if ($str_length + $pos_colon + 1 > $this->_source_length) { 393 $this->last_error = PEAR::raiseError('File_Bittorrent_Decode::_decode_string() - Input too short for string length.'); 394 return false; 366 $str_length = intval(substr($this->source, $this->position, $pos_colon)); 367 if ($str_length + $pos_colon + 1 > $this->source_length) { 368 throw new File_Bittorrent_Exception('Input too short for string length.', File_Bittorrent_Exception::decode); 395 369 } 396 370 // Get string … … 398 372 $return = ''; 399 373 } else { 400 $return = substr($this-> _source, $pos_colon + 1, $str_length);374 $return = substr($this->source, $pos_colon + 1, $str_length); 401 375 } 402 376 // Move Pointer after string 403 $this-> _position = $pos_colon + $str_length + 1;377 $this->position = $pos_colon + $str_length + 1; 404 378 return $return; 405 379 } … … 412 386 * i-3272002e. 413 387 * 414 * @access private415 388 * @return int 416 */ 417 function _decode_int() 418 { 419 $pos_e = strpos($this->_source, 'e', $this->_position); 420 $p = $this->_position; 389 * @throws File_Bittorrent_Exception if bencoded data is invalid 390 */ 391 protected function decode_int() 392 { 393 $pos_e = strpos($this->source, 'e', $this->position); 394 $p = $this->position; 421 395 if ($p === $pos_e) { 422 $this->last_error = PEAR::raiseError('File_Bittorrent_Decode::_decode_int() - Empty integer.'); 423 return false; 424 } 425 if (substr($this->_source, $this->_position, 1) == '-') $p++; 426 if (substr($this->_source, $p, 1) == '0' and 427 ($p != $this->_position or $pos_e > $p+1)) { 428 $this->last_error = PEAR::raiseError('File_Bittorrent_Decode::_decode_int() - Leading zero in integer.'); 429 return false; 396 throw new File_Bittorrent_Exception('Empty integer.', File_Bittorrent_Exception::decode); 397 } 398 if (substr($this->source, $this->position, 1) == '-') $p++; 399 if (substr($this->source, $p, 1) == '0' and 400 ($p != $this->position or $pos_e > $p+1)) { 401 throw new File_Bittorrent_Exception('Leading zero in integer.', File_Bittorrent_Exception::decode); 430 402 } 431 403 for ($i = $p; $i < $pos_e-1; $i++) { 432 if (!ctype_digit(substr($this->_source, $i, 1))) { 433 $this->last_error = PEAR::raiseError('File_Bittorrent_Decode::_decode_int() - Non-digit characters in integer.'); 434 return false; 404 if (!ctype_digit(substr($this->source, $i, 1))) { 405 throw new File_Bittorrent_Exception('Non-digit characters in integer.', File_Bittorrent_Exception::decode); 435 406 } 436 407 } … … 438 409 // overflow. The "+ 0" accomplishes exactly that, using the internal casting 439 410 // logic of PHP 440 $return = substr($this-> _source, $this->_position, $pos_e - $this->_position) + 0;441 $this-> _position = $pos_e + 1;411 $return = substr($this->source, $this->position, $pos_e - $this->position) + 0; 412 $this->position = $pos_e + 1; 442 413 return $return; 443 414 } … … 452 423 * would bEncode to li1e7:Mondunai3el3:Sub4:Listee 453 424 * 454 * @access private455 425 * @return array 456 */ 457 function _decode_list() 426 * @throws File_Bittorrent_Exception if bencoded data is invalid 427 */ 428 protected function decode_list() 458 429 { 459 430 $return = array(); 460 $char = $this-> _getChar();431 $char = $this->getChar(); 461 432 $p1 = $p2 = 0; 462 433 if ($char === false) { 463 $this->last_error = PEAR::raiseError('File_Bittorrent_Decode::_decode_list() - Unterminated list.'); 464 return false; 465 } 466 while ($char !== false && substr($this->_source, $this->_position, 1) != 'e') { 467 $p1 = $this->_position; 468 $val = $this->_bdecode(); 469 $p2 = $this->_position; 434 throw new File_Bittorrent_Exception('Unterminated list.', File_Bittorrent_Exception::decode); 435 } 436 while ($char !== false && substr($this->source, $this->position, 1) != 'e') { 437 $p1 = $this->position; 438 $val = $this->bdecode(); 439 $p2 = $this->position; 470 440 // Empty does not work here 471 441 if($p1 == $p2) { 472 $this->last_error = PEAR::raiseError('File_Bittorrent_Decode::_decode_list() - Unterminated list.'); 473 return false; 442 throw new File_Bittorrent_Exception('Unterminated list.', File_Bittorrent_Exception::decode); 474 443 } 475 444 $return[] = $val; 476 445 } 477 $this-> _position++;446 $this->position++; 478 447 return $return; 479 448 } … … 482 451 * Get the char at the current position 483 452 * 484 * @access private485 453 * @return string|false 486 454 */ 487 function _getChar()488 { 489 if (empty($this-> _source)) return false;490 if ($this-> _position >= $this->_source_length) return false;491 return substr($this-> _source, $this->_position, 1);455 protected function getChar() 456 { 457 if (empty($this->source)) return false; 458 if ($this->position >= $this->source_length) return false; 459 return substr($this->source, $this->position, 1); 492 460 } 493 461 … … 496 464 * 497 465 * @return array|false 466 * @throws File_Bittorrent_Exception if allow_url_fopen is disabled or scrape data is invalid 498 467 */ 499 468 function getStats() … … 501 470 // Check if we can access remote data 502 471 if (!ini_get('allow_url_fopen')) { 503 $this->last_error = PEAR::raiseError('File_Bittorrent_Decode::getStats() - "allow_url_fopen" must be enabled.');472 throw new File_Bittorrent_Exception('\'allow_url_fopen\' must be enabled.', File_Bittorrent_Exception::source); 504 473 return false; 505 474 } … … 508 477 $scrape_url = preg_replace('/\/announce$/', '/scrape', $this->announce) . '?info_hash=' . urlencode($packed_hash); 509 478 $scrape_data = file_get_contents($scrape_url); 510 $stats = $this->decode($scrape_data); 511 if (!isset($stats['files'][$packed_hash])) { 512 $this->last_error = PEAR::raiseError('File_Bittorrent_Decode::getStats() - Invalid scrape data: "' . $scrape_data . '"'); 513 return false; 514 } 479 try { 480 $stats = $this->decode($scrape_data); 481 } catch (File_Bittorrent_Exception $e) { 482 throw new File_Bittorrent_Exception('Invalid scrape data: \'' . $scrape_data . '\'', File_Bittorrent_Exception::decode); 483 } 484 if (!isset($stats['files'][$packed_hash])) { 485 throw new File_Bittorrent_Exception('Invalid scrape data: \'' . $scrape_data . '\'', File_Bittorrent_Exception::decode); 486 } 515 487 return $stats['files'][$packed_hash]; 516 488 } 489 490 /** 491 * Returns the Name of the torrent 492 * 493 * @return string 494 */ 495 function getName() 496 { 497 return $this->name; 498 } 499 500 /** 501 * Returns the Filename of the torrent 502 * 503 * @return string 504 */ 505 function getFilename() 506 { 507 return $this->filename; 508 } 509 510 /** 511 * Returns the Comment of the torrent 512 * 513 * @return string 514 */ 515 function getComment() 516 { 517 return $this->comment; 518 } 519 520 /** 521 * Returns the Date of the torrent 522 * 523 * @return string 524 */ 525 function getDate() 526 { 527 return $this->date; 528 } 529 530 /** 531 * Returns the Creator info of the torrent 532 * 533 * @return string 534 */ 535 function getCreator() 536 { 537 return $this->created_by; 538 } 539 540 /** 541 * Returns the Files of the torrent 542 * 543 * @return array 544 */ 545 function getFiles() 546 { 547 return $this->files; 548 } 549 550 /** 551 * Returns the the tracker the torrent has been received from 552 * 553 * @return string 554 */ 555 function getAnnounce() 556 { 557 return $this->announce; 558 } 559 560 /** 561 * Returns the known tracker list of the torrent 562 * 563 * @return array 564 */ 565 function getAnnounceList() 566 { 567 return $this->announe_list; 568 } 569 570 /** 571 * Returns the info hash of the torrent 572 * 573 * @return string 574 */ 575 function getInfoHash() 576 { 577 return $this->info_hash; 578 } 517 579 } 518 580 -
trunk/File/Bittorrent/Encode.php
r76 r84 46 46 */ 47 47 require_once 'PEAR.php'; 48 require_once 'File/Bittorrent/Exception.php'; 48 49 49 50 /** … … 72 73 * @param mixed Variable to encode 73 74 * @return string 75 * @throws File_Bittorrent_Exception if unsupported type should be encoded 74 76 */ 75 77 function encode($mixed) … … 86 88 return $this->encode_array($mixed); 87 89 default: 88 PEAR::raiseError('File_Bittorrent_Encode::encode() - Unsupported type.', null, null, "Variable must be one of 'string', 'integer', 'double' or 'array'");90 throw new File_Bittorrent_Exception('Unsupported type. Variable must be one of \'string\', \'integer\', \'double\' or \'array\'', File_Bittorrent_Exception::encode); 89 91 } 90 92 } … … 139 141 * @return string 140 142 */ 141 function encode_array( $array)143 function encode_array(array $array) 142 144 { 143 145 // Check for strings in the keys -
trunk/File/Bittorrent/MakeTorrent.php
r76 r84 42 42 require_once 'PEAR.php'; 43 43 require_once 'File/Bittorrent/Encode.php'; 44 require_once 'File/Bittorrent/Exception.php'; 44 45 45 46 /** … … 58 59 /** 59 60 * @var string Path to the file or directory to create the torrent from. 60 * @access private 61 */ 62 var $_path = ''; 61 */ 62 protected $path = ''; 63 63 64 64 /** 65 65 * @var bool Whether or not $path is a file 66 * @access private 67 */ 68 var $_is_file = false; 66 */ 67 protected $is_file = false; 69 68