使用cakephp登录,访问,上传和删除Dropbox的API

时间:2013-12-10 13:15:15

标签: php cakephp dropbox dropbox-api

我在Dropbox开发者帐户中创建了应用程序。

我正在使用此组件类用于dropbox。当我尝试登录时,我收到此错误“请在您的用户模型中创建dropbox_token和dropbox_token_secret字段。”

 <?php 
/**
 * CAKEPHP DROPBOX COMPONENT v0.4
 * Connects Cakephp to Dropbox using cURL.
 * 
 * Copyright (C) 2010 Kyle Robinson Young
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 * 
 * @author Kyle Robinson Young <kyle at kyletyoung.com>
 * @copyright 2010 Kyle Robinson Young
 * @license http://www.opensource.org/licenses/mit-license.php The MIT License
 * @version 0.4
 * @link http://www.kyletyoung.com/code/cakephp_dropbox_component
 * 
 * SETTINGS:
 *     email/password: To your dropbox account
 *     cache: Set to name of cache config or false for no cache
 * 
 * When in doubt, clear the cache.
 * 
 * TODO:
 * Make sync function smarter (use modified).
 *
 */
class DropboxComponent extends Object 
{
    var $email, $password;
    var $loggedin = false;
    var $post, $cookie = array();
    var $cache = 'default';
    var $_wcache = array();

    /**
     * INITIALIZE
     * @param class $controller
     * @param array $settings
     */
    function initialize(&$controller, $settings=array())
    {
        if (!extension_loaded('curl'))
        {
            trigger_error('Dropbox Component: I require the cURL extension to work.');
        } // no curl
        if (empty($settings['email']) || empty($settings['password']))
        {
            trigger_error('Dropbox Component: I need your dropbox email and password to login.');
        } // email|pass empty
        else
        {
            $this->email = $settings['email'];
            $this->password = $settings['password'];
            if (isset($settings['cache'])) $this->cache = $settings['cache'];
            $this->login();
        } // else
    } // initialize

    /**
     * UPLOAD
     * Upload a local file to a remote folder.
     * 
     * @param $file
     * @param $dir
     * @return bool
     */
    function upload($from=null, $to='/')
    {
        if (!file_exists($from)) return false;
        $data = $this->request('https://www.dropbox.com/home');
        $token = $this->findOnDropbox('token_upload', $data);
        if ($token === false) return false;
        $this->post = array(
            'plain'    => 'yes',
            'file'     => '@'.$from,
            'dest'     => $to,
            't'        => $token
        );
        $data = $this->request('https://dl-web.dropbox.com/upload');
        if (strpos($data, 'HTTP/1.1 302 FOUND') === false) return false;
        return true;
    } // upload

    /**
     * DOWNLOAD
     * Download a remote file to a local folder.
     * Both from and to must be a path to a file name.
     * 
     * @param str $from
     * @param str $to
     * @param str $w
     * @return bool
     */
    function download($from=null, $to=null, $w=null)
    {
        $data = $this->file($from, $w);
        if (empty($data['data'])) return false;
        if (!is_writable(dirname($to))) return false;
        if (!$fp = fopen($to, 'w')) return false;
        if (fwrite($fp, $data['data']) === false) return false;
        fclose($fp);
        return true;
    } // download

    /**
     * SYNC
     * Compares files from the local and remote folders 
     * then syncs them.
     * Both local and remote must be folders.
     * 
     * TODO:
     * Currently only checks if files exists. Doesn't 
     * check if they are up to date which it should.
     * 
     * @param str $local
     * @param str $remote
     * @return bool
     */
    function sync($local=null, $remote=null)
    {
        if (!is_dir($local)) return false;

        // GET REMOTE FILES
        $remote_files = $this->files($remote);

        // GET LOCAL FILES
        $local_files = array();
        $d = dir($local);
        while (false !== ($entry = $d->read())) 
        {
            if (substr($entry, 0, 1) == '.') continue;
            if (is_dir($local.DS.$entry)) continue;
            $local_files[] = $entry;
        } // while
        $d->close();

        // DOWNLOAD FILES
        $tmp = array();
        foreach ($remote_files as $file)
        {
            if (empty($file['w'])) continue;
            $tmp[] = $file['name'];
            if (in_array($file['name'], $local_files)) continue;
            $this->download($file['path'].$file['name'], $local.$file['name'], $file['w']);
        } // foreach

        // UPLOAD FILES
        foreach ($local_files as $file)
        {
            if (in_array($file, $tmp)) continue;
            $this->upload($local.$file, $remote);
        } // foreach

        return true;
    } // sync

