MDL-19168, dropbox repository plugin for moodle, and oauth support for filepicker...
authorDongsheng Cai <unoter@gmail.com>
Fri, 14 May 2010 08:29:33 +0000 (08:29 +0000)
committerDongsheng Cai <unoter@gmail.com>
Fri, 14 May 2010 08:29:33 +0000 (08:29 +0000)
lib/oauthlib.php [new file with mode: 0644]
repository/dropbox/db/access.php [new file with mode: 0755]
repository/dropbox/db/upgrade.php [new file with mode: 0755]
repository/dropbox/icon.png [new file with mode: 0644]
repository/dropbox/lang/en/repository_dropbox.php [new file with mode: 0755]
repository/dropbox/lib.php [new file with mode: 0644]
repository/dropbox/repository.class.php [new file with mode: 0755]
repository/dropbox/version.php [new file with mode: 0755]
repository/lib.php
repository/repository_ajax.php

diff --git a/lib/oauthlib.php b/lib/oauthlib.php
new file mode 100644 (file)
index 0000000..36ee14e
--- /dev/null
@@ -0,0 +1,351 @@
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * OAuth helper class
+ *
+ * 1. You can extends oauth_helper to add specific functions, such as twitter extends oauth_helper
+ * 2. Call request_token method to get oauth_token and oauth_token_secret, and redirect user to authorize_url,
+ *    developer needs to store oauth_token and oauth_token_secret somewhere, we will use them to request
+ *    access token later on
+ * 3. User approved the request, and get back to moodle
+ * 4. Call get_access_token, it takes previous oauth_token and oauth_token_secret as arguments, oauth_token
+ *    will be used in OAuth request, oauth_token_secret will be used to bulid signature, this method will
+ *    return access_token and access_secret, store these two values in database or session
+ * 5. Now you can access oauth protected resources by access_token and access_secret using oauth_helper::request
+ *    method (or get() post())
+ *
+ * Note:
+ * 1. This class only support HMAC-SHA1
+ * 2. oauth_helper class don't store tokens and secrets, you must store them manually
+ * 3. Some functions are based on http://code.google.com/p/oauth/
+ *
+ * @package    moodlecore
+ * @copyright  2010 Dongsheng Cai <dongsheng@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+class oauth_helper {
+    /** @var string consumer key, issued by oauth provider*/
+    protected $consumer_key;
+    /** @var string consumer secret, issued by oauth provider*/
+    protected $consumer_secret;
+    /** @var string oauth root*/
+    protected $api_root;
+    /** @var string request token url*/
+    protected $request_token_api;
+    /** @var string authorize url*/
+    protected $authorize_url;
+    protected $http_method;
+    /** @var string */
+    protected $access_token_api;
+    /** @var curl */
+    protected $http;
+
+    /**
+     * Contructor for oauth_helper.
+     * Subclass can override construct to build its own $this->http
+     *
+     * @param array $args requires at least three keys, oauth_consumer_key
+     *                    oauth_consumer_secret and api_root, oauth_helper will
+     *                    guess request_token_api, authrize_url and access_token_api
+     *                    based on api_root, but it not always works
+     */
+    function __construct($args) {
+        if (!empty($args['api_root'])) {
+            $this->api_root = $args['api_root'];
+        } else {
+            $this->api_root = '';
+        }
+        $this->consumer_key = $args['oauth_consumer_key'];
+        $this->consumer_secret = $args['oauth_consumer_secret'];
+
+        if (empty($args['request_token_api'])) {
+            $this->request_token_api = $this->api_root . '/request_token';
+        } else {
+            $this->request_token_api = $args['request_token_api'];
+        }
+
+        if (empty($args['authorize_url'])) {
+            $this->authorize_url = $this->api_root . '/authorize';
+        } else {
+            $this->authorize_url = $args['authorize_url'];
+        }
+
+        if (empty($args['access_token_api'])) {
+            $this->access_token_api = $this->api_root . '/access_token';
+        } else {
+            $this->access_token_api = $args['access_token_api'];
+        }
+
+        if (!empty($args['oauth_callback'])) {
+            $this->oauth_callback = new moodle_url($args['oauth_callback']);
+        }
+        if (!empty($args['access_token'])) {
+            $this->access_token = $args['access_token'];
+        }
+        if (!empty($args['access_token_secret'])) {
+            $this->access_token_secret = $args['access_token_secret'];
+        }
+        $this->http = new curl(array('debug'=>false));
+    }
+
+    /**
+     * Build parameters list:
+     *    oauth_consumer_key="0685bd9184jfhq22",
+     *    oauth_nonce="4572616e48616d6d65724c61686176",
+     *    oauth_token="ad180jjd733klru7",
+     *    oauth_signature_method="HMAC-SHA1",
+     *    oauth_signature="wOJIO9A2W5mFwDgiDvZbTSMK%2FPY%3D",
+     *    oauth_timestamp="137131200",
+     *    oauth_version="1.0"
+     *    oauth_verifier="1.0"
+     * @param array $param
+     * @return string
+     */
+    function get_signable_parameters($params){
+        $sorted = $params;
+        ksort($sorted);
+
+        $total = array();
+        foreach ($sorted as $k => $v) {
+            if ($k == 'oauth_signature') {
+                continue;
+            }
+
+            $total[] = rawurlencode($k) . '=' . rawurlencode($v);
+        }
+        return implode('&', $total);
+    }
+
+    /**
+     * Create signature for oauth request
+     * @param string $url
+     * @param string $secret
+     * @param array $params
+     * @return string
+     */
+    public function sign($http_method, $url, $params, $secret) {
+        $sig = array(
+            strtoupper($http_method),
+            preg_replace('/%7E/', '~', rawurlencode($url)),
+            rawurlencode($this->get_signable_parameters($params)),
+        );
+
+        $base_string = implode('&', $sig);
+        $sig = base64_encode(hash_hmac('sha1', $base_string, $secret, true));
+        return $sig;
+    }
+
+    /**
+     * Initilize oauth request parameters, including:
+     *    oauth_consumer_key="0685bd9184jfhq22",
+     *    oauth_token="ad180jjd733klru7",
+     *    oauth_signature_method="HMAC-SHA1",
+     *    oauth_signature="wOJIO9A2W5mFwDgiDvZbTSMK%2FPY%3D",
+     *    oauth_timestamp="137131200",
+     *    oauth_nonce="4572616e48616d6d65724c61686176",
+     *    oauth_version="1.0"
+     * To access protected resources, oauth_token should be defined
+     *
+     * @param string $url
+     * @param string $token
+     * @param string $http_method
+     * @return array
+     */
+    public function prepare_oauth_parameters($url, $params, $http_method = 'POST') {
+        if (is_array($params)) {
+            $oauth_params = $params;
+        } else {
+            $oauth_params = array();
+        }
+        $oauth_params['oauth_version']     = '1.0';
+        $oauth_params['oauth_nonce']       = $this->get_nonce();
+        $oauth_params['oauth_timestamp']    = $this->get_timestamp();
+        $oauth_params['oauth_consumer_key'] = $this->consumer_key;
+        if (!empty($this->oauth_callback)) {
+            $oauth_params['oauth_callback'] = $this->oauth_callback->out(false);
+        }
+        $oauth_params['oauth_signature_method']        = 'HMAC-SHA1';
+        $oauth_params['oauth_signature']       = $this->sign($http_method, $url, $oauth_params, $this->sign_secret);
+        return $oauth_params;
+    }
+
+    public function setup_oauth_http_header($params) {
+
+        $total = array();
+        ksort($params);
+        foreach ($params as $k => $v) {
+            $total[] = rawurlencode($k) . '="' . rawurlencode($v).'"';
+        }
+        $str = implode(', ', $total);
+        $str = 'Authorization: OAuth '.$str;
+        $this->http->setHeader('Expect:');
+        $this->http->setHeader($str);
+    }
+
+    /**
+     * Request token for authentication
+     * This is the first step to use OAuth, it will return oauth_token and oauth_token_secret
+     * @return array
+     */
+    public function request_token() {
+        $this->sign_secret = $this->consumer_secret.'&';
+        $params = $this->prepare_oauth_parameters($this->request_token_api, array(), 'GET');
+        $content = $this->http->get($this->request_token_api, $params);
+        // Including:
+        //     oauth_token
+        //     oauth_token_secret
+        $result = $this->parse_result($content);
+        if (empty($result['oauth_token'])) {
+            // failed
+            var_dump($result);
+            exit;
+        }
+        // build oauth authrize url
+        if (!empty($this->oauth_callback)) {
+            // url must be rawurlencode
+            $result['authorize_url'] = $this->authorize_url . '?oauth_token='.$result['oauth_token'].'&oauth_callback='.rawurlencode($this->oauth_callback->out(false));
+        } else {
+            // no callback
+            $result['authorize_url'] = $this->authorize_url . '?oauth_token='.$result['oauth_token'];
+        }
+        return $result;
+    }
+
+    /**
+     * Set oauth access token for oauth request
+     * @param string $token
+     * @param string $secret
+     */
+    public function set_access_token($token, $secret) {
+        $this->access_token = $token;
+        $this->access_token_secret = $secret;
+    }
+
+    /**
+     * Request oauth access token from server
+     * @param string $method
+     * @param string $url
+     * @param string $token
+     * @param string $secret
+     */
+    public function get_access_token($token, $secret, $verifier='') {
+        $this->sign_secret = $this->consumer_secret.'&'.$secret;
+        $params = $this->prepare_oauth_parameters($this->access_token_api, array('oauth_token'=>$token, 'oauth_verifier'=>$verifier), 'POST');
+        $this->setup_oauth_http_header($params);
+        $content = $this->http->post($this->access_token_api, $params);
+        $keys = $this->parse_result($content);
+        $this->set_access_token($keys['oauth_token'], $keys['oauth_token_secret']);
+        return $keys;
+    }
+
+    /**
+     * Request oauth protected resources
+     * @param string $method
+     * @param string $url
+     * @param string $token
+     * @param string $secret
+     */
+    public function request($method, $url, $params=array(), $token='', $secret='') {
+        if (empty($token)) {
+            $token = $this->access_token;
+        }
+        if (empty($secret)) {
+            $secret = $this->access_token_secret;
+        }
+        // to access protected resource, sign_secret will alwasy be consumer_secret+token_secret
+        $this->sign_secret = $this->consumer_secret.'&'.$secret;
+        $oauth_params = $this->prepare_oauth_parameters($url, array('oauth_token'=>$token), $method);
+        $this->setup_oauth_http_header($oauth_params);
+        $content = call_user_func_array(array($this->http, strtolower($method)), array($url, $params));
+        return $content;
+    }
+
+    /**
+     * shortcut to start http get request
+     */
+    public function get($url, $params=array(), $token='', $secret='') {
+        return $this->request('GET', $url, $params, $token, $secret);
+    }
+
+    /**
+     * shortcut to start http post request
+     */
+    public function post($url, $params=array(), $token='', $secret='') {
+        return $this->request('POST', $url, $params, $token, $secret);
+    }
+
+    /**
+     * A method to parse oauth response to get oauth_token and oauth_token_secret
+     * @param string $str
+     * @return array
+     */
+    public function parse_result($str) {
+        if (empty($str)) {
+            throw new moodle_exception('error');
+        }
+        $parts = explode('&', $str);
+        $result = array();
+        foreach ($parts as $part){
+            list($k, $v) = explode('=', $part, 2);
+            $result[urldecode($k)] = urldecode($v);
+        }
+        if (empty($result)) {
+            throw new moodle_exception('error');
+        }
+        return $result;
+    }
+
+    /**
+     * Set nonce
+     */
+    function set_nonce($str) {
+        $this->nonce = $str;
+    }
+    /**
+     * Set timestamp
+     */
+    function set_timestamp($time) {
+        $this->timestamp = $time;
+    }
+    /**
+     * Generate timestamp
+     */
+    function get_timestamp() {
+        if (!empty($this->timestamp)) {
+            $timestamp = $this->timestamp;
+            unset($this->timestamp);
+            return $timestamp;
+        }
+        return time();
+    }
+    /**
+     * Generate nonce for oauth request
+     */
+    function get_nonce() {
+        if (!empty($this->nonce)) {
+            $nonce = $this->nonce;
+            unset($this->nonce);
+            return $nonce;
+        }
+        $mt = microtime();
+        $rand = mt_rand();
+
+        return md5($mt . $rand);
+    }
+}
diff --git a/repository/dropbox/db/access.php b/repository/dropbox/db/access.php
new file mode 100755 (executable)
index 0000000..eaac9d6
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+$capabilities = array(
+
+    'repository/dropbox:view' => array(
+        'captype' => 'read',
+        'contextlevel' => CONTEXT_SYSTEM,
+        'legacy' => array(
+            'user' => CAP_ALLOW,
+            'student' => CAP_ALLOW,
+            'teacher' => CAP_ALLOW,
+            'editingteacher' => CAP_ALLOW,
+            'manager' => CAP_ALLOW
+        )
+    )
+);
diff --git a/repository/dropbox/db/upgrade.php b/repository/dropbox/db/upgrade.php
new file mode 100755 (executable)
index 0000000..8b3e4e7
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+function xmldb_repository_dropbox_upgrade($oldversion) {
+
+    global $CFG, $DB;
+
+    $dbman = $DB->get_manager();
+    $result = true;
+
+/// And upgrade begins here. For each one, you'll need one
+/// block of code similar to the next one. Please, delete
+/// this comment lines once this file start handling proper
+/// upgrade code.
+
+/// if ($result && $oldversion < YYYYMMDD00) { //New version in version.php
+///     $result = result of database_manager methods
+/// }
+
+    return $result;
+}
diff --git a/repository/dropbox/icon.png b/repository/dropbox/icon.png
new file mode 100644 (file)
index 0000000..ffcf88e
Binary files /dev/null and b/repository/dropbox/icon.png differ
diff --git a/repository/dropbox/lang/en/repository_dropbox.php b/repository/dropbox/lang/en/repository_dropbox.php
new file mode 100755 (executable)
index 0000000..f93e03b
--- /dev/null
@@ -0,0 +1,33 @@
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Strings for component 'repository_dropbox', language 'en', branch 'MOODLE_20_STABLE'
+ *
+ * @package   repository_dropbox
+ * @copyright 2010 Dongsheng Cai
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+$string['configplugin'] = 'Dropbox configuration';
+$string['notitle'] = 'notitle';
+$string['remember'] = 'Remember me';
+$string['repositorydesc'] = '';
+$string['repositoryname'] = 'Dropbox';
+$string['apikey'] = 'Dropbox API Key';
+$string['secret'] = 'Dropbox Secret';
+$string['instruction'] = 'You can get your API Key and secret from <a href="http://www.dropbox.com/developers/apps">Dropbox developers</a>';
diff --git a/repository/dropbox/lib.php b/repository/dropbox/lib.php
new file mode 100644 (file)
index 0000000..963124c
--- /dev/null
@@ -0,0 +1,58 @@
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * dropbox class
+ * A helper class to access dropbox resources
+ *
+ * @since 2.0
+ * @package moodlecore
+ * @subpackage repository
+ * @copyright 2010 Dongsheng Cai
+ * @author Dongsheng Cai <dongsheng@moodle.com>
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+
+require_once(dirname(dirname(dirname(__FILE__))).'/config.php');
+require_once($CFG->libdir.'/oauthlib.php');
+
+class dropbox extends oauth_helper {
+    private $mode = 'sandbox';
+    private $dropbox_api = 'http://api.dropbox.com/0';
+    private $dropbox_content_api = 'http://api-content.dropbox.com/0';
+    function __construct($args) {
+        parent::__construct($args);
+    }
+    public function get_listing($path='/', $token='', $secret='') {
+        $url = $this->dropbox_api.'/metadata/'.$this->mode.$path;
+        $content = $this->get($url, array(), $token, $secret);
+        $data = json_decode($content);
+        return $data;
+    }
+    public function get_account_info($token, $secret) {
+        $url = $this->dropbox_api.'/account/info';
+        $content = $this->get($url, array(), $token, $secret);
+        return $content;
+    }
+    public function get_file($filepath, $saveas) {
+        $url = 'http://api-content.dropbox.com/0/files/sandbox'.$filepath;
+        $content = $this->get($url, array());
+        file_put_contents($saveas, $content);
+        return array('path'=>$saveas, 'url'=>$url);
+    }
+}
diff --git a/repository/dropbox/repository.class.php b/repository/dropbox/repository.class.php
new file mode 100755 (executable)
index 0000000..693d8e3
--- /dev/null
@@ -0,0 +1,294 @@
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * repository_dropbox class
+ * This plugin is used to access user's dropbox files
+ *
+ * TODO:
+ * Dropbox has problems to process filepath with spaces, tried to use
+ * urlencode filepath, still doesn't work
+ * http://code.google.com/p/dropbox-php/ has the same problem
+ *
+ * @since 2.0
+ * @package moodlecore
+ * @subpackage repository
+ * @copyright 2010 Dongsheng Cai
+ * @author Dongsheng Cai <dongsheng@moodle.com>
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require_once($CFG->dirroot.'/repository/dropbox/lib.php');
+
+class repository_dropbox extends repository {
+    private $dropbox;
+    public $files;
+    public $logged=false;
+
+    /**
+     * Constructor of dropbox plugin
+     * @param int $repositoryid
+     * @param object $context
+     * @param array $options
+     */
+    public function __construct($repositoryid, $context = SYSCONTEXTID, $options = array()) {
+        global $SESSION, $CFG;
+        $options['page']    = optional_param('p', 1, PARAM_INT);
+        parent::__construct($repositoryid, $context, $options);
+
+        $this->setting = 'dropbox_';
+
+        $this->dropbox_key = $this->get_option('dropbox_key');
+        $this->dropbox_secret  = $this->get_option('dropbox_secret');
+
+        $this->access_key    = get_user_preferences($this->setting.'_access_key', '');
+        $this->access_secret = get_user_preferences($this->setting.'_access_secret', '');
+
+        if (!empty($this->access_key) && !empty($this->access_secret)) {
+            $this->logged = true;
+        }
+
+        $this->callback = new moodle_url($CFG->wwwroot.'/repository/repository_ajax.php', array(
+            'callback'=>'yes',
+            'repo_id'=>$repositoryid
+            ));
+
+        $args = array(
+            'oauth_consumer_key'=>$this->dropbox_key,
+            'oauth_consumer_secret'=>$this->dropbox_secret,
+            'oauth_callback' => $this->callback->out(false),
+            'api_root' => 'http://api.dropbox.com/0/oauth',
+        );
+
+        $this->dropbox = new dropbox($args);
+    }
+
+    /**
+     * Check if moodle has got access token and secret
+     * @return bool
+     */
+    public function check_login() {
+        return !empty($this->logged);
+    }
+
+    /**
+     * Generate dropbox login url
+     * @return array
+     */
+    public function print_login() {
+        $result = $this->dropbox->request_token();
+        set_user_preference($this->setting.'_request_secret', $result['oauth_token_secret']);
+        $url = $result['authorize_url'];
+        if ($this->options['ajax']) {
+            $ret = array();
+            $popup_btn = new stdclass;
+            $popup_btn->type = 'popup';
+            $popup_btn->url = $url;
+            $ret['login'] = array($popup_btn);
+            return $ret;
+        } else {
+            echo '<a target="_blank" href="'.$this->flickr->auth().'">'.get_string('login', 'repository').'</a>';
+        }
+    }
+
+    /**
+     * Request access token
+     * @return array
+     */
+    public function callback() {
+        $token  = optional_param('oauth_token', '', PARAM_TEXT);
+        $secret = get_user_preferences($this->setting.'_request_secret', '');
+        $access_token = $this->dropbox->get_access_token($token, $secret);
+        set_user_preference($this->setting.'_access_key', $access_token['oauth_token']);
+        set_user_preference($this->setting.'_access_secret', $access_token['oauth_token_secret']);
+    }
+
+    /**
+     * Get dropbox files
+     * @param string $path
+     * @param int $page
+     * @return array
+     */
+    public function get_listing($path = '', $page = '1') {
+        global $OUTPUT;
+        if (empty($path) || $path=='/') {
+            $path = '/';
+        } else {
+            $path = file_correct_filepath($path);
+        }
+        $result = $this->dropbox->get_listing($path, $this->access_key, $this->access_secret);
+        $current_path = file_correct_filepath($result->path);
+        if (empty($result->path)) {
+            $current_path = '/';
+        }
+
+        $list = array();
+        $list['list'] = array();
+        // process breacrumb trail
+        $list['path'] = array(
+            array('name'=>'Dropbox Sandbox', 'path'=>'/')
+        );
+        $trail = '';
+        if (!empty($path)) {
+            $parts = explode('/', $path);
+            if (count($parts) > 1) {
+                foreach ($parts as $part) {
+                    if (!empty($part)) {
+                        $trail .= ('/'.$part);
+                        $list['path'][] = array('name'=>$part, 'path'=>$trail);
+                    }
+                }
+            } else {
+                $list['path'][] = array('name'=>$path, 'path'=>$path);
+            }
+        }
+        $list['manage'] = false;
+        $list['dynload'] = true;
+        $list['nosearch'] = true;
+
+        $files = $result->contents;
+        foreach ($files as $file) {
+            if ($file->is_dir) {
+                $list['list'][] = array(
+                    'title' => substr($file->path, strpos($file->path, $current_path)+strlen($current_path)),
+                    'path' => file_correct_filepath($file->path),
+                    'size' => $file->size,
+                    'date' => $file->modified,
+                    'thumbnail' => $OUTPUT->pix_url('f/folder-32').'',
+                    'children' => array(),
+                );
+            } else {
+                $list['list'][] = array(
+                    'title' => substr($file->path, strpos($file->path, $current_path)+strlen($current_path)),
+                    'source' => $file->path,
+                    'size' => $file->size,
+                    'date' => $file->modified,
+                    'thumbnail' => $OUTPUT->pix_url(file_extension_icon($file->path, 32)).''
+                );
+            }
+        }
+        return $list;
+    }
+    /**
+     * Logout from dropbox
+     * @return array
+     */
+    public function logout() {
+        set_user_preference($this->setting.'_access_key', '');
+        set_user_preference($this->setting.'_access_secret', '');
+        $this->access_key    = '';
+        $this->access_secret = '';
+        return $this->print_login();
+    }
+
+    /**
+     * Set dropbox option
+     * @param array $options
+     * @return mixed
+     */
+    public function set_option($options = array()) {
+        if (!empty($options['dropbox_key'])) {
+            set_config('dropbox_key', trim($options['dropbox_key']), 'dropbox');
+        }
+        if (!empty($options['dropbox_secret'])) {
+            set_config('dropbox_secret', trim($options['dropbox_secret']), 'dropbox');
+        }
+        unset($options['dropbox_key']);
+        unset($options['dropbox_secret']);
+        $ret = parent::set_option($options);
+        return $ret;
+    }
+
+    /**
+     * Get dropbox options
+     * @param string $config
+     * @return mixed
+     */
+    public function get_option($config = '') {
+        if ($config==='dropbox_key') {
+            return trim(get_config('dropbox', 'dropbox_key'));
+        } elseif ($config==='dropbox_secret') {
+            return trim(get_config('dropbox', 'dropbox_secret'));
+        } else {
+            $options['dropbox_key'] = trim(get_config('dropbox', 'dropbox_key'));
+            $options['dropbox_secret'] = trim(get_config('dropbox', 'dropbox_secret'));
+        }
+        $options = parent::get_option($config);
+        return $options;
+    }
+
+    /**
+     *
+     * @param string $photo_id
+     * @param string $file
+     * @return string
+     */
+    public function get_file($filepath, $saveas = '') {
+        $this->dropbox->set_access_token($this->access_key, $this->access_secret);
+        return $this->dropbox->get_file($filepath, $saveas);
+    }
+    /**
+     * Add Plugin settings input to Moodle form
+     * @param object $mform
+     */
+    public function type_config_form($mform) {
+        global $CFG;
+        $key    = get_config('dropbox', 'dropbox_key');
+        $secret = get_config('dropbox', 'dropbox_secret');
+
+        if (empty($key)) {
+            $key = '';
+        }
+        if (empty($secret)) {
+            $secret = '';
+        }
+
+        $strrequired = get_string('required');
+
+        $mform->addElement('text', 'dropbox_key', get_string('apikey', 'repository_dropbox'), array('value'=>$key,'size' => '40'));
+        $mform->addElement('text', 'dropbox_secret', get_string('secret', 'repository_dropbox'), array('value'=>$secret,'size' => '40'));
+
+        $mform->addRule('dropbox_key', $strrequired, 'required', null, 'client');
+        $mform->addRule('dropbox_secret', $strrequired, 'required', null, 'client');
+        $str_getkey = get_string('instruction', 'repository_dropbox');
+        $mform->addElement('static', null, '',  $str_getkey);
+    }
+
+    /**
+     * Option names of dropbox plugin
+     * @return array
+     */
+    public static function get_type_option_names() {
+        return array('dropbox_key', 'dropbox_secret');
+    }
+
+    /**
+     * Dropbox plugin supports all kinds of files
+     * @return array
+     */
+    public function supported_filetypes() {
+        return '*';
+    }
+
+    /**
+     * User cannot use the external link to dropbox
+     * @return int
+     */
+    public function supported_returntypes() {
+        return FILE_INTERNAL;
+    }
+}
diff --git a/repository/dropbox/version.php b/repository/dropbox/version.php
new file mode 100755 (executable)
index 0000000..7a86ea6
--- /dev/null
@@ -0,0 +1,18 @@
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+$plugin->version = 2010051400;
index 936b1e6..a0146e9 100644 (file)
@@ -1531,6 +1531,13 @@ abstract class repository {
         return $str;
     }
 
