<?php
 
/**
 
 * 
 
 * Simple rapidshare file checker class.
 
 * Usage:
 
 *  $files = RSFile::getInstance($id1, $name1);
 
 *  $files = RSFile::getInstance($id2, $name2);
 
 *  $files->processFiles();
 
 *  if ($files->getStatus() === RSFile::STATUS_FILE_OK) {
 
 *      echo $files->getSize(RSFile::SIZE_MB);
 
 *      echo $files->getDownloadMirror();
 
 *  }
 
 * 
 
 * @version v1.0
 
 * @author Alex
 
 */
 
 
class RSFile implements Iterator {
 
    
 
    /**
 
     * The file was not found on the rapidshare servers.
 
     * @var integer
 
     */
 
    const STATUS_FILE_NOT_FOUND = 0;
 
    
 
    /**
 
     * File was found and everything is OK.
 
     * @var integer
 
     */
 
    const STATUS_FILE_OK        = 1;
 
    
 
    /**
 
     * The rapidshare server is down.
 
     * @var integer
 
     */
 
    const STATUS_SERVER_DOWN    = 3;
 
    
 
    /**
 
     * The file was marked as illegal.
 
     * @var integer
 
     */
 
    const STATUS_ILLEGAL_FILE   = 4;
 
    
 
    /**
 
     * Format file size to bytes (by default).
 
     * @var string
 
     */
 
    const SIZE_B  = 'b';
 
    
 
    /**
 
     * Format file size to kilobytes
 
     * @var string
 
     */
 
    const SIZE_KB = 'kb';
 
    
 
    /**
 
     * Format file size to megabytes
 
     * @var string
 
     */
 
    const SIZE_MB = 'mb';
 
    
 
    /**
 
     * Format file size to gigabytes
 
     * @var string
 
     */
 
    const SIZE_GB = 'gb';
 
    
 
    /**
 
     * The maximum number of calls to the rapidshare servers.
 
     * @var integer
 
     */
 
    const MAX_SERVER_CALLS = 3;
 
    
 
    /**
 
     * Stores the latest error (if any)
 
     * @var string
 
     */
 
    private $_error = null;
 
    
 
    /**
 
     * Stores the latest error number (if any)
 
     * @var string
 
     */
 
    private $_errno = null;
 
    
 
    /**
 
     * Stores the current file id
 
     * @var string
 
     */
 
    private $_id;
 
    
 
    /**
 
     * Stores the current file name
 
     * @var string
 
     */
 
    private $_name;
 
    
 
    /**
 
     * Stores the current file size in bytes
 
     * @var integer
 
     */
 
    private $_size;
 
    
 
    /**
 
     * Stores the server id for the current file
 
     * @var integer
 
     */
 
    private $_serverId;
 
    
 
    /**
 
     * Stores the status for the current file
 
     * @var integer
 
     */
 
    private $_status;
 
    
 
    /**
 
     * Stores the short host for the current file
 
     * @var string
 
     */
 
    private $_shortHost;
 
    
 
    /**
 
     * Stores the md5sum of the current file
 
     * @var string
 
     */
 
    private $_md5sum;
 
 
    /**
 
     * We use this simple variable to know if more than MAX_SERVER_CALLS calls 
 
     * are made to the rapidshare server, you should never make more than one
 
     * call to processFiles() function that connects to the rapidshare servers.
 
     * @var integer
 
     */
 
    private static $calls = 0;
 
 
    /**
 
     * The list of instances of this class
 
     * @var object
 
     */
 
    private static $instances = array();
 
        
 
    /**
 
     * Private constructor
 
     */
 
    private function  __construct($id, $name) {
 
        $this->_id   = $id;
 
        $this->_name = $name;
 
    }
 
    
 
    /**
 
     * Returns only one instance of this class per id/name
 
     *
 
     * @param string $id File id on rapidshare servers
 
     * @param string $name File name on rapidshare servers
 
     *
 
     * @return object
 
     */
 
    public static function getInstance($id, $name) {
 
        $instance = (string) $id.$name;
 
        if (!empty($instance)) {
 
            if (!isset(self::$instances[$instance]) || !self::$instances[$instance] instanceof self)
 
                self::$instances[$instance] = new self($id, $name);
 
    
 
            return self::$instances[$instance];
 
        }
 
        trigger_error("Empty instance id!", E_USER_ERROR);
 
    }
 
    
 
