From e35194bec4b0f2c8678dd013c23c1ecf924798dc Mon Sep 17 00:00:00 2001 From: Dongsheng Cai Date: Mon, 5 Jul 2010 07:27:49 +0000 Subject: [PATCH] MDL-22982 1. rename repository.class to lib.php 2. fixed repository_callback.php 3. repository_ajax use moodle default exception handler 4. improve file_get_user_used_space performance --- lang/en/repository.php | 1 + lib/filelib.php | 41 +- lib/simpletest/testrepositorylib.php | 2 +- .../{repository.class.php => lib.php} | 4 +- .../boxnet/{repository.class.php => lib.php} | 0 repository/dropbox/lib.php | 292 +++++- repository/dropbox/locallib.php | 58 ++ repository/dropbox/repository.class.php | 293 ------ repository/filepicker.js | 18 +- repository/filepicker.php | 4 +- .../{repository.class.php => lib.php} | 0 .../flickr/{repository.class.php => lib.php} | 0 .../{repository.class.php => lib.php} | 1 + .../{repository.class.php => lib.php} | 2 +- repository/lib.php | 120 +-- repository/local/db/install.php | 15 + .../local/{repository.class.php => lib.php} | 13 +- .../merlot/{repository.class.php => lib.php} | 0 .../picasa/{repository.class.php => lib.php} | 2 +- .../recent/{repository.class.php => lib.php} | 30 +- repository/repository_ajax.php | 254 +++--- repository/repository_callback.php | 21 +- .../s3/{repository.class.php => lib.php} | 0 repository/upload/db/install.php | 15 + .../upload/{repository.class.php => lib.php} | 178 ++-- repository/url/lib.php | 851 ++++-------------- repository/url/locallib.php | 702 +++++++++++++++ repository/url/repository.class.php | 165 ---- .../user/{repository.class.php => lib.php} | 17 +- .../webdav/{repository.class.php => lib.php} | 0 .../{repository.class.php => lib.php} | 0 .../youtube/{repository.class.php => lib.php} | 0 32 files changed, 1511 insertions(+), 1588 deletions(-) rename repository/alfresco/{repository.class.php => lib.php} (99%) rename repository/boxnet/{repository.class.php => lib.php} (100%) create mode 100644 repository/dropbox/locallib.php delete mode 100755 repository/dropbox/repository.class.php rename repository/filesystem/{repository.class.php => lib.php} (100%) rename repository/flickr/{repository.class.php => lib.php} (100%) rename repository/flickr_public/{repository.class.php => lib.php} (99%) rename repository/googledocs/{repository.class.php => lib.php} (97%) rename repository/local/{repository.class.php => lib.php} (91%) rename repository/merlot/{repository.class.php => lib.php} (100%) rename repository/picasa/{repository.class.php => lib.php} (97%) rename repository/recent/{repository.class.php => lib.php} (85%) rename repository/s3/{repository.class.php => lib.php} (100%) rename repository/upload/{repository.class.php => lib.php} (56%) create mode 100644 repository/url/locallib.php delete mode 100755 repository/url/repository.class.php rename repository/user/{repository.class.php => lib.php} (88%) rename repository/webdav/{repository.class.php => lib.php} (100%) rename repository/wikimedia/{repository.class.php => lib.php} (100%) rename repository/youtube/{repository.class.php => lib.php} (100%) diff --git a/lang/en/repository.php b/lang/en/repository.php index bf3b11d5a82b1..80abb944692ac 100644 --- a/lang/en/repository.php +++ b/lang/en/repository.php @@ -101,6 +101,7 @@ $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'; diff --git a/lib/filelib.php b/lib/filelib.php index 8d7c7a7546c7a..2ea4351a796d7 100644 --- a/lib/filelib.php +++ b/lib/filelib.php @@ -514,26 +514,17 @@ function file_get_draft_area_info($draftitemid) { * @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; } /** @@ -2874,7 +2865,7 @@ function __construct($module = 'repository'){ } /** - * @todo Document this function + * Get cached value * * @global object * @global object @@ -2901,10 +2892,10 @@ public function get($param){ } /** - * @todo Document this function + * Set cache value * - * @global object - * @global object + * @global object $CFG + * @global object $USER * @param mixed $param * @param mixed $val */ @@ -2917,7 +2908,7 @@ public function set($param, $val){ } /** - * @todo Document this function + * Remove cache files * * @param int $expire The number os seconds before expiry */ @@ -2936,8 +2927,8 @@ public function cleanup($expire){ /** * delete current user's cache file * - * @global object - * @global object + * @global object $CFG + * @global object $USER */ public function refresh(){ global $CFG, $USER; diff --git a/lib/simpletest/testrepositorylib.php b/lib/simpletest/testrepositorylib.php index 3e8b691b4d614..04f185f6068a9 100644 --- a/lib/simpletest/testrepositorylib.php +++ b/lib/simpletest/testrepositorylib.php @@ -42,7 +42,7 @@ $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')); } diff --git a/repository/alfresco/repository.class.php b/repository/alfresco/lib.php similarity index 99% rename from repository/alfresco/repository.class.php rename to repository/alfresco/lib.php index c3fc791095c5d..df3d77c9e385f 100755 --- a/repository/alfresco/repository.class.php +++ b/repository/alfresco/lib.php @@ -202,8 +202,8 @@ public function get_file($uuid, $file = '') { 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 .= '
'; - str += ''; - str += ''; + str += ''; + for (var i in types) { + str += ''; + } + str += ''; str += ''; str += ''; str += ''; diff --git a/repository/filepicker.php b/repository/filepicker.php index 2b7cf2e78d7cc..d257e62378a17 100755 --- a/repository/filepicker.php +++ b/repository/filepicker.php @@ -80,8 +80,8 @@ '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)); diff --git a/repository/filesystem/repository.class.php b/repository/filesystem/lib.php similarity index 100% rename from repository/filesystem/repository.class.php rename to repository/filesystem/lib.php diff --git a/repository/flickr/repository.class.php b/repository/flickr/lib.php similarity index 100% rename from repository/flickr/repository.class.php rename to repository/flickr/lib.php diff --git a/repository/flickr_public/repository.class.php b/repository/flickr_public/lib.php similarity index 99% rename from repository/flickr_public/repository.class.php rename to repository/flickr_public/lib.php index bbc0e4c6f38c6..ab508e10bb2b8 100644 --- a/repository/flickr_public/repository.class.php +++ b/repository/flickr_public/lib.php @@ -389,6 +389,7 @@ public function print_search() { 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']; diff --git a/repository/googledocs/repository.class.php b/repository/googledocs/lib.php similarity index 97% rename from repository/googledocs/repository.class.php rename to repository/googledocs/lib.php index 9c8a02022f86d..1a58b569f39a1 100644 --- a/repository/googledocs/repository.class.php +++ b/repository/googledocs/lib.php @@ -68,7 +68,7 @@ public function print_login($ajax = true){ $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; diff --git a/repository/lib.php b/repository/lib.php index 4ac21bf46bccb..a423437b0e79c 100644 --- a/repository/lib.php +++ b/repository/lib.php @@ -426,7 +426,7 @@ public function delete() { * 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 @@ -457,15 +457,20 @@ abstract class repository { * 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 { @@ -480,10 +485,10 @@ public function __construct($repositoryid, $contextid = SYSCONTEXTID, $options = } /** - * 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; @@ -496,7 +501,7 @@ public static function get_type_by_typename($typename) { } /** - * 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 @@ -512,9 +517,10 @@ public static function get_type_by_id($id) { } /** - * 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 */ @@ -528,7 +534,7 @@ public static function get_types($visible=null) { } 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); } } @@ -538,14 +544,15 @@ public static function get_types($visible=null) { } /** - * 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) { @@ -556,7 +563,7 @@ public static function check_context($ctx_id) { } } 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; @@ -626,8 +633,8 @@ public static function get_instances($args = array()) { } $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 @@ -681,10 +688,10 @@ public static function get_instances($args = array()) { $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; @@ -723,12 +730,10 @@ public static function get_instances($args = array()) { } } 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) { @@ -757,8 +762,7 @@ public static function get_instance($id) { 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; @@ -771,7 +775,7 @@ public static function get_instance($id) { } /** - * 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 @@ -781,7 +785,7 @@ public static function static_function($plugin, $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; @@ -798,8 +802,7 @@ public static function static_function($plugin, $function) { $args = func_get_args(); if (count($args) <= 2) { $args = array(); - } - else { + } else { array_shift($args); array_shift($args); } @@ -963,13 +966,12 @@ public static function display_instances_list($context, $typename = null) { //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 .= "

" . get_string('siteinstances', 'repository') . " "; - $output .= "

"; + $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'); @@ -1044,8 +1046,9 @@ public static function display_instances_list($context, $typename = null) { if (!empty($type) && $type->get_visible()) { $instanceoptionnames = repository::static_function($type->get_typename(), 'get_instance_option_names'); if (!empty($instanceoptionnames)) { - $instancehtml .= '
  • '.get_string('createxxinstance', 'repository', get_string('pluginname', 'repository_'.$type->get_typename())) - .'
  • '; + $baseurl->param('new', $type->get_typename()); + $instancehtml .= '
  • '.get_string('createxxinstance', 'repository', get_string('pluginname', 'repository_'.$type->get_typename())). '
  • '; + $baseurl->remove_params('new'); $addable++; } } @@ -1056,9 +1059,11 @@ public static function display_instances_list($context, $typename = null) { $instanceoptionnames = repository::static_function($typename, 'get_instance_option_names'); if (!empty($instanceoptionnames)) { //create a unique type of instance $addable = 1; - $instancehtml .= "
    -

    + $baseurl->param('new', $typename); + $instancehtml .= " +

    "; + $baseurl->remove_params('new'); } } @@ -1074,8 +1079,7 @@ public static function display_instances_list($context, $typename = null) { } /** - * 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) { @@ -1217,7 +1221,7 @@ final public function get_meta() { 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; @@ -1289,37 +1293,6 @@ final public function hide($hide = 'toggle') { 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')); @@ -1548,6 +1521,7 @@ public static function get_type_option_names() { 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)).'...'; @@ -1569,8 +1543,6 @@ public function get_short_filename($str, $maxlength) { class repository_exception extends moodle_exception { } - - /** * This is a class used to define a repository instance form * diff --git a/repository/local/db/install.php b/repository/local/db/install.php index 971b551094541..d71d0b068aa49 100644 --- a/repository/local/db/install.php +++ b/repository/local/db/install.php @@ -1,5 +1,20 @@ . + function xmldb_repository_local_install() { global $CFG; $result = true; diff --git a/repository/local/repository.class.php b/repository/local/lib.php similarity index 91% rename from repository/local/repository.class.php rename to repository/local/lib.php index f5df31348c8ac..ca06fdf9f12e2 100755 --- a/repository/local/repository.class.php +++ b/repository/local/lib.php @@ -75,7 +75,6 @@ public function get_listing($encodedpath = '') { $itemid = $params['itemid']; $filename = $params['filename']; $filearea = $params['filearea']; - $component = $params['component']; $filepath = $params['filepath']; $context = get_context_instance_by_id($params['contextid']); } @@ -83,7 +82,6 @@ public function get_listing($encodedpath = '') { $itemid = null; $filename = null; $filearea = null; - $component = null; $filepath = null; $context = get_system_context(); } @@ -91,7 +89,7 @@ public function get_listing($encodedpath = '') { 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())); @@ -119,7 +117,7 @@ public function get_listing($encodedpath = '') { $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( @@ -184,7 +182,7 @@ public function supported_returntypes() { * @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(); @@ -193,15 +191,14 @@ public function copy_to_area($encoded, $new_filearea='ignored', $new_itemid = '' $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; } diff --git a/repository/merlot/repository.class.php b/repository/merlot/lib.php similarity index 100% rename from repository/merlot/repository.class.php rename to repository/merlot/lib.php diff --git a/repository/picasa/repository.class.php b/repository/picasa/lib.php similarity index 97% rename from repository/picasa/repository.class.php rename to repository/picasa/lib.php index 7de106d345d8b..bc9128a596651 100644 --- a/repository/picasa/repository.class.php +++ b/repository/picasa/lib.php @@ -65,7 +65,7 @@ public function check_login() { 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(); diff --git a/repository/recent/repository.class.php b/repository/recent/lib.php similarity index 85% rename from repository/recent/repository.class.php rename to repository/recent/lib.php index 78d74311f41a3..c431950b6622a 100755 --- a/repository/recent/repository.class.php +++ b/repository/recent/lib.php @@ -30,7 +30,7 @@ class repository_recent extends repository { /** - * initialize recent plugin + * Initialize recent plugin * @param int $repositoryid * @param int $context * @param array $options @@ -65,23 +65,20 @@ public function search($search_text) { 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; @@ -124,7 +121,6 @@ public function get_listing($encodedpath = '', $page = '') { } catch (Exception $e) { throw new repository_exception('emptyfilelist', 'repository_recent'); } - $ret['list'] = $list; $ret['list'] = array_filter($list, array($this, 'filter')); return $ret; } @@ -165,13 +161,13 @@ public function supported_returntypes() { * * @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(); @@ -179,10 +175,7 @@ public function copy_to_area($encoded, $new_filearea='ignored', $new_itemid = '' $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']; @@ -191,17 +184,14 @@ public function copy_to_area($encoded, $new_filearea='ignored', $new_itemid = '' // 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); diff --git a/repository/repository_ajax.php b/repository/repository_ajax.php index 7c5de1d7a58ab..53c07ded47588 100755 --- a/repository/repository_ajax.php +++ b/repository/repository_ajax.php @@ -26,6 +26,8 @@ * @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'); @@ -35,7 +37,6 @@ /// 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); @@ -45,6 +46,7 @@ $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); @@ -55,7 +57,6 @@ 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'); @@ -64,7 +65,7 @@ /// Check permissions if (! (isloggedin() && repository::check_context($contextid)) ) { - $err->e = get_string('nopermissiontoaccess', 'repository'); + $err->error = get_string('nopermissiontoaccess', 'repository'); die(json_encode($err)); } @@ -88,20 +89,14 @@ $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; @@ -118,23 +113,18 @@ '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)); } @@ -144,160 +134,132 @@ 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; } diff --git a/repository/repository_callback.php b/repository/repository_callback.php index f24116e6b7868..ab73445b7139d 100755 --- a/repository/repository_callback.php +++ b/repository/repository_callback.php @@ -17,7 +17,7 @@ /** - * The Web service script that is called from the filepicker front end + * Repository instance callback script * * @since 2.0 * @package moodlecore @@ -33,36 +33,27 @@ 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); } diff --git a/repository/s3/repository.class.php b/repository/s3/lib.php similarity index 100% rename from repository/s3/repository.class.php rename to repository/s3/lib.php diff --git a/repository/upload/db/install.php b/repository/upload/db/install.php index a3443dd75f5ac..e9ad182e76fd1 100644 --- a/repository/upload/db/install.php +++ b/repository/upload/db/install.php @@ -1,5 +1,20 @@ . + function xmldb_repository_upload_install() { global $CFG; $result = true; diff --git a/repository/upload/repository.class.php b/repository/upload/lib.php similarity index 56% rename from repository/upload/repository.class.php rename to repository/upload/lib.php index 3e3ce486bb5c5..ae717b86bbcba 100755 --- a/repository/upload/repository.class.php +++ b/repository/upload/lib.php @@ -16,37 +16,21 @@ // along with Moodle. If not, see . /** - * 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 - * @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() { @@ -55,74 +39,36 @@ 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])) { @@ -137,36 +83,80 @@ public function upload_to_filepool($elname, $record, $override = true) { $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) { } } diff --git a/repository/url/lib.php b/repository/url/lib.php index f9c65f81c9c33..171b6cd1c453d 100644 --- a/repository/url/lib.php +++ b/repository/url/lib.php @@ -1,702 +1,165 @@ . /** - * 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 or "img" for . The values for these entries - * are associative arrays where the keys are attribute names for those - * tags, such as "href" for . 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 + * @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>/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 << + +{$strurl}: + + + +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; -} diff --git a/repository/url/locallib.php b/repository/url/locallib.php new file mode 100644 index 0000000000000..f9c65f81c9c33 --- /dev/null +++ b/repository/url/locallib.php @@ -0,0 +1,702 @@ + or "img" for . The values for these entries + * are associative arrays where the keys are attribute names for those + * tags, such as "href" for . 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>/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; +} diff --git a/repository/url/repository.class.php b/repository/url/repository.class.php deleted file mode 100755 index 91ed08e05fe23..0000000000000 --- a/repository/url/repository.class.php +++ /dev/null @@ -1,165 +0,0 @@ -. - -/** - * 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 - * @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 << - -{$strurl}: - - - -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); - } -} - diff --git a/repository/user/repository.class.php b/repository/user/lib.php similarity index 88% rename from repository/user/repository.class.php rename to repository/user/lib.php index 8759505343e2b..e3eabc1c237fb 100755 --- a/repository/user/repository.class.php +++ b/repository/user/lib.php @@ -69,23 +69,19 @@ public function get_listing($encodedpath = '') { $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); } @@ -93,11 +89,11 @@ public function get_listing($encodedpath = '') { 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(); @@ -170,7 +166,7 @@ public function supported_returntypes() { * @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(); @@ -179,15 +175,14 @@ public function copy_to_area($encoded, $new_filearea='ignored', $new_itemid = '' $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; } diff --git a/repository/webdav/repository.class.php b/repository/webdav/lib.php similarity index 100% rename from repository/webdav/repository.class.php rename to repository/webdav/lib.php diff --git a/repository/wikimedia/repository.class.php b/repository/wikimedia/lib.php similarity index 100% rename from repository/wikimedia/repository.class.php rename to repository/wikimedia/lib.php diff --git a/repository/youtube/repository.class.php b/repository/youtube/lib.php similarity index 100% rename from repository/youtube/repository.class.php rename to repository/youtube/lib.php