    /**
     * FILES
     * Returns an array of remote files/folders 
     * within the given dir param.
     * 
     * @param str $dir
     * @return array
     */
    function files($dir='/') 
    {
        $dir = $this->escape($dir);
        if ($this->cache === false) Cache::delete('dropbox_files_'.$dir, $this->cache);
        if (($files = Cache::read('dropbox_files_'.$dir, $this->cache)) === false)
        {
            $files = array();
            $data = $this->request('https://www.dropbox.com/browse_plain/'.$dir.'?no_js=true');

            // GET FILES
            $matches = $this->findOnDropbox('files', $data);
            if ($matches === false) return false;

            // GET TYPES
            $types = $this->findOnDropbox('file_types', $data);

            // GET SIZES
            $sizes = $this->findOnDropbox('file_sizes', $data);

            // GET MODS
            $mods = $this->findOnDropbox('file_modified_dates', $data);

            $i = 0;
            foreach ($matches as $key => $file)
            {
                // IF PARENT
                if (strpos($file, "Parent folder") !== false) continue;

                // GET FILENAME
                $found = $this->findOnDropbox('filename', $file);
                if ($found === false) continue;
                $found = parse_url($found);
                $filename = pathinfo($found['path']);
                $filename = $filename['basename'];
                if (empty($filename)) continue;

                // SET DEFAULTS
                $path = $dir.$filename;
                $type = 'unknown';
                $size = 0;
                $modified = 0;

                // GET TYPE
                if (!empty($types[$key])) $type = trim($types[$key]);

                // GET SIZE
                if (!empty($sizes[$key])) $size = trim($sizes[$key]);

                // GET MODIFIED
                if (!empty($mods[$key])) $modified = trim($mods[$key]);

                // ADD TO FILES
                $files[$i] = array(
                    'path'        => urldecode($dir),
                    'name'        => $filename,
                    'type'        => $type,
                    'size'        => $size,
                    'modified'    => $modified
                );

                // IF FILE OR FOLDER - FILES HAVE W
                $w = $this->findOnDropbox('w', $file);
                if ($w !== false)
                {
                    $files[$i]['w'] = $w;

                    // SAVE W FOR LATER
                    $this->_wcache[$dir.'/'.$filename] = $w;
                } // !empty

                $i++;
            } // foreach

        } // Cache::read
        if ($this->cache !== false) 
        {
            Cache::write('dropbox_files_'.$dir, $files, $this->cache);
        } // if cache
        return $files;
    } // files

    /**
     * FILE
     * Returns a remote file as an array.
     * 
     * @param str $file
     * @param str $w
     * @return array
     */
    function file($file=null, $w=null)
    {
        $file = $this->escape($file);
        if ($this->cache === false) Cache::delete('dropbox_file_'.$file, $this->cache);
        if (($out = Cache::read('dropbox_file_'.$file, $this->cache)) === false)
        {
            if (empty($w))
            {
                if (!empty($this->_wcache[$file])) $w = $this->_wcache[$file];
                else return false;
            } // empty w
            $data = $this->request('https://dl-web.dropbox.com/get/'.$file.'?w='.$w);
            $type = $this->findOnDropbox('content_type', $data);
            $data = substr(stristr($data, "\r\n\r\n"), 4);
            if (!empty($type[0])) $type = $type[0];
            $out = array(
                'path'              => $file,
                'w'                  => $w,
                'data'            => $data,
                'content_type'    => $type
            );
            if ($this->cache !== false) 
            {
                Cache::write('dropbox_file_'.$file, $out, $this->cache);
            } // if cache
        } // Cache::read
        return $out;
    } // file

    /**
     * LOGIN
     * to dropbox
     * 
     * @return bool
     */
    function login() 
    {
        if (!$this->loggedin)
        {
            if (empty($this->email) || empty($this->password)) return false;
            $data = $this->request('https://www.dropbox.com/login');

            // GET TOKEN
            $token = $this->findOnDropbox('token_login', $data);
            if ($token === false) return false;

            // LOGIN TO DROPBOX
            $this->post = array(
                'login_email'        => $this->email,
                'login_password'     => $this->password,
                't'                  => $token
            );
            $data = $this->request('https://www.dropbox.com/login');

            // IF WERE HOME
            if (stripos($data, 'location: /home') === false) return false;
            $this->loggedin = true;
        } // if loggedin
        return true;
    } // login

    /**
     * REQUEST
     * Returns data from given url and 
     * saves cookies. Use $this->post and 
     * $this->cookie to submit params.
     * 
     * @param str $url
     * @return str
     */
    function request($url=null)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
        curl_setopt($ch, CURLOPT_HEADER, 1);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

