diff --git a/scripts/langindex.json b/scripts/langindex.json
index fe23eb125..2c1ca2a62 100644
--- a/scripts/langindex.json
+++ b/scripts/langindex.json
@@ -1557,6 +1557,7 @@
"core.errorsomedatanotdownloaded": "local_moodlemobileapp",
"core.errorsync": "local_moodlemobileapp",
"core.errorsyncblocked": "local_moodlemobileapp",
+ "core.errorurlschemeinvalidscheme": "local_moodlemobileapp",
"core.errorurlschemeinvalidsite": "local_moodlemobileapp",
"core.explanationdigitalminor": "moodle",
"core.favourites": "moodle",
@@ -1750,6 +1751,7 @@
"core.login.erroraccesscontrolalloworigin": "local_moodlemobileapp",
"core.login.errordeletesite": "local_moodlemobileapp",
"core.login.errorexampleurl": "local_moodlemobileapp",
+ "core.login.errorqrnoscheme": "local_moodlemobileapp",
"core.login.errorupdatesite": "local_moodlemobileapp",
"core.login.faqcannotconnectanswer": "local_moodlemobileapp",
"core.login.faqcannotconnectquestion": "local_moodlemobileapp",
diff --git a/src/assets/lang/en.json b/src/assets/lang/en.json
index 93dcadfc1..0a0fe7631 100644
--- a/src/assets/lang/en.json
+++ b/src/assets/lang/en.json
@@ -1557,6 +1557,7 @@
"core.errorsomedatanotdownloaded": "If you downloaded this activity, please notice that some data isn't downloaded during the download process for performance and data usage reasons.",
"core.errorsync": "An error occurred while synchronising. Please try again.",
"core.errorsyncblocked": "This {{$a}} cannot be synchronised right now because of an ongoing process. Please try again later. If the problem persists, try restarting the app.",
+ "core.errorurlschemeinvalidscheme": "This URL is meant to be used in another app: {{$a}}.",
"core.errorurlschemeinvalidsite": "This site URL cannot be opened in this app.",
"core.explanationdigitalminor": "This information is required to determine if your age is over the digital age of consent. This is the age when an individual can consent to terms and conditions and their data being legally stored and processed.",
"core.favourites": "Starred",
@@ -1750,6 +1751,7 @@
"core.login.erroraccesscontrolalloworigin": "The cross-origin call you're trying to perform has been rejected. Please check https://docs.moodle.org/dev/Moodle_Mobile_development_using_Chrome_or_Chromium",
"core.login.errordeletesite": "An error occurred while deleting this site. Please try again.",
"core.login.errorexampleurl": "The URL https://campus.example.edu is only an example URL, it's not a real site. Please use the URL of your school or organization's site.",
+ "core.login.errorqrnoscheme": "This URL isn't a valid login URL.",
"core.login.errorupdatesite": "An error occurred while updating the site's token.",
"core.login.faqcannotconnectanswer": "Please, contact your site administrator.",
"core.login.faqcannotconnectquestion": "I typed my site address correctly but I still can't connect.",
diff --git a/src/core/login/lang/en.json b/src/core/login/lang/en.json
index e89da5819..c0003e51b 100644
--- a/src/core/login/lang/en.json
+++ b/src/core/login/lang/en.json
@@ -25,6 +25,7 @@
"erroraccesscontrolalloworigin": "The cross-origin call you're trying to perform has been rejected. Please check https://docs.moodle.org/dev/Moodle_Mobile_development_using_Chrome_or_Chromium",
"errordeletesite": "An error occurred while deleting this site. Please try again.",
"errorexampleurl": "The URL https://campus.example.edu is only an example URL, it's not a real site. Please use the URL of your school or organization's site.",
+ "errorqrnoscheme": "This URL isn't a valid login URL.",
"errorupdatesite": "An error occurred while updating the site's token.",
"faqcannotconnectanswer": "Please, contact your site administrator.",
"faqcannotconnectquestion": "I typed my site address correctly but I still can't connect.",
diff --git a/src/core/login/pages/credentials/credentials.ts b/src/core/login/pages/credentials/credentials.ts
index 88d59bcb8..57541ce34 100644
--- a/src/core/login/pages/credentials/credentials.ts
+++ b/src/core/login/pages/credentials/credentials.ts
@@ -20,6 +20,7 @@ import { CoreUtils } from '@providers/utils/utils';
import { CoreEventsProvider } from '@providers/events';
import { CoreSitesProvider } from '@providers/sites';
import { CoreDomUtilsProvider } from '@providers/utils/dom';
+import { CoreUrlUtils } from '@providers/utils/url';
import { CoreLoginHelperProvider } from '../../providers/helper';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { CoreConfigConstants } from '../../../../configconstants';
@@ -324,6 +325,15 @@ export class CoreLoginCredentialsPage {
} catch (error) {
CoreCustomURLSchemes.instance.treatHandleCustomURLError(error);
}
+ } else if (text) {
+ // Not a custom URL scheme, check if it's a URL scheme to another app.
+ const scheme = CoreUrlUtils.instance.getUrlProtocol(text);
+
+ if (scheme && scheme != 'http' && scheme != 'https') {
+ this.domUtils.showErrorModal(this.translate.instant('core.errorurlschemeinvalidscheme', {$a: text}));
+ } else {
+ this.domUtils.showErrorModal('core.login.errorqrnoscheme', true);
+ }
}
}
}
diff --git a/src/core/login/pages/site/site.ts b/src/core/login/pages/site/site.ts
index e9d43091b..68b1c6142 100644
--- a/src/core/login/pages/site/site.ts
+++ b/src/core/login/pages/site/site.ts
@@ -429,10 +429,19 @@ export class CoreLoginSitePage {
}
}
} else {
- // Not a custom URL scheme, put the text in the field.
- this.siteForm.controls.siteUrl.setValue(text);
+ // Not a custom URL scheme, check if it's a URL scheme to another app.
+ const scheme = this.urlUtils.getUrlProtocol(text);
- this.connect(new Event('click'), text);
+ if (scheme && scheme != 'http' && scheme != 'https') {
+ this.domUtils.showErrorModal(this.translate.instant('core.errorurlschemeinvalidscheme', {$a: text}));
+ } else if (this.loginHelper.isSiteUrlAllowed(text)) {
+ // Put the text in the field (if present).
+ this.siteForm.controls.siteUrl.setValue(text);
+
+ this.connect(new Event('click'), text);
+ } else {
+ this.domUtils.showErrorModal('core.errorurlschemeinvalidsite', true);
+ }
}
}
}
diff --git a/src/core/login/providers/helper.ts b/src/core/login/providers/helper.ts
index 700a98d11..69d8a94c0 100644
--- a/src/core/login/providers/helper.ts
+++ b/src/core/login/providers/helper.ts
@@ -33,6 +33,7 @@ import { CoreConfigConstants } from '../../../configconstants';
import { CoreConstants } from '@core/constants';
import { Md5 } from 'ts-md5/dist/md5';
import { CoreSite } from '@classes/site';
+import { CoreUrl } from '@singletons/url';
/**
* Data related to a SSO authentication.
@@ -691,6 +692,35 @@ export class CoreLoginHelperProvider {
return false;
}
+ /**
+ * Check if a site URL is "allowed". In case the app has fixed sites, only those will be allowed to connect to.
+ *
+ * @param siteUrl Site URL to check.
+ * @return Promise resolved with boolean: whether is one of the fixed sites.
+ */
+ async isSiteUrlAllowed(siteUrl: string): Promise {
+ if (this.isFixedUrlSet()) {
+ // Only 1 site allowed.
+ return CoreUrl.sameDomainAndPath(siteUrl, this.getFixedSites());
+ } else if (this.hasSeveralFixedSites()) {
+ const sites = this.getFixedSites();
+
+ return sites.some((site) => {
+ return CoreUrl.sameDomainAndPath(siteUrl, site.url);
+ });
+ } else if (CoreConfigConstants.multisitesdisplay == 'sitefinder' && CoreConfigConstants.onlyallowlistedsites) {
+ // Call the sites finder to validate the site.
+ const result = await this.sitesProvider.findSites(siteUrl.replace(/^https?\:\/\/|\.\w{2,3}\/?$/g, ''));
+
+ return result && result.some((site) => {
+ return CoreUrl.sameDomainAndPath(siteUrl, site.url);
+ });
+ } else {
+ // No fixed sites or it uses a non-restrictive sites finder. Allow connecting.
+ return true;
+ }
+ }
+
/**
* Check if SSO login should use an embedded browser.
*
diff --git a/src/lang/en.json b/src/lang/en.json
index 68341442e..40da0174b 100644
--- a/src/lang/en.json
+++ b/src/lang/en.json
@@ -102,6 +102,7 @@
"errorsomedatanotdownloaded": "If you downloaded this activity, please notice that some data isn't downloaded during the download process for performance and data usage reasons.",
"errorsync": "An error occurred while synchronising. Please try again.",
"errorsyncblocked": "This {{$a}} cannot be synchronised right now because of an ongoing process. Please try again later. If the problem persists, try restarting the app.",
+ "errorurlschemeinvalidscheme": "This URL is meant to be used in another app: {{$a}}.",
"errorurlschemeinvalidsite": "This site URL cannot be opened in this app.",
"explanationdigitalminor": "This information is required to determine if your age is over the digital age of consent. This is the age when an individual can consent to terms and conditions and their data being legally stored and processed.",
"favourites": "Starred",
diff --git a/src/providers/urlschemes.ts b/src/providers/urlschemes.ts
index 20e466e81..5b3828ec9 100644
--- a/src/providers/urlschemes.ts
+++ b/src/providers/urlschemes.ts
@@ -29,7 +29,6 @@ import { CoreSitePluginsProvider } from '@core/siteplugins/providers/siteplugins
import { CoreConfigConstants } from '../configconstants';
import { CoreConstants } from '@core/constants';
import { makeSingleton } from '@singletons/core.singletons';
-import { CoreUrl } from '@singletons/url';
/**
* All params that can be in a custom URL scheme.
@@ -167,7 +166,7 @@ export class CoreCustomURLSchemesProvider {
}
try {
- const isValid = await this.isInFixedSiteUrls(data.siteUrl);
+ const isValid = await this.loginHelper.isSiteUrlAllowed(data.siteUrl);
if (!isValid) {
throw this.translate.instant('core.errorurlschemeinvalidsite');
@@ -547,38 +546,6 @@ export class CoreCustomURLSchemesProvider {
this.domUtils.showErrorModalDefault(error.error, this.translate.instant('core.login.invalidsite'));
}
}
-
- /**
- * Check if a site URL is one of the fixed sites for the app (in case there are fixed sites).
- *
- * @param siteUrl Site URL to check.
- * @return Promise resolved with boolean: whether is one of the fixed sites.
- */
- protected async isInFixedSiteUrls(siteUrl: string): Promise {
- if (this.loginHelper.isFixedUrlSet()) {
-
- return CoreUrl.sameDomainAndPath(siteUrl, this.loginHelper.getFixedSites());
- } else if (this.loginHelper.hasSeveralFixedSites()) {
- const sites = this.loginHelper.getFixedSites();
-
- const site = sites.find((site) => {
- return CoreUrl.sameDomainAndPath(siteUrl, site.url);
- });
-
- return !!site;
- } else if (CoreConfigConstants.multisitesdisplay == 'sitefinder' && CoreConfigConstants.onlyallowlistedsites) {
- // Call the sites finder to validate the site.
- const result = await this.sitesProvider.findSites(siteUrl.replace(/^https?\:\/\/|\.\w{2,3}\/?$/g, ''));
-
- const site = result && result.find((site) => {
- return CoreUrl.sameDomainAndPath(siteUrl, site.url);
- });
-
- return !!site;
- }
-
- return true;
- }
}
/**