$string['instancesforothers'] = 'private instance(s)';
$string['invalidjson'] = 'Invalid JSON string';
$string['invalidplugin'] = 'Invalid repository {$a} plug-in';
+$string['invalidfiletype'] = '{$a} filetype cannot be accepted.';
$string['invalidrepositoryid'] = 'Invalid repository ID';
$string['isactive'] = 'Active?';
$string['keyword'] = 'Keyword';
* @return int total bytes
*/
function file_get_user_used_space() {
- global $DB, $CFG, $USER;
+ global $DB, $USER;
$usercontext = get_context_instance(CONTEXT_USER, $USER->id);
-
- $totalbytes = 0;
- $files = array();
- //TODO: rewrite to true sql SUM(), this is goign to run out of memory if limits are hight!
- $file_records = $DB->get_records('files', "contextid = ? AND component = 'user' AND filearea != 'draft'", array($usercontext->id));
- foreach ($file_records as $file_record) {
- if ($file_record->filename === '.') {
- continue;
- }
- // doesn't count same files
- if (!isset($files[$file_record->contenthash])) {
- $totalbytes += $file_record->filesize;
- } else {
- $files[$file_record->contenthash] = true;
- }
- }
- return (int)$totalbytes;
+ $sql = "SELECT SUM(files1.filesize) AS totalbytes FROM {files} files1
+ JOIN (SELECT contenthash, filename, MAX(id) AS id
+ FROM {files}
+ WHERE contextid = ? AND component = ? AND filearea != ?
+ GROUP BY contenthash, filename) files2 ON files1.id = files2.id";
+ $params = array('contextid'=>$usercontext->id, 'component'=>'user', 'filearea'=>'draft');
+ $record = $DB->get_record_sql($sql, $params);
+ return (int)$record->totalbytes;
}
/**
}
/**
- * @todo Document this function
+ * Get cached value
*
* @global object
* @global object
}
/**
- * @todo Document this function
+ * Set cache value
*
- * @global object
- * @global object
+ * @global object $CFG
+ * @global object $USER
* @param mixed $param
* @param mixed $val
*/
}
/**
- * @todo Document this function
+ * Remove cache files
*
* @param int $expire The number os seconds before expiry
*/
/**
* delete current user's cache file
*
- * @global object
- * @global object
+ * @global object $CFG
+ * @global object $USER
*/
public function refresh(){
global $CFG, $USER;
$repository_plugins = get_list_of_plugins('repository');
foreach ($repository_plugins as $plugin) {
- require_once($CFG->dirroot . "/repository/$plugin/repository.class.php");
+ require_once($CFG->dirroot . "/repository/$plugin/lib.php");
Mock::generatePartial("repository_$plugin", "partialmock_$plugin", array('send_package'));
}
return array('path'=>$path, 'url'=>$url);
}
- public function print_search($client_id) {
- $str = parent::print_search($client_id);
+ public function print_search() {
+ $str = parent::print_search();
$str .= '<label>Space: </label><br /><select name="space">';
foreach ($this->user_session->stores as $v) {
$str .= '<option ';
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
- * dropbox class
- * A helper class to access dropbox resources
+ * 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
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+require_once(dirname(__FILE__).'/locallib.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 '*';
+ }
-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);
+ /**
+ * User cannot use the external link to dropbox
+ * @return int
+ */
+ public function supported_returntypes() {
+ return FILE_INTERNAL;
}
}
--- /dev/null
+<?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);
+ }
+}
+++ /dev/null
-<?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_callback.php', array(
- '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;
- }
-}
params['env']=this.options.env;
// the form element only accept certain file types
params['accepted_types']=this.options.accepted_types;
- params['sesskey']=M.cfg.sesskey;
+ params['sesskey'] = M.cfg.sesskey;
params['client_id'] = args.client_id;
params['itemid'] = this.options.itemid?this.options.itemid:0;
params['maxbytes'] = this.options.maxbytes?this.options.maxbytes:-1;
return;
}
// error checking
- if (data && data.e) {
- //Y.one(panel_id).set('innerHTML', 'ERROR: '+data.e);
- scope.print_msg(data.e, 'error');
+ if (data && data.error) {
+ scope.print_msg(data.error, 'error');
scope.list();
return;
} else {
}
this.msg_dlg.setHeader(type);
this.msg_dlg.show();
-
},
build_tree: function(node, level) {
var client_id = this.options.client_id;
}
if (count==0) {
if (this.options.externallink) {
- list.set('innerHTML', M.str.repository.norepositoriesavexternalailable);
+ list.set('innerHTML', M.str.repository.norepositoriesexternalavailable);
} else {
list.set('innerHTML', M.str.repository.norepositoriesavailable);
}
create_upload_form: function(data) {
var client_id = this.options.client_id;
Y.one('#panel-'+client_id).set('innerHTML', '');
+ var types = this.options.accepted_types;
this.print_header();
var id = data.upload.id+'_'+client_id;
str += '<tr><td class="mdl-right">';
str += '<label for="'+id+'_file">'+data.upload.label+': </label></td>';
str += '<td class="mdl-left"><input type="file" id="'+id+'_file" name="repo_upload_file" />';
- str += '<input type="hidden" name="itemid" value="'+this.options.itemid+'" /></tr>';
- str += '<tr>';
+ str += '<input type="hidden" name="itemid" value="'+this.options.itemid+'" />';
+ for (var i in types) {
+ str += '<input type="hidden" name="accepted_types[]" value="'+types[i]+'" />';
+ }
+ str += '</td></tr><tr>';
str += '<td class="mdl-right"><label>'+M.str.repository.author+': </label></td>';
str += '<td class="mdl-left"><input type="text" name="author" value="'+this.options.author+'" /></td>';
str += '</tr>';
'WHERE i.id=? AND i.typeid=r.id';
if ($repository = $DB->get_record_sql($sql, array($repo_id))) {
$type = $repository->type;
- if (file_exists($CFG->dirroot.'/repository/'.$type.'/repository.class.php')) {
- require_once($CFG->dirroot.'/repository/'.$type.'/repository.class.php');
+ if (file_exists($CFG->dirroot.'/repository/'.$type.'/lib.php')) {
+ require_once($CFG->dirroot.'/repository/'.$type.'/lib.php');
$classname = 'repository_' . $type;
try {
$repo = new $classname($repo_id, $contextid, array('ajax'=>false, 'name'=>$repository->name));
public function get_link($photo_id) {
global $CFG;
$result = $this->flickr->photos_getSizes($photo_id);
+ throw new file_exception('abc');
$url = '';
if(!empty($result[4])) {
$url = $result[4]['source'];
$ret = array();
$popup_btn = new stdclass;
$popup_btn->type = 'popup';
- $returnurl = $CFG->wwwroot.'/repository/repository_callback.php?repo_id='.$this->id;
+ $returnurl = $CFG->wwwroot.'/repository/repository_ajax.php?callback=yes&repo_id='.$this->id;
$popup_btn->url = google_authsub::login_url($returnurl, google_docs::REALM);
$ret['login'] = array($popup_btn);
return $ret;
* To use repository plugin, see:
* http://docs.moodle.org/en/Development:Repository_How_to_Create_Plugin
* class repository is an abstract class, some functions must be implemented in subclass.
- * See an example: repository/boxnet/repository.class.php
+ * See an example: repository/boxnet/lib.php
*
* A few notes:
* // for ajax file picker, this will print a json string to tell file picker
* 1. Initialize context and options
* 2. Accept necessary parameters
*
- * @param integer $repositoryid
- * @param integer $contextid
- * @param array $options
+ * @param integer $repositoryid repository instance id
+ * @param integer|object a context id or context object
+ * @param array $options repository options
*/
- public function __construct($repositoryid, $contextid = SYSCONTEXTID, $options = array(), $readonly = 0) {
+ public function __construct($repositoryid, $context = SYSCONTEXTID, $options = array(), $readonly = 0) {
$this->id = $repositoryid;
- $this->context = get_context_instance_by_id($contextid);
+ if (!empty($context->id)) {
+ $this->context = $context;
+ } else {
+ $this->context = get_context_instance_by_id($context);
+ }
$this->readonly = $readonly;
$this->options = array();
+
if (is_array($options)) {
$options = array_merge($this->get_option(), $options);
} else {
}
/**
- * Return a type for a given type name.
+ * Get a repository type object by a given type name.
* @global object $DB
- * @param string $typename the type name
- * @return repository_type
+ * @param string $typename the repository type name
+ * @return repository_type|bool
*/
public static function get_type_by_typename($typename) {
global $DB;
}
/**
- * Return a type for a given type id.
+ * Get the repository type by a given repository type id.
* @global object $DB
* @param int $id the type id
* @return object
}
/**
- * Return all repository types ordered by sortorder
- * first type in returnedarray[0], second type in returnedarray[1], ...
+ * Return all repository types ordered by sortorder field
+ * first repository type in returnedarray[0], second repository type in returnedarray[1], ...
* @global object $DB
+ * @global object $CFG
* @param boolean $visible can return types by visiblity, return all types if null
* @return array Repository types
*/
}
if ($records = $DB->get_records('repository',$params,'sortorder')) {
foreach($records as $type) {
- if (file_exists($CFG->dirroot . '/repository/'. $type->type .'/repository.class.php')) {
+ if (file_exists($CFG->dirroot . '/repository/'. $type->type .'/lib.php')) {
$types[] = new repository_type($type->type, (array)get_config($type->type), $type->visible, $type->sortorder);
}
}
}
/**
- * Check context
- * @param int $ctx_id
+ * To check if the context id is valid
+ * @global object $USER
+ * @param int $contextid
* @return boolean
*/
- public static function check_context($ctx_id) {
+ public static function check_context($contextid) {
global $USER;
- $context = get_context_instance_by_id($ctx_id);
+ $context = get_context_instance_by_id($contextid);
$level = $context->contextlevel;
if ($level == CONTEXT_COURSE) {
}
} else if ($level == CONTEXT_USER) {
$c = get_context_instance(CONTEXT_USER, $USER->id);
- if ($c->id == $ctx_id) {
+ if ($c->id == $contextid) {
return true;
} else {
return false;
}
$onlyvisible = isset($args['onlyvisible']) ? $args['onlyvisible'] : true;
+ $returntypes = isset($args['return_types']) ? $args['return_types'] : 3;
$type = isset($args['type']) ? $args['type'] : null;
- $returntypes = isset($args['return_types']) ? $args['return_types'] : 3;
$params = array();
$sql = "SELECT i.*, r.type AS repositorytype, r.sortorder, r.visible
$accepted_types = '*';
}
foreach ($records as $record) {
- if (!file_exists($CFG->dirroot . '/repository/'. $record->repositorytype.'/repository.class.php')) {
+ if (!file_exists($CFG->dirroot . '/repository/'. $record->repositorytype.'/lib.php')) {
continue;
}
- require_once($CFG->dirroot . '/repository/'. $record->repositorytype.'/repository.class.php');
+ require_once($CFG->dirroot . '/repository/'. $record->repositorytype.'/lib.php');
$options['visible'] = $record->visible;
$options['name'] = $record->name;
$options['type'] = $record->repositorytype;
}
}
if (!$onlyvisible || ($repository->is_visible() && !$repository->disabled)) {
-
// check capability in current context
if (!empty($current_context)) {
$capability = has_capability('repository/'.$record->repositorytype.':view', $current_context);
} else {
- // TODO: what should we do if current context isn't set?
$capability = has_capability('repository/'.$record->repositorytype.':view', get_system_context());
}
if ($is_supported && $capability) {
if (!$instance = $DB->get_record_sql($sql, array($id))) {
return false;
}
- require_once($CFG->dirroot . '/repository/'. $instance->repositorytype
- . '/repository.class.php');
+ require_once($CFG->dirroot . '/repository/'. $instance->repositorytype.'/lib.php');
$classname = 'repository_' . $instance->repositorytype;
$options['typeid'] = $instance->typeid;
$options['type'] = $instance->repositorytype;
}
/**
- * call a static function. Any additional arguments than plugin and function will be passed through.
+ * Call a static function. Any additional arguments than plugin and function will be passed through.
* @global object $CFG
* @param string $plugin
* @param string $function
global $CFG;
//check that the plugin exists
- $typedirectory = $CFG->dirroot . '/repository/'. $plugin . '/repository.class.php';
+ $typedirectory = $CFG->dirroot . '/repository/'. $plugin . '/lib.php';
if (!file_exists($typedirectory)) {
//throw new repository_exception('invalidplugin', 'repository');
return false;
$args = func_get_args();
if (count($args) <= 2) {
$args = array();
- }
- else {
+ } else {
array_shift($args);
array_shift($args);
}
//if the context is SYSTEM, so we call it from administration page
$admin = ($context->id == SYSCONTEXTID) ? true : false;
if ($admin) {
- $baseurl = "$CFG->httpswwwroot/$CFG->admin/repositoryinstance.php?sesskey=" . sesskey();
- $output .= "<div ><h2 style='text-align: center'>" . get_string('siteinstances', 'repository') . " ";
- $output .= "</h2></div>";
+ $baseurl = new moodle_url('/'.$CFG->admin.'/repositoryinstance.php', array('sesskey'=>sesskey()));
+ $output .= $OUTPUT->heading(get_string('siteinstances', 'repository'));
} else {
- $baseurl = $CFG->httpswwwroot . '/repository/manage_instances.php?contextid=' . $context->id . '&sesskey=' . sesskey();
+ $baseurl = new moodle_url('/repository/manage_instances.php', array('contextid'=>$context->id, 'sesskey'=>sesskey()));
}
- $url = new moodle_url($baseurl);
+ $url = $baseurl;
$namestr = get_string('name');
$pluginstr = get_string('plugin', 'repository');
if (!empty($type) && $type->get_visible()) {
$instanceoptionnames = repository::static_function($type->get_typename(), 'get_instance_option_names');
if (!empty($instanceoptionnames)) {
- $instancehtml .= '<li><a href="'.$baseurl.'&new='.$type->get_typename().'">'.get_string('createxxinstance', 'repository', get_string('pluginname', 'repository_'.$type->get_typename()))
- .'</a></li>';
+ $baseurl->param('new', $type->get_typename());
+ $instancehtml .= '<li><a href="'.$baseurl->out().'">'.get_string('createxxinstance', 'repository', get_string('pluginname', 'repository_'.$type->get_typename())). '</a></li>';
+ $baseurl->remove_params('new');
$addable++;
}
}
$instanceoptionnames = repository::static_function($typename, 'get_instance_option_names');
if (!empty($instanceoptionnames)) { //create a unique type of instance
$addable = 1;
- $instancehtml .= "<form action='".$baseurl."&new=".$typename."' method='post'>
- <p style='text-align:center'><input type='submit' value='".get_string('createinstance', 'repository')."'/></p>
+ $baseurl->param('new', $typename);
+ $instancehtml .= "<form action='".$baseurl->out()."' method='post'>
+ <p><input type='submit' value='".get_string('createinstance', 'repository')."'/></p>
</form>";
+ $baseurl->remove_params('new');
}
}
}
/**
- * Decide where to save the file, can be
- * reused by sub class
+ * Decide where to save the file, can be overwriten by subclass
* @param string filename
*/
public function prepare_file($filename) {
public static function create($type, $userid, $context, $params, $readonly=0) {
global $CFG, $DB;
$params = (array)$params;
- require_once($CFG->dirroot . '/repository/'. $type . '/repository.class.php');
+ require_once($CFG->dirroot . '/repository/'. $type . '/lib.php');
$classname = 'repository_' . $type;
if ($repo = $DB->get_record('repository', array('type'=>$type))) {
$record = new stdclass;
return false;
}
- /**
- * Cache login details for repositories
- * @global object $DB
- * @param string $username
- * @param string $password
- * @param integer $userid The id of specific user
- * @return integer Id of the record
- */
- public function store_login($username = '', $password = '', $userid = 1) {
- global $DB;
-
- $repository = new stdclass;
- if (!empty($this->id)) {
- $repository->id = $this->id;
- } else {
- $repository->userid = $userid;
- $repository->repositorytype = $this->type;
- $repository->contextid = $this->context->id;
- }
- if ($entry = $DB->get_record('repository', $repository)) {
- $repository->id = $entry->id;
- $repository->username = $username;
- $repository->password = $password;
- return $DB->update_record('repository', $repository);
- } else {
- $repository->username = $username;
- $repository->password = $password;
- return $DB->insert_record('repository', $repository);
- }
- }
-
/**
* Save settings for repository instance
* $repo->set_option(array('api_key'=>'f2188bde132', 'name'=>'dongsheng'));
public static function get_instance_option_names() {
return array();
}
+
public function get_short_filename($str, $maxlength) {
if (strlen($str) >= $maxlength) {
return trim(substr($str, 0, $maxlength)).'...';
class repository_exception extends moodle_exception {
}
-
-
/**
* This is a class used to define a repository instance form
*
<?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_local_install() {
global $CFG;
$result = true;
$itemid = $params['itemid'];
$filename = $params['filename'];
$filearea = $params['filearea'];
- $component = $params['component'];
$filepath = $params['filepath'];
$context = get_context_instance_by_id($params['contextid']);
}
$itemid = null;
$filename = null;
$filearea = null;
- $component = null;
$filepath = null;
$context = get_system_context();
}
try {
$browser = get_file_browser();
- if ($fileinfo = $browser->get_file_info($context, $component, $filearea, $itemid, $filepath, $filename)) {
+ if ($fileinfo = $browser->get_file_info($context, $filearea, $itemid, $filepath, $filename)) {
// build path navigation
$pathnodes = array();
$encodedpath = base64_encode(serialize($fileinfo->get_params()));
$encodedpath = base64_encode(serialize($params));
// hide user_private area from local plugin, user should
// use private file plugin to access private files
- if ($params['component'] = 'user' and $params['filearea'] == 'private') {
+ if ($params['filearea'] == 'user_private') {
continue;
}
$node = array(
* @param string $new_filepath the new path in draft area
* @return array The information of file
*/
- public function copy_to_area($encoded, $new_filearea='ignored', $new_itemid = '', $new_filepath = '/', $new_filename = '') {
+ public function copy_to_area($encoded, $new_filearea='user_draft', $new_itemid = '', $new_filepath = '/', $new_filename = '') {
global $USER, $DB;
$info = array();
$user_context = get_context_instance(CONTEXT_USER, $USER->id);
// the final file
$contextid = $params['contextid'];
- $component = $params['component'];
$filearea = $params['filearea'];
$filepath = $params['filepath'];
$filename = $params['filename'];
$fileitemid = $params['itemid'];
$context = get_context_instance_by_id($contextid);
try {
- $file_info = $browser->get_file_info($context, $component, $filearea, $fileitemid, $filepath, $filename);
- $file_info->copy_to_storage($user_context->id, 'user', 'draft', $new_itemid, $new_filepath, $new_filename);
+ $file_info = $browser->get_file_info($context, $filearea, $fileitemid, $filepath, $filename);
+ $file_info->copy_to_storage($user_context->id, $new_filearea, $new_itemid, $new_filepath, $new_filename);
} catch (Exception $e) {
throw $e;
}
public function print_login(){
global $CFG;
- $returnurl = $CFG->wwwroot.'/repository/repository_callback.php?repo_id='.$this->id;
+ $returnurl = $CFG->wwwroot.'/repository/repository_ajax.php?callback=yes&repo_id='.$this->id;
$authurl = google_authsub::login_url($returnurl, google_picasa::REALM);
if($this->options['ajax']){
$ret = array();
class repository_recent extends repository {
/**
- * initialize recent plugin
+ * Initialize recent plugin
* @param int $repositoryid
* @param int $context
* @param array $options
private function get_recent_files($limitfrom = 0, $limit = DEFAULT_RECENT_FILES_NUM) {
global $USER, $DB;
-
- // TODO: this is not really secure, we should validate the result with file_browser (skodak)
-
+ // TODO: should exclude user_draft area files?
$sql = 'SELECT * FROM {files} files1
JOIN (SELECT contenthash, filename, MAX(id) AS id
FROM {files}
- WHERE userid = :userid AND filename != :filename AND filearea != :filearea
+ WHERE userid = ? AND filename != ? AND filearea != ?
GROUP BY contenthash, filename) files2 ON files1.id = files2.id
ORDER BY files1.timemodified DESC';
- $params = array('userid'=>$USER->id, 'filename'=>'.', 'filearea'=>'draft');
+ $params = array('userid'=>$USER->id, 'filename'=>'.', 'filearea'=>'user_draft');
$rs = $DB->get_recordset_sql($sql, $params, $limitfrom, $limit);
$result = array();
foreach ($rs as $file_record) {
$info = array();
$info['contextid'] = $file_record->contextid;
$info['itemid'] = $file_record->itemid;
- $info['component'] = $file_record->component;
$info['filearea'] = $file_record->filearea;
$info['filepath'] = $file_record->filepath;
$info['filename'] = $file_record->filename;
} catch (Exception $e) {
throw new repository_exception('emptyfilelist', 'repository_recent');
}
- $ret['list'] = $list;
$ret['list'] = array_filter($list, array($this, 'filter'));
return $ret;
}
*
* @global object $USER
* @global object $DB
- * @param string $encoded The information of file, it is base64 encoded php serialized data
+ * @param string $encoded The information of file, it is base64 encoded php seriablized data
* @param string $new_filename The intended name of file
* @param string $new_itemid itemid
* @param string $new_filepath the new path in draft area
* @return array The information of file
*/
- public function copy_to_area($encoded, $new_filearea='ignored', $new_itemid = '', $new_filepath = '/', $new_filename = '') {
+ public function copy_to_area($encoded, $new_filearea='user_draft', $new_itemid = '', $new_filepath = '/', $new_filename = '') {
global $USER, $DB;
$info = array();
$fs = get_file_storage();
$params = unserialize(base64_decode($encoded));
$user_context = get_context_instance(CONTEXT_USER, $USER->id);
- //TODO: this is really HORRIBLE!!! Where is any security check??????? (skodak)
-
$contextid = $params['contextid'];
- $component = $params['component'];
$filearea = $params['filearea'];
$filepath = $params['filepath'];
$filename = $params['filename'];
// XXX:
// When user try to pick a file from other filearea, normally file api will use file browse to
// operate the files with capability check, but in some areas, users don't have permission to
- // browse the files (for example, forum attachment area).
+ // browse the files (for example, forum_attachment area).
//
// To get 'recent' plugin working, we need to use lower level file_stoarge class to bypass the
// capability check, we will use a better workaround to improve it.
- //
- // TODO: no this is a BIG security hole, we should really use file_browser here and instead filter the available files (skodak)
- //
- if ($stored_file = $fs->get_file($contextid, $component, $filearea, $fileitemid, $filepath, $filename)) {
- $file_record = array('contextid'=>$user_context->id, 'component'=>'user', 'filearea'=>'draft',
+ if ($stored_file = $fs->get_file($contextid, $filearea, $fileitemid, $filepath, $filename)) {
+ $file_record = array('contextid'=>$user_context->id, 'filearea'=>$new_filearea,
'itemid'=>$new_itemid, 'filepath'=>$new_filepath, 'filename'=>$new_filename);
- if ($file = $fs->get_file($user_context->id, 'user' ,'draft', $new_itemid, $new_filepath, $new_filename)) {
+ if ($file = $fs->get_file($user_context->id, $new_filearea, $new_itemid, $new_filepath, $new_filename)) {
$file->delete();
}
$fs->create_file_from_storedfile($file_record, $stored_file);
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+define('AJAX_SCRIPT', true);
+
require_once(dirname(dirname(__FILE__)).'/config.php');
require_once(dirname(dirname(__FILE__)).'/lib/filelib.php');
require_once(dirname(__FILE__).'/lib.php');
/// Parameters
$action = optional_param('action', '', PARAM_ALPHA);
$repo_id = optional_param('repo_id', 0, PARAM_INT); // Pepository ID
-$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);
$page = optional_param('page', '', PARAM_RAW); // Page
$maxbytes = optional_param('maxbytes', 0, PARAM_INT); // Maxbytes
$req_path = optional_param('p', '', PARAM_RAW); // Path
+$accepted_types = optional_param('accepted_types', '*', PARAM_RAW);
$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);
header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
$err = new stdclass;
-$err->client_id = $client_id;
if (!confirm_sesskey()) {
$err->error = get_string('invalidsesskey');
/// Check permissions
if (! (isloggedin() && repository::check_context($contextid)) ) {
- $err->e = get_string('nopermissiontoaccess', 'repository');
+ $err->error = get_string('nopermissiontoaccess', 'repository');
die(json_encode($err));
}
$list = array();
foreach($repos as $repo){
if ($repo->global_search()) {
- try {
- $ret = $repo->search($search_text);
- array_walk($ret['list'], 'repository_attach_id', $repo->id); // See function below
- $tmp = array_merge($list, $ret['list']);
- $list = $tmp;
- } catch (repository_exception $e) {
- $err->e = $e->getMessage();
- die(json_encode($err));
- }
+ $ret = $repo->search($search_text);
+ array_walk($ret['list'], 'repository_attach_id', $repo->id); // See function below
+ $tmp = array_merge($list, $ret['list']);
+ $list = $tmp;
}
}
$listing = array('list'=>$list);
$listing['gsearch'] = true;
- $listing['client_id'] = $client_id;
die(json_encode($listing));
break;
'WHERE i.id=? AND i.typeid=r.id';
if (!$repository = $DB->get_record_sql($sql, array($repo_id))) {
- $err->e = get_string('invalidrepositoryid', 'repository');
+ $err->error = get_string('invalidrepositoryid', 'repository');
die(json_encode($err));
} else {
$type = $repository->type;
}
-if (file_exists($CFG->dirroot.'/repository/'.$type.'/repository.class.php')) {
- require_once($CFG->dirroot.'/repository/'.$type.'/repository.class.php');
+if (file_exists($CFG->dirroot.'/repository/'.$type.'/lib.php')) {
+ require_once($CFG->dirroot.'/repository/'.$type.'/lib.php');
$classname = 'repository_' . $type;
- try {
- $repo = new $classname($repo_id, $contextid, array('ajax'=>true, 'name'=>$repository->name, 'type'=>$type, 'client_id'=>$client_id));
- } catch (repository_exception $e){
- $err->e = $e->getMessage();
- die(json_encode($err));
- }
+ $repo = new $classname($repo_id, $contextid, array('ajax'=>true, 'name'=>$repository->name, 'type'=>$type));
} else {
- $err->e = get_string('invalidplugin', 'repository', $type);
+ $err->error = get_string('invalidplugin', 'repository', $type);
die(json_encode($err));
}
case 'signin':
case 'list':
if ($repo->check_login()) {
- try {
- $listing = $repo->get_listing($req_path, $page);
- $listing['client_id'] = $client_id;
- $listing['repo_id'] = $repo_id;
- echo json_encode($listing);
- } catch (repository_exception $e) {
- $err->e = $e->getMessage();
- die(json_encode($err));
- }
+ $listing = $repo->get_listing($req_path, $page);
+ $listing['repo_id'] = $repo_id;
+ echo json_encode($listing);
break;
} else {
$action = 'login';
}
case 'login':
- try {
- $listing = $repo->print_login();
- $listing['client_id'] = $client_id;
- $listing['repo_id'] = $repo_id;
- echo json_encode($listing);
- } catch (repository_exception $e){
- $err->e = $e->getMessage();
- die(json_encode($err));
- }
+ $listing = $repo->print_login();
+ $listing['repo_id'] = $repo_id;
+ echo json_encode($listing);
break;
case 'logout':
$logout = $repo->logout();
- $logout['client_id'] = $client_id;
$logout['repo_id'] = $repo_id;
echo json_encode($logout);
break;
case 'searchform':
- $search_form['form'] = $repo->print_search($client_id);
- $search_form['client_id'] = $client_id;
+ $search_form['form'] = $repo->print_search();
echo json_encode($search_form);
break;
case 'search':
- try {
- $search_result = $repo->search($search_text, (int)$page);
- $search_result['client_id'] = $client_id;
- $search_result['repo_id'] = $repo_id;
- $search_result['search_result'] = true;
- echo json_encode($search_result);
- } catch (repository_exception $e) {
- $err->e = $e->getMessage();
- die(json_encode($err));
- }
+ $search_result = $repo->search($search_text, (int)$page);
+ $search_result['repo_id'] = $repo_id;
+ $search_result['search_result'] = true;
+ echo json_encode($search_result);
break;
case 'download':
- try {
- // We have two special repoisitory type need to deal with
- // local and recent plugins don't added new files to moodle, just add new records to database
- // so we don't check user quota and maxbytes here
- if (in_array($repo->options['type'], array('local', 'recent', 'user'))) {
- try {
- $fileinfo = $repo->copy_to_area($source, 'draft', $itemid, $saveas_path, $saveas_filename);
- } catch (Exception $e) {
- throw $e;
- }
+ // validate mimetype
+ $mimetypes = array();
+ if (in_array('*', $accepted_types) or $accepted_types == '*') {
+ $mimetypes = '*';
+ } else {
+ foreach ($accepted_types as $type) {
+ $mimetypes = mimeinfo('type', $type);
+ }
+ if (!in_array(mimeinfo('type', $saveas_filename), $mimetypes)) {
+ throw new moodle_exception('invalidfiletype', 'repository', '', mimeinfo('type', $_FILES[$elname]['name']));
+ }
+ }
+
+ // We have two special repoisitory type need to deal with
+ // local and recent plugins don't added new files to moodle, just add new records to database
+ // so we don't check user quota and maxbytes here
+ if (in_array($repo->options['type'], array('local', 'recent', 'user'))) {
+ $fileinfo = $repo->copy_to_area($source, 'draft', $itemid, $saveas_path, $saveas_filename);
+ $info = array();
+ $info['file'] = $fileinfo['title'];
+ $info['id'] = $itemid;
+ $info['url'] = $CFG->httpswwwroot.'/draftfile.php/'.$fileinfo['contextid'].'/user_draft/'.$itemid.'/'.$fileinfo['title'];
+ $filesize = $fileinfo['filesize'];
+ if (($maxbytes!==-1) && ($filesize>$maxbytes)) {
+ throw new file_exception('maxbytes');
+ }
+ echo json_encode($info);
+ die; // ends here!!
+ } else {
+ $allowexternallink = (int)get_config(null, 'repositoryallowexternallinks');
+ if (!empty($allowexternallink)) {
+ $allowexternallink = true;
+ } else {
+ $allowexternallink = false;
+ }
+ // allow external links in url element all the time
+ $allowexternallink = ($allowexternallink || ($env == 'url'));
+
+ // Use link of the files
+ if ($allowexternallink and $linkexternal === 'yes' and ($repo->supported_returntypes() & FILE_EXTERNAL)) {
+ // use external link
+ $link = $repo->get_link($source);
$info = array();
- $info['client_id'] = $client_id;
- $info['file'] = $fileinfo['title'];
- $info['id'] = $itemid;
- $info['url'] = $CFG->httpswwwroot.'/draftfile.php/'.$fileinfo['contextid'].'/user_draft/'.$itemid.'/'.$fileinfo['title'];
- $filesize = $fileinfo['filesize'];
- if (($maxbytes!==-1) && ($filesize>$maxbytes)) {
- throw new file_exception('maxbytes');
- }
+ $info['filename'] = $saveas_filename;
+ $info['type'] = 'link';
+ $info['url'] = $link;
echo json_encode($info);
- die; // ends here!!
+ die;
} else {
- $allowexternallink = (int)get_config(null, 'repositoryallowexternallinks');
- if (!empty($allowexternallink)) {
- $allowexternallink = true;
- } else {
- $allowexternallink = false;
+ // Download file to moodle
+ $file = $repo->get_file($source, $saveas_filename);
+ if ($file['path'] === false) {
+ $err->error = get_string('cannotdownload', 'repository');
+ die(json_encode($err));
}
- // allow external links in url element all the time
- $allowexternallink = ($allowexternallink || ($env == 'url'));
-
- // Use link of the files
- if ($allowexternallink and $linkexternal === 'yes' and ($repo->supported_returntypes() || FILE_EXTERNAL)) {
- // use external link
- try {
- $link = $repo->get_link($source);
- } catch (repository_exception $e){
- throw $e;
- }
- $info = array();
- $info['filename'] = $saveas_filename;
- $info['type'] = 'link';
- $info['url'] = $link;
- echo json_encode($info);
- die;
- } else {
- // Download file to moodle
- $file = $repo->get_file($source, $saveas_filename);
- if ($file['path'] === false) {
- $err->e = get_string('cannotdownload', 'repository');
- die(json_encode($err));
- }
- // check if exceed maxbytes
- if (($maxbytes!==-1) && (filesize($file['path']) > $maxbytes)) {
- throw new file_exception('maxbytes');
- }
+ // check if exceed maxbytes
+ if (($maxbytes!==-1) && (filesize($file['path']) > $maxbytes)) {
+ throw new file_exception('maxbytes');
+ }
- // check if exceed user quota
- $userquota = file_get_user_used_space();
- if (filesize($file['path'])+$userquota>=(int)$CFG->userquota) {
- throw new file_exception('userquotalimit');
- }
+ // check if exceed user quota
+ $userquota = file_get_user_used_space();
+ if (filesize($file['path'])+$userquota>=(int)$CFG->userquota) {
+ throw new file_exception('userquotalimit');
+ }
- $record = new stdclass;
- $record->filepath = $saveas_path;
- $record->filename = $saveas_filename;
- $record->component = 'user';
- $record->filearea = 'draft';
- $record->itemid = $itemid;
+ $record = new stdclass;
+ $record->filepath = $saveas_path;
+ $record->filename = $saveas_filename;
+ $record->component = 'user';
+ $record->filearea = 'draft';
+ $record->itemid = $itemid;
- if (!empty($file['license'])) {
- $record->license = $file['license'];
- } else {
- $record->license = $license;
- }
- if (!empty($file['author'])) {
- $record->author = $file['author'];
- } else {
- $record->author = $author;
- }
- $record->source = !empty($file['url']) ? $file['url'] : '';
+ if (!empty($file['license'])) {
+ $record->license = $file['license'];
+ } else {
+ $record->license = $license;
+ }
+ if (!empty($file['author'])) {
+ $record->author = $file['author'];
+ } else {
+ $record->author = $author;
+ }
+ $record->source = !empty($file['url']) ? $file['url'] : '';
- $info = repository::move_to_filepool($file['path'], $record);
- if (empty($info)) {
- $info['e'] = get_string('error', 'moodle');
- }
- echo json_encode($info);
- die;
+ $info = repository::move_to_filepool($file['path'], $record);
+ if (empty($info)) {
+ $info['e'] = get_string('error', 'moodle');
}
+ echo json_encode($info);
+ die;
}
- } catch (Exception $e) {
- $err->e = $e->getMessage();
- die(json_encode($err));
}
break;
case 'upload':
- try {
- $result = $repo->upload();
- $result['client_id'] = $client_id;
- echo json_encode($result);
- } catch (Exception $e){
- $err->e = $e->getMessage();
- $err->client_id = $client_id;
- die(json_encode($err));
- }
+ $result = $repo->upload();
+ echo json_encode($result);
break;
}
/**
- * The Web service script that is called from the filepicker front end
+ * Repository instance callback script
*
* @since 2.0
* @package moodlecore
require_login();
/// Parameters
-
-$repo_id = required_param('repo_id', PARAM_INT); // Repository ID
-
-$client_id = optional_param('client_id', '', PARAM_RAW); // Client ID
-$contextid = optional_param('ctx_id', SYSCONTEXTID, PARAM_INT); // Context ID
+$repo_id = required_param('repo_id', PARAM_INT); // Repository ID
/// Headers to make it not cacheable
header('Cache-Control: no-cache, must-revalidate');
header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
-/// Check permissions
-if (repository::check_context($contextid)) { //TODO: this is weird (skodak)
- print_error('nopermissiontoaccess', 'repository');
-}
-
/// Wait as long as it takes for this script to finish
set_time_limit(0);
/// Get repository instance information
-$sql = 'SELECT i.name, i.typeid, r.type FROM {repository} r, {repository_instances} i '.
+$sql = 'SELECT i.name, i.typeid, r.type, i.contextid FROM {repository} r, {repository_instances} i '.
'WHERE i.id=? AND i.typeid=r.id';
$repository = $DB->get_record_sql($sql, array($repo_id), '*', MUST_EXIST);
$type = $repository->type;
-if (file_exists($CFG->dirroot.'/repository/'.$type.'/repository.class.php')) {
- require_once($CFG->dirroot.'/repository/'.$type.'/repository.class.php');
+if (file_exists($CFG->dirroot.'/repository/'.$type.'/lib.php')) {
+ require_once($CFG->dirroot.'/repository/'.$type.'/lib.php');
$classname = 'repository_' . $type;
- $repo = new $classname($repo_id, $contextid, array('ajax'=>true, 'name'=>$repository->name, 'type'=>$type, 'client_id'=>$client_id)); //TODO: this is very weird constructor! (skodak)
+ $repo = new $classname($repo_id, $repository->contextid);
} else {
print_error('invalidplugin', 'repository', $type);
}
<?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_upload_install() {
global $CFG;
$result = true;
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
- * repository_upload class
- * A subclass of repository, which is used to upload file
+ * A repository plugin to allow user uploading files
*
* @since 2.0
* @package moodlecore
* @subpackage repository
* @copyright 2009 Dongsheng Cai
* @author Dongsheng Cai <dongsheng@moodle.com>
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class repository_upload extends repository {
-
- /**
- *
- * @param int $repositoryid
- * @param object $context
- * @param array $options
- */
- public function __construct($repositoryid, $context = SYSCONTEXTID, $options = array()){
- global $CFG;
- parent::__construct($repositoryid, $context, $options);
- $this->itemid = optional_param('itemid', '', PARAM_INT);
- $this->license = optional_param('license', $CFG->sitedefaultlicense, PARAM_TEXT);
- $this->author = optional_param('author', '', PARAM_TEXT);
- $this->filepath = urldecode(optional_param('savepath', '/', PARAM_PATH));
- }
+ private $mimetypes = array();
/**
* Print a upload form
- *
* @return array
*/
public function print_login() {
/**
* Process uploaded file
- *
- * @return array
+ * @return array|bool
*/
public function upload() {
- try {
- $record = new stdclass;
- $record->filearea = 'draft';;
- $record->component = 'user';;
- $record->filepath = $this->filepath;
- $record->itemid = $this->itemid;
- $record->license = $this->license;
- $record->author = $this->author;
- $this->info = $this->upload_to_filepool('repo_upload_file', $record);
- } catch(Exception $e) {
- throw $e;
- }
- return $this->info;
- }
-
- public function get_listing() {
- global $CFG;
- $ret = array();
- $ret['nologin'] = true;
- $ret['nosearch'] = true;
- $ret['norefresh'] = true;
- // define upload form in file picker
- $ret['upload'] = array('label'=>get_string('attachment', 'repository'), 'id'=>'repo-form');
+ global $USER, $CFG;
- if (has_capability('moodle/course:managefiles', $this->context)) {
- $ret['manage'] = $CFG->wwwroot .'/files/index.php';
+ $types = optional_param('accepted_types', '*', PARAM_RAW);
+ if ((is_array($types) and in_array('*', $types)) or $types == '*') {
+ $this->mimetypes = '*';
+ } else {
+ foreach ($types as $type) {
+ $this->mimetypes[] = mimeinfo('type', $type);
+ }
}
- $ret['list'] = array();
- $ret['dynload'] = false;
- return $ret;
- }
-
- /**
- * Define the name of this repository
- * @return string
- */
- public function get_name(){
- return get_string('pluginname', 'repository_upload');
- }
- /**
- * supported return types
- * @return int
- */
- public function supported_returntypes() {
- return FILE_INTERNAL;
- }
+ $record = new stdclass;
+ $record->filearea = 'draft';
+ $record->component = 'user';
+ $record->filepath = urldecode(optional_param('savepath', '/', PARAM_PATH));
+ $record->itemid = optional_param('itemid', 0, PARAM_INT);
+ $record->license = optional_param('license', $CFG->sitedefaultlicense, PARAM_TEXT);
+ $record->author = optional_param('author', '', PARAM_TEXT);
- /**
- * Upload file to local filesystem pool
- * @param string $elname name of element
- * @param object $record
- * @param bool $override override file if exists
- * @return mixed stored_file object or false if error; may throw exception if duplicate found
- */
- public function upload_to_filepool($elname, $record, $override = true) {
- global $USER, $CFG;
$context = get_context_instance(CONTEXT_USER, $USER->id);
+ $elname = 'repo_upload_file';
$fs = get_file_storage();
+ $browser = get_file_browser();
if ($record->filepath !== '/') {
- $record->filepath = trim($record->filepath, '/');
- $record->filepath = '/'.$record->filepath.'/';
+ $record->filepath = file_correct_filepath($record->filepath);
}
if (!isset($_FILES[$elname])) {
$record->filename = $_FILES[$elname]['name'];
}
+ if ($this->mimetypes != '*') {
+ // check filetype
+ if (!in_array(mimeinfo('type', $_FILES[$elname]['name']), $this->mimetypes)) {
+ throw new moodle_exception('invalidfiletype', 'repository', '', mimeinfo('type', $_FILES[$elname]['name']));
+ }
+ }
+
+ $userquota = file_get_user_used_space();
+ if (filesize($_FILES[$elname]['tmp_name'])+$userquota>=(int)$CFG->userquota) {
+ throw new file_exception('userquotalimit');
+ }
+
if (empty($record->itemid)) {
$record->itemid = 0;
}
- if ($file = $fs->get_file($context->id, 'user', 'draft', $record->itemid, $record->filepath, $record->filename)) {
- if ($override) {
- $file->delete();
- } else {
- throw new moodle_exception('fileexist');
- }
+ if ($file = $browser->get_file_info($context, $record->filearea, $record->itemid, $record->filepath, $record->filename)) {
+ $file->delete();
+ //throw new moodle_exception('fileexist');
}
$record->contextid = $context->id;
- $record->component = 'user';
- $record->filearea = 'draft';
$record->userid = $USER->id;
$record->source = '';
- try {
- $file = $fs->create_file_from_pathname($record, $_FILES[$elname]['tmp_name']);
- } catch (Exception $e) {
- //TODO: ??? (skodak)
- $e->obj = $_FILES[$elname];
- throw $e;
- }
+ $stored_file = $fs->create_file_from_pathname($record, $_FILES[$elname]['tmp_name']);
return array(
- 'url'=>file_draftfile_url($file->get_itemid(), $file->get_filepath(), $file->get_filename()),
+ 'url'=>file_draftfile_url($record->itemid, $record->filepath, $record->filename),
'id'=>$record->itemid,
- 'file'=>$file->get_filename()
- );
+ 'file'=>$record->filename);
+ }
+
+ /**
+ * Return a upload form
+ * @return array
+ */
+ public function get_listing() {
+ global $CFG;
+ $ret = array();
+ $ret['nologin'] = true;
+ $ret['nosearch'] = true;
+ $ret['norefresh'] = true;
+ $ret['list'] = array();
+ $ret['dynload'] = false;
+ $ret['upload'] = array('label'=>get_string('attachment', 'repository'), 'id'=>'repo-form');
+ return $ret;
+ }
+
+ /**
+ * Define the readable name of this repository
+ * @return string
+ */
+ public function get_name(){
+ return get_string('pluginname', 'repository_upload');
+ }
+
+ /**
+ * supported return types
+ * @return int
+ */
+ public function supported_returntypes() {
+ return FILE_INTERNAL;
+ }
+
+ /**
+ * Upload file to local filesystem pool
+ * @param string $elname name of element
+ * @param string $filearea
+ * @param string $filepath
+ * @param string $filename - use specified filename, if not specified name of uploaded file used
+ * @param bool $override override file if exists
+ * @return mixed stored_file object or false if error; may throw exception if duplicate found
+ */
+ public function upload_to_filepool($elname, $record, $override = true) {
}
}
<?php
-/**
- * Copyright (c) 2008, David R. Nadeau, NadeauSoftware.com.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * * Neither the names of David R. Nadeau or NadeauSoftware.com, nor
- * the names of its contributors may be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
- * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- */
-
-/*
- * This is a BSD License approved by the Open Source Initiative (OSI).
- * See: http://www.opensource.org/licenses/bsd-license.php
- */
-
-/**
- * Combine a base URL and a relative URL to produce a new
- * absolute URL. The base URL is often the URL of a page,
- * and the relative URL is a URL embedded on that page.
- *
- * This function implements the "absolutize" algorithm from
- * the RFC3986 specification for URLs.
- *
- * This function supports multi-byte characters with the UTF-8 encoding,
- * per the URL specification.
- *
- * Parameters:
- * baseUrl the absolute base URL.
- *
- * url the relative URL to convert.
- *
- * Return values:
- * An absolute URL that combines parts of the base and relative
- * URLs, or FALSE if the base URL is not absolute or if either
- * URL cannot be parsed.
- */
-function url_to_absolute( $baseUrl, $relativeUrl )
-{
- // If relative URL has a scheme, clean path and return.
- $r = split_url( $relativeUrl );
- if ( $r === FALSE )
- return FALSE;
- if ( !empty( $r['scheme'] ) )
- {
- if ( !empty( $r['path'] ) && $r['path'][0] == '/' )
- $r['path'] = url_remove_dot_segments( $r['path'] );
- return join_url( $r );
- }
-
- // Make sure the base URL is absolute.
- $b = split_url( $baseUrl );
- if ( $b === FALSE || empty( $b['scheme'] ) || empty( $b['host'] ) )
- return FALSE;
- $r['scheme'] = $b['scheme'];
-
- // If relative URL has an authority, clean path and return.
- if ( isset( $r['host'] ) )
- {
- if ( !empty( $r['path'] ) )
- $r['path'] = url_remove_dot_segments( $r['path'] );
- return join_url( $r );
- }
- unset( $r['port'] );
- unset( $r['user'] );
- unset( $r['pass'] );
-
- // Copy base authority.
- $r['host'] = $b['host'];
- if ( isset( $b['port'] ) ) $r['port'] = $b['port'];
- if ( isset( $b['user'] ) ) $r['user'] = $b['user'];
- if ( isset( $b['pass'] ) ) $r['pass'] = $b['pass'];
-
- // If relative URL has no path, use base path
- if ( empty( $r['path'] ) )
- {
- if ( !empty( $b['path'] ) )
- $r['path'] = $b['path'];
- if ( !isset( $r['query'] ) && isset( $b['query'] ) )
- $r['query'] = $b['query'];
- return join_url( $r );
- }
-
- // If relative URL path doesn't start with /, merge with base path
- if ( $r['path'][0] != '/' )
- {
- $base = mb_strrchr( $b['path'], '/', TRUE, 'UTF-8' );
- if ( $base === FALSE ) $base = '';
- $r['path'] = $base . '/' . $r['path'];
- }
- $r['path'] = url_remove_dot_segments( $r['path'] );
- return join_url( $r );
-}
-
-/**
- * Filter out "." and ".." segments from a URL's path and return
- * the result.
- *
- * This function implements the "remove_dot_segments" algorithm from
- * the RFC3986 specification for URLs.
- *
- * This function supports multi-byte characters with the UTF-8 encoding,
- * per the URL specification.
- *
- * Parameters:
- * path the path to filter
- *
- * Return values:
- * The filtered path with "." and ".." removed.
- */
-function url_remove_dot_segments( $path )
-{
- // multi-byte character explode
- $inSegs = preg_split( '!/!u', $path );
- $outSegs = array( );
- foreach ( $inSegs as $seg )
- {
- if ( $seg == '' || $seg == '.')
- continue;
- if ( $seg == '..' )
- array_pop( $outSegs );
- else
- array_push( $outSegs, $seg );
- }
- $outPath = implode( '/', $outSegs );
- if ( $path[0] == '/' )
- $outPath = '/' . $outPath;
- // compare last multi-byte character against '/'
- if ( $outPath != '/' &&
- (mb_strlen($path)-1) == mb_strrpos( $path, '/', 'UTF-8' ) )
- $outPath .= '/';
- return $outPath;
-}
-
-/**
- * This function parses an absolute or relative URL and splits it
- * into individual components.
- *
- * RFC3986 specifies the components of a Uniform Resource Identifier (URI).
- * A portion of the ABNFs are repeated here:
- *
- * URI-reference = URI
- * / relative-ref
- *
- * URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
- *
- * relative-ref = relative-part [ "?" query ] [ "#" fragment ]
- *
- * hier-part = "//" authority path-abempty
- * / path-absolute
- * / path-rootless
- * / path-empty
- *
- * relative-part = "//" authority path-abempty
- * / path-absolute
- * / path-noscheme
- * / path-empty
- *
- * authority = [ userinfo "@" ] host [ ":" port ]
- *
- * So, a URL has the following major components:
- *
- * scheme
- * The name of a method used to interpret the rest of
- * the URL. Examples: "http", "https", "mailto", "file'.
- *
- * authority
- * The name of the authority governing the URL's name
- * space. Examples: "example.com", "user@example.com",
- * "example.com:80", "user:password@example.com:80".
- *
- * The authority may include a host name, port number,
- * user name, and password.
- *
- * The host may be a name, an IPv4 numeric address, or
- * an IPv6 numeric address.
- *
- * path
- * The hierarchical path to the URL's resource.
- * Examples: "/index.htm", "/scripts/page.php".
- *
- * query
- * The data for a query. Examples: "?search=google.com".
- *
- * fragment
- * The name of a secondary resource relative to that named
- * by the path. Examples: "#section1", "#header".
- *
- * An "absolute" URL must include a scheme and path. The authority, query,
- * and fragment components are optional.
- *
- * A "relative" URL does not include a scheme and must include a path. The
- * authority, query, and fragment components are optional.
- *
- * This function splits the $url argument into the following components
- * and returns them in an associative array. Keys to that array include:
- *
- * "scheme" The scheme, such as "http".
- * "host" The host name, IPv4, or IPv6 address.
- * "port" The port number.
- * "user" The user name.
- * "pass" The user password.
- * "path" The path, such as a file path for "http".
- * "query" The query.
- * "fragment" The fragment.
- *
- * One or more of these may not be present, depending upon the URL.
- *
- * Optionally, the "user", "pass", "host" (if a name, not an IP address),
- * "path", "query", and "fragment" may have percent-encoded characters
- * decoded. The "scheme" and "port" cannot include percent-encoded
- * characters and are never decoded. Decoding occurs after the URL has
- * been parsed.
- *
- * Parameters:
- * url the URL to parse.
- *
- * decode an optional boolean flag selecting whether
- * to decode percent encoding or not. Default = TRUE.
- *
- * Return values:
- * the associative array of URL parts, or FALSE if the URL is
- * too malformed to recognize any parts.
- */
-function split_url( $url, $decode=TRUE )
-{
- // Character sets from RFC3986.
- $xunressub = 'a-zA-Z\d\-._~\!$&\'()*+,;=';
- $xpchar = $xunressub . ':@%';
-
- // Scheme from RFC3986.
- $xscheme = '([a-zA-Z][a-zA-Z\d+-.]*)';
-
- // User info (user + password) from RFC3986.
- $xuserinfo = '(([' . $xunressub . '%]*)' .
- '(:([' . $xunressub . ':%]*))?)';
-
- // IPv4 from RFC3986 (without digit constraints).
- $xipv4 = '(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})';
-
- // IPv6 from RFC2732 (without digit and grouping constraints).
- $xipv6 = '(\[([a-fA-F\d.:]+)\])';
-
- // Host name from RFC1035. Technically, must start with a letter.
- // Relax that restriction to better parse URL structure, then
- // leave host name validation to application.
- $xhost_name = '([a-zA-Z\d-.%]+)';
-
- // Authority from RFC3986. Skip IP future.
- $xhost = '(' . $xhost_name . '|' . $xipv4 . '|' . $xipv6 . ')';
- $xport = '(\d*)';
- $xauthority = '((' . $xuserinfo . '@)?' . $xhost .
- '?(:' . $xport . ')?)';
-
- // Path from RFC3986. Blend absolute & relative for efficiency.
- $xslash_seg = '(/[' . $xpchar . ']*)';
- $xpath_authabs = '((//' . $xauthority . ')((/[' . $xpchar . ']*)*))';
- $xpath_rel = '([' . $xpchar . ']+' . $xslash_seg . '*)';
- $xpath_abs = '(/(' . $xpath_rel . ')?)';
- $xapath = '(' . $xpath_authabs . '|' . $xpath_abs .
- '|' . $xpath_rel . ')';
-
- // Query and fragment from RFC3986.
- $xqueryfrag = '([' . $xpchar . '/?' . ']*)';
-
- // URL.
- $xurl = '^(' . $xscheme . ':)?' . $xapath . '?' .
- '(\?' . $xqueryfrag . ')?(#' . $xqueryfrag . ')?$';
-
-
- // Split the URL into components.
- if ( !preg_match( '!' . $xurl . '!', $url, $m ) )
- return FALSE;
-
- if ( !empty($m[2]) ) $parts['scheme'] = strtolower($m[2]);
-
- if ( !empty($m[7]) ) {
- if ( isset( $m[9] ) ) $parts['user'] = $m[9];
- else $parts['user'] = '';
- }
- if ( !empty($m[10]) ) $parts['pass'] = $m[11];
-
- if ( !empty($m[13]) ) $h=$parts['host'] = $m[13];
- else if ( !empty($m[14]) ) $parts['host'] = $m[14];
- else if ( !empty($m[16]) ) $parts['host'] = $m[16];
- else if ( !empty( $m[5] ) ) $parts['host'] = '';
- if ( !empty($m[17]) ) $parts['port'] = $m[18];
-
- if ( !empty($m[19]) ) $parts['path'] = $m[19];
- else if ( !empty($m[21]) ) $parts['path'] = $m[21];
- else if ( !empty($m[25]) ) $parts['path'] = $m[25];
-
- if ( !empty($m[27]) ) $parts['query'] = $m[28];
- if ( !empty($m[29]) ) $parts['fragment']= $m[30];
-
- if ( !$decode )
- return $parts;
- if ( !empty($parts['user']) )
- $parts['user'] = rawurldecode( $parts['user'] );
- if ( !empty($parts['pass']) )
- $parts['pass'] = rawurldecode( $parts['pass'] );
- if ( !empty($parts['path']) )
- $parts['path'] = rawurldecode( $parts['path'] );
- if ( isset($h) )
- $parts['host'] = rawurldecode( $parts['host'] );
- if ( !empty($parts['query']) )
- $parts['query'] = rawurldecode( $parts['query'] );
- if ( !empty($parts['fragment']) )
- $parts['fragment'] = rawurldecode( $parts['fragment'] );
- return $parts;
-}
+// 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/>.
/**
- * This function joins together URL components to form a complete URL.
- *
- * RFC3986 specifies the components of a Uniform Resource Identifier (URI).
- * This function implements the specification's "component recomposition"
- * algorithm for combining URI components into a full URI string.
- *
- * The $parts argument is an associative array containing zero or
- * more of the following:
- *
- * "scheme" The scheme, such as "http".
- * "host" The host name, IPv4, or IPv6 address.
- * "port" The port number.
- * "user" The user name.
- * "pass" The user password.
- * "path" The path, such as a file path for "http".
- * "query" The query.
- * "fragment" The fragment.
- *
- * The "port", "user", and "pass" values are only used when a "host"
- * is present.
- *
- * The optional $encode argument indicates if appropriate URL components
- * should be percent-encoded as they are assembled into the URL. Encoding
- * is only applied to the "user", "pass", "host" (if a host name, not an
- * IP address), "path", "query", and "fragment" components. The "scheme"
- * and "port" are never encoded. When a "scheme" and "host" are both
- * present, the "path" is presumed to be hierarchical and encoding
- * processes each segment of the hierarchy separately (i.e., the slashes
- * are left alone).
- *
- * The assembled URL string is returned.
- *
- * Parameters:
- * parts an associative array of strings containing the
- * individual parts of a URL.
- *
- * encode an optional boolean flag selecting whether
- * to do percent encoding or not. Default = true.
- *
- * Return values:
- * Returns the assembled URL string. The string is an absolute
- * URL if a scheme is supplied, and a relative URL if not. An
- * empty string is returned if the $parts array does not contain
- * any of the needed values.
- */
-function join_url( $parts, $encode=TRUE )
-{
- if ( $encode )
- {
- if ( isset( $parts['user'] ) )
- $parts['user'] = rawurlencode( $parts['user'] );
- if ( isset( $parts['pass'] ) )
- $parts['pass'] = rawurlencode( $parts['pass'] );
- if ( isset( $parts['host'] ) &&
- !preg_match( '!^(\[[\da-f.:]+\]])|([\da-f.:]+)$!ui', $parts['host'] ) )
- $parts['host'] = rawurlencode( $parts['host'] );
- if ( !empty( $parts['path'] ) )
- $parts['path'] = preg_replace( '!%2F!ui', '/',
- rawurlencode( $parts['path'] ) );
- if ( isset( $parts['query'] ) )
- $parts['query'] = rawurlencode( $parts['query'] );
- if ( isset( $parts['fragment'] ) )
- $parts['fragment'] = rawurlencode( $parts['fragment'] );
- }
-
- $url = '';
- if ( !empty( $parts['scheme'] ) )
- $url .= $parts['scheme'] . ':';
- if ( isset( $parts['host'] ) )
- {
- $url .= '//';
- if ( isset( $parts['user'] ) )
- {
- $url .= $parts['user'];
- if ( isset( $parts['pass'] ) )
- $url .= ':' . $parts['pass'];
- $url .= '@';
- }
- if ( preg_match( '!^[\da-f]*:[\da-f.:]+$!ui', $parts['host'] ) )
- $url .= '[' . $parts['host'] . ']'; // IPv6
- else
- $url .= $parts['host']; // IPv4 or name
- if ( isset( $parts['port'] ) )
- $url .= ':' . $parts['port'];
- if ( !empty( $parts['path'] ) && $parts['path'][0] != '/' )
- $url .= '/';
- }
- if ( !empty( $parts['path'] ) )
- $url .= $parts['path'];
- if ( isset( $parts['query'] ) )
- $url .= '?' . $parts['query'];
- if ( isset( $parts['fragment'] ) )
- $url .= '#' . $parts['fragment'];
- return $url;
-}
-/**
- * Extract URLs from a web page.
- *
- * URLs are extracted from a long list of tags and attributes as defined
- * by the HTML 2.0, HTML 3.2, HTML 4.01, and draft HTML 5.0 specifications.
- * URLs are also extracted from tags and attributes that are common
- * extensions of HTML, from the draft Forms 2.0 specification, from XHTML,
- * and from WML 1.3 and 2.0.
- *
- * The function returns an associative array of associative arrays of
- * arrays of URLs. The outermost array's keys are the tag (element) name,
- * such as "a" for <a> or "img" for <img>. The values for these entries
- * are associative arrays where the keys are attribute names for those
- * tags, such as "href" for <a href="...">. Finally, the values for
- * those arrays are URLs found in those tags and attributes throughout
- * the text.
- *
- * Parameters:
- * text the UTF-8 text to scan
- *
- * Return values:
- * an associative array where keys are tags and values are an
- * associative array where keys are attributes and values are
- * an array of URLs.
- *
- * See:
- * http://nadeausoftware.com/articles/2008/01/php_tip_how_extract_urls_web_page
+ * repository_url class
+ * A subclass of repository, which is used to download a file from a specific url
+ *
+ * @since 2.0
+ * @package moodlecore
+ * @subpackage repository
+ * @copyright 2009 Dongsheng Cai
+ * @author Dongsheng Cai <dongsheng@moodle.com>
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-function extract_html_urls( $text )
-{
- $match_elements = array(
- // HTML
- array('element'=>'a', 'attribute'=>'href'), // 2.0
- array('element'=>'a', 'attribute'=>'urn'), // 2.0
- array('element'=>'base', 'attribute'=>'href'), // 2.0
- array('element'=>'form', 'attribute'=>'action'), // 2.0
- array('element'=>'img', 'attribute'=>'src'), // 2.0
- array('element'=>'link', 'attribute'=>'href'), // 2.0
-
- array('element'=>'applet', 'attribute'=>'code'), // 3.2
- array('element'=>'applet', 'attribute'=>'codebase'), // 3.2
- array('element'=>'area', 'attribute'=>'href'), // 3.2
- array('element'=>'body', 'attribute'=>'background'), // 3.2
- array('element'=>'img', 'attribute'=>'usemap'), // 3.2
- array('element'=>'input', 'attribute'=>'src'), // 3.2
-
- array('element'=>'applet', 'attribute'=>'archive'), // 4.01
- array('element'=>'applet', 'attribute'=>'object'), // 4.01
- array('element'=>'blockquote', 'attribute'=>'cite'), // 4.01
- array('element'=>'del', 'attribute'=>'cite'), // 4.01
- array('element'=>'frame', 'attribute'=>'longdesc'), // 4.01
- array('element'=>'frame', 'attribute'=>'src'), // 4.01
- array('element'=>'head', 'attribute'=>'profile'), // 4.01
- array('element'=>'iframe', 'attribute'=>'longdesc'), // 4.01
- array('element'=>'iframe', 'attribute'=>'src'), // 4.01
- array('element'=>'img', 'attribute'=>'longdesc'), // 4.01
- array('element'=>'input', 'attribute'=>'usemap'), // 4.01
- array('element'=>'ins', 'attribute'=>'cite'), // 4.01
- array('element'=>'object', 'attribute'=>'archive'), // 4.01
- array('element'=>'object', 'attribute'=>'classid'), // 4.01
- array('element'=>'object', 'attribute'=>'codebase'), // 4.01
- array('element'=>'object', 'attribute'=>'data'), // 4.01
- array('element'=>'object', 'attribute'=>'usemap'), // 4.01
- array('element'=>'q', 'attribute'=>'cite'), // 4.01
- array('element'=>'script', 'attribute'=>'src'), // 4.01
-
- array('element'=>'audio', 'attribute'=>'src'), // 5.0
- array('element'=>'command', 'attribute'=>'icon'), // 5.0
- array('element'=>'embed', 'attribute'=>'src'), // 5.0
- array('element'=>'event-source','attribute'=>'src'), // 5.0
- array('element'=>'html', 'attribute'=>'manifest'), // 5.0
- array('element'=>'source', 'attribute'=>'src'), // 5.0
- array('element'=>'video', 'attribute'=>'src'), // 5.0
- array('element'=>'video', 'attribute'=>'poster'), // 5.0
-
- array('element'=>'bgsound', 'attribute'=>'src'), // Extension
- array('element'=>'body', 'attribute'=>'credits'), // Extension
- array('element'=>'body', 'attribute'=>'instructions'), // Extension
- array('element'=>'body', 'attribute'=>'logo'), // Extension
- array('element'=>'div', 'attribute'=>'href'), // Extension
- array('element'=>'div', 'attribute'=>'src'), // Extension
- array('element'=>'embed', 'attribute'=>'code'), // Extension
- array('element'=>'embed', 'attribute'=>'pluginspage'), // Extension
- array('element'=>'html', 'attribute'=>'background'), // Extension
- array('element'=>'ilayer', 'attribute'=>'src'), // Extension
- array('element'=>'img', 'attribute'=>'dynsrc'), // Extension
- array('element'=>'img', 'attribute'=>'lowsrc'), // Extension
- array('element'=>'input', 'attribute'=>'dynsrc'), // Extension
- array('element'=>'input', 'attribute'=>'lowsrc'), // Extension
- array('element'=>'table', 'attribute'=>'background'), // Extension
- array('element'=>'td', 'attribute'=>'background'), // Extension
- array('element'=>'th', 'attribute'=>'background'), // Extension
- array('element'=>'layer', 'attribute'=>'src'), // Extension
- array('element'=>'xml', 'attribute'=>'src'), // Extension
-
- array('element'=>'button', 'attribute'=>'action'), // Forms 2.0
- array('element'=>'datalist', 'attribute'=>'data'), // Forms 2.0
- array('element'=>'form', 'attribute'=>'data'), // Forms 2.0
- array('element'=>'input', 'attribute'=>'action'), // Forms 2.0
- array('element'=>'select', 'attribute'=>'data'), // Forms 2.0
-
- // XHTML
- array('element'=>'html', 'attribute'=>'xmlns'),
-
- // WML
- array('element'=>'access', 'attribute'=>'path'), // 1.3
- array('element'=>'card', 'attribute'=>'onenterforward'), // 1.3
- array('element'=>'card', 'attribute'=>'onenterbackward'),// 1.3
- array('element'=>'card', 'attribute'=>'ontimer'), // 1.3
- array('element'=>'go', 'attribute'=>'href'), // 1.3
- array('element'=>'option', 'attribute'=>'onpick'), // 1.3
- array('element'=>'template', 'attribute'=>'onenterforward'), // 1.3
- array('element'=>'template', 'attribute'=>'onenterbackward'),// 1.3
- array('element'=>'template', 'attribute'=>'ontimer'), // 1.3
- array('element'=>'wml', 'attribute'=>'xmlns'), // 2.0
- );
-
- $match_metas = array(
- 'content-base',
- 'content-location',
- 'referer',
- 'location',
- 'refresh',
- );
-
- // Extract all elements
- if ( !preg_match_all( '/<([a-z][^>]*)>/iu', $text, $matches ) )
- return array( );
- $elements = $matches[1];
- $value_pattern = '=(("([^"]*)")|([^\s]*))';
-
- // Match elements and attributes
- foreach ( $match_elements as $match_element )
- {
- $name = $match_element['element'];
- $attr = $match_element['attribute'];
- $pattern = '/^' . $name . '\s.*' . $attr . $value_pattern . '/iu';
- if ( $name == 'object' )
- $split_pattern = '/\s*/u'; // Space-separated URL list
- else if ( $name == 'archive' )
- $split_pattern = '/,\s*/u'; // Comma-separated URL list
- else
- unset( $split_pattern ); // Single URL
- foreach ( $elements as $element )
- {
- if ( !preg_match( $pattern, $element, $match ) )
- continue;
- $m = empty($match[3]) ? (!empty($match[4])?$match[4]:'') : $match[3];
- if ( !isset( $split_pattern ) )
- $urls[$name][$attr][] = $m;
- else
- {
- $msplit = preg_split( $split_pattern, $m );
- foreach ( $msplit as $ms )
- $urls[$name][$attr][] = $ms;
- }
- }
- }
-
- // Match meta http-equiv elements
- foreach ( $match_metas as $match_meta )
- {
- $attr_pattern = '/http-equiv="?' . $match_meta . '"?/iu';
- $content_pattern = '/content' . $value_pattern . '/iu';
- $refresh_pattern = '/\d*;\s*(url=)?(.*)$/iu';
- foreach ( $elements as $element )
- {
- if ( !preg_match( '/^meta/iu', $element ) ||
- !preg_match( $attr_pattern, $element ) ||
- !preg_match( $content_pattern, $element, $match ) )
- continue;
- $m = empty($match[3]) ? $match[4] : $match[3];
- if ( $match_meta != 'refresh' )
- $urls['meta']['http-equiv'][] = $m;
- else if ( preg_match( $refresh_pattern, $m, $match ) )
- $urls['meta']['http-equiv'][] = $match[2];
- }
- }
- // Match style attributes
- $urls['style'] = array( );
- $style_pattern = '/style' . $value_pattern . '/iu';
- foreach ( $elements as $element )
- {
- if ( !preg_match( $style_pattern, $element, $match ) )
- continue;
- $m = empty($match[3]) ? $match[4] : $match[3];
- $style_urls = extract_css_urls( $m );
- if ( !empty( $style_urls ) )
- $urls['style'] = array_merge_recursive(
- $urls['style'], $style_urls );
- }
-
- // Match style bodies
- if ( preg_match_all( '/<style[^>]*>(.*?)<\/style>/siu', $text, $style_bodies ) )
- {
- foreach ( $style_bodies[1] as $style_body )
- {
- $style_urls = extract_css_urls( $style_body );
- if ( !empty( $style_urls ) )
- $urls['style'] = array_merge_recursive(
- $urls['style'], $style_urls );
- }
- }
- if ( empty($urls['style']) )
- unset( $urls['style'] );
-
- return $urls;
+require_once(dirname(__FILE__).'/locallib.php');
+
+class repository_url extends repository {
+
+ /**
+ * @param int $repositoryid
+ * @param object $context
+ * @param array $options
+ */
+ public function __construct($repositoryid, $context = SYSCONTEXTID, $options = array()){
+ global $CFG;
+ parent::__construct($repositoryid, $context, $options);
+ if (!empty($options['client_id'])) {
+ // will be used to construct download form
+ $this->client_id = $options['client_id'];
+ }
+ $this->file_url = optional_param('file', '', PARAM_RAW);
+ }
+
+ public function get_file($url, $file = '') {
+ global $CFG;
+ //$CFG->repository_no_delete = true;
+ $path = $this->prepare_file($file);
+ $fp = fopen($path, 'w');
+ $c = new curl;
+ $c->download(array(array('url'=>$url, 'file'=>$fp)));
+ return array('path'=>$path, 'url'=>$url);
+ }
+
+ public function check_login() {
+ if (!empty($this->file_url)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ /**
+ * @return mixed
+ */
+ public function print_login() {
+ $strdownload = get_string('download', 'repository');
+ $strname = get_string('rename', 'repository_url');
+ $strurl = get_string('url', 'repository_url');
+ if ($this->options['ajax']) {
+ $url = new stdclass;
+ $url->label = $strurl.': ';
+ $url->id = 'fileurl-'.$this->client_id;
+ $url->type = 'text';
+ $url->name = 'file';
+
+ $ret['login'] = array($url);
+ $ret['login_btn_label'] = get_string('download', 'repository_url');
+ return $ret;
+ } else {
+ echo <<<EOD
+<table>
+<tr>
+<td>{$strurl}: </td><td><input name="file" type="text" /></td>
+</tr>
+</table>
+<input type="submit" value="{$strdownload}" />
+EOD;
+
+ }
+ }
+
+ /**
+ * @param mixed $path
+ * @param string $search
+ * @return array
+ */
+ public function get_listing($path='', $page='') {
+ global $CFG, $OUTPUT;
+ $ret = array();
+ $curl = new curl;
+ $msg = $curl->head($this->file_url);
+ $info = $curl->get_info();
+ if ($info['http_code'] != 200) {
+ $ret['e'] = $msg;
+ } else {
+ $ret['list'] = array();
+ $ret['nosearch'] = true;
+ $ret['nologin'] = true;
+ $filename = $this->guess_filename($info['url'], $info['content_type']);
+ if (strstr($info['content_type'], 'text/html') || empty($info['content_type'])) {
+ // analysis this web page, general file list
+ $ret['list'] = array();
+ $content = $curl->get($info['url']);
+ $this->analyse_page($info['url'], $content, $ret);
+ } else {
+ // download this file
+ $ret['list'][] = array(
+ 'title'=>$filename,
+ 'source'=>$this->file_url,
+ 'thumbnail' => $OUTPUT->pix_url(file_extension_icon($filename, 32))
+ );
+ }
+ }
+ return $ret;
+ }
+ public function analyse_page($baseurl, $content, &$list) {
+ global $CFG, $OUTPUT;
+ $urls = extract_html_urls($content);
+ $images = $urls['img']['src'];
+ $pattern = '#img(.+)src="?\'?([[:alnum:]:?=&@/._+-]+)"?\'?#i';
+ if (!empty($images)) {
+ foreach($images as $url) {
+ $list['list'][] = array(
+ 'title'=>$this->guess_filename($url, ''),
+ 'source'=>url_to_absolute($baseurl, $url),
+ 'thumbnail'=>url_to_absolute($baseurl, $url),
+ 'thumbnail_height'=>84,
+ 'thumbnail_width'=>84
+ );
+ }
+ }
+ }
+ public function guess_filename($url, $type) {
+ $pattern = '#\/([\w_\?\-.]+)$#';
+ $matches = null;
+ preg_match($pattern, $url, $matches);
+ if (empty($matches[1])) {
+ return $url;
+ } else {
+ return $matches[1];
+ }
+ }
+
+ public function get_name(){
+ return get_string('pluginname', 'repository_url');;
+ }
+ public function supported_returntypes() {
+ return (FILE_INTERNAL | FILE_EXTERNAL);
+ }
}
-/**
- * Extract URLs from UTF-8 CSS text.
- *
- * URLs within @import statements and url() property functions are extracted
- * and returned in an associative array of arrays. Array keys indicate
- * the use context for the URL, including:
- *
- * "import"
- * "property"
- *
- * Each value in the associative array is an array of URLs.
- *
- * Parameters:
- * text the UTF-8 text to scan
- *
- * Return values:
- * an associative array of arrays of URLs.
- *
- * See:
- * http://nadeausoftware.com/articles/2008/01/php_tip_how_extract_urls_css_file
- */
-function extract_css_urls( $text )
-{
- $urls = array( );
-
- $url_pattern = '(([^\\\\\'", \(\)]*(\\\\.)?)+)';
- $urlfunc_pattern = 'url\(\s*[\'"]?' . $url_pattern . '[\'"]?\s*\)';
- $pattern = '/(' .
- '(@import\s*[\'"]' . $url_pattern . '[\'"])' .
- '|(@import\s*' . $urlfunc_pattern . ')' .
- '|(' . $urlfunc_pattern . ')' . ')/iu';
- if ( !preg_match_all( $pattern, $text, $matches ) )
- return $urls;
-
- // @import '...'
- // @import "..."
- foreach ( $matches[3] as $match )
- if ( !empty($match) )
- $urls['import'][] =
- preg_replace( '/\\\\(.)/u', '\\1', $match );
- // @import url(...)
- // @import url('...')
- // @import url("...")
- foreach ( $matches[7] as $match )
- if ( !empty($match) )
- $urls['import'][] =
- preg_replace( '/\\\\(.)/u', '\\1', $match );
-
- // url(...)
- // url('...')
- // url("...")
- foreach ( $matches[11] as $match )
- if ( !empty($match) )
- $urls['property'][] =
- preg_replace( '/\\\\(.)/u', '\\1', $match );
-
- return $urls;
-}
--- /dev/null
+<?php
+
+/**
+ * Copyright (c) 2008, David R. Nadeau, NadeauSoftware.com.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * * Neither the names of David R. Nadeau or NadeauSoftware.com, nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ */
+
+/*
+ * This is a BSD License approved by the Open Source Initiative (OSI).
+ * See: http://www.opensource.org/licenses/bsd-license.php
+ */
+
+/**
+ * Combine a base URL and a relative URL to produce a new
+ * absolute URL. The base URL is often the URL of a page,
+ * and the relative URL is a URL embedded on that page.
+ *
+ * This function implements the "absolutize" algorithm from
+ * the RFC3986 specification for URLs.
+ *
+ * This function supports multi-byte characters with the UTF-8 encoding,
+ * per the URL specification.
+ *
+ * Parameters:
+ * baseUrl the absolute base URL.
+ *
+ * url the relative URL to convert.
+ *
+ * Return values:
+ * An absolute URL that combines parts of the base and relative
+ * URLs, or FALSE if the base URL is not absolute or if either
+ * URL cannot be parsed.
+ */
+function url_to_absolute( $baseUrl, $relativeUrl )
+{
+ // If relative URL has a scheme, clean path and return.
+ $r = split_url( $relativeUrl );
+ if ( $r === FALSE )
+ return FALSE;
+ if ( !empty( $r['scheme'] ) )
+ {
+ if ( !empty( $r['path'] ) && $r['path'][0] == '/' )
+ $r['path'] = url_remove_dot_segments( $r['path'] );
+ return join_url( $r );
+ }
+
+ // Make sure the base URL is absolute.
+ $b = split_url( $baseUrl );
+ if ( $b === FALSE || empty( $b['scheme'] ) || empty( $b['host'] ) )
+ return FALSE;
+ $r['scheme'] = $b['scheme'];
+
+ // If relative URL has an authority, clean path and return.
+ if ( isset( $r['host'] ) )
+ {
+ if ( !empty( $r['path'] ) )
+ $r['path'] = url_remove_dot_segments( $r['path'] );
+ return join_url( $r );
+ }
+ unset( $r['port'] );
+ unset( $r['user'] );
+ unset( $r['pass'] );
+
+ // Copy base authority.
+ $r['host'] = $b['host'];
+ if ( isset( $b['port'] ) ) $r['port'] = $b['port'];
+ if ( isset( $b['user'] ) ) $r['user'] = $b['user'];
+ if ( isset( $b['pass'] ) ) $r['pass'] = $b['pass'];
+
+ // If relative URL has no path, use base path
+ if ( empty( $r['path'] ) )
+ {
+ if ( !empty( $b['path'] ) )
+ $r['path'] = $b['path'];
+ if ( !isset( $r['query'] ) && isset( $b['query'] ) )
+ $r['query'] = $b['query'];
+ return join_url( $r );
+ }
+
+ // If relative URL path doesn't start with /, merge with base path
+ if ( $r['path'][0] != '/' )
+ {
+ $base = mb_strrchr( $b['path'], '/', TRUE, 'UTF-8' );
+ if ( $base === FALSE ) $base = '';
+ $r['path'] = $base . '/' . $r['path'];
+ }
+ $r['path'] = url_remove_dot_segments( $r['path'] );
+ return join_url( $r );
+}
+
+/**
+ * Filter out "." and ".." segments from a URL's path and return
+ * the result.
+ *
+ * This function implements the "remove_dot_segments" algorithm from
+ * the RFC3986 specification for URLs.
+ *
+ * This function supports multi-byte characters with the UTF-8 encoding,
+ * per the URL specification.
+ *
+ * Parameters:
+ * path the path to filter
+ *
+ * Return values:
+ * The filtered path with "." and ".." removed.
+ */
+function url_remove_dot_segments( $path )
+{
+ // multi-byte character explode
+ $inSegs = preg_split( '!/!u', $path );
+ $outSegs = array( );
+ foreach ( $inSegs as $seg )
+ {
+ if ( $seg == '' || $seg == '.')
+ continue;
+ if ( $seg == '..' )
+ array_pop( $outSegs );
+ else
+ array_push( $outSegs, $seg );
+ }
+ $outPath = implode( '/', $outSegs );
+ if ( $path[0] == '/' )
+ $outPath = '/' . $outPath;
+ // compare last multi-byte character against '/'
+ if ( $outPath != '/' &&
+ (mb_strlen($path)-1) == mb_strrpos( $path, '/', 'UTF-8' ) )
+ $outPath .= '/';
+ return $outPath;
+}
+
+/**
+ * This function parses an absolute or relative URL and splits it
+ * into individual components.
+ *
+ * RFC3986 specifies the components of a Uniform Resource Identifier (URI).
+ * A portion of the ABNFs are repeated here:
+ *
+ * URI-reference = URI
+ * / relative-ref
+ *
+ * URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
+ *
+ * relative-ref = relative-part [ "?" query ] [ "#" fragment ]
+ *
+ * hier-part = "//" authority path-abempty
+ * / path-absolute
+ * / path-rootless
+ * / path-empty
+ *
+ * relative-part = "//" authority path-abempty
+ * / path-absolute
+ * / path-noscheme
+ * / path-empty
+ *
+ * authority = [ userinfo "@" ] host [ ":" port ]
+ *
+ * So, a URL has the following major components:
+ *
+ * scheme
+ * The name of a method used to interpret the rest of
+ * the URL. Examples: "http", "https", "mailto", "file'.
+ *
+ * authority
+ * The name of the authority governing the URL's name
+ * space. Examples: "example.com", "user@example.com",
+ * "example.com:80", "user:password@example.com:80".
+ *
+ * The authority may include a host name, port number,
+ * user name, and password.
+ *
+ * The host may be a name, an IPv4 numeric address, or
+ * an IPv6 numeric address.
+ *
+ * path
+ * The hierarchical path to the URL's resource.
+ * Examples: "/index.htm", "/scripts/page.php".
+ *
+ * query
+ * The data for a query. Examples: "?search=google.com".
+ *
+ * fragment
+ * The name of a secondary resource relative to that named
+ * by the path. Examples: "#section1", "#header".
+ *
+ * An "absolute" URL must include a scheme and path. The authority, query,
+ * and fragment components are optional.
+ *
+ * A "relative" URL does not include a scheme and must include a path. The
+ * authority, query, and fragment components are optional.
+ *
+ * This function splits the $url argument into the following components
+ * and returns them in an associative array. Keys to that array include:
+ *
+ * "scheme" The scheme, such as "http".
+ * "host" The host name, IPv4, or IPv6 address.
+ * "port" The port number.
+ * "user" The user name.
+ * "pass" The user password.
+ * "path" The path, such as a file path for "http".
+ * "query" The query.
+ * "fragment" The fragment.
+ *
+ * One or more of these may not be present, depending upon the URL.
+ *
+ * Optionally, the "user", "pass", "host" (if a name, not an IP address),
+ * "path", "query", and "fragment" may have percent-encoded characters
+ * decoded. The "scheme" and "port" cannot include percent-encoded
+ * characters and are never decoded. Decoding occurs after the URL has
+ * been parsed.
+ *
+ * Parameters:
+ * url the URL to parse.
+ *
+ * decode an optional boolean flag selecting whether
+ * to decode percent encoding or not. Default = TRUE.
+ *
+ * Return values:
+ * the associative array of URL parts, or FALSE if the URL is
+ * too malformed to recognize any parts.
+ */
+function split_url( $url, $decode=TRUE )
+{
+ // Character sets from RFC3986.
+ $xunressub = 'a-zA-Z\d\-._~\!$&\'()*+,;=';
+ $xpchar = $xunressub . ':@%';
+
+ // Scheme from RFC3986.
+ $xscheme = '([a-zA-Z][a-zA-Z\d+-.]*)';
+
+ // User info (user + password) from RFC3986.
+ $xuserinfo = '(([' . $xunressub . '%]*)' .
+ '(:([' . $xunressub . ':%]*))?)';
+
+ // IPv4 from RFC3986 (without digit constraints).
+ $xipv4 = '(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})';
+
+ // IPv6 from RFC2732 (without digit and grouping constraints).
+ $xipv6 = '(\[([a-fA-F\d.:]+)\])';
+
+ // Host name from RFC1035. Technically, must start with a letter.
+ // Relax that restriction to better parse URL structure, then
+ // leave host name validation to application.
+ $xhost_name = '([a-zA-Z\d-.%]+)';
+
+ // Authority from RFC3986. Skip IP future.
+ $xhost = '(' . $xhost_name . '|' . $xipv4 . '|' . $xipv6 . ')';
+ $xport = '(\d*)';
+ $xauthority = '((' . $xuserinfo . '@)?' . $xhost .
+ '?(:' . $xport . ')?)';
+
+ // Path from RFC3986. Blend absolute & relative for efficiency.
+ $xslash_seg = '(/[' . $xpchar . ']*)';
+ $xpath_authabs = '((//' . $xauthority . ')((/[' . $xpchar . ']*)*))';
+ $xpath_rel = '([' . $xpchar . ']+' . $xslash_seg . '*)';
+ $xpath_abs = '(/(' . $xpath_rel . ')?)';
+ $xapath = '(' . $xpath_authabs . '|' . $xpath_abs .
+ '|' . $xpath_rel . ')';
+
+ // Query and fragment from RFC3986.
+ $xqueryfrag = '([' . $xpchar . '/?' . ']*)';
+
+ // URL.
+ $xurl = '^(' . $xscheme . ':)?' . $xapath . '?' .
+ '(\?' . $xqueryfrag . ')?(#' . $xqueryfrag . ')?$';
+
+
+ // Split the URL into components.
+ if ( !preg_match( '!' . $xurl . '!', $url, $m ) )
+ return FALSE;
+
+ if ( !empty($m[2]) ) $parts['scheme'] = strtolower($m[2]);
+
+ if ( !empty($m[7]) ) {
+ if ( isset( $m[9] ) ) $parts['user'] = $m[9];
+ else $parts['user'] = '';
+ }
+ if ( !empty($m[10]) ) $parts['pass'] = $m[11];
+
+ if ( !empty($m[13]) ) $h=$parts['host'] = $m[13];
+ else if ( !empty($m[14]) ) $parts['host'] = $m[14];
+ else if ( !empty($m[16]) ) $parts['host'] = $m[16];
+ else if ( !empty( $m[5] ) ) $parts['host'] = '';
+ if ( !empty($m[17]) ) $parts['port'] = $m[18];
+
+ if ( !empty($m[19]) ) $parts['path'] = $m[19];
+ else if ( !empty($m[21]) ) $parts['path'] = $m[21];
+ else if ( !empty($m[25]) ) $parts['path'] = $m[25];
+
+ if ( !empty($m[27]) ) $parts['query'] = $m[28];
+ if ( !empty($m[29]) ) $parts['fragment']= $m[30];
+
+ if ( !$decode )
+ return $parts;
+ if ( !empty($parts['user']) )
+ $parts['user'] = rawurldecode( $parts['user'] );
+ if ( !empty($parts['pass']) )
+ $parts['pass'] = rawurldecode( $parts['pass'] );
+ if ( !empty($parts['path']) )
+ $parts['path'] = rawurldecode( $parts['path'] );
+ if ( isset($h) )
+ $parts['host'] = rawurldecode( $parts['host'] );
+ if ( !empty($parts['query']) )
+ $parts['query'] = rawurldecode( $parts['query'] );
+ if ( !empty($parts['fragment']) )
+ $parts['fragment'] = rawurldecode( $parts['fragment'] );
+ return $parts;
+}
+
+/**
+ * This function joins together URL components to form a complete URL.
+ *
+ * RFC3986 specifies the components of a Uniform Resource Identifier (URI).
+ * This function implements the specification's "component recomposition"
+ * algorithm for combining URI components into a full URI string.
+ *
+ * The $parts argument is an associative array containing zero or
+ * more of the following:
+ *
+ * "scheme" The scheme, such as "http".
+ * "host" The host name, IPv4, or IPv6 address.
+ * "port" The port number.
+ * "user" The user name.
+ * "pass" The user password.
+ * "path" The path, such as a file path for "http".
+ * "query" The query.
+ * "fragment" The fragment.
+ *
+ * The "port", "user", and "pass" values are only used when a "host"
+ * is present.
+ *
+ * The optional $encode argument indicates if appropriate URL components
+ * should be percent-encoded as they are assembled into the URL. Encoding
+ * is only applied to the "user", "pass", "host" (if a host name, not an
+ * IP address), "path", "query", and "fragment" components. The "scheme"
+ * and "port" are never encoded. When a "scheme" and "host" are both
+ * present, the "path" is presumed to be hierarchical and encoding
+ * processes each segment of the hierarchy separately (i.e., the slashes
+ * are left alone).
+ *
+ * The assembled URL string is returned.
+ *
+ * Parameters:
+ * parts an associative array of strings containing the
+ * individual parts of a URL.
+ *
+ * encode an optional boolean flag selecting whether
+ * to do percent encoding or not. Default = true.
+ *
+ * Return values:
+ * Returns the assembled URL string. The string is an absolute
+ * URL if a scheme is supplied, and a relative URL if not. An
+ * empty string is returned if the $parts array does not contain
+ * any of the needed values.
+ */
+function join_url( $parts, $encode=TRUE )
+{
+ if ( $encode )
+ {
+ if ( isset( $parts['user'] ) )
+ $parts['user'] = rawurlencode( $parts['user'] );
+ if ( isset( $parts['pass'] ) )
+ $parts['pass'] = rawurlencode( $parts['pass'] );
+ if ( isset( $parts['host'] ) &&
+ !preg_match( '!^(\[[\da-f.:]+\]])|([\da-f.:]+)$!ui', $parts['host'] ) )
+ $parts['host'] = rawurlencode( $parts['host'] );
+ if ( !empty( $parts['path'] ) )
+ $parts['path'] = preg_replace( '!%2F!ui', '/',
+ rawurlencode( $parts['path'] ) );
+ if ( isset( $parts['query'] ) )
+ $parts['query'] = rawurlencode( $parts['query'] );
+ if ( isset( $parts['fragment'] ) )
+ $parts['fragment'] = rawurlencode( $parts['fragment'] );
+ }
+
+ $url = '';
+ if ( !empty( $parts['scheme'] ) )
+ $url .= $parts['scheme'] . ':';
+ if ( isset( $parts['host'] ) )
+ {
+ $url .= '//';
+ if ( isset( $parts['user'] ) )
+ {
+ $url .= $parts['user'];
+ if ( isset( $parts['pass'] ) )
+ $url .= ':' . $parts['pass'];
+ $url .= '@';
+ }
+ if ( preg_match( '!^[\da-f]*:[\da-f.:]+$!ui', $parts['host'] ) )
+ $url .= '[' . $parts['host'] . ']'; // IPv6
+ else
+ $url .= $parts['host']; // IPv4 or name
+ if ( isset( $parts['port'] ) )
+ $url .= ':' . $parts['port'];
+ if ( !empty( $parts['path'] ) && $parts['path'][0] != '/' )
+ $url .= '/';
+ }
+ if ( !empty( $parts['path'] ) )
+ $url .= $parts['path'];
+ if ( isset( $parts['query'] ) )
+ $url .= '?' . $parts['query'];
+ if ( isset( $parts['fragment'] ) )
+ $url .= '#' . $parts['fragment'];
+ return $url;
+}
+/**
+ * Extract URLs from a web page.
+ *
+ * URLs are extracted from a long list of tags and attributes as defined
+ * by the HTML 2.0, HTML 3.2, HTML 4.01, and draft HTML 5.0 specifications.
+ * URLs are also extracted from tags and attributes that are common
+ * extensions of HTML, from the draft Forms 2.0 specification, from XHTML,
+ * and from WML 1.3 and 2.0.
+ *
+ * The function returns an associative array of associative arrays of
+ * arrays of URLs. The outermost array's keys are the tag (element) name,
+ * such as "a" for <a> or "img" for <img>. The values for these entries
+ * are associative arrays where the keys are attribute names for those
+ * tags, such as "href" for <a href="...">. Finally, the values for
+ * those arrays are URLs found in those tags and attributes throughout
+ * the text.
+ *
+ * Parameters:
+ * text the UTF-8 text to scan
+ *
+ * Return values:
+ * an associative array where keys are tags and values are an
+ * associative array where keys are attributes and values are
+ * an array of URLs.
+ *
+ * See:
+ * http://nadeausoftware.com/articles/2008/01/php_tip_how_extract_urls_web_page
+ */
+function extract_html_urls( $text )
+{
+ $match_elements = array(
+ // HTML
+ array('element'=>'a', 'attribute'=>'href'), // 2.0
+ array('element'=>'a', 'attribute'=>'urn'), // 2.0
+ array('element'=>'base', 'attribute'=>'href'), // 2.0
+ array('element'=>'form', 'attribute'=>'action'), // 2.0
+ array('element'=>'img', 'attribute'=>'src'), // 2.0
+ array('element'=>'link', 'attribute'=>'href'), // 2.0
+
+ array('element'=>'applet', 'attribute'=>'code'), // 3.2
+ array('element'=>'applet', 'attribute'=>'codebase'), // 3.2
+ array('element'=>'area', 'attribute'=>'href'), // 3.2
+ array('element'=>'body', 'attribute'=>'background'), // 3.2
+ array('element'=>'img', 'attribute'=>'usemap'), // 3.2
+ array('element'=>'input', 'attribute'=>'src'), // 3.2
+
+ array('element'=>'applet', 'attribute'=>'archive'), // 4.01
+ array('element'=>'applet', 'attribute'=>'object'), // 4.01
+ array('element'=>'blockquote', 'attribute'=>'cite'), // 4.01
+ array('element'=>'del', 'attribute'=>'cite'), // 4.01
+ array('element'=>'frame', 'attribute'=>'longdesc'), // 4.01
+ array('element'=>'frame', 'attribute'=>'src'), // 4.01
+ array('element'=>'head', 'attribute'=>'profile'), // 4.01
+ array('element'=>'iframe', 'attribute'=>'longdesc'), // 4.01
+ array('element'=>'iframe', 'attribute'=>'src'), // 4.01
+ array('element'=>'img', 'attribute'=>'longdesc'), // 4.01
+ array('element'=>'input', 'attribute'=>'usemap'), // 4.01
+ array('element'=>'ins', 'attribute'=>'cite'), // 4.01
+ array('element'=>'object', 'attribute'=>'archive'), // 4.01
+ array('element'=>'object', 'attribute'=>'classid'), // 4.01
+ array('element'=>'object', 'attribute'=>'codebase'), // 4.01
+ array('element'=>'object', 'attribute'=>'data'), // 4.01
+ array('element'=>'object', 'attribute'=>'usemap'), // 4.01
+ array('element'=>'q', 'attribute'=>'cite'), // 4.01
+ array('element'=>'script', 'attribute'=>'src'), // 4.01
+
+ array('element'=>'audio', 'attribute'=>'src'), // 5.0
+ array('element'=>'command', 'attribute'=>'icon'), // 5.0
+ array('element'=>'embed', 'attribute'=>'src'), // 5.0
+ array('element'=>'event-source','attribute'=>'src'), // 5.0
+ array('element'=>'html', 'attribute'=>'manifest'), // 5.0
+ array('element'=>'source', 'attribute'=>'src'), // 5.0
+ array('element'=>'video', 'attribute'=>'src'), // 5.0
+ array('element'=>'video', 'attribute'=>'poster'), // 5.0
+
+ array('element'=>'bgsound', 'attribute'=>'src'), // Extension
+ array('element'=>'body', 'attribute'=>'credits'), // Extension
+ array('element'=>'body', 'attribute'=>'instructions'), // Extension
+ array('element'=>'body', 'attribute'=>'logo'), // Extension
+ array('element'=>'div', 'attribute'=>'href'), // Extension
+ array('element'=>'div', 'attribute'=>'src'), // Extension
+ array('element'=>'embed', 'attribute'=>'code'), // Extension
+ array('element'=>'embed', 'attribute'=>'pluginspage'), // Extension
+ array('element'=>'html', 'attribute'=>'background'), // Extension
+ array('element'=>'ilayer', 'attribute'=>'src'), // Extension
+ array('element'=>'img', 'attribute'=>'dynsrc'), // Extension
+ array('element'=>'img', 'attribute'=>'lowsrc'), // Extension
+ array('element'=>'input', 'attribute'=>'dynsrc'), // Extension
+ array('element'=>'input', 'attribute'=>'lowsrc'), // Extension
+ array('element'=>'table', 'attribute'=>'background'), // Extension
+ array('element'=>'td', 'attribute'=>'background'), // Extension
+ array('element'=>'th', 'attribute'=>'background'), // Extension
+ array('element'=>'layer', 'attribute'=>'src'), // Extension
+ array('element'=>'xml', 'attribute'=>'src'), // Extension
+
+ array('element'=>'button', 'attribute'=>'action'), // Forms 2.0
+ array('element'=>'datalist', 'attribute'=>'data'), // Forms 2.0
+ array('element'=>'form', 'attribute'=>'data'), // Forms 2.0
+ array('element'=>'input', 'attribute'=>'action'), // Forms 2.0
+ array('element'=>'select', 'attribute'=>'data'), // Forms 2.0
+
+ // XHTML
+ array('element'=>'html', 'attribute'=>'xmlns'),
+
+ // WML
+ array('element'=>'access', 'attribute'=>'path'), // 1.3
+ array('element'=>'card', 'attribute'=>'onenterforward'), // 1.3
+ array('element'=>'card', 'attribute'=>'onenterbackward'),// 1.3
+ array('element'=>'card', 'attribute'=>'ontimer'), // 1.3
+ array('element'=>'go', 'attribute'=>'href'), // 1.3
+ array('element'=>'option', 'attribute'=>'onpick'), // 1.3
+ array('element'=>'template', 'attribute'=>'onenterforward'), // 1.3
+ array('element'=>'template', 'attribute'=>'onenterbackward'),// 1.3
+ array('element'=>'template', 'attribute'=>'ontimer'), // 1.3
+ array('element'=>'wml', 'attribute'=>'xmlns'), // 2.0
+ );
+
+ $match_metas = array(
+ 'content-base',
+ 'content-location',
+ 'referer',
+ 'location',
+ 'refresh',
+ );
+
+ // Extract all elements
+ if ( !preg_match_all( '/<([a-z][^>]*)>/iu', $text, $matches ) )
+ return array( );
+ $elements = $matches[1];
+ $value_pattern = '=(("([^"]*)")|([^\s]*))';
+
+ // Match elements and attributes
+ foreach ( $match_elements as $match_element )
+ {
+ $name = $match_element['element'];
+ $attr = $match_element['attribute'];
+ $pattern = '/^' . $name . '\s.*' . $attr . $value_pattern . '/iu';
+ if ( $name == 'object' )
+ $split_pattern = '/\s*/u'; // Space-separated URL list
+ else if ( $name == 'archive' )
+ $split_pattern = '/,\s*/u'; // Comma-separated URL list
+ else
+ unset( $split_pattern ); // Single URL
+ foreach ( $elements as $element )
+ {
+ if ( !preg_match( $pattern, $element, $match ) )
+ continue;
+ $m = empty($match[3]) ? (!empty($match[4])?$match[4]:'') : $match[3];
+ if ( !isset( $split_pattern ) )
+ $urls[$name][$attr][] = $m;
+ else
+ {
+ $msplit = preg_split( $split_pattern, $m );
+ foreach ( $msplit as $ms )
+ $urls[$name][$attr][] = $ms;
+ }
+ }
+ }
+
+ // Match meta http-equiv elements
+ foreach ( $match_metas as $match_meta )
+ {
+ $attr_pattern = '/http-equiv="?' . $match_meta . '"?/iu';
+ $content_pattern = '/content' . $value_pattern . '/iu';
+ $refresh_pattern = '/\d*;\s*(url=)?(.*)$/iu';
+ foreach ( $elements as $element )
+ {
+ if ( !preg_match( '/^meta/iu', $element ) ||
+ !preg_match( $attr_pattern, $element ) ||
+ !preg_match( $content_pattern, $element, $match ) )
+ continue;
+ $m = empty($match[3]) ? $match[4] : $match[3];
+ if ( $match_meta != 'refresh' )
+ $urls['meta']['http-equiv'][] = $m;
+ else if ( preg_match( $refresh_pattern, $m, $match ) )
+ $urls['meta']['http-equiv'][] = $match[2];
+ }
+ }
+
+ // Match style attributes
+ $urls['style'] = array( );
+ $style_pattern = '/style' . $value_pattern . '/iu';
+ foreach ( $elements as $element )
+ {
+ if ( !preg_match( $style_pattern, $element, $match ) )
+ continue;
+ $m = empty($match[3]) ? $match[4] : $match[3];
+ $style_urls = extract_css_urls( $m );
+ if ( !empty( $style_urls ) )
+ $urls['style'] = array_merge_recursive(
+ $urls['style'], $style_urls );
+ }
+
+ // Match style bodies
+ if ( preg_match_all( '/<style[^>]*>(.*?)<\/style>/siu', $text, $style_bodies ) )
+ {
+ foreach ( $style_bodies[1] as $style_body )
+ {
+ $style_urls = extract_css_urls( $style_body );
+ if ( !empty( $style_urls ) )
+ $urls['style'] = array_merge_recursive(
+ $urls['style'], $style_urls );
+ }
+ }
+ if ( empty($urls['style']) )
+ unset( $urls['style'] );
+
+ return $urls;
+}
+/**
+ * Extract URLs from UTF-8 CSS text.
+ *
+ * URLs within @import statements and url() property functions are extracted
+ * and returned in an associative array of arrays. Array keys indicate
+ * the use context for the URL, including:
+ *
+ * "import"
+ * "property"
+ *
+ * Each value in the associative array is an array of URLs.
+ *
+ * Parameters:
+ * text the UTF-8 text to scan
+ *
+ * Return values:
+ * an associative array of arrays of URLs.
+ *
+ * See:
+ * http://nadeausoftware.com/articles/2008/01/php_tip_how_extract_urls_css_file
+ */
+function extract_css_urls( $text )
+{
+ $urls = array( );
+
+ $url_pattern = '(([^\\\\\'", \(\)]*(\\\\.)?)+)';
+ $urlfunc_pattern = 'url\(\s*[\'"]?' . $url_pattern . '[\'"]?\s*\)';
+ $pattern = '/(' .
+ '(@import\s*[\'"]' . $url_pattern . '[\'"])' .
+ '|(@import\s*' . $urlfunc_pattern . ')' .
+ '|(' . $urlfunc_pattern . ')' . ')/iu';
+ if ( !preg_match_all( $pattern, $text, $matches ) )
+ return $urls;
+
+ // @import '...'
+ // @import "..."
+ foreach ( $matches[3] as $match )
+ if ( !empty($match) )
+ $urls['import'][] =
+ preg_replace( '/\\\\(.)/u', '\\1', $match );
+
+ // @import url(...)
+ // @import url('...')
+ // @import url("...")
+ foreach ( $matches[7] as $match )
+ if ( !empty($match) )
+ $urls['import'][] =
+ preg_replace( '/\\\\(.)/u', '\\1', $match );
+
+ // url(...)
+ // url('...')
+ // url("...")
+ foreach ( $matches[11] as $match )
+ if ( !empty($match) )
+ $urls['property'][] =
+ preg_replace( '/\\\\(.)/u', '\\1', $match );
+
+ return $urls;
+}
+++ /dev/null
-<?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_url class
- * A subclass of repository, which is used to download a file from a specific url
- *
- * @since 2.0
- * @package moodlecore
- * @subpackage repository
- * @copyright 2009 Dongsheng Cai
- * @author Dongsheng Cai <dongsheng@moodle.com>
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-require_once(dirname(__FILE__).'/lib.php');
-
-class repository_url extends repository {
-
- /**
- * @param int $repositoryid
- * @param object $context
- * @param array $options
- */
- public function __construct($repositoryid, $context = SYSCONTEXTID, $options = array()){
- global $CFG;
- parent::__construct($repositoryid, $context, $options);
- if (!empty($options['client_id'])) {
- // will be used to construct download form
- $this->client_id = $options['client_id'];
- }
- $this->file_url = optional_param('file', '', PARAM_RAW);
- }
-
- public function get_file($url, $file = '') {
- global $CFG;
- //$CFG->repository_no_delete = true;
- $path = $this->prepare_file($file);
- $fp = fopen($path, 'w');
- $c = new curl;
- $c->download(array(array('url'=>$url, 'file'=>$fp)));
- return array('path'=>$path, 'url'=>$url);
- }
-
- public function check_login() {
- if (!empty($this->file_url)) {
- return true;
- } else {
- return false;
- }
- }
- /**
- * @return mixed
- */
- public function print_login() {
- $strdownload = get_string('download', 'repository');
- $strname = get_string('rename', 'repository_url');
- $strurl = get_string('url', 'repository_url');
- if ($this->options['ajax']) {
- $url = new stdclass;
- $url->label = $strurl.': ';
- $url->id = 'fileurl-'.$this->client_id;
- $url->type = 'text';
- $url->name = 'file';
-
- $ret['login'] = array($url);
- $ret['login_btn_label'] = get_string('download', 'repository_url');
- return $ret;
- } else {
- echo <<<EOD
-<table>
-<tr>
-<td>{$strurl}: </td><td><input name="file" type="text" /></td>
-</tr>
-</table>
-<input type="submit" value="{$strdownload}" />
-EOD;
-
- }
- }
-
- /**
- * @param mixed $path
- * @param string $search
- * @return array
- */
- public function get_listing($path='', $page='') {
- global $CFG, $OUTPUT;
- $ret = array();
- $curl = new curl;
- $msg = $curl->head($this->file_url);
- $info = $curl->get_info();
- if ($info['http_code'] != 200) {
- $ret['e'] = $msg;
- } else {
- $ret['list'] = array();
- $ret['nosearch'] = true;
- $ret['nologin'] = true;
- $filename = $this->guess_filename($info['url'], $info['content_type']);
- if (strstr($info['content_type'], 'text/html') || empty($info['content_type'])) {
- // analysis this web page, general file list
- $ret['list'] = array();
- $content = $curl->get($info['url']);
- $this->analyse_page($info['url'], $content, $ret);
- } else {
- // download this file
- $ret['list'][] = array(
- 'title'=>$filename,
- 'source'=>$this->file_url,
- 'thumbnail' => $OUTPUT->pix_url(file_extension_icon($filename, 32))
- );
- }
- }
- return $ret;
- }
- public function analyse_page($baseurl, $content, &$list) {
- global $CFG, $OUTPUT;
- $urls = extract_html_urls($content);
- $images = $urls['img']['src'];
- $pattern = '#img(.+)src="?\'?([[:alnum:]:?=&@/._+-]+)"?\'?#i';
- if (!empty($images)) {
- foreach($images as $url) {
- $list['list'][] = array(
- 'title'=>$this->guess_filename($url, ''),
- 'source'=>url_to_absolute($baseurl, $url),
- 'thumbnail'=>url_to_absolute($baseurl, $url),
- 'thumbnail_height'=>84,
- 'thumbnail_width'=>84
- );
- }
- }
- }
- public function guess_filename($url, $type) {
- $pattern = '#\/([\w_\?\-.]+)$#';
- $matches = null;
- preg_match($pattern, $url, $matches);
- if (empty($matches[1])) {
- return $url;
- } else {
- return $matches[1];
- }
- }
-
- public function get_name(){
- return get_string('pluginname', 'repository_url');;
- }
- public function supported_returntypes() {
- return (FILE_INTERNAL | FILE_EXTERNAL);
- }
-}
-
$ret['nologin'] = true;
$list = array();
- //TODO: this is weird, why not only user context? (skodak)
-
if (!empty($encodedpath)) {
$params = unserialize(base64_decode($encodedpath));
if (is_array($params)) {
$itemid = $params['itemid'];
$filename = $params['filename'];
$filearea = $params['filearea'];
- $component = $params['component'];
$filepath = $params['filepath'];
$context = get_context_instance_by_id($params['contextid']);
}
} else {
$itemid = 0;
$filename = null;
- $component = 'user';
- $filearea = 'private';
+ $filearea = 'user_private';
$filepath = '/';
$context = get_context_instance(CONTEXT_USER, $USER->id);
}
try {
$browser = get_file_browser();
- if ($fileinfo = $browser->get_file_info($context, $component, $filearea, $itemid, $filepath, $filename)) {
+ if ($fileinfo = $browser->get_file_info($context, $filearea, $itemid, $filepath, $filename)) {
$pathnodes = array();
$level = $fileinfo;
$params = $fileinfo->get_params();
- while ($level && $params['filearea'] == 'private' && $params['component'] == 'user') {
+ while ($level && $params['filearea'] == 'user_private') {
$encodedpath = base64_encode(serialize($level->get_params()));
$pathnodes[] = array('name'=>$level->get_visible_name(), 'path'=>$encodedpath);
$level = $level->get_parent();
* @param string $new_filepath the new path in draft area
* @return array The information of file
*/
- public function copy_to_area($encoded, $new_filearea='ignored', $new_itemid = '', $new_filepath = '/', $new_filename = '') {
+ public function copy_to_area($encoded, $new_filearea='user_draft', $new_itemid = '', $new_filepath = '/', $new_filename = '') {
global $USER, $DB;
$info = array();
$user_context = get_context_instance(CONTEXT_USER, $USER->id);
// the final file
$contextid = $params['contextid'];
- $component = $params['component'];
$filearea = $params['filearea'];
$filepath = $params['filepath'];
$filename = $params['filename'];
$fileitemid = $params['itemid'];
$context = get_context_instance_by_id($contextid);
try {
- $file_info = $browser->get_file_info($context, $component, $filearea, $fileitemid, $filepath, $filename);
- $file_info->copy_to_storage($user_context->id, 'user', 'draft', $new_itemid, $new_filepath, $new_filename);
+ $file_info = $browser->get_file_info($context, $filearea, $fileitemid, $filepath, $filename);
+ $file_info->copy_to_storage($user_context->id, $new_filearea, $new_itemid, $new_filepath, $new_filename);
} catch (Exception $e) {
throw $e;
}