Assign new value to variable if unserialize() fail - php

Is there a better or more robust solution to this problem than the one I have found?
$string = "a:1:{s:19:\"is_featured_service\";b:0;}";
$unserialized_string = #unserialize($string);
if ($unserialized_string === false){
$unserialized_string = 'another value';
}

I like this because you don't have to try to supress errors:
/**
* Check value to find if it is serialized data.
*
* Function borrowed from Wordpress.
*
* #param mixed $data Value to check to see if was serialized.
* #return bool False if not serialized and true if it was.
*/
function is_serialized( $data ) {
// if it isn't a string, it isn't serialized
if ( ! is_string( $data ) )
return false;
$data = trim( $data );
if ( 'N;' == $data )
return true;
$length = strlen( $data );
if ( $length < 4 )
return false;
if ( ':' !== $data[1] )
return false;
$lastc = $data[$length-1];
if ( ';' !== $lastc && '}' !== $lastc )
return false;
$token = $data[0];
switch ( $token ) {
case 's' :
if ( '"' !== $data[$length-2] )
return false;
case 'a' :
case 'O' :
return (bool) preg_match( "/^{$token}:[0-9]+:/s", $data );
case 'b' :
case 'i' :
case 'd' :
return (bool) preg_match( "/^{$token}:[0-9.E-]+;\$/", $data );
}
return false;
}
$string = "a:1:{s:19:\"is_featured_service\";b:0;}";
$x = is_serialized( $string )
? unserialize( $string )
: 'Some default value';

I would only keep the # if you dont want to deal with errors, which it seems like you do. Then change it into ternary to make it smaller:
$unserialized_string = #unserialize($string) ?: 'another value';

Related

PHP Datetime constructor returns now for strange values

