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.

bencodetorrent.class.php 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. <?php
  2. # todo: Replace this with https://github.com/OPSnet/bencode-torrent
  3. /**
  4. * Torrent class that contains some convenient functions related to torrent meta data
  5. */
  6. class BencodeTorrent extends BencodeDecode
  7. {
  8. private $PathKey = 'path';
  9. public $Files = [];
  10. public $Size = 0;
  11. /**
  12. * Create a list of the files in the torrent and their sizes as well as the total torrent size
  13. *
  14. * @return array with a list of files and file sizes
  15. */
  16. public function file_list()
  17. {
  18. if (empty($this->Dec)) {
  19. return false;
  20. }
  21. $InfoDict =& $this->Dec['info'];
  22. if (!isset($InfoDict['files'])) {
  23. // Single-file torrent
  24. $this->Size = (Int64::is_int($InfoDict['length'])
  25. ? Int64::get($InfoDict['length'])
  26. : $InfoDict['length']);
  27. $Name = (isset($InfoDict['name.utf-8'])
  28. ? $InfoDict['name.utf-8']
  29. : $InfoDict['name']);
  30. $this->Files[] = array($this->Size, $Name);
  31. } else {
  32. if (isset($InfoDict['path.utf-8']['files'][0])) {
  33. $this->PathKey = 'path.utf-8';
  34. }
  35. foreach ($InfoDict['files'] as $File) {
  36. $TmpPath = [];
  37. foreach ($File[$this->PathKey] as $SubPath) {
  38. $TmpPath[] = $SubPath;
  39. }
  40. $CurSize = (Int64::is_int($File['length'])
  41. ? Int64::get($File['length'])
  42. : $File['length']);
  43. $this->Files[] = array($CurSize, implode('/', $TmpPath));
  44. $this->Size += $CurSize;
  45. }
  46. uasort($this->Files, function ($a, $b) {
  47. return strnatcasecmp($a[1], $b[1]);
  48. });
  49. }
  50. return array($this->Size, $this->Files);
  51. }
  52. /**
  53. * Find out the name of the torrent
  54. *
  55. * @return string torrent name
  56. */
  57. public function get_name()
  58. {
  59. if (empty($this->Dec)) {
  60. return false;
  61. }
  62. if (isset($this->Dec['info']['name.utf-8'])) {
  63. return $this->Dec['info']['name.utf-8'];
  64. }
  65. return $this->Dec['info']['name'];
  66. }
  67. /**
  68. * Find out the total size of the torrent
  69. *
  70. * @return string torrent size
  71. */
  72. public function get_size()
  73. {
  74. if (empty($this->Files)) {
  75. if (empty($this->Dec)) {
  76. return false;
  77. }
  78. $FileList = $this->file_list();
  79. }
  80. return $FileList[0];
  81. }
  82. /**
  83. * Checks if the "private" flag is present in the torrent
  84. *
  85. * @return true if the "private" flag is set
  86. */
  87. public function is_private()
  88. {
  89. if (empty($this->Dec)) {
  90. return false;
  91. }
  92. return isset($this->Dec['info']['private']) && Int64::get($this->Dec['info']['private']) == 1;
  93. }
  94. /**
  95. * Add the "private" flag to the torrent
  96. *
  97. * @return true if a change was required
  98. */
  99. public function make_private()
  100. {
  101. if (empty($this->Dec)) {
  102. return false;
  103. }
  104. if ($this->is_private()) {
  105. return false;
  106. }
  107. $this->Dec['info']['private'] = Int64::make(1);
  108. ksort($this->Dec['info']);
  109. return true;
  110. }
  111. /**
  112. * Add the "source" field to the torrent
  113. *
  114. * @return true if a change was required
  115. */
  116. public function make_sourced()
  117. {
  118. $Sources = Users::get_upload_sources();
  119. if (empty($this->Dec)) {
  120. return false;
  121. }
  122. if (isset($this->Dec['info']['source']) && ($this->Dec['info']['source'] == $Sources[0] || $this->Dec['info']['source'] == $Sources[1])) {
  123. return false;
  124. }
  125. $this->Dec['info']['source'] = $Sources[0];
  126. ksort($this->Dec['info']);
  127. return true;
  128. }
  129. /**
  130. * Calculate the torrent's info hash
  131. *
  132. * @return info hash in hexadecimal form
  133. */
  134. public function info_hash()
  135. {
  136. if (empty($this->Dec) || !isset($this->Dec['info'])) {
  137. return false;
  138. }
  139. return sha1($this->encode(false, 'info'));
  140. }
  141. /**
  142. * Add the announce URL to a torrent
  143. */
  144. public static function add_announce_url($Data, $Url)
  145. {
  146. return 'd8:announce'.strlen($Url).':'.$Url.substr($Data, 1);
  147. }
  148. /**
  149. * Add list of announce URLs to a torrent
  150. */
  151. public static function add_announce_list($Data, $Urls)
  152. {
  153. $r = 'd13:announce-listl';
  154. for ($i = 0; $i < count($Urls); $i++) {
  155. $r .= 'l';
  156. for ($j = 0; $j < count($Urls[$i]); $j++) {
  157. $r .= strlen($Urls[$i][$j]).':'.$Urls[$i][$j];
  158. }
  159. $r .= 'e';
  160. }
  161. return $r.'e'.substr($Data, 1);
  162. }
  163. }