BioTorrents.de’s version of Gazelle
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

bencode.class.php 3.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. <?php
  2. /**
  3. * If we're running a 32bit PHP version, we use small objects to store ints.
  4. * Overhead from the function calls is small enough to not worry about
  5. */
  6. class Int64
  7. {
  8. private $Num;
  9. public function __construct($Val)
  10. {
  11. $this->Num = $Val;
  12. }
  13. public static function make($Val)
  14. {
  15. return PHP_INT_SIZE === 4 ? new Int64($Val) : (int)$Val;
  16. }
  17. public static function get($Val)
  18. {
  19. return PHP_INT_SIZE === 4 ? $Val->Num : $Val;
  20. }
  21. public static function is_int($Val)
  22. {
  23. return is_int($Val) || (is_object($Val) && get_class($Val) === 'Int64');
  24. }
  25. }
  26. /**
  27. * The encode class is simple and straightforward. The only thing to
  28. * note is that empty dictionaries are represented by boolean trues
  29. */
  30. class Bencode
  31. {
  32. private $DefaultKeys = array( // Get rid of everything except these keys to save some space
  33. 'created by', 'creation date', 'encoding', 'info', 'comment');
  34. private $Data;
  35. public $Enc;
  36. /**
  37. * Encode an arbitrary array (usually one that's just been decoded)
  38. *
  39. * @param array $Arg the thing to encode
  40. * @param mixed $Keys string or array with keys in the input array to encode or true to encode everything
  41. * @return bencoded string representing the content of the input array
  42. */
  43. public function encode($Arg = false, $Keys = false)
  44. {
  45. if ($Arg === false) {
  46. $Data =& $this->Dec;
  47. } else {
  48. $Data =& $Arg;
  49. }
  50. if ($Keys === true) {
  51. $this->Data = $Data;
  52. } elseif ($Keys === false) {
  53. $this->Data = array_intersect_key($Data, array_flip($this->DefaultKeys));
  54. } elseif (is_array($Keys)) {
  55. $this->Data = array_intersect_key($Data, array_flip($Keys));
  56. } else {
  57. $this->Data = isset($Data[$Keys]) ? $Data[$Keys] : false;
  58. }
  59. if (!$this->Data) {
  60. return false;
  61. }
  62. $this->Enc = $this->_benc();
  63. return $this->Enc;
  64. }
  65. /**
  66. * Internal encoding function that does the actual job
  67. *
  68. * @return bencoded string
  69. */
  70. private function _benc()
  71. {
  72. if (!is_array($this->Data)) {
  73. if (Int64::is_int($this->Data)) { // Integer
  74. return 'i'.Int64::get($this->Data).'e';
  75. }
  76. if ($this->Data === true) { // Empty dictionary
  77. return 'de';
  78. }
  79. return strlen($this->Data).':'.$this->Data; // String
  80. }
  81. if (empty($this->Data) || Int64::is_int(key($this->Data))) {
  82. $IsDict = false;
  83. } else {
  84. $IsDict = true;
  85. ksort($this->Data); // Dictionaries must be sorted
  86. }
  87. $Ret = $IsDict ? 'd' : 'l';
  88. foreach ($this->Data as $Key => $Value) {
  89. if ($IsDict) {
  90. $Ret .= strlen($Key).':'.$Key;
  91. }
  92. $this->Data = $Value;
  93. $Ret .= $this->_benc();
  94. }
  95. return $Ret.'e';
  96. }
  97. }