16 Commits
11 changed files with 307 additions and 207 deletions

No files matched your search

+46
View File
@@ -0,0 +1,46 @@
name: Test
on:
push:
branches: [ '*' ]
pull_request:
branches: [ '*' ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
php-version: ['7.2', '7.3', '7.4', '8.0']
steps:
- uses: actions/checkout@v2
- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
tools: composer, pecl
coverage: pcov
- name: Validate composer.json and composer.lock
run: composer validate
- name: Cache Composer packages
id: composer-cache
uses: actions/cache@v2
with:
path: vendor
key: ${{ runner.os }}-${{ matrix.php-version }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: |
${{ runner.os }}-${{ matrix.php-version }}-composer-
${{ runner.os }}-composer-
- name: Install dependencies
if: steps.composer-cache.outputs.cache-hit != 'true'
run: composer install --prefer-dist --no-progress --no-suggest
- run: composer lint
- run: composer stan
- run: composer test
+1
View File
@@ -3,3 +3,4 @@ report/
vendor/
.DS_Store
composer.lock
.phpunit.result.cache
-26
View File
@@ -1,26 +0,0 @@
language: php
sudo: true
dist: trusty
php:
- '7.0'
- '7.1'
- '7.2'
- nightly
matrix:
fast_finish: true
allow_failures:
- php: nightly
cache:
directories:
- $HOME/.composer/cache
install:
- composer install
script:
- vendor/bin/phpunit
- vendor/bin/phpcs src
- vendor/bin/phpcs tests
+15 -9
View File
@@ -1,16 +1,22 @@
BEncode Torrent
===============
[![Build Status](https://travis-ci.org/ApolloRIP/bencode-torrent.svg?branch=master)](https://travis-ci.org/ApolloRIP/bencode-torrent)
[![Packagist](https://img.shields.io/packagist/v/apollorip/bencode-torrent.svg)](https://packagist.org/packages/apollorip/bencode-torrent)
![PHP from Travis config](https://img.shields.io/travis/php-v/ApolloRIP/bencode-torrent.svg)
[![Test](https://github.com/OPSnet/bencode-torrent/workflows/Test/badge.svg?branch=master&event=push)](https://github.com/OPSnet/bencode-torrent/actions?query=workflow%3ATest+branch%3Amaster+event%3Apush)
[![Packagist](https://img.shields.io/packagist/v/orpheusnet/bencode-torrent.svg)](https://packagist.org/packages/orpheusnet/bencode-torrent)
![Packagist PHP Version Support](https://img.shields.io/packagist/php-v/orpheusnet/bencode-torrent)
PHP library for encoding and decoding BitTorrent BEncode data, focused around
[Gazelle](https://github.com/ApolloRIP/Gazelle).
PHP library for encoding and decoding BitTorrent BEncode data, focused around usage within
[Gazelle](https://github.com/OPSnet/Gazelle).
Usage
-----
`composer require apollorip/bencode-torrent`
`composer require orpheusnet/bencode-torrent`
```php
use OrpheusNET\BencodeTorrent;
$bencode = new Bencode();
$bencode->decodeFile('path/to/file.torrent');
```
Description
-----------
@@ -34,7 +40,7 @@ As such, this library will make some checks when loading data that these mandato
raised. More information on these fields can be found at
[BitTorrentSpecification#Metainfo_File_Structure](https://wiki.theory.org/index.php/BitTorrentSpecification#Metainfo_File_Structure).
Finally, this library is primarily aimed at being used within the [Gazelle](https://github.com/ApolloRIP/Gazelle) so
Finally, this library is primarily aimed at being used within the [Gazelle](https://github.com/OPSnet/Gazelle) so
we have some utility functions within the library that make sense there to accomplish the following things:
* Ensuring torrent files are marked as 'private'
* Setting a 'source' on torrents (to ensure unique info hash)
@@ -43,5 +49,5 @@ we have some utility functions within the library that make sense there to accom
This is based (loosely) off the code in the two separate BEncode libraries within WCD's Gazelle
([bencodetorrent.class.php](https://github.com/WhatCD/Gazelle/blob/master/classes/bencodetorrent.class.php) and
[torrent.class.php](https://github.com/WhatCD/Gazelle/blob/master/classes/torrent.class.php)), but without the
necessary 32bit shims as well as make it a unified library used for both uploading and downloading the torrent files.
[torrent.class.php](https://github.com/WhatCD/Gazelle/blob/master/classes/torrent.class.php)), but without the now
unnecessary 32bit shims as well as making it a unified library used for both uploading and downloading the torrent files.
+15 -8
View File
@@ -1,24 +1,31 @@
{
"type": "library",
"name": "apollorip/bencode-torrent",
"name": "orpheusnet/bencode-torrent",
"description": "PHP Library for decoding and encoding BitTorrent BEncoded data, built for Gazelle",
"license": "Unlicense",
"authors": [
{
"name": "itismadness",
"email": "[email protected]"
"name": "Orpheus",
"email": "[email protected]"
}
],
"autoload": {
"psr-4": {
"ApolloRIP\\BencodeTorrent\\": "src/"
"OrpheusNET\\BencodeTorrent\\": "src/"
}
},
"require": {},
"require": {
"php": ">=7.2"
},
"require-dev": {
"phpunit/phpunit": "^6",
"phpunit/phpunit": "^8",
"squizlabs/php_codesniffer": "3.*",
"php": "^7",
"ext-mbstring": "^7"
"phpstan/phpstan": "^0.12.48"
},
"scripts": {
"test": "phpunit",
"lint": "phpcs",
"lint:fix": "phpcbf",
"stan": "phpstan analyse"
}
}
+5 -36
View File
@@ -1,38 +1,7 @@
<?xml version="1.0"?>
<ruleset name="Gazelle Standard">
<description>The coding standard for the Gazelle project</description>
<ruleset name="PSR12 Standard">
<file>src</file>
<file>tests</file>
<!-- Include the whole PSR-1 standard -->
<rule ref="PSR1"/>
<!-- Include the whole PSR-2 standard -->
<rule ref="PSR2">
<exclude name="PSR2.Classes.ClassDeclaration.OpenBraceNewLine"/>
</rule>
<!-- Do not allow trailing whitespace at the end of lines -->
<rule ref="Squiz.WhiteSpace.SuperfluousWhitespace" />
<rule ref="Squiz.Functions.MultiLineFunctionDeclaration.BraceOnSameLine">
<severity>0</severity>
</rule>
<rule ref="Squiz.ControlStructures.ControlSignature.SpaceAfterCloseBrace">
<severity>0</severity>
</rule>
<rule ref="Generic.Classes.OpeningBraceSameLine"/>
<rule ref="Generic.Functions.OpeningFunctionBraceKernighanRitchie"/>
<!-- Ensure that proper line endings are used -->
<rule ref="Generic.Files.LineEndings">
<properties>
<property name="eolChar" value="\n"/>
</properties>
</rule>
<!-- Increase PHPCS/PEAR limit of 85 chars per line to 100 -->
<rule ref="Generic.Files.LineLength">
<properties>
<property name="lineLimit" value="100"/>
<property name="absoluteLineLimit" value="0"/>
</properties>
</rule>
</ruleset>
<rule ref="PSR12" />
</ruleset>
+5
View File
@@ -0,0 +1,5 @@
parameters:
level: 5
paths:
- src
- tests
+33 -28
View File
@@ -1,16 +1,20 @@
<?php
namespace ApolloRIP\BencodeTorrent;
declare(strict_types=1);
class Bencode {
protected $data = null;
namespace OrpheusNET\BencodeTorrent;
class Bencode
{
/** @var array */
protected $data;
/**
* Sets the internal data array
* @param mixed $data
* @throws \RuntimeException
*/
public function setData($data) {
public function setData($data)
{
$this->data = $data;
}
@@ -19,7 +23,8 @@ class Bencode {
* @param string $data
* @throws \RuntimeException
*/
public function decodeString(string $data) {
public function decodeString(string $data)
{
$this->data = $this->decode($data);
}
@@ -29,8 +34,9 @@ class Bencode {
* @param string $path
* @throws \RuntimeException
*/
public function decodeFile(string $path) {
$this->data = $this->decode(file_get_contents($path, FILE_BINARY));
public function decodeFile(string $path)
{
$this->data = $this->decode(file_get_contents($path));
}
/**
@@ -46,7 +52,8 @@ class Bencode {
* @param int $pos
* @return mixed
*/
protected function decode(string $data, int &$pos = 0) {
protected function decode(string $data, int &$pos = 0)
{
$start_decode = $pos === 0;
if ($data[$pos] === 'd') {
$pos++;
@@ -58,14 +65,13 @@ class Bencode {
break;
}
if (!is_string($key)) {
throw new \RuntimeException('Invalid key type, must be string: '.gettype($key));
throw new \RuntimeException('Invalid key type, must be string: ' . gettype($key));
}
$return[$key] = $value;
}
ksort($return);
$pos++;
}
elseif ($data[$pos] === 'l') {
} elseif ($data[$pos] === 'l') {
$pos++;
$return = [];
while ($data[$pos] !== 'e') {
@@ -73,8 +79,7 @@ class Bencode {
$return[] = $value;
}
$pos++;
}
elseif ($data[$pos] === 'i') {
} elseif ($data[$pos] === 'i') {
$pos++;
$digits = strpos($data, 'e', $pos) - $pos;
$return = substr($data, $pos, $digits);
@@ -87,13 +92,12 @@ class Bencode {
$return = substr($return, 1);
}
if (!ctype_digit($return)) {
$msg = 'Cannot have non-digit values in integer number: '.$return;
$msg = 'Cannot have non-digit values in integer number: ' . $return;
throw new \RuntimeException($msg);
}
$return = $multiplier * ((int) $return);
$pos += $digits + 1;
}
else {
} else {
$digits = strpos($data, ':', $pos) - $pos;
$len = (int) substr($data, $pos, $digits);
$pos += ($digits + 1);
@@ -112,14 +116,16 @@ class Bencode {
* Get the internal data array
* @return mixed
*/
public function getData() {
public function getData()
{
return $this->data;
}
/**
* @throws \RuntimeException
*/
protected function hasData() {
protected function hasData()
{
if ($this->data === null) {
throw new \RuntimeException('Must decode proper bencode string first');
}
@@ -128,7 +134,8 @@ class Bencode {
/**
* @return string
*/
public function getEncode() : string {
public function getEncode(): string
{
$this->hasData();
return $this->encodeVal($this->data);
}
@@ -137,7 +144,8 @@ class Bencode {
* @param mixed $data
* @return string
*/
protected function encodeVal($data) : string {
protected function encodeVal($data): string
{
if (is_array($data)) {
$return = '';
$check = -1;
@@ -154,8 +162,7 @@ class Bencode {
foreach ($data as $value) {
$return .= $this->encodeVal($value);
}
}
else {
} else {
$return .= 'd';
foreach ($data as $key => $value) {
$return .= $this->encodeVal(strval($key));
@@ -163,11 +170,9 @@ class Bencode {
}
}
$return .= 'e';
}
elseif (is_integer($data)) {
$return = 'i'.$data.'e';
}
else {
} elseif (is_integer($data)) {
$return = 'i' . $data . 'e';
} else {
$return = strlen($data) . ':' . $data;
}
return $return;
+77 -45
View File
@@ -1,6 +1,8 @@
<?php
namespace ApolloRip\BencodeTorrent;
declare(strict_types=1);
namespace OrpheusNET\BencodeTorrent;
/**
* BEncode service that allows us to encode PHP objects into BEncode and decode
@@ -24,11 +26,14 @@ namespace ApolloRip\BencodeTorrent;
* For Gazelle, this also acts as a unification of the two original BEncode implementations
* which were both used in separate areas of the codebase.
*/
class BencodeTorrent extends Bencode {
const FILELIST_DELIM = 0xF7;
class BencodeTorrent extends Bencode
{
public const FILELIST_DELIM = 0xF7;
/** @var string */
private static $utf8_filelist_delim = null;
public function __construct() {
public function __construct()
{
$this->setDelim();
}
@@ -37,7 +42,8 @@ class BencodeTorrent extends Bencode {
* and char to set a class constant or variable, so we wait till the class is initialized
* for the first time to set it.
*/
private function setDelim() {
private function setDelim(): void
{
if (self::$utf8_filelist_delim === null) {
self::$utf8_filelist_delim = utf8_encode(chr(self::FILELIST_DELIM));
}
@@ -48,7 +54,8 @@ class BencodeTorrent extends Bencode {
* @param array $data
* @throws \RuntimeException
*/
public function setData($data) {
public function setData($data): void
{
parent::setData($data);
$this->validate();
}
@@ -58,7 +65,8 @@ class BencodeTorrent extends Bencode {
* @param string $data
* @throws \RuntimeException
*/
public function decodeString(string $data) {
public function decodeString(string $data): void
{
parent::decodeString($data);
$this->validate();
}
@@ -69,16 +77,18 @@ class BencodeTorrent extends Bencode {
* @param string $path
* @throws \RuntimeException
*/
public function decodeFile(string $path) {
public function decodeFile(string $path): void
{
parent::decodeFile($path);
$this->validate();
}
/**
* Validates that the internal data array
* @throws \RuntimeException
* @throws \TypeError|\RuntimeException
*/
public function validate() {
public function validate(): void
{
if (!is_array($this->data)) {
throw new \TypeError('Data must be an array');
}
@@ -95,8 +105,8 @@ class BencodeTorrent extends Bencode {
return strlen($element) === 0;
}
);
if (count($filter) > 0) {
throw new \RuntimeException('Cannot have empty path for a file');
if (count($filter) === count($file[$path_key]) && $file['length'] !== 0) {
throw new \RuntimeException('Cannot have a file with no path');
}
}
}
@@ -111,7 +121,8 @@ class BencodeTorrent extends Bencode {
*
* @return bool flag to indicate if we altered the info dictionary
*/
public function clean() : bool {
public function clean(): bool
{
$this->cleanDataDictionary();
return $this->cleanInfoDictionary();
}
@@ -121,7 +132,8 @@ class BencodeTorrent extends Bencode {
* overwritten dynamically on any downloaded torrent (like announce or comment), so that we
* store the smallest encoded string within the database and cuts down on potential waste.
*/
public function cleanDataDictionary() {
public function cleanDataDictionary(): void
{
$allowed_keys = array('encoding', 'info');
foreach ($this->data as $key => $value) {
if (!in_array($key, $allowed_keys)) {
@@ -144,7 +156,8 @@ class BencodeTorrent extends Bencode {
*
* @return bool
*/
public function cleanInfoDictionary() : bool {
public function cleanInfoDictionary(): bool
{
$cleaned = false;
$allowed_keys = array('files', 'name', 'piece length', 'pieces', 'private', 'length',
'name.utf8', 'name.utf-8', 'md5sum', 'sha1', 'source',
@@ -164,7 +177,8 @@ class BencodeTorrent extends Bencode {
*
* @return bool
*/
public function isPrivate() : bool {
public function isPrivate(): bool
{
$this->hasData();
return isset($this->data['info']['private']) && $this->data['info']['private'] === 1;
}
@@ -178,7 +192,8 @@ class BencodeTorrent extends Bencode {
*
* @return bool
*/
public function makePrivate() : bool {
public function makePrivate(): bool
{
$this->hasData();
if ($this->isPrivate()) {
return false;
@@ -194,12 +209,9 @@ class BencodeTorrent extends Bencode {
* 'official' flag (no accepted BEP on it), but it has become the defacto standard with more
* clients supporting it natively. Returns a boolean on whether or not the source was changed
* so that an appropriate screen can be shown to the user.
*
* @param string $source
*
* @return bool true if the source was set/changed, false if no change
*/
public function setSource(string $source) : bool {
public function setSource(string $source): bool
{
$this->hasData();
if (isset($this->data['info']['source']) && $this->data['info']['source'] === $source) {
return false;
@@ -212,15 +224,32 @@ class BencodeTorrent extends Bencode {
return true;
}
/**
* Get the source flag if one has been set
*/
public function getSource(): ?string
{
$this->hasData();
return $this->data['info']['source'] ?? null;
}
/**
* Get the creation date for torrent if one has been set
*/
public function getCreationDate(): ?int
{
$this->hasData();
return $this->data['creation date'] ?? null;
}
/**
* Function to allow you set any number of keys and values in the data dictionary. You can
* set the value in a dictionary by concatenating the keys into a string with a period
* separator (ex: info.name will set name field in the info dictionary) so that the rest
* of the dictionary is unaffected.
*
* @param array $array
*/
public function setValue(array $array) {
public function setValue(array $array): void
{
foreach ($array as $key => $value) {
if (is_array($value)) {
ksort($value);
@@ -253,19 +282,20 @@ class BencodeTorrent extends Bencode {
*
* @return string
*/
public function getInfoHash() : string {
public function getInfoHash(): string
{
$this->hasData();
return sha1($this->encodeVal($this->data['info']));
}
public function getHexInfoHash(): string {
public function getHexInfoHash(): string
{
return pack('H*', $this->getInfoHash());
}
/**
* @return string
*/
public function getName() {
public function getName(): string
{
$this->hasData();
if (isset($this->data['info']['name.utf-8'])) {
return $this->data['info']['name.utf-8'];
}
@@ -276,15 +306,14 @@ class BencodeTorrent extends Bencode {
* Get the total size in bytes of the files in the torrent. For a single file torrent, it'll
* just be the 'length' key in the 'info' dictionary, else we iterate through the 'files' list
* and add up the 'length' of each element.
*
* @return int
*/
public function getSize() : int {
public function getSize(): int
{
$this->hasData();
$cur_size = 0;
if (!isset($this->data['info']['files'])) {
$cur_size = $this->data['info']['length'];
}
else {
} else {
foreach ($this->data['info']['files'] as $file) {
$cur_size += $file['length'];
}
@@ -301,7 +330,8 @@ class BencodeTorrent extends Bencode {
*
* @return array
*/
public function getFileList() : array {
public function getFileList(): array
{
$files = [];
if (!isset($this->data['info']['files'])) {
// Single-file torrent
@@ -310,8 +340,7 @@ class BencodeTorrent extends Bencode {
$this->data['info']['name']);
$size = $this->data['info']['length'];
$files[] = ['path' => $name, 'size' => $size];
}
else {
} else {
$size = 0;
foreach ($this->data['info']['files'] as $file) {
$size += $file['length'];
@@ -328,11 +357,13 @@ class BencodeTorrent extends Bencode {
return array('total_size' => $size, 'files' => $files);
}
public function hasFiles(): bool {
public function hasFiles(): bool
{
return isset($this->data['info']['files']);
}
public function hasEncryptedFiles(): bool {
public function hasEncryptedFiles(): bool
{
return isset($this->data['encrypted_files']);
}
@@ -346,7 +377,8 @@ class BencodeTorrent extends Bencode {
*
* @return array
*/
public function getGazelleFileList() : array {
public function getGazelleFileList(): array
{
$files = [];
foreach ($this->getFileList()['files'] as $file) {
$path = $file['path'];
@@ -368,7 +400,8 @@ class BencodeTorrent extends Bencode {
*
* @return string
*/
private function makeUTF8(string $str) : string {
private function makeUTF8(string $str): string
{
if (preg_match('//u', $str)) {
$encoding = 'UTF-8';
}
@@ -383,8 +416,7 @@ class BencodeTorrent extends Bencode {
// @codeCoverageIgnoreEnd
if ($encoding === 'UTF-8') {
return $str;
}
else {
} else {
return @mb_convert_encoding($str, 'UTF-8', $encoding);
}
}
+22 -17
View File
@@ -1,9 +1,13 @@
<?php
namespace ApolloRip\BencodeTorrent;
declare(strict_types=1);
class BencodeTest extends \PHPUnit\Framework\TestCase {
public function dataProvider() {
namespace OrpheusNET\BencodeTorrent;
class BencodeTest extends \PHPUnit\Framework\TestCase
{
public function dataProvider(): array
{
return [
['i0e', 0],
['i-1e', -1],
@@ -18,50 +22,51 @@ class BencodeTest extends \PHPUnit\Framework\TestCase {
/**
* @dataProvider dataProvider
* @param string $bencoded_string
* @param mixed $expected
*/
public function testDecodeEncode($bencoded_string, $expected) {
public function testDecodeEncode(string $bencoded_string, $expected): void
{
$bencode = new Bencode();
$bencode->decodeString($bencoded_string);
$this->assertEquals($expected, $bencode->getData());
$this->assertEquals($bencoded_string, $bencode->getEncode());
}
public function testEmptyDict() {
public function testEmptyDict(): void
{
$bencode = new Bencode();
$bencode->decodeString('de');
$this->assertEquals([], $bencode->getData());
$this->assertEquals('le', $bencode->getEncode());
}
/**
* @expectedException \RuntimeException
*/
public function testInvalidDictionaryKey() {
public function testInvalidDictionaryKey(): void
{
$bencode = new Bencode();
$this->expectException(\RuntimeException::class);
$bencode->decodeString('di1e5:valuee');
}
public function invalidIntegers() {
public function invalidIntegers(): array
{
return [['-0'], ['a'], ['1.0']];
}
/**
* @param string $value
* @dataProvider invalidIntegers
* @expectedException \RuntimeException
*/
public function testInvalidInteger(string $value) {
public function testInvalidInteger(string $value): void
{
$bencode = new Bencode();
$this->expectException(\RuntimeException::class);
$bencode->decodeString("i{$value}e");
}
/**
* @expectedException \RuntimeException
*/
public function testInvalidString() {
public function testInvalidString(): void
{
$bencode = new Bencode();
$this->expectException(\RuntimeException::class);
$bencode->decodeString('i1e0e');
}
}
+88 -38
View File
@@ -1,14 +1,17 @@
<?php
namespace ApolloRip\BencodeTorrent;
declare(strict_types=1);
class BencodeTorrentTest extends \PHPUnit\Framework\TestCase {
public function testLoadTorrent() {
namespace OrpheusNET\BencodeTorrent;
class BencodeTorrentTest extends \PHPUnit\Framework\TestCase
{
public function testLoadTorrent(): void
{
$bencode = new BencodeTorrent();
try {
$bencode->decodeFile(__DIR__.'/data/test_1.torrent');
}
catch (\Exception $exc) {
$bencode->decodeFile(__DIR__ . '/data/test_1.torrent');
} catch (\Exception $exc) {
$this->fail('Decode should not have thrown exception');
}
$data = $bencode->getData();
@@ -83,11 +86,11 @@ class BencodeTorrentTest extends \PHPUnit\Framework\TestCase {
$this->assertEquals(16020, strlen($data['info']['pieces']));
$this->assertEquals(1, $data['info']['private']);
$this->assertEquals('APL', $data['info']['source']);
$this->assertStringEqualsFile(__DIR__.'/data/test_1.torrent', $bencode->getEncode());
$this->assertStringEqualsFile(__DIR__ . '/data/test_1.torrent', $bencode->getEncode());
$this->assertEquals(104916260, $bencode->getSize());
$this->assertTrue($bencode->isPrivate());
$bencode->decodeString($bencode->getEncode());
$this->assertStringEqualsFile(__DIR__.'/data/test_1.torrent', $bencode->getEncode());
$this->assertStringEqualsFile(__DIR__ . '/data/test_1.torrent', $bencode->getEncode());
$this->assertEquals('1f830103427029a88dd5fde85be74e622ee07951', $bencode->getInfoHash());
$this->assertEquals($bencode->getInfoHash(), unpack('H*', $bencode->getHexInfoHash())[1]);
$this->assertFalse($bencode->hasEncryptedFiles());
@@ -141,9 +144,11 @@ class BencodeTorrentTest extends \PHPUnit\Framework\TestCase {
]
];
$this->assertEquals($file_list, $bencode->getFileList());
$this->assertSame(1425699508, $bencode->getCreationDate());
}
public function testSetData() {
public function testSetData(): void
{
$data = [
'encoding' => 'UTF8',
'info' => [
@@ -175,7 +180,8 @@ class BencodeTorrentTest extends \PHPUnit\Framework\TestCase {
);
}
public function testEmptyDictionary() {
public function testEmptyDictionary(): void
{
$expected = [
'encoding' => 'UTF8',
'info' => [
@@ -187,13 +193,14 @@ class BencodeTorrentTest extends \PHPUnit\Framework\TestCase {
];
$bencode = new BencodeTorrent();
$bencode->decodeString(
'd8:encoding4:UTF84:infod4:name4:test6:lengthi1213134e'.
'd8:encoding4:UTF84:infod4:name4:test6:lengthi1213134e' .
'6:pieces18:fake pieces stringe4:test0:e'
);
$this->assertEquals($expected, $bencode->getData());
}
public function testClean() {
public function testClean(): void
{
$data = [
'encoding' => 'UTF8',
'info' => [
@@ -226,7 +233,8 @@ class BencodeTorrentTest extends \PHPUnit\Framework\TestCase {
$this->assertEquals($data, $bencode->getData());
}
public function testSetPrivate() {
public function testSetPrivate(): void
{
$data = [
'encoding' => 'UTF8',
'info' => [
@@ -246,7 +254,8 @@ class BencodeTorrentTest extends \PHPUnit\Framework\TestCase {
$this->assertEquals(1, $actual['info']['private']);
}
public function testSetAlreadyPrivate() {
public function testSetAlreadyPrivate(): void
{
$data = [
'encoding' => 'UTF8',
'info' => [
@@ -260,7 +269,8 @@ class BencodeTorrentTest extends \PHPUnit\Framework\TestCase {
$this->assertFalse($bencode->makePrivate());
}
public function testSetSource() {
public function testSetSource(): void
{
$data = [
'encoding' => 'UTF8',
'info' => [
@@ -272,14 +282,17 @@ class BencodeTorrentTest extends \PHPUnit\Framework\TestCase {
];
$bencode = new BencodeTorrent();
$bencode->setData($data);
$this->assertNull($bencode->getSource());
$this->assertTrue($bencode->setSource('APL'));
$actual = $bencode->getData();
$this->assertEquals('APL', $actual['info']['source']);
$this->assertSame('APL', $bencode->getSource());
$this->assertFalse($bencode->setSource('APL'));
$this->assertNotContains('unique', $actual['info']);
$this->assertNotContains('x_cross_seed', $actual['info']);
}
public function testSetAlreadySourced() {
public function testSetAlreadySourced(): void
{
$data = [
'encoding' => 'UTF8',
'info' => [
@@ -297,7 +310,8 @@ class BencodeTorrentTest extends \PHPUnit\Framework\TestCase {
$this->assertEquals($data, $bencode->getData());
}
public function testSetDifferentSource() {
public function testSetDifferentSource(): void
{
$data = [
'encoding' => 'UTF8',
'info' => [
@@ -317,7 +331,8 @@ class BencodeTorrentTest extends \PHPUnit\Framework\TestCase {
$this->assertNotContains('x_cross_seed', $actual['info']);
}
public function testSetValue() {
public function testSetValue(): void
{
$data = [
'encoding' => 'UTF8',
'info' => [
@@ -374,7 +389,8 @@ class BencodeTorrentTest extends \PHPUnit\Framework\TestCase {
$this->assertTrue($bencode->hasFiles());
}
public function testGetUtf8Name() {
public function testGetUtf8Name(): void
{
$data = [
'encoding' => 'UTF8',
'info' => [
@@ -403,7 +419,8 @@ class BencodeTorrentTest extends \PHPUnit\Framework\TestCase {
$this->assertEquals(['. s12345s test!! ÷'], $bencode->getGazelleFileList());
}
public function testIso88591Name() {
public function testIso88591Name(): void
{
$data = [
'info' => [
'length' => 1234,
@@ -416,19 +433,16 @@ class BencodeTorrentTest extends \PHPUnit\Framework\TestCase {
$this->assertFalse($bencode->hasFiles());
}
/**
* @expectedException \RuntimeException
*/
public function testInvalidSet() {
public function testInvalidSet(): void
{
$data = ['encoding' => 'UTF8', 'announce' => 'http://localhost:8080/announce'];
$bencode = new BencodeTorrent();
$this->expectException(\RuntimeException::class);
$bencode->setData($data);
}
/**
* @expectedException \RuntimeException
*/
public function testInvalidSetValue() {
public function testInvalidSetValue(): void
{
$data = [
'encoding' => 'UTF8',
'info' => [
@@ -440,28 +454,29 @@ class BencodeTorrentTest extends \PHPUnit\Framework\TestCase {
$bencode = new BencodeTorrent();
$bencode->setData($data);
$this->expectException(\RuntimeException::class);
$bencode->setValue(['info' => []]);
}
/**
* @expectedException \RuntimeException
*/
public function testGetEncodeNoData() {
public function testGetEncodeNoData(): void
{
$bencode = new BencodeTorrent();
$this->expectException(\RuntimeException::class);
$bencode->getEncode();
}
/**
* @expectedException \RuntimeException
*/
public function testInvalidPath() {
public function testEmptyPathPart(): void
{
$data = [
'encoding' => 'UTF8',
'info' => [
'files' => [
0 => [
'length' => 1234,
'path' => ['']
'path' => [
'',
'01 - test test',
]
]
],
'name' => 'test',
@@ -471,5 +486,40 @@ class BencodeTorrentTest extends \PHPUnit\Framework\TestCase {
];
$bencode = new BencodeTorrent();
$bencode->setData($data);
$this->assertSame(
[
'total_size' => 1234,
'files' => [
0 => [
'path' => '/01 - test test',
'size' => 1234,
],
],
],
$bencode->getFileList()
);
}
public function testEmptyPath(): void
{
$data = [
'encoding' => 'UTF8',
'info' => [
'files' => [
0 => [
'length' => 1234,
'path' => [
'',
]
]
],
'name' => 'test',
'length' => 1213134,
'pieces' => 'fake pieces string'
]
];
$bencode = new BencodeTorrent();
$this->expectException(\RuntimeException::class);
$bencode->setData($data);
}
}