    /**
 
     * Removes the instance.
 
     * @param string $id
 
     */
 
    public function unsetInstance($id, $name) {
 
        $instance = (string) $id.$name;
 
        if (!empty($instance)) {
 
            if (isset(self::$instances[$instance]))
 
                unset(self::$instances[$instance]);
 
            return true;
 
        }
 
        trigger_error("Empty instance id!", E_USER_ERROR);
 
    }
 
    
 
    /**
 
     * Returns the id for the current file
 
     * @return string
 
     */
 
    public function getFileId() {
 
        return $this->_id;
 
    }
 
    
 
    /**
 
     * Returns the name of the current file
 
     * @return string
 
     */
 
    public function getFileName() {
 
        return $this->_name;
 
    }
 
    
 
    /**
 
     * Returns the size of the current file
 
     * @param string $format Use one of the defined SIZE_* constants
 
     * @param int $precision Precision for round function
 
     * 
 
     * @return float The file size changed in the desired format.
 
     */
 
    public function getFileSize($format = self::SIZE_B, $precision = 2) {
 
        
 
        if (!is_int($precision))
 
            $precision = (int) $precision;
 
        
 
        switch ($format) {
 
            case self::SIZE_GB:
 
                return round($this->_size / (1024 * 1024 * 1024), $precision);
 
                
 
            case self::SIZE_MB:
 
                return round($this->_size / (1024 * 1024), $precision);
 
                        
 
            case self::SIZE_KB:
 
                return round($this->_size / 1024, $precision);
 
            
 
            default:
 
            case self::SIZE_B:
 
                return $this->_size;
 
        }    
 
    }
 
    
 
    /**
 
     * Returns the server id where the file is hosted.
 
     * @return integer
 
     */
 
    public function getServerId() {
 
        return $this->_serverId;
 
    }
 
    
 
    /**
 
     * Returns the status of the current file
 
     * @returns integer.
 
     */
 
    public function getFileStatus() {
 
        return $this->_status;
 
    }
 
    
 
    /**
 
     * Returns the short host for the current file, is used to get the best
 
     * download mirror.
 
     * @return string.
 
     */
 
    public function getShortHost() {
 
        return $this->_shortHost;
 
    }
 
    
 
    /**
 
     * Returns the best download mirror for the current file or null if the 
 
     * file status is not equal to 1
 
     * 
 
     * @return mixed 
 
     */
 
    public function getDownloadMirror() {
 
        // The status of the file MUST be ok or there is no file.
 
        if ($this->getFileStatus() !== self::STATUS_FILE_OK)
 
            return null;
 
        
 
        // http://rs$serverid$shorthost.rapidshare.com/files/$fileid/$filename
 
        $url  = 'http://rs';
 
        $url .= $this->getServerId();
 
        $url .= $this->getShortHost();
 
        $url .= '.rapidshare.com/files/';
 
        $url .= $this->getFileId();
 
        $url .= '/';
 
        $url .= $this->getFileName();
 
        return $url;
 
    }
 
    
 
    /**
 
     * Returns the md5sum of the current file
 
     * @return string
 
     */
 
    public function getMd5sum() {
 
        return $this->_md5sum;
 
    }
 
 
    /**
 
     * Simple implode function but works with multiton objects.
 
     *
 
     * @param string $glue String separator
 
     * @param object $objs Instance of class implementing Iterator interface
 
     * @param string $callback Object method used to get the string for
 
     * concatenation
 
     */
 
    public function implodeObjs($glue, $objs, $callback) {
 
    
 
        $returns = '';
 
        foreach ($objs as $obj) {
 
            $returns .= $obj->$callback();
 
            $returns .= $glue;
 
        }
 
    
 
        /*
 
         * If the separator is not an empty string then remove it from the end 
 
         * of the final string.
 
         */
 
        if (isset($glue[0]))
 
            $returns = substr($returns, 0, (count($glue) * -1));
 
    
 
        return $returns;
 
    }
 
    
 