I've discovered that the PHP \Datetime class returns "now" values for some odd inputs. I've already seen the similar question at DateTime constructor in php -- which explains inputs such as single letters of the alphabet (they're military time zones). But I've discovered some new oddballs that I would expect to cause an error, not return a value. Such as...
new \Datetime( '.' )
new \Datetime( ',' )
Can anyone explain WHY these don't cause errors, and can anyone tell me what other odd values I should expect to return valid dates? Is this a bug in PHP?
(Yes, I've already noticed 0 and basically anything you find in timezone_abbreviations_list() )
UPDATE:
I thought I'd share my "turn various inputs into PHP Datetime object" function with you all. Originally done as a conditional "whatever I'm handed, output an object", but thanks to #Syscall's input I've been able to harden it a bit against spurious inputs that inappropriately return "now" datetimes.
I could crank this down even harder against various timezone strings, but I don't think it's necessary for my usage.
/**
* If $input is already a DateTime object, leave it alone. Otherwise convert to a DateTime object
* If $immutable = true, converts strings OR DateTime to DateTimeImmutable
* Can be used to convert DateTimeInterface objects to and from immutable
*
* #param string|\DatetimeInterface $input
* #param bool $immutable
* #return \DateTime|\DateTimeImmutable|\DateTimeInterface|null
*/
function ensureDateTime ( $input, $immutable = NULL ) {
if ( ! $input instanceof \DateTimeInterface ) {
$output = NULL;
if( is_string( $input ) || ! $input ) {
$trimmed = trim( $input, ".,\n\0\t " ); // Thanks https://stackoverflow.com/a/48956505/339440
$ignore = ( $trimmed == '' && $trimmed != $input )
|| in_array( $trimmed, ['0000-00-00', '0000-00-00 00:00:00'], true )
|| ( strlen( $trimmed ) == 1 && preg_match( '#[a-zA-Z]#', $trimmed ) == 1 );
if ( ! $ignore ) {
try {
$input = trim( $input );
if ( $immutable ) {
$output = new \DateTimeImmutable( $input );
} else {
$output = new \DateTime( $input );
}
} catch( \Exception $e ) {
// suppress DateTime::__construct() errors. $output remains NULL
}
}
}
} elseif ( true === $immutable && $input instanceof \DateTime ) {
$output = new \DateTimeImmutable( $input->format(TIMESTAMPFORMAT), $input->getTimezone() );
} elseif ( false === $immutable && $input instanceof \DateTimeImmutable ) {
$output = new \DateTime( $input->format(TIMESTAMPFORMAT), $input->getTimezone() );
} else {
$output = $input;
}
return $output;
}
Values ".,\n\0\t " are trimmed :
See /php-7.2.2/ext/date/lib/parse_date.c, static int scan() :
switch (yych) {
case 0x00:
case '\n': goto yy51;
case '\t':
case ' ': goto yy48;
case ',':
case '.': goto yy50;
Other characters like (+-#, letters, numbers, requires other validation.
Example :
new Datetime("\0 \n\t,."); // works
But :
new Datetime('#') ; // fails

Preg_replace not working in WP-CLI search-replace

I have to change filenames to images/filename and files/filename in Wordpress and I ended up using WP-CLI's search-replace function.
Here is the shell command I execute:
wp search-replace '(")(5\.jpg)' 'images/${2}' wp_postmeta --regex --regex-delimiter='/' --dry-run --skip-columns=meta_key --debug=true
This gives me back message: 0 replacements to be made.
Here is one entry from the database:
a:5:{s:5:"width";i:2048;s:6:"height";i:1536;s:4:"file";s:5:"5.jpg";s:5:"sizes";a:4:{s:9:"thumbnail";a:4:{s:4:"file";s:13:"5-150x150.jpg";s:5:"width";i:150;s:6:"height";i:150;s:9:"mime-type";s:10:"image/jpeg";}s:6:"medium";a:4:{s:4:"file";s:13:"5-300x225.jpg";s:5:"width";i:300;s:6:"height";i:225;s:9:"mime-type";s:10:"image/jpeg";}s:12:"medium_large";a:4:{s:4:"file";s:13:"5-768x576.jpg";s:5:"width";i:768;s:6:"height";i:576;s:9:"mime-type";s:10:"image/jpeg";}s:5:"large";a:4:{s:4:"file";s:14:"5-1024x768.jpg";s:5:"width";i:1024;s:6:"height";i:768;s:9:"mime-type";s:10:"image/jpeg";}}s:10:"image_meta";a:12:{s:8:"aperture";s:1:"0";s:6:"credit";s:0:"";s:6:"camera";s:0:"";s:7:"caption";s:0:"";s:17:"created_timestamp";s:1:"0";s:9:"copyright";s:0:"";s:12:"focal_length";s:1:"0";s:3:"iso";s:1:"0";s:13:"shutter_speed";s:1:"0";s:5:"title";s:0:"";s:11:"orientation";s:1:"0";s:8:"keywords";a:0:{}}}
I created a custom PHP script as the following:
$data = 'a:5:{s:5:"width";i:2048;s:6:"height";i:1536;s:4:"file";s:5:"5.jpg";s:5:"sizes";a:4:{s:9:"thumbnail";a:4:{s:4:"file";s:13:"5-150x150.jpg";s:5:"width";i:150;s:6:"height";i:150;s:9:"mime-type";s:10:"image/jpeg";}s:6:"medium";a:4:{s:4:"file";s:13:"5-300x225.jpg";s:5:"width";i:300;s:6:"height";i:225;s:9:"mime-type";s:10:"image/jpeg";}s:12:"medium_large";a:4:{s:4:"file";s:13:"5-768x576.jpg";s:5:"width";i:768;s:6:"height";i:576;s:9:"mime-type";s:10:"image/jpeg";}s:5:"large";a:4:{s:4:"file";s:14:"5-1024x768.jpg";s:5:"width";i:1024;s:6:"height";i:768;s:9:"mime-type";s:10:"image/jpeg";}}s:10:"image_meta";a:12:{s:8:"aperture";s:1:"0";s:6:"credit";s:0:"";s:6:"camera";s:0:"";s:7:"caption";s:0:"";s:17:"created_timestamp";s:1:"0";s:9:"copyright";s:0:"";s:12:"focal_length";s:1:"0";s:3:"iso";s:1:"0";s:13:"shutter_speed";s:1:"0";s:5:"title";s:0:"";s:11:"orientation";s:1:"0";s:8:"keywords";a:0:{}}}';
if (preg_match('/(")(5\.jpg)/', $data)) {
echo "A match was found.";
} else {
echo "A match was not found.";
}
echo '<br>';
$data = preg_replace( '/(")(5\.jpg)/', 'images/${2}', $data );
var_dump($data);
This replaces the data fine, I get result as
a:5:{s:5:"width";i:2048;s:6:"height";i:1536;s:4:"file";s:5:"images/5.jpg" ...
This is the source code of WP-CLI search-replace:
<?php
namespace WP_CLI;
class SearchReplacer {
private $from, $to;
private $recurse_objects;
private $regex;
private $regex_flags;
private $regex_delimiter;
private $logging;
private $log_data;
private $max_recursion;
/**
* #param string $from String we're looking to replace.
* #param string $to What we want it to be replaced with.
* #param bool $recurse_objects Should objects be recursively replaced?
* #param bool $regex Whether `$from` is a regular expression.
* #param string $regex_flags Flags for regular expression.
* #param string $regex_delimiter Delimiter for regular expression.
* #param bool $logging Whether logging.
*/
function __construct( $from, $to, $recurse_objects = false, $regex = false, $regex_flags = '', $regex_delimiter = '/', $logging = false ) {
$this->from = $from;
$this->to = $to;
$this->recurse_objects = $recurse_objects;
$this->regex = $regex;
$this->regex_flags = $regex_flags;
$this->regex_delimiter = $regex_delimiter;
$this->logging = $logging;
$this->clear_log_data();
// Get the XDebug nesting level. Will be zero (no limit) if no value is set
$this->max_recursion = intval( ini_get( 'xdebug.max_nesting_level' ) );
}
/**
* Take a serialised array and unserialise it replacing elements as needed and
* unserialising any subordinate arrays and performing the replace on those too.
* Ignores any serialized objects unless $recurse_objects is set to true.
*
* #param array|string $data The data to operate on.
* #param bool $serialised Does the value of $data need to be unserialized?
*
* #return array The original array with all elements replaced as needed.
*/
function run( $data, $serialised = false ) {
return $this->_run( $data, $serialised );
}
/**
* #param int $recursion_level Current recursion depth within the original data.
* #param array $visited_data Data that has been seen in previous recursion iterations.
*/
private function _run( $data, $serialised, $recursion_level = 0, $visited_data = array() ) {
// some unseriliased data cannot be re-serialised eg. SimpleXMLElements
try {
if ( $this->recurse_objects ) {
// If we've reached the maximum recursion level, short circuit
if ( $this->max_recursion != 0 && $recursion_level >= $this->max_recursion ) {
return $data;
}
if ( is_array( $data ) || is_object( $data ) ) {
// If we've seen this exact object or array before, short circuit
if ( in_array( $data, $visited_data, true ) ) {
return $data; // Avoid infinite loops when there's a cycle
}
// Add this data to the list of
$visited_data[] = $data;
}
}
if ( is_string( $data ) && ( $unserialized = #unserialize( $data ) ) !== false ) {
$data = $this->_run( $unserialized, true, $recursion_level + 1 );
}
elseif ( is_array( $data ) ) {
$keys = array_keys( $data );
foreach ( $keys as $key ) {
$data[ $key ]= $this->_run( $data[$key], false, $recursion_level + 1, $visited_data );
}
}
elseif ( $this->recurse_objects && is_object( $data ) ) {
foreach ( $data as $key => $value ) {
$data->$key = $this->_run( $value, false, $recursion_level + 1, $visited_data );
}
}
else if ( is_string( $data ) ) {
if ( $this->logging ) {
$old_data = $data;
}
if ( $this->regex ) {
$search_regex = $this->regex_delimiter;
$search_regex .= $this->from;
$search_regex .= $this->regex_delimiter;
$search_regex .= $this->regex_flags;
$data = preg_replace( $search_regex, $this->to, $data );
} else {
$data = str_replace( $this->from, $this->to, $data );
}
if ( $this->logging && $old_data !== $data ) {
$this->log_data[] = $old_data;
}
}
if ( $serialised )
return serialize( $data );
} catch( Exception $error ) {
}
return $data;
}
/**
* Gets existing data saved for this run when logging.
* #return array Array of data strings, prior to replacements.
*/
public function get_log_data() {
return $this->log_data;
}
/**
* Clears data stored for logging.
*/
public function clear_log_data() {
$this->log_data = array();
}
}
I use the exact same preg_replace as used here,
$data = preg_replace( $search_regex, $this->to, $data );
Why this is not working in WP-CLI?

How to: unserialize($data) if $data is serialized?

Some data in my MySQL database is stored in serialized format, e.g. a:1:{s:3:"url";s:70:"http://www.myurl.com/wp-content/uploads/2014/01/Crash_Test_Dummy-1.jpg";}
other data in the same type of field is stored unserialized, eg. http://www.myurl.com/wp-content/uploads/2014/01/Crash_Test_Dummy-1.jpg.
Now when I try to retrieve data with $var=unserialize($data); with $data being the above unserialized string, I get an error Notice: unserialize(): Error at offset 0 of 69 bytes in ...
Is there a quick way to serialize all unserialized fields in my DB? Alternatively, is there a way to tell the server unserialize($data) if $data is serialized?
Thank you!
WordPress likes to complicate things a bit when it comes to store information on db...
If you are developing code inside WP, just use maybe_unserialize
Otherwise, you can copy that function form wp-includes/functions.php
/**
* Unserialize value only if it was serialized.
*
* #since 2.0.0
*
* #param string $original Maybe unserialized original, if is needed.
* #return mixed Unserialized data can be any type.
*/
function maybe_unserialize( $original ) {
if ( is_serialized( $original ) ) // don't attempt to unserialize data that wasn't serialized going in
return #unserialize( $original );
return $original;
}
/**
* Check value to find if it was serialized.
*
* If $data is not an string, then returned value will always be false.
* Serialized data is always a string.
*
* #since 2.0.5
*
* #param mixed $data Value to check to see if was serialized.
* #param bool $strict Optional. Whether to be strict about the end of the string. Defaults true.
* #return bool False if not serialized and true if it was.
*/
function is_serialized( $data, $strict = true ) {
// if it isn't a string, it isn't serialized
if ( ! is_string( $data ) )
return false;
$data = trim( $data );
if ( 'N;' == $data )
return true;
$length = strlen( $data );
if ( $length < 4 )
return false;
if ( ':' !== $data[1] )
return false;
if ( $strict ) {
$lastc = $data[ $length - 1 ];
if ( ';' !== $lastc && '}' !== $lastc )
return false;
} else {
$semicolon = strpos( $data, ';' );
$brace = strpos( $data, '}' );
// Either ; or } must exist.
if ( false === $semicolon && false === $brace )
return false;
// But neither must be in the first X characters.
if ( false !== $semicolon && $semicolon < 3 )
return false;
if ( false !== $brace && $brace < 4 )
return false;
}
$token = $data[0];
switch ( $token ) {
case 's' :
if ( $strict ) {
if ( '"' !== $data[ $length - 2 ] )
return false;
} elseif ( false === strpos( $data, '"' ) ) {
return false;
}
// or else fall through
case 'a' :
case 'O' :
return (bool) preg_match( "/^{$token}:[0-9]+:/s", $data );
case 'b' :
case 'i' :
case 'd' :
$end = $strict ? '$' : '';
return (bool) preg_match( "/^{$token}:[0-9.E-]+;$end/", $data );
}
return false;
}

turning this trainwreck of a function into a recursive one

I've been trying to build this recursive function for the better part of a day now, but I just can't seem to get it to work the way I want.
First, I have a property which holds some data that the function have to access:
$this->data
And then I have this string which the intention is to turn into a relative path:
$path = 'path.to.%id%-%folder%.containing.%info%';
The part of the string that are like this: %value% will load some dynamic values found in the $this->data property (like so: $this->data['id']; or $this->data['folder'];
and to make things really interesting, the property can reference itself again like so: $this->data['folder'] = 'foldername.%subfolder%'; and also have two %values% separated by a - that would have to be left alone.
So to the problem, I've been trying to make a recursive function that will load the dynamic values from the data property, and then again if the new value contains another %value% and so on until no more %value%'s are loaded.
So far, this is what I've been able to come up with:
public function recursiveFolder( $folder, $pathArr = null )
{
$newPathArr = explode( '.', $folder );
if ( count ( $newPathArr ) !== 1 )
{
foreach( $newPathArr as $id => $folder )
{
$value = $this->recursiveFolder( $folder, $newPathArr );
$resultArr = explode( '.', $value );
if ( count ( $resultArr ) !== 1 )
{
foreach ( $resultArr as $nid => $result )
{
$nvalue = $this->recursiveFolder( $result, $newPathArr );
$resultArr[$nid] = $nvalue;
}
}
$resultArr = implode( '.',$resultArr );
$newPathArr[$id] = $resultArr;
}
}
else
{
$pattern = '/%(.*?)%/si';
preg_match_all( $pattern, $folder, $matches );
if ( empty( $matches[0] ) )
{
return $folder;
}
foreach ( $matches[1] as $mid => $match )
{
if ( isset( $this->data[$match] ) && $this->data[$match] != '' )
{
$folder = str_replace( $matches[0][$mid], $this->data[$match], $folder );
return $folder;
}
}
}
return $newPathArr;
}
Unfortunately it is not a recursive function at all as it grinds to a halt when it has multiple layers of %values%, but works with two layers -barely-. (I just coded it so that it would work at a bare minimalistic level this point).
Here's how it should work:
It should turn:
'files.%folder%.blog-%type%.and.%time%'
into:
'files.foldername.blog-post.and.2013.feb-12th.09'
based on this:
$data['folder'] = 'foldername';
$data['type'] = 'post';
$data['time'] = '%year%.%month%-%day%';
$data['year'] = 2013;
$data['month'] = 'feb';
$data['day'] = '12th.%hour%';
$data['hour'] = '09';
Hope you can help!
Jay
I don't see the need for this too be solved recursively:
<?php
function putData($str, $data)
{
// Repeat the replacing process until no more matches are found:
while (preg_match("/%(.*?)%/si", $str, $matches))
{
// Use $matches to make your replaces
}
return $str;
}
?>

How to add a class function to get completed peers in a torrent?

I have created a script that generates information about a torrent file! But I'm lacking in creating a seeds and peers displaying function! Someone told me that they are in the completed field defined in the torrent. Please my class function codes from which I display the generated information using a bencode.php which takes out the data and this script ,named torrent.php converts it in readable form!
<?php
include_once('bencode.php');
class Torrent
{
// Private class members
private $torrent;
private $info;
// Public error message, $error is set if load() returns false
public $error;
// Load torrent file data
// $data - raw torrent file contents
public function load( &$data )
{
$this->torrent = BEncode::decode( $data );
if ( $this->torrent->get_type() == 'error' )
{
$this->error = $this->torrent->get_plain();
return false;
}
else if ( $this->torrent->get_type() != 'dictionary' )
{
$this->error = 'The file was not a valid torrent file.';
return false;
}
$this->info = $this->torrent->get_value('info');
if ( !$this->info )
{
$this->error = 'Could not find info dictionary.';
return false;
}
return true;
}
// Get comment
// return - string
public function getComment() {
return $this->torrent->get_value('comment') ? $this->torrent->get_value('comment')->get_plain() : null;
}
// Get creatuion date
// return - php date
public function getCreationDate() {
return $this->torrent->get_value('creation date') ? $this->torrent->get_value('creation date')->get_plain() : null;
}
// Get created by
// return - string
public function getCreatedBy() {
return $this->torrent->get_value('created by') ? $this->torrent->get_value('created by')->get_plain() : null;
}
// Get name
// return - filename (single file torrent)
// directory (multi-file torrent)
// see also - getFiles()
public function getName() {
return $this->info->get_value('name')->get_plain();
}
// Get piece length
// return - int
public function getPieceLength() {
return $this->info->get_value('piece length')->get_plain();
}
// Get pieces
// return - raw binary of peice hashes
public function getPieces() {
return $this->info->get_value('pieces')->get_plain();
}
// Get private flag
// return - -1 public, implicit
// 0 public, explicit
// 1 private
public function getPrivate() {
if ( $this->info->get_value('private') )
{
return $this->info->get_value('private')->get_plain();
}
return -1;
}
// Get a list of files
// return - array of Torrent_File
public function getFiles() {
// Load files
$filelist = array();
$length = $this->info->get_value('length');
if ( $length )
{
$file = new Torrent_File();
$file->name = $this->info->get_value('name')->get_plain();
$file->length = $this->info->get_value('length')->get_plain();
array_push( $filelist, $file );
}
else if ( $this->info->get_value('files') )
{
$files = $this->info->get_value('files')->get_plain();
while ( list( $key, $value ) = each( $files ) )
{
$file = new Torrent_File();
$path = $value->get_value('path')->get_plain();
while ( list( $key, $value2 ) = each( $path ) )
{
$file->name .= "/" . $value2->get_plain();
}
$file->name = ltrim( $file->name, '/' );
$file->length = $value->get_value('length')->get_plain();
array_push( $filelist, $file );
}
}
return $filelist;
}
// Get a list of trackers
// return - array of strings
public function getTrackers() {
// Load tracker list
$trackerlist = array();
if ( $this->torrent->get_value('announce-list') )
{
$trackers = $this->torrent->get_value('announce-list')->get_plain();
while ( list( $key, $value ) = each( $trackers ) )
{
if ( is_array( $value->get_plain() ) ) {
while ( list( $key, $value2 ) = each( $value ) )
{
while ( list( $key, $value3 ) = each( $value2 ) )
{
array_push( $trackerlist, $value3->get_plain() );
}
}
} else {
array_push( $trackerlist, $value->get_plain() );
}
}
}
else if ( $this->torrent->get_value('announce') )
{
array_push( $trackerlist, $this->torrent->get_value('announce')->get_plain() );
}
return $trackerlist;
}
// Helper function to make adding a tracker easier
// $tracker_url - string
public function addTracker( $tracker_url )
{
$trackers = $this->getTrackers();
$trackers[] = $tracker_url;
$this->setTrackers( $trackers );
}
// Replace the current trackers with the supplied list
// $trackerlist - array of strings
public function setTrackers( $trackerlist )
{
if ( count( $trackerlist ) >= 1 )
{
$this->torrent->remove('announce-list');
$string = new BEncode_String( $trackerlist[0] );
$this->torrent->set( 'announce', $string );
}
if ( count( $trackerlist ) > 1 )
{
$list = new BEncode_List();
while ( list( $key, $value ) = each( $trackerlist ) )
{
$list2 = new BEncode_List();
$string = new BEncode_String( $value );
$list2->add( $string );
$list->add( $list2 );
}
$this->torrent->set( 'announce-list', $list );
}
}
// Update the list of files
// $filelist - array of Torrent_File
public function setFiles( $filelist )
{
// Load files
$length = $this->info->get_value('length');
if ( $length )
{
$filelist[0] = str_replace( '\\', '/', $filelist[0] );
$string = new BEncode_String( $filelist[0] );
$this->info->set( 'name', $string );
}
else if ( $this->info->get_value('files') )
{
$files = $this->info->get_value('files')->get_plain();
for ( $i = 0; $i < count( $files ); ++$i )
{
$file_parts = split( '/', $filelist[$i] );
$path = new BEncode_List();
foreach ( $file_parts as $part )
{
$string = new BEncode_String( $part );
$path->add( $string );
}
$files[$i]->set( 'path', $path );
}
}
}
// Set the comment field
// $value - string
public function setComment( $value )
{
$type = 'comment';
$key = $this->torrent->get_value( $type );
if ( $value == '' ) {
$this->torrent->remove( $type );
} elseif ( $key ) {
$key->set( $value );
} else {
$string = new BEncode_String( $value );
$this->torrent->set( $type, $string );
}
}
// Set the created by field
// $value - string
public function setCreatedBy( $value )
{
$type = 'created by';
$key = $this->torrent->get_value( $type );
if ( $value == '' ) {
$this->torrent->remove( $type );
} elseif ( $key ) {
$key->set( $value );
} else {
$string = new BEncode_String( $value );
$this->torrent->set( $type, $string );
}
}
// Set the creation date
// $value - php date
public function setCreationDate( $value )
{
$type = 'creation date';
$key = $this->torrent->get_value( $type );
if ( $value == '' ) {
$this->torrent->remove( $type );
} elseif ( $key ) {
$key->set( $value );
} else {
$int = new BEncode_Int( $value );
$this->torrent->set( $type, $int );
}
}
// Change the private flag
// $value - -1 public, implicit
// 0 public, explicit
// 1 private
public function setPrivate( $value )
{
if ( $value == -1 ) {
$this->info->remove( 'private' );
} else {
$int = new BEncode_Int( $value );
$this->info->set( 'private', $int );
}
}
// Bencode the torrent
public function bencode()
{
return $this->torrent->encode();
}
// Return the torrent's hash
public function getHash()
{
return strtoupper( sha1( $this->info->encode() ) );
}
}
// Simple class to encapsulate filename and length
class Torrent_File
{
public $name;
public $length;
}
?>
Please help me out!
Thanks in advance!
Little late but the class you say to have created comes from:
https://github.com/torrage/Torrage
It's original purpose was not intended to retrieve that kind of data.
A class that gets you seeds and peers for torrent inclusive the rest of the data see:
https://github.com/adriengibrat/torrent-rw
That information's not stored in the .torrent file. It's highly dynamic data, which can change every microsecond on a 'busy' torrent. The server's not going to build a custom .torrent file with up-to-the-minute statistics every time someone downloads it.
Think about it for a second. You download a .torrent file on Monday, but only look at it next Friday. The stats are now a week old and stale.
You can, however, take the tracker information in the .torrent and query those trackers for the stats.

Categories