Merge pull request #2151 from dpalou/MOBILE-3164

Mobile 3164
main
Juan Leyva 2019-11-11 14:43:11 +01:00 committed by GitHub
commit 4db1ef7807
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 98 additions and 23 deletions

View File

@ -125,7 +125,7 @@ export class AddonModBookProvider {
promise = this.filepoolProvider.downloadUrl(siteId, indexUrl, false, AddonModBookProvider.COMPONENT, moduleId); promise = this.filepoolProvider.downloadUrl(siteId, indexUrl, false, AddonModBookProvider.COMPONENT, moduleId);
} else { } else {
// We return the live URL. // We return the live URL.
return Promise.resolve(this.sitesProvider.getCurrentSite().fixPluginfileURL(indexUrl)); return this.sitesProvider.getCurrentSite().checkAndFixPluginfileURL(indexUrl);
} }
return promise.then((url) => { return promise.then((url) => {

View File

@ -245,7 +245,7 @@ export class AddonModImscpProvider {
if (indexUrl) { if (indexUrl) {
return this.sitesProvider.getSite(siteId).then((site) => { return this.sitesProvider.getSite(siteId).then((site) => {
return site.fixPluginfileURL(indexUrl); return site.checkAndFixPluginfileURL(indexUrl);
}); });
} }
} }

View File

@ -76,7 +76,7 @@ export class AddonModPageHelperProvider {
AddonModPageProvider.COMPONENT, moduleId); AddonModPageProvider.COMPONENT, moduleId);
} else { } else {
// We return the live URL. // We return the live URL.
promise = Promise.resolve(this.sitesProvider.getCurrentSite().fixPluginfileURL(indexUrl)); promise = this.sitesProvider.getCurrentSite().checkAndFixPluginfileURL(indexUrl);
} }
return promise.then((url) => { return promise.then((url) => {

View File

@ -82,7 +82,7 @@ export class AddonModResourceHelperProvider {
// Error getting directory, there was an error downloading or we're in browser. Return online URL. // Error getting directory, there was an error downloading or we're in browser. Return online URL.
if (this.appProvider.isOnline() && mainFile.fileurl) { if (this.appProvider.isOnline() && mainFile.fileurl) {
// This URL is going to be injected in an iframe, we need this to make it work. // This URL is going to be injected in an iframe, we need this to make it work.
return Promise.resolve(this.sitesProvider.getCurrentSite().fixPluginfileURL(mainFile.fileurl)); return this.sitesProvider.getCurrentSite().checkAndFixPluginfileURL(mainFile.fileurl);
} }
return Promise.reject(null); return Promise.reject(null);

View File

@ -230,6 +230,8 @@ export class CoreSite {
protected ongoingRequests: { [cacheId: string]: Promise<any> } = {}; protected ongoingRequests: { [cacheId: string]: Promise<any> } = {};
protected requestQueue: RequestQueueItem[] = []; protected requestQueue: RequestQueueItem[] = [];
protected requestQueueTimeout = null; protected requestQueueTimeout = null;
protected tokenPluginFileWorks: boolean;
protected tokenPluginFileWorksPromise: Promise<boolean>;
/** /**
* Create a site. * Create a site.
@ -1226,6 +1228,18 @@ export class CoreSite {
return this.db.execute(sql, [key + '%']); return this.db.execute(sql, [key + '%']);
} }
/**
* Check if tokenpluginfile can be used, and fix the URL afterwards.
*
* @param url The url to be fixed.
* @return Promise resolved with the fixed URL.
*/
checkAndFixPluginfileURL(url: string): Promise<string> {
return this.checkTokenPluginFile(url).then(() => {
return this.fixPluginfileURL(url);
});
}
/** /**
* Generic function for adding the wstoken to Moodle urls and for pointing to the correct script. * Generic function for adding the wstoken to Moodle urls and for pointing to the correct script.
* Uses CoreUtilsProvider.fixPluginfileURL, passing site's token. * Uses CoreUtilsProvider.fixPluginfileURL, passing site's token.
@ -1234,7 +1248,10 @@ export class CoreSite {
* @return Fixed URL. * @return Fixed URL.
*/ */
fixPluginfileURL(url: string): string { fixPluginfileURL(url: string): string {
return this.urlUtils.fixPluginfileURL(url, this.token, this.siteUrl); const accessKey = this.tokenPluginFileWorks || typeof this.tokenPluginFileWorks == 'undefined' ?
this.infos && this.infos.userprivateaccesskey : undefined;
return this.urlUtils.fixPluginfileURL(url, this.token, this.siteUrl, accessKey);
} }
/** /**
@ -1886,4 +1903,44 @@ export class CoreSite {
return expirationDelay; return expirationDelay;
} }
/*
* Check if tokenpluginfile script works in the site.
*
* @param url URL to check.
* @return Promise resolved with boolean: whether it works or not.
*/
checkTokenPluginFile(url: string): Promise<boolean> {
if (!this.infos || !this.infos.userprivateaccesskey) {
// No access key, cannot use tokenpluginfile.
return Promise.resolve(false);
} else if (typeof this.tokenPluginFileWorks != 'undefined') {
// Already checked.
return Promise.resolve(this.tokenPluginFileWorks);
} else if (this.tokenPluginFileWorksPromise) {
// Check ongoing, use the same promise.
return this.tokenPluginFileWorksPromise;
} else if (!this.appProvider.isOnline()) {
// Not online, cannot check it. Assume it's working, but don't save the result.
return Promise.resolve(true);
} else if (!this.urlUtils.isPluginFileUrl(url)) {
// Not a pluginfile URL, ignore it.
return Promise.resolve(false);
}
url = this.fixPluginfileURL(url);
this.tokenPluginFileWorksPromise = this.wsProvider.performHead(url).then((result) => {
return result.ok;
}).catch((error) => {
// Error performing head request.
return false;
}).then((result) => {
this.tokenPluginFileWorks = result;
return result;
});
return this.tokenPluginFileWorksPromise;
}
} }

View File

@ -569,7 +569,8 @@ export class CoreCourseHelperProvider {
if (this.fileHelper.shouldOpenInBrowser(mainFile)) { if (this.fileHelper.shouldOpenInBrowser(mainFile)) {
if (this.appProvider.isOnline()) { if (this.appProvider.isOnline()) {
// Open in browser. // Open in browser.
let fixedUrl = site.fixPluginfileURL(fileUrl).replace('&offline=1', ''); return site.checkAndFixPluginfileURL(fileUrl).then((fixedUrl) => {
fixedUrl = fixedUrl.replace('&offline=1', '');
// Remove forcedownload when followed by another param. // Remove forcedownload when followed by another param.
fixedUrl = fixedUrl.replace(/forcedownload=\d+&/, ''); fixedUrl = fixedUrl.replace(/forcedownload=\d+&/, '');
// Remove forcedownload when not followed by any param. // Remove forcedownload when not followed by any param.
@ -582,8 +583,8 @@ export class CoreCourseHelperProvider {
// Download will be in background, don't return the promise. // Download will be in background, don't return the promise.
this.downloadModule(module, courseId, component, componentId, files, siteId); this.downloadModule(module, courseId, component, componentId, files, siteId);
} }
});
return;
} else { } else {
// Not online, get the offline file. It will fail if not found. // Not online, get the offline file. It will fail if not found.
return this.filepoolProvider.getInternalUrlByUrl(siteId, fileUrl).then((path) => { return this.filepoolProvider.getInternalUrlByUrl(siteId, fileUrl).then((path) => {
@ -664,7 +665,8 @@ export class CoreCourseHelperProvider {
}; };
return this.sitesProvider.getSite(siteId).then((site) => { return this.sitesProvider.getSite(siteId).then((site) => {
const fixedUrl = site.fixPluginfileURL(fileUrl); return site.checkAndFixPluginfileURL(fileUrl);
}).then((fixedUrl) => {
result.fixedUrl = fixedUrl; result.fixedUrl = fixedUrl;
if (this.fileProvider.isAvailable()) { if (this.fileProvider.isAvailable()) {

View File

@ -119,7 +119,8 @@ export class CoreFileHelperProvider {
siteId = siteId || this.sitesProvider.getCurrentSiteId(); siteId = siteId || this.sitesProvider.getCurrentSiteId();
return this.sitesProvider.getSite(siteId).then((site) => { return this.sitesProvider.getSite(siteId).then((site) => {
const fixedUrl = site.fixPluginfileURL(fileUrl); return site.checkAndFixPluginfileURL(fileUrl);
}).then((fixedUrl) => {
if (this.fileProvider.isAvailable()) { if (this.fileProvider.isAvailable()) {
let promise; let promise;

View File

@ -1321,7 +1321,7 @@ export class CoreFilepoolProvider {
*/ */
protected fixPluginfileURL(siteId: string, fileUrl: string): Promise<string> { protected fixPluginfileURL(siteId: string, fileUrl: string): Promise<string> {
return this.sitesProvider.getSite(siteId).then((site) => { return this.sitesProvider.getSite(siteId).then((site) => {
return site.fixPluginfileURL(fileUrl); return site.checkAndFixPluginfileURL(fileUrl);
}); });
} }
@ -1417,6 +1417,10 @@ export class CoreFilepoolProvider {
// Decode URL. // Decode URL.
url = this.textUtils.decodeHTML(this.textUtils.decodeURIComponent(url)); url = this.textUtils.decodeHTML(this.textUtils.decodeURIComponent(url));
// If site supports it, since 3.8 we use tokenpluginfile instead of pluginfile.
// For compatibility with files already downloaded, we need to use pluginfile to calculate the file ID.
url = url.replace(/\/tokenpluginfile\.php\/[^\/]+\//, '/webservice/pluginfile.php/');
if (url.indexOf('/webservice/pluginfile') !== -1) { if (url.indexOf('/webservice/pluginfile') !== -1) {
// Remove attributes that do not matter. // Remove attributes that do not matter.
this.urlAttributes.forEach((regex) => { this.urlAttributes.forEach((regex) => {

View File

@ -130,9 +130,10 @@ export class CoreUrlUtilsProvider {
* @param url The url to be fixed. * @param url The url to be fixed.
* @param token Token to use. * @param token Token to use.
* @param siteUrl The URL of the site the URL belongs to. * @param siteUrl The URL of the site the URL belongs to.
* @param accessKey User access key for tokenpluginfile.
* @return Fixed URL. * @return Fixed URL.
*/ */
fixPluginfileURL(url: string, token: string, siteUrl: string): string { fixPluginfileURL(url: string, token: string, siteUrl: string, accessKey?: string): string {
if (!url) { if (!url) {
return ''; return '';
} }
@ -140,7 +141,7 @@ export class CoreUrlUtilsProvider {
url = url.replace(/&amp;/g, '&'); url = url.replace(/&amp;/g, '&');
// First check if we need to fix this url or is already fixed. // First check if we need to fix this url or is already fixed.
if (url.indexOf('token=') != -1) { if (!accessKey && url.indexOf('token=') != -1) {
return url; return url;
} }
@ -149,7 +150,17 @@ export class CoreUrlUtilsProvider {
return url; return url;
} }
// Check if the URL already has params. const hasSlashParams = !url.match(/[\&?]file=/);
if (accessKey && hasSlashParams) {
// We have the user access key, use tokenpluginfile.php.
// Do not use it without slash params, the URL doesn't work.
url = url.replace(/(\/webservice)?\/pluginfile\.php/, '/tokenpluginfile.php/' + accessKey);
return url;
}
// No access key, use pluginfile.php. Check if the URL already has params.
if (url.match(/\?[^=]+=/)) { if (url.match(/\?[^=]+=/)) {
url += '&'; url += '&';
} else { } else {