        // IF POST
        if (!empty($this->post)) 
        {
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $this->post);
            $this->post = array();
        } // !empty

        // IF COOKIES
        if (!empty($this->cookie))
        {
            $cookies = array();
            foreach ($this->cookie as $key => $val)
            {
                $cookies[] = "$key=$val";
            } // foreach
            $cookies = implode(';', $cookies);
            curl_setopt($ch, CURLOPT_COOKIE, $cookies);
        } // !empty

        // GET DATA
        $data = curl_exec($ch);

        // SAVE COOKIES
        $cookies = $this->findOnDropbox('cookies', $data);
        if ($cookies !== false)
        {
            $this->cookie = array_merge($this->cookie, $cookies);
        } // if cookies

        curl_close($ch);
        return $data;
    } // request

    /**
     * ESCAPE
     * Returns a dropbox friendly str
     * for a url
     * 
     * @param str $str
     * @return str
     */
    function escape($str=null)
    {
        return str_replace(
            array('+','_','%2E','-','%2F','%3A'),
            array('%20','%5F','.','%2D','/',':'),
            urlencode($str)
        );
    } // escape

    /**
     * FIND ON DROPBOX
     * A single function for parsing data from 
     * Dropbox. For easy update when/if Dropbox 
     * updates their html.
     * 
     * @param str $key
     * @param str $data
     * @return mixed
     */
    function findOnDropbox($key=null, $data=null)
    {
        switch (strtolower($key))
        {
            // FIND FILES & NAMES
            case 'files':
                preg_match_all('/<div.*details-filename.*>(.*?)<\/div>/i', $data, $matches);
                if (!empty($matches[0])) return $matches[0];
                break;

            // FIND FILE TYPES
            case 'file_types':
                preg_match_all('/<div.*details-icon.*>(<img.*class="sprite s_(.*)".*>)<\/div>/i', $data, $matches);
                if (!empty($matches[2])) return $matches[2];
                break;

            // FIND FILE SIZES
            case 'file_sizes':
                preg_match_all('/<div.*details-size.*>(.*)<\/div>/i', $data, $matches);
                if (!empty($matches[1])) return $matches[1];
                break;

            // FIND FILE MODIFIED DATES
            case 'file_modified_dates':
                preg_match_all('/<div.*details-modified.*>(.*)<\/div>/i', $data, $matches);
                if (!empty($matches[1])) return $matches[1];
                break;

            // FIND FILE NAME
            case 'filename':
                preg_match('/href=[("|\')]([^("|\')]+)/i', $data, $match);
                if (!empty($match[1])) return $match[1];
                break;

            // FIND W
            case 'w':
                preg_match('/\?w=(.[^"]*)/i', $data, $match);
                if (!empty($match[1])) return $match[1];
                break;

            // FIND CONTENT TYPE
            case 'content_type':
                preg_match('/Content-Type: .+\/.+/i', $data, $type);
                if (!empty($type)) return $type;
                break;

            // FIND COOKIES
            case 'cookies':
                preg_match_all('/Set-Cookie: ([^=]+)=(.*?);/i', $data, $matches);
                $return = array();
                foreach ($matches[1] as $key => $val)
                {
                    $return[(string)$val] = $matches[2][$key];
                } // foreach
                if (!empty($return)) return $return;
                break;

            // FIND LOGIN FORM TOKEN
            case 'token_login':
                preg_match('/<form [^>]*\/login[^>]*>.*?<\/form>/si', $data, $match);
                if (!empty($match[0]))
                {
                    preg_match('/<input [^>]*name="t" [^>]*value="(.*?)"[^>]*>/si', $match[0], $match);
                    if (!empty($match[1])) return $match[1];
                } // !empty
                break;

            // FIND UPLOAD FORM TOKEN
            case 'token_upload':
                preg_match('/<form [^>]*https\:\/\/dl-web\.dropbox\.com\/upload[^>]*>.*?<\/form>/si', $data, $match);
                if (!empty($match[0]))
                {
                    preg_match('/<input [^>]*name="t" [^>]*value="(.*?)"[^>]*>/si', $match[0], $match);
                    if (!empty($match[1])) return $match[1];
                } // !empty
                break;

        } // switch
        return false;
    } // findOnDropbox

} // DropboxComponent
?> 

控制器代码

class DropboxWebserverController extends AppController
{
    var $name = 'DropboxWebserver';
    var $uses = array();
    var $autoRender = false;
    var $components = array('Dropbox' => array(
        'email'     => 'email@gmail.com',
        'password'    => 'password',
        //'cache'        => false
    ));

    var $root_folder = '/';
    var $default_home = array('index.html', 'index.htm', 'index.php');

    /**
     * INDEX
     */
    function index()
    {
        $args = func_get_args();
        $args = implode('/', $args);

        $path = pathinfo($args);
        if ($path['dirname'] == ".")
        {
            $folder = $path['basename'];
            $file = '';
        } // dirname == .
        else
        {
            $folder = $path['dirname'];
            $file = $path['basename'];
        } // else

        $files = $this->Dropbox->files($this->root_folder.$folder);
        //debug($files);

        // FIND FILE
        foreach ($files as $f)
        {
            if (strpos($f['type'], 'folder') !== false) continue;
            if (empty($f['name'])) continue;
            if ($f['name'] == $file)
            {
                $file = $this->Dropbox->file($this->root_folder.$folder.'/'.$file, $f['w']);
                $output = $file['data'];
                $content_type = $file['content_type'];
                break;
            } // name == file

            // FIND DEFAULT HOME
            if (in_array($f['name'], $this->default_home))
            {
                $default = $f;
            } // in_array
        } // foreach

        if (!empty($output))
        {
            header('Content-Type: '.$content_type);
            echo $output;
        } // !empty
        elseif (!empty($default))
        {
            $file = $this->Dropbox->file($this->root_folder.$folder.'/'.$default['name'], $default['w']);
            header('Content-Type: '.$file['content_type']);
            echo $file['data'];
        } // !empty default
        else
        {
            echo 'Error 404: File Not Found';
        } // else

    } // index

}

如何使用cakephp登录和访问投递箱帐户

0 个答案:

没有答案