Source for file MakeTorrent.php
Documentation is available at MakeTorrent.php
// +----------------------------------------------------------------------+
// | Decode and Encode data in Bittorrent format |
// +----------------------------------------------------------------------+
// | Copyright (C) 2004-2005 |
// | Justin Jones <j.nagash@gmail.com> |
// | Markus Tacker <m@tacker.org> |
// +----------------------------------------------------------------------+
// | This library is free software; you can redistribute it and/or |
// | modify it under the terms of the GNU Lesser General Public |
// | License as published by the Free Software Foundation; either |
// | version 2.1 of the License, or (at your option) any later version. |
// | This library is distributed in the hope that it will be useful, |
// | but WITHOUT ANY WARRANTY; without even the implied warranty of |
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
// | Lesser General Public License for more details. |
// | You should have received a copy of the GNU Lesser General Public |
// | License along with this library; if not, write to the |
// | Free Software Foundation, Inc. |
// | 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
// +----------------------------------------------------------------------+
* Provides a class for making .torrent files
* from a file or directory. Produces virtually
* identical torrent files as btmaketorrent.py
* from Bram Cohen's original BT client.
* @author Justin Jones <j.nagash@gmail.com>
* @author Markus Tacker <m@tacker.org>
* @version $Id: MakeTorrent.php 56 2006-07-02 17:14:17Z m $
* @package File_Bittorrent
* Include required classes
require_once 'File/Bittorrent/Encode.php';
* Provides a class for making .torrent files
* from a file or directory. Produces virtually
* identical torrent files as btmaketorrent.py
* from Bram Cohen's original BT client.
* @author Justin Jones <j.nagash@gmail.com>
* @author Markus Tacker <m@tacker.org>
* @package File_Bittorrent
* @var string Path to the file or directory to create the torrent from.
* @var bool Whether or not $path is a file
* @var bool Where or not $path is a directory
* @var string The .torrent announce URL
* @var array The .torrent announce_list extension
var $_announce_list = array ();
* @var string The .torrent comment
* @var string The .torrent created by string
var $_created_by = 'File_Bittorrent_MakeTorrent $Rev: 56 $. http://pear.php.net/package/File_Bittorrent';
* @var string The .torrent suggested name (file/dir)
* @var string The .torrent packed piece data
* @var int The size of each piece in bytes.
var $_piece_length = 524288;
* @var array The list of files (if this is a multi-file torrent)
* @var string|falseThe data gap used to join two files into the same piece. string if it contains data or false
* @var resource file pointer
* @var mixed The last error object or null if no error has occurred.
* Sets up the path to the file/dir to create
* @param string Path to use
* Function to set the announce URL for
* @param string announce url
$this->_announce = strval($announce);
* Function to set the announce list for
* @param array announce list
$this->last_error = PEAR ::raiseError (__CLASS__ . '::'. __FUNCTION__ . '() - No array given.');
$this->_announce_list = $announce_list;
* Function to set the comment for the
$this->_comment = strval($comment);
* Function to set the path for the
* file/dir to make the .torrent for
* Can also be set through the constructor.
* @param string path to file/dir
* Function to set the piece length for
* min: 32 (32KB), max: 4096 (4MB)
* @param int piece length in kilobytes
if ($piece_length < 32 or $piece_length > 4096 ) {
$this->last_error = PEAR ::raiseError (__CLASS__ . '::'. __FUNCTION__ . '() - Invalid piece lenth: "' . $piece_length . '"');
$this->_piece_length = $piece_length * 1024;
* Function to build the .torrent file
* based on the parameters you have set
* with the set* functions.
* @return mixed false on failure or a string containing the metainfo
if (!$info = $this->_addFile ($this->_path)) {
if (!$metainfo = $this->_encodeTorrent ($info)) {
} else if ($this->_is_dir) {
if (!$diradd_ok = $this->_addDir ($this->_path)) {
$metainfo = $this->_encodeTorrent ();
$this->last_error = PEAR ::raiseError (__CLASS__ . '::'. __FUNCTION__ . '() - You must provide a file or directory.');
* Internal function which bencodes the data
* into a valid torrent metainfo string
* @return mixed false on failure or the bencoded metainfo string
function _encodeTorrent ($info = array ())
$bencdata['info'] = array ();
$bencdata['info']['length'] = $info['length'];
$bencdata['info']['md5sum'] = $info['md5sum'];
} else if ($this->_is_dir) {
if ($this->_data_gap !== false ) {
$this->_pieces .= pack('H*', sha1($this->_data_gap));
$this->_data_gap = false;
$bencdata['info']['files'] = $this->_files;
$this->last_error = PEAR ::raiseError (__CLASS__ . '::'. __FUNCTION__ . '() - Use ' . __CLASS__ . '::setPath() to define a file or directory.');
$bencdata['info']['name'] = $this->_name;
$bencdata['info']['piece length'] = $this->_piece_length;
$bencdata['info']['pieces'] = $this->_pieces;
$bencdata['announce'] = $this->_announce;
$bencdata['creation date'] = time();
$bencdata['comment'] = $this->_comment;
$bencdata['created by'] = $this->_created_by;
// $bencdata['announce-list'] = array($this->_announce)
return $Encoder->encode_array ($bencdata);
* Internal function which generates
* metainfo data for a file
* @param string path to the file
* @return mixed false on failure or file metainfo data
if (!$this->_openFile ($file)) {
$this->last_error = PEAR ::raiseError (__CLASS__ . '::'. __FUNCTION__ . " () - Failed to open file '$file'." );
while (!feof($this->_fp)) {
if ($this->_is_dir && $this->_data_gap !== false ) {
$data = $this->_data_gap;
$this->_data_gap = false;
while (!feof($this->_fp) && ($datalength < $this->_piece_length)) {
if (($datalength + 8192 ) > $this->_piece_length) {
$readlength = $this->_piece_length - $datalength;
$tmpdata = fread($this->_fp, $readlength);
$actual_readlength = strlen($tmpdata);
$datalength += $actual_readlength;
$filelength += $actual_readlength;
// We've either reached the end of the file, or
// we have a whole piece, or both.
if ($datalength == $this->_piece_length) {
$this->_pieces .= pack('H*', sha1($data));
if (($datalength != $this->_piece_length) && feof($this->_fp)) {
// We've reached the end of the file, and
// we dont have a whole piece.
$this->_data_gap = $data;
$this->_pieces .= pack('H*', sha1($data));
// Close the file pointer.
* Internal function which iterates through
* directories and subdirectories, using
* _addFile for each file it finds.
* @param string path to the directory
$filelist = $this->_dirList ($path);
foreach ($filelist as $file) {
$filedata = $this->_addFile ($file);
if ($filedata !== false ) {
$filedata['path'] = array ();
while (basename($dirname) != $this->_name) {
$filedata['path'][] = basename($dirname);
$this->_files[] = $filedata;
* Internal function which recurses through
* subdirectory and returns an array of file paths
* @param string path to the directory
* @return array file list
while ( ($file = readdir($dh)) !== false ) {
if ($file{0 } == '.') continue;
$current_file = $current_dir . '/' . $file;
$file_list[] = $current_dir . '/' . $file;
} else if (is_dir($current_file)) {
$stack[] = $current_file;
* Internal function to get the filesize
* of a file. Workaround for files >2GB.
* @param string path to the file
* @return int the filesize
function _filesize ($file)
if (PHP_OS != 'Linux') return false;
* Internal function to open a file.
* Workaround for files >2GB using popen
* @param string path to the file
function _openFile ($file)
$fsize = $this->_filesize ($file);
if ($fsize <= 2*1024*1024*1024 ) {
if (!$this->_fp = fopen($file, 'r')) {
$this->last_error = PEAR ::raiseError (__CLASS__ . '::'. __FUNCTION__ . '() - Failed to open "' . $file . '"');
$this->last_error = PEAR ::raiseError (__CLASS__ . '::'. __FUNCTION__ . '() - File size is greater than 2GB. This is only supported under Linux.');
* Internal function to close a file pointer
Documentation generated on Tue, 13 Mar 2007 10:00:14 -0500 by phpDocumentor 1.3.0. PEAR Logo Copyright © PHP Group 2004.
|