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

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