    /**
 
     * This function must be called only after every file is already created.
 
     * e.g. $files = RSFile::getInstance(id1, name1)->getInstance(id2, name2)...
 
     * $files->processFiles();
 
     * foreach($files as $file)
 
     *     $file->getFileSize() ...
 
     *     
 
     * @return boolean true on success and false otherwise.
 
     */
 
    public function processFiles() {
 
        
 
        // Make sure we dont call to many times the rapidshare api.
 
        if (self::$calls >= self::MAX_SERVER_CALLS) {
 
            $this->_error = 'You can NOT call this method more than 
 
                    MAX_SERVER_CALLS times!';
 
            $this->_errno = '0001';
 
            return false;
 
        }
 
        // Get file ids separated by comma
 
        $files     = $this->implodeObjs(',', $this, 'getFileId');
 
        // Get file names separated by comma
 
        $filenames = $this->implodeObjs(',', $this, 'getFileName');
 
        
 
        // Some checking before getting any error from the server.
 
        if (count($files) > 3000 || count($filenames) > 30000) {
 
            $this->_error = 'There is a server based limitation. Files are limited
 
                     to 3000 characters and filenames to 30.000';
 
            $this->_errno = '0002';
 
            return false;
 
        }
 
        
 
        // Create all POST fields
 
        $chPostFields  = 'sub=checkfiles';
 
        $chPostFields .= '&files=';
 
        $chPostFields .= $files;
 
        $chPostFields .= '&filenames=';
 
        $chPostFields .= $filenames;
 
        
 
        // Initiate cURL
 
        $ch = curl_init('http://api.rapidshare.com/cgi-bin/rsapi.cgi');
 
        curl_setopt($ch, CURLOPT_POST, 1);
 
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
 
        curl_setopt($ch, CURLOPT_POSTFIELDS, $chPostFields);
 
 
        // Get all files from the response
 
        $data = curl_exec($ch);
 
        if ($data === false) {
 
            // There was an error. Take note of that...
 
            $this->_error = curl_error($ch);
 
            $this->_errno = curl_errno($ch);
 
            
 
            // Close the connection
 
            @curl_close($ch);
 
            
 
            // Return false so we know ther is an error.
 
            return false;
 
        }
 
        // Explode the results
 
        $files = explode("\n", $data);
 
        
 
        // Remove the last item
 
        array_pop($files);
 
        foreach ($files as $file) {
 
            list($id, $name, $size, $serverId, $status, $shortHost, $md5sum)
 
                = explode(',', $file);
 
            // Set all fields.
 
            self::$instances[$id.$name]->_size      = (int) $size;
 
            self::$instances[$id.$name]->_serverId  = (int) $serverId;
 
            self::$instances[$id.$name]->_status    = (int) $status;
 
            self::$instances[$id.$name]->_shortHost = $shortHost;
 
            self::$instances[$id.$name]->_md5sum    = $md5sum;
 
        }
 
        
 
        curl_close($ch);
 
        self::$calls++;
 
        
 
        return true;
 
    }
 
    
 
    /**
 
     * Returns the last error description.
 
     * @return string
 
     */
 
    public function error() {
 
        return $this->_error;
 
    }
 
    
 
    /**
 
     * Returns the last error number.
 
     * @return string
 
     */
 
    public function errno() {
 
        return $this->_errno;
 
    }
 
    
 
    /**
 
     * No serialization allowed
 
     */
 
    public function __sleep() {
 
        trigger_error("No serialization allowed!", E_USER_ERROR);
 
    }
 
    
 
    /**
 
     * No cloning allowed
 
     */
 
    public function __clone() {
 
        trigger_error("No cloning allowed!", E_USER_ERROR);
 
    }
 
 
    /**
 
     * Implementing Iterator
 
     */
 
    public function current() {
 
        return current(self::$instances);
 
    }
 
    
 
    public function key() {
 
        return key(self::$instances);
 
    }
 
    
 
    public function next() {
 
        return next(self::$instances);
 
    }
 
    
 
    public function rewind() {
 
        reset(self::$instances);
 
    }
 
    
 
    public function valid() {
 
        return current(self::$instances) !== false;
 
    }
 
}
 
 
 |