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