+    /**
+     * For oauth like external authentication, when external repository direct user back to moodle,
+     * this funciton will be called to set up token and token_secret
+     */
+    public function callback() {
+    }
+
     /**
      * is it possible to do glboal search?
      * @return boolean
index dbddc49..e79aef3 100755 (executable)
@@ -34,21 +34,21 @@ require_login();
 
 /// Parameters
 $action    = optional_param('action', '', PARAM_ALPHA);
-$repo_id   = optional_param('repo_id', 0, PARAM_INT);           // repository ID
-$callback  = optional_param('callback', '', PARAM_CLEANHTML);
-$client_id = optional_param('client_id', '', PARAM_RAW);        // client ID
-$contextid = optional_param('ctx_id', SYSCONTEXTID, PARAM_INT);       // context ID
-$env       = optional_param('env', 'filepicker', PARAM_ALPHA);  // opened in editor or moodleform
+$repo_id   = optional_param('repo_id', 0, PARAM_INT);           // Pepository ID
+$callback  = optional_param('callback', '', PARAM_CLEANHTML);   // Is this a callback from external site?
+$client_id = optional_param('client_id', '', PARAM_RAW);        // Client ID
+$contextid = optional_param('ctx_id', SYSCONTEXTID, PARAM_INT); // Context ID
+$env       = optional_param('env', 'filepicker', PARAM_ALPHA);  // Opened in editor or moodleform
 $license   = optional_param('license', $CFG->sitedefaultlicense, PARAM_TEXT);
-$author    = optional_param('author', '', PARAM_TEXT);
-$source    = optional_param('source', '', PARAM_RAW);           // file to download
-$itemid    = optional_param('itemid', 0, PARAM_INT);
-$page      = optional_param('page', '', PARAM_RAW);             // page
-$maxbytes  = optional_param('maxbytes', 0, PARAM_INT);
-$req_path  = optional_param('p', '', PARAM_RAW);                // path
+$author    = optional_param('author', '', PARAM_TEXT);          // File author
+$source    = optional_param('source', '', PARAM_RAW);           // File to download
+$itemid    = optional_param('itemid', 0, PARAM_INT);            // Itemid
+$page      = optional_param('page', '', PARAM_RAW);             // Page
+$maxbytes  = optional_param('maxbytes', 0, PARAM_INT);          // Maxbytes
+$req_path  = optional_param('p', '', PARAM_RAW);                // Path
 $saveas_filearea = optional_param('filearea', 'user_draft', PARAM_TEXT);
-$saveas_filename = optional_param('title', '', PARAM_FILE);           // new file name
-$saveas_path   = optional_param('savepath', '/', PARAM_PATH);
+$saveas_filename = optional_param('title', '', PARAM_FILE);     // save as file name
+$saveas_path   = optional_param('savepath', '/', PARAM_PATH);   // save as file path
 $search_text   = optional_param('s', '', PARAM_CLEANHTML);
 $linkexternal  = optional_param('linkexternal', '', PARAM_ALPHA);
 
@@ -59,18 +59,18 @@ header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
 $err = new stdclass;
 $err->client_id = $client_id;
 
-$moodle_maxbytes = get_max_upload_file_size();
-// to prevent maxbytes greater than moodle maxbytes setting
-if ($maxbytes == 0 || $maxbytes>=$moodle_maxbytes) {
-    $maxbytes = $moodle_maxbytes;
-}
-
 /// Check permissions
 if (! (isloggedin() && repository::check_context($contextid)) ) {
     $err->e = get_string('nopermissiontoaccess', 'repository');
     die(json_encode($err));
 }
 
+$moodle_maxbytes = get_max_upload_file_size();
+// to prevent maxbytes greater than moodle maxbytes setting
+if ($maxbytes == 0 || $maxbytes>=$moodle_maxbytes) {
+    $maxbytes = $moodle_maxbytes;
+}
+
 /// Wait as long as it takes for this script to finish
 set_time_limit(0);
 
@@ -137,6 +137,8 @@ if (file_exists($CFG->dirroot.'/repository/'.$type.'/repository.class.php')) {
 
 
 if (!empty($callback)) {
+    // post callback
+    $repo->callback();
     // call opener window to refresh repository
     // the callback url should be something like this:
     // http://xx.moodle.com/repository/repository_ajax.php?callback=yes&repo_id=1&sid=xxx