diff --git a/lib/boxlib.php b/lib/boxlib.php index 974124f89ff..ed8f175addb 100644 --- a/lib/boxlib.php +++ b/lib/boxlib.php @@ -15,10 +15,9 @@ // along with Moodle. If not, see . /** - * Box REST Client Library for PHP5 Developers + * Box.net client. * - * - * @package moodlecore + * @package core * @author James Levy * @link http://enabled.box.net * @access public @@ -27,10 +26,171 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +defined('MOODLE_INTERNAL') || die(); +require_once($CFG->libdir . '/oauthlib.php'); + /** - * @package moodlecore + * Box.net client class. + * + * @package core + * @copyright 2013 Frédéric Massart + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class boxnet_client extends oauth2_client { + + /** @const API URL */ + const API = 'https://api.box.com/2.0'; + + /** + * Return authorize URL. + * + * @return string + */ + protected function auth_url() { + return 'https://www.box.com/api/oauth2/authorize'; + } + + /** + * Download the file. + * + * @param int $fileid File ID. + * @param string $path Path to download the file to. + * @return bool Success or not. + */ + public function download_file($fileid, $path) { + $result = $this->download_one($this->make_url("/files/$fileid/content"), array(), array('filepath' => $path)); + return ($result === true && $this->info['http_code'] === 200); + } + + /** + * Get info of a file. + * + * @param int $fileid File ID. + * @return object + */ + public function get_file_info($fileid) { + $result = $this->request($this->make_url("/files/$fileid")); + return json_decode($result); + } + + /** + * Get a folder content. + * + * @param int $folderid Folder ID. + * @return object + */ + public function get_folder_items($folderid = 0) { + $result = $this->request($this->make_url("/folders/$folderid/items", + array('fields' => 'id,name,type,modified_at,size,owned_by'))); + return json_decode($result); + } + + /** + * Log out. + * + * @return void + */ + public function log_out() { + if ($this->accesstoken) { + $params = array( + 'client_id' => $this->clientid, + 'client_secret' => $this->clientsecret, + 'token' => $this->accesstoken->token + ); + $this->post($this->get_revoke_url(), $params); + } + parent::log_out(); + } + + /** + * Build a request URL. + * + * @param string $uri The URI to request. + * @param array $params Query string parameters. + * @return string + */ + protected function make_url($uri, $params = array()) { + $url = new moodle_url(self::API . '/' . ltrim($uri, '/'), $params); + return $url->out(false); + } + + /** + * Return the revoke URL. + * + * @return string + */ + protected function revoke_url() { + return 'https://www.box.com/api/oauth2/revoke'; + } + + /** + * Share a file and return the link to it. + * + * @param string $fileid The file ID. + * @param bool $businesscheck Whether or not to check if the user can share files, has a business account. + * @return object + */ + public function share_file($fileid, $businesscheck = true) { + // Sharing the file, this requires a PUT request with data within it. We cannot use + // the standard PUT request 'CURLOPT_PUT' because it expects a file. + $data = array('shared_link' => array('access' => 'open', 'permissions' => + array('can_download' => true, 'can_preview' => true))); + $options = array( + 'CURLOPT_CUSTOMREQUEST' => 'PUT', + 'CURLOPT_POSTFIELDS' => json_encode($data) + ); + $result = $this->request($this->make_url("/files/$fileid"), $options); + $result = json_decode($result); + + if ($businesscheck) { + // Checks that the user has the right to share the file. If not, throw an exception. + $this->resetopt(); + $this->resetHeader(); + $this->head($result->shared_link->download_url); + $info = $this->get_info(); + if ($info['http_code'] == 403) { + throw new moodle_exception('No permission to share the file'); + } + } + + return $result->shared_link; + } + + /** + * Search. + * + * @return object + */ + public function search($query) { + $result = $this->request($this->make_url('/search', array('query' => $query, 'limit' => 50, 'offset' => 0))); + return json_decode($result); + } + + /** + * Return token URL. + * + * @return string + */ + protected function token_url() { + return 'https://www.box.com/api/oauth2/token'; + } + +} + +/** + * Box REST Client Library for PHP5 Developers. + * + * Deprecation note: As of the 14th of December 2013 Box.net APIv1, used by this class, + * is reaching its end of life. Please use boxnet_client() instead. + * + * @package core + * @author James Levy + * @link http://enabled.box.net + * @access public + * @version 1.0 * @copyright copyright Box.net 2007 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @deprecated since 2.6, 2.5.3, 2.4.7 */ class boxclient { /** @var string */ diff --git a/lib/upgrade.txt b/lib/upgrade.txt index 83c8712b826..4f6b6606a29 100644 --- a/lib/upgrade.txt +++ b/lib/upgrade.txt @@ -3,8 +3,12 @@ information provided here is intended especially for developers. === 2.5.3 === * update_internal_user_password() and setnew_password_and_mail() now trigger user_updated event. +* The library to interact with Box.net (class boxclient) is only compatible with their APIv1 which + reaches its end of life on the 14th of Dec. You should migrate your scripts to make usage of the + new class boxnet_client(). Note that the method names and return values have changed. === 2.5.2 === + * Use new function moodleform::mock_submit() to simulate form submission in unit tests. * Use behat_selectors::get_allowed_text_selectors() and behat_selectors::get_allowed_selectors() instead of behat_command::$allowedtextselectors and behat_command::$allowedselectors diff --git a/repository/boxnet/lang/en/repository_boxnet.php b/repository/boxnet/lang/en/repository_boxnet.php index 27defbeceab..3e920c2b4fd 100644 --- a/repository/boxnet/lang/en/repository_boxnet.php +++ b/repository/boxnet/lang/en/repository_boxnet.php @@ -25,15 +25,12 @@ $string['apikey'] = 'API key'; $string['boxnet:view'] = 'View box.net repository'; +$string['cannotcreatereference'] = 'Cannot create a reference, not enough permissions to share the file on Box.net.'; +$string['clientid'] = 'Client ID'; +$string['clientsecret'] = 'Client secret'; $string['configplugin'] = 'Box.net configuration'; -$string['callbackurl'] = 'Redirect URL'; -$string['callbackurltext'] = '1. Visit www.box.net/developers/services again. -2. Make sure you set the redirect URL of this box.net service to {$a}.'; -$string['callbackwarning'] = '1. Get a Box.net API from www.box.net/developers/services for this Moodle site. -2. Enter the Box.net API key here, then click Save and then return to this page. You will see that Moodle has generated a redirect URL for you. -3. Edit your Box.net details on the box.net website again and set the redirect URL.'; - -$string['information'] = 'Get an API key from the Box.net developer page for your Moodle site.'; +$string['filesourceinfo'] = 'Box.net ({$a->fullname}): {$a->filename}'; +$string['information'] = 'Get a client ID and secret from the Box.net developer page for your Moodle site.'; $string['invalidpassword'] = 'Invalid password'; $string['nullfilelist'] = 'There are no files in this repository'; $string['password'] = 'Password'; @@ -42,3 +39,4 @@ $string['pluginname'] = 'Box.net'; $string['saved'] = 'Box.net data saved'; $string['shareurl'] = 'Share URL'; $string['username'] = 'Username for Box.net'; +$string['warninghttps'] = 'Box.net requires your website to be using HTTPS in order for the repository to work.'; diff --git a/repository/boxnet/lib.php b/repository/boxnet/lib.php index 0e7fc6a3060..08074901cfb 100644 --- a/repository/boxnet/lib.php +++ b/repository/boxnet/lib.php @@ -30,11 +30,28 @@ require_once($CFG->libdir . '/boxlib.php'); * * @since 2.0 * @package repository_boxnet - * @copyright 2009 Dongsheng Cai {@link http://dongsheng.org} + * @copyright 2010 Dongsheng Cai {@link http://dongsheng.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class repository_boxnet extends repository { - private $boxclient; + + /** @const MANAGE_URL Manage URL. */ + const MANAGE_URL = 'https://app.box.com/files'; + + /** @const SESSION_PREFIX Key used to store information in the session. */ + const SESSION_PREFIX = 'repository_boxnet'; + + /** @var string Client ID */ + protected $clientid; + + /** @var string Client secret */ + protected $clientsecret; + + /** @var string Access token */ + protected $accesstoken; + + /** @var object Box.net object */ + protected $boxnetclient; /** * Constructor @@ -45,22 +62,87 @@ class repository_boxnet extends repository { */ public function __construct($repositoryid, $context = SYSCONTEXTID, $options = array()) { parent::__construct($repositoryid, $context, $options); - $this->api_key = $this->get_option('api_key'); - $this->setting_prefix = 'boxnet_'; - $this->auth_token = get_user_preferences($this->setting_prefix.'_auth_token', ''); - $this->logged = false; - if (!empty($this->auth_token)) { - $this->logged = true; - } - // already logged - if(!empty($this->logged)) { - if(empty($this->boxclient)) { - $this->boxclient = new boxclient($this->api_key, $this->auth_token); + $clientid = get_config('boxnet', 'clientid'); + $clientsecret = get_config('boxnet', 'clientsecret'); + $returnurl = new moodle_url('/repository/repository_callback.php'); + $returnurl->param('callback', 'yes'); + $returnurl->param('repo_id', $this->id); + $returnurl->param('sesskey', sesskey()); + + $this->boxnetclient = new boxnet_client($clientid, $clientsecret, $returnurl, ''); + } + + /** + * Construct a breadcrumb from a path. + * + * @param string $fullpath Path containing multiple parts separated by slashes. + * @return array Array expected to be generated in {@link self::get_listing()}. + */ + protected function build_breadcrumb($fullpath) { + $breadcrumb = array(array( + 'name' => get_string('pluginname', 'repository_boxnet'), + 'path' => '' + )); + $breadcrumbpath = ''; + $crumbs = explode('/', $fullpath); + foreach ($crumbs as $crumb) { + if (empty($crumb)) { + // That is probably the root crumb, we've already added it. + continue; } - } else { - $this->boxclient = new boxclient($this->api_key); + list($unused, $tosplit) = explode(':', $crumb, 2); + if (strpos($tosplit, '|') !== false) { + list($id, $crumbname) = explode('|', $tosplit, 2); + } else { + $crumbname = $tosplit; + } + $breadcrumbpath .= '/' . $crumb; + $breadcrumb[] = array( + 'name' => urldecode($crumbname), + 'path' => $breadcrumbpath + ); } + return $breadcrumb; + } + + /** + * Build a part of the path. + * + * This is used to construct the path that the user is currently browsing. + * It must contain a 'type', and a 'value'. Then it can also contain a + * 'name' which is very useful to prevent extra queries to get the name only. + * + * See {@link self::split_part} to extra the information from a part. + * + * @param string $type Type of part, typically 'folder' or 'search'. + * @param string $value The value of the part, eg. a folder ID or search terms. + * @param string $name The name of the part. + * @return string type:value or type:value|name + */ + protected function build_part($type, $value, $name = '') { + $return = $type . ':' . urlencode($value); + if ($name !== '') { + $return .= '|' . urlencode($name); + } + return $return; + } + + /** + * Extract information from a part of path. + * + * @param string $part value generated from {@link self::build_parth()}. + * @return array containing type, value and name. + */ + protected function split_part($part) { + list($type, $tosplit) = explode(':', $part); + $name = ''; + if (strpos($tosplit, '|') !== false) { + list($value, $name) = explode('|', $tosplit, 2); + } else { + $value = $tosplit; + } + return array($type, urldecode($value), urldecode($name)); } /** @@ -69,7 +151,7 @@ class repository_boxnet extends repository { * @return boolean */ public function check_login() { - return $this->logged; + return $this->boxnetclient->is_logged_in(); } /** @@ -78,42 +160,12 @@ class repository_boxnet extends repository { * @return string */ public function logout() { - // reset auth token - set_user_preference($this->setting_prefix . '_auth_token', ''); + if ($this->check_login()) { + $this->boxnetclient->log_out(); + } return $this->print_login(); } - /** - * Save settings - * - * @param array $options - * @return mixed - */ - public function set_option($options = array()) { - if (!empty($options['api_key'])) { - set_config('api_key', trim($options['api_key']), 'boxnet'); - } - unset($options['api_key']); - $ret = parent::set_option($options); - return $ret; - } - - /** - * Get settings - * - * @param string $config - * @return mixed - */ - public function get_option($config = '') { - if($config==='api_key') { - return trim(get_config('boxnet', 'api_key')); - } else { - $options['api_key'] = trim(get_config('boxnet', 'api_key')); - } - $options = parent::get_option($config); - return $options; - } - /** * Search files from box.net * @@ -121,29 +173,33 @@ class repository_boxnet extends repository { * @return mixed */ public function search($search_text, $page = 0) { - global $OUTPUT; - $list = array(); - $ret = array(); - $tree = $this->boxclient->getAccountTree(); - if (!empty($tree)) { - $filenames = $tree['file_name']; - $fileids = $tree['file_id']; - $filesizes = $tree['file_size']; - $filedates = $tree['file_date']; - $fileicon = $tree['thumbnail']; - foreach ($filenames as $n=>$v){ - if(strstr(strtolower($v), strtolower($search_text)) !== false) { - $list[] = array('title'=>$v, - 'size'=>$filesizes[$n], - 'date'=>$filedates[$n], - 'source'=>'https://www.box.com/api/1.0/download/' - .$this->auth_token.'/'.$fileids[$n], - 'thumbnail' => $OUTPUT->pix_url(file_extension_icon($v, 90))->out(false)); - } + return $this->get_listing($this->build_part('search', $search_text)); + } + + /** + * Downloads a repository file and saves to a path. + * + * @param string $ref reference to the file + * @param string $filename to save file as + * @return array + */ + public function get_file($ref, $filename = '') { + $ref = unserialize(self::convert_to_valid_reference($ref)); + $path = $this->prepare_file($filename); + if (!empty($ref->downloadurl)) { + $c = new curl(); + $result = $c->download_one($ref->downloadurl, null, array('filepath' => $filename, + 'timeout' => self::GETFILE_TIMEOUT, 'followlocation' => true)); + $info = $c->get_info(); + if ($result !== true || !isset($info['http_code']) || $info['http_code'] != 200) { + throw new moodle_exception('errorwhiledownload', 'repository', '', $result); + } + } else { + if (!$this->boxnetclient->download_file($ref->fileid, $path)) { + throw new moodle_exception('cannotdownload', 'repository'); } } - $ret['list'] = array_filter($list, array($this, 'filter')); - return $ret; + return array('path' => $path); } /** @@ -153,16 +209,65 @@ class repository_boxnet extends repository { * @param string $page * @return mixed */ - public function get_listing($path = '/', $page = ''){ - $list = array(); - $ret = array(); + public function get_listing($fullpath = '', $page = ''){ + global $OUTPUT; + + $ret = array(); $ret['list'] = array(); - $tree = $this->boxclient->getfiletree($path); - $ret['manage'] = 'http://www.box.com/files'; - $ret['path'] = array(array('name'=>'Root', 'path'=>0)); - if(!empty($tree)) { - $ret['list'] = array_filter($tree, array($this, 'filter')); + $ret['manage'] = self::MANAGE_URL; + $ret['dynload'] = true; + + $crumbs = explode('/', $fullpath); + $path = array_pop($crumbs); + + if (empty($path)) { + $type = 'folder'; + $pathid = 0; + $pathname = get_string('pluginname', 'repository_boxnet'); + } else { + list($type, $pathid, $pathname) = $this->split_part($path); } + + $ret['path'] = $this->build_breadcrumb($fullpath); + $folders = array(); + $files = array(); + + if ($type == 'search') { + $result = $this->boxnetclient->search($pathname); + } else { + $result = $this->boxnetclient->get_folder_items($pathid); + } + foreach ($result->entries as $item) { + if ($item->type == 'folder') { + $folders[$item->name . ':' . $item->id] = array( + 'title' => $item->name, + 'path' => $fullpath . '/' . $this->build_part('folder', $item->id, $item->name), + 'date' => strtotime($item->modified_at), + 'thumbnail' => $OUTPUT->pix_url(file_folder_icon(64))->out(false), + 'thumbnail_height' => 64, + 'thumbnail_width' => 64, + 'children' => array(), + 'size' => $item->size, + ); + } else { + $files[$item->name . ':' . $item->id] = array( + 'title' => $item->name, + 'source' => $this->build_part('file', $item->id, $item->name), + 'size' => $item->size, + 'date' => strtotime($item->modified_at), + 'thumbnail' => $OUTPUT->pix_url(file_extension_icon($item->name, 64))->out(false), + 'thumbnail_height' => 64, + 'thumbnail_width' => 64, + 'author' => $item->owned_by->name, + ); + } + } + + collatorlib::ksort($folders, collatorlib::SORT_NATURAL); + collatorlib::ksort($files, collatorlib::SORT_NATURAL); + $ret['list'] = array_merge($folders, $files); + $ret['list'] = array_filter($ret['list'], array($this, 'filter')); + return $ret; } @@ -172,24 +277,16 @@ class repository_boxnet extends repository { * @return array */ public function print_login(){ - $t = $this->boxclient->getTicket(); + $url = $this->boxnetclient->get_login_url(); if ($this->options['ajax']) { + $ret = array(); $popup_btn = new stdClass(); $popup_btn->type = 'popup'; - $popup_btn->url = ' https://www.box.com/api/1.0/auth/' . $t['ticket']; - - $ret = array(); + $popup_btn->url = $url->out(false); $ret['login'] = array($popup_btn); return $ret; } else { - echo ''; - echo ''.get_string('username', 'repository_boxnet').''; - echo ''; - echo ''.get_string('password', 'repository_boxnet').''; - echo ''; - echo ''; - echo ''; - echo ''; + echo html_writer::link($url, get_string('login', 'repository'), array('target' => '_blank')); } } @@ -199,15 +296,14 @@ class repository_boxnet extends repository { * @return array */ public static function get_type_option_names() { - return array('api_key', 'pluginname'); + return array('clientid', 'clientsecret', 'pluginname'); } /** - * Store the auth token returned by box.net + * Catch the request token. */ public function callback() { - $this->auth_token = optional_param('auth_token', '', PARAM_TEXT); - set_user_preference($this->setting_prefix . '_auth_token', $this->auth_token); + $this->boxnetclient->is_logged_in(); } /** @@ -219,32 +315,23 @@ class repository_boxnet extends repository { public static function type_config_form($mform, $classname = 'repository') { global $CFG; parent::type_config_form($mform); - $public_account = get_config('boxnet', 'public_account'); - $api_key = get_config('boxnet', 'api_key'); - if (empty($api_key)) { - $api_key = ''; - } - $strrequired = get_string('required'); - $mform->addElement('text', 'api_key', get_string('apikey', 'repository_boxnet'), array('value'=>$api_key,'size' => '40')); - $mform->addRule('api_key', $strrequired, 'required', null, 'client'); - $mform->setType('api_key', PARAM_RAW_TRIMMED); - $mform->addElement('static', null, '', get_string('information','repository_boxnet')); - //retrieve the flickr instances - $params = array(); - $params['context'] = array(); - //$params['currentcontext'] = $this->context; - $params['onlyvisible'] = false; - $params['type'] = 'boxnet'; - $instances = repository::get_instances($params); - if (empty($instances)) { - $callbackurl = get_string('callbackwarning', 'repository_boxnet'); - $mform->addElement('static', null, '', $callbackurl); - } else { - $instance = array_shift($instances); - $callbackurl = $CFG->wwwroot.'/repository/repository_callback.php?repo_id='.$instance->id; - $mform->addElement('static', 'callbackurl', '', get_string('callbackurltext', 'repository_boxnet', $callbackurl)); - } + $clientid = get_config('boxnet', 'clientid'); + $clientsecret = get_config('boxnet', 'clientsecret'); + $strrequired = get_string('required'); + + $mform->addElement('text', 'clientid', get_string('clientid', 'repository_boxnet'), + array('value' => $clientid, 'size' => '40')); + $mform->addRule('clientid', $strrequired, 'required', null, 'client'); + $mform->setType('clientid', PARAM_RAW_TRIMMED); + + $mform->addElement('text', 'clientsecret', get_string('clientsecret', 'repository_boxnet'), + array('value' => $clientsecret, 'size' => '40')); + $mform->addRule('clientsecret', $strrequired, 'required', null, 'client'); + $mform->setType('clientsecret', PARAM_RAW_TRIMMED); + + $mform->addElement('static', null, '', get_string('information', 'repository_boxnet')); + $mform->addElement('static', null, '', get_string('warninghttps', 'repository_boxnet')); } /** @@ -256,6 +343,25 @@ class repository_boxnet extends repository { return FILE_INTERNAL | FILE_EXTERNAL | FILE_REFERENCE; } + /** + * Convert a reference to the new reference style. + * + * While converting Box.net to APIv2 we introduced a new format for + * file references, see {@link self::get_file_reference()}. This function + * ensures that the format is always the same regardless of the whether + * the reference was from APIv1 or v2. + * + * @param mixed $reference File reference. + * @return stdClass Valid file reference. + */ + public static function convert_to_valid_reference($reference) { + if (strpos($reference, 'http') === 0) { + // It is faster to check if the reference is a URL rather than trying to unserialize it. + $reference = serialize((object) array('downloadurl' => $reference, 'fileid' => '', 'filename' => '', 'userid' => '')); + } + return $reference; + } + /** * Prepare file reference information * @@ -263,11 +369,40 @@ class repository_boxnet extends repository { * @return string file referece */ public function get_file_reference($source) { - // Box.net returns a url. - return $source; + global $USER; + list($type, $fileid, $filename) = $this->split_part($source); + $reference = new stdClass(); + $reference->fileid = $fileid; + $reference->filename = $filename; + $reference->userid = $USER->id; + $reference->downloadurl = ''; + if (optional_param('usefilereference', false, PARAM_BOOL)) { + try { + $shareinfo = $this->boxnetclient->share_file($reference->fileid, false); + } catch (moodle_exception $e) { + throw new repository_exception('cannotcreatereference', 'repository_boxnet'); + } + $reference->downloadurl = $shareinfo->download_url; + } + return serialize($reference); } /** + * Get a link to the file. + * + * This returns the URL of the web view of the file. To generate this link the + * file must be shared. + * + * @param stdClass $reference Reference. + * @return string URL. + */ + public function get_link($reference) { + $reference = unserialize(self::convert_to_valid_reference($reference)); + $shareinfo = $this->boxnetclient->share_file($reference->fileid, false); + return $shareinfo->url; + } + + /** * Returns information about file in this repository by reference * {@link repository::get_file_reference()} * {@link repository::get_file()} @@ -278,21 +413,16 @@ class repository_boxnet extends repository { * @return null|stdClass with attribute 'filepath' */ public function get_file_by_reference($reference) { - $array = explode('/', $reference->reference); - $fileid = array_pop($array); - $fileinfo = $this->boxclient->get_file_info($fileid, self::SYNCFILE_TIMEOUT); - if ($fileinfo) { - $size = (int)$fileinfo->size; - if (file_extension_in_typegroup($fileinfo->file_name, 'web_image')) { - // this is an image - download it to moodle - $path = $this->prepare_file(''); - $c = new curl; - $result = $c->download_one($reference->reference, null, array('filepath' => $path, 'timeout' => self::SYNCIMAGE_TIMEOUT)); - if ($result === true) { - return (object)array('filepath' => $path); - } - } - return (object)array('filesize' => $size); + $reference = unserialize(self::convert_to_valid_reference($file->get_reference())); + $url = $reference->downloadurl; + $c = new curl(); + $c->get($url, null, array('timeout' => self::SYNCIMAGE_TIMEOUT, 'followlocation' => true, 'nobody' => true)); + $info = $c->get_info(); + if (isset($info['http_code']) && $info['http_code'] == 200 && + array_key_exists('download_content_length', $info) && + $info['download_content_length'] >= 0) { + $filesize = (int)$info['download_content_length']; + return (object) array('filesize' => $filesize); } return null; } @@ -306,37 +436,25 @@ class repository_boxnet extends repository { * @return string */ public function get_reference_details($reference, $filestatus = 0) { - // Indicate it's from box.net repository + secure URL - $array = explode('/', $reference); - $fileid = array_pop($array); - $fileinfo = $this->boxclient->get_file_info($fileid, self::SYNCFILE_TIMEOUT); - if (!empty($fileinfo)) { - $reference = (string)$fileinfo->file_name; - } - $details = $this->get_name() . ': ' . $reference; - if (!empty($fileinfo)) { - return $details; + // Indicate it's from box.net repository. + $reference = unserialize(self::convert_to_valid_reference($reference)); + if (!$filestatus) { + return $this->get_name() . ': ' . $reference->filename; } else { return get_string('lostsource', 'repository', $details); } } /** - * Return the source information + * Return the source information. * - * @param stdClass $url + * @param string $source Not the reference, just the source. * @return string|null */ - public function get_file_source_info($url) { + public function get_file_source_info($source) { global $USER; - $array = explode('/', $url); - $fileid = array_pop($array); - $fileinfo = $this->boxclient->get_file_info($fileid, self::SYNCFILE_TIMEOUT); - if (!empty($fileinfo)) { - return 'Box ('. fullname($USER). '): '. (string)$fileinfo->file_name. ': '. $url; - } else { - return 'Box: '. $url; - } + list($type, $fileid, $filename) = $this->split_part($source); + return 'Box ('. fullname($USER) . '): ' . $filename; } /** @@ -349,9 +467,7 @@ class repository_boxnet extends repository { * @param array $options additional options affecting the file serving */ public function send_file($storedfile, $lifetime=86400 , $filter=0, $forcedownload=false, array $options = null) { - $ref = $storedfile->get_reference(); - // Let box.net serve the file. It will return 'no such file' content if file not found - // also if file has the different name than alias, it will be returned with the box.net filename - header('Location: ' . $ref); + $ref = unserialize(self::convert_to_valid_reference($storedfile->get_reference())); + header('Location: ' . $ref->downloadurl); } }