Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 3 additions & 11 deletions www/addons/messages/controllers/discussion.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,18 +148,14 @@ angular.module('mm.addons.messages')

notifyNewMessage();
});
}, function(error) {
}).catch(function(error) {
messagesBeingSent--;

// Only close the keyboard if an error happens, we want the user to be able to send multiple
// messages without the keyboard being closed.
$mmApp.closeKeyboard();

if (typeof error === 'string') {
$mmUtil.showErrorModal(error);
} else {
$mmUtil.showErrorModal('mma.messages.messagenotsent', true);
}
$mmUtil.showErrorModalDefault(error, 'mma.messages.messagenotsent', true);
$scope.messages.splice($scope.messages.indexOf(message), 1);
});
});
Expand Down Expand Up @@ -570,11 +566,7 @@ angular.module('mm.addons.messages')
$scope.messages.splice(index, 1); // Remove message from the list without having to wait for re-fetch.
fetchMessages(); // Re-fetch messages to update cached data.
}).catch(function(error) {
if (typeof error === 'string') {
$mmUtil.showErrorModal(error);
} else {
$mmUtil.showErrorModal('mma.messages.errordeletemessage', true);
}
$mmUtil.showErrorModalDefault(error, 'mma.messages.errordeletemessage', true);
}).finally(function() {
modal.dismiss();
});
Expand Down
6 changes: 2 additions & 4 deletions www/addons/messages/services/messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ angular.module('mm.addons.messages')
* @ngdoc service
* @name $mmaMessages
*/
.factory('$mmaMessages', function($mmSite, $mmSitesManager, $log, $q, $mmUser, $mmaMessagesOffline, $mmApp,
.factory('$mmaMessages', function($mmSite, $mmSitesManager, $log, $q, $mmUser, $mmaMessagesOffline, $mmApp, $mmUtil,
mmaMessagesNewMessageEvent, mmaMessagesLimitMessages) {
$log = $log.getInstance('$mmaMessages');

Expand Down Expand Up @@ -1092,7 +1092,7 @@ angular.module('mm.addons.messages')
return self.sendMessagesOnline(messages, siteId).catch(function(error) {
return $q.reject({
error: error,
wserror: false
wserror: $mmUtil.isWebServiceError(error)
});
}).then(function(response) {
if (response && response[0] && response[0].msgid === -1) {
Expand Down Expand Up @@ -1122,8 +1122,6 @@ angular.module('mm.addons.messages')
* have been sent, the resolve param can contain errors for messages not sent.
*/
self.sendMessagesOnline = function(messages, siteId) {
siteId = siteId || $mmSite.getId();

return $mmSitesManager.getSite(siteId).then(function(site) {
var data = {
messages: messages
Expand Down
8 changes: 5 additions & 3 deletions www/core/lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -179,13 +179,15 @@
"twoparagraphs": "{{p1}}<br><br>{{p2}}",
"tryagain": "Try again",
"uhoh": "Uh oh!",
"unicodenotsupported" : "Unicode text like emojis are not supported on this site, text will be sent removing those characters.",
"unicodenotsupportedcleanerror" : "Empty text was found when cleaning Unicode chars.",
"unknown": "Unknown",
"unlimited": "Unlimited",
"unzipping": "Unzipping",
"upgraderunning": "Site is being upgraded, please retry later.",
"unexpectederror": "Unexepected error. Please close and reopen the application to try again",
"userdeleted": "This user account has been deleted",
"userdetails": "User details",
"unknown": "Unknown",
"unlimited": "Unlimited",
"unzipping": "Unzipping",
"usernotfullysetup": "User not fully set-up",
"users": "Users",
"view": "View",
Expand Down
24 changes: 23 additions & 1 deletion www/core/lib/sitesfactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ angular.module('mm.core')
mmCoreWSPrefix, mmCoreSessionExpired, $mmEvents, mmCoreEventSessionExpired, mmCoreUserDeleted, mmCoreEventUserDeleted,
$mmText, $translate, mmCoreConfigConstants, mmCoreUserPasswordChangeForced, mmCoreEventPasswordChangeForced,
mmCoreLoginTokenChangePassword, mmCoreSecondsMinute, mmCoreUserNotFullySetup, mmCoreEventUserNotFullySetup,
mmCoreSitePolicyNotAgreed, mmCoreEventSitePolicyNotAgreed) {
mmCoreSitePolicyNotAgreed, mmCoreEventSitePolicyNotAgreed, mmCoreUnicodeNotSupported) {

$log = $log.getInstance('$mmSite');

Expand Down Expand Up @@ -182,6 +182,7 @@ angular.module('mm.core')
this.privateToken = privateToken;
this.config = config;
this.loggedOut = !!loggedOut;
this.cleanUnicode = false;

if (this.id) {
this.db = $mmDB.getDB('Site-' + this.id, siteSchema, dboptions);
Expand Down Expand Up @@ -423,6 +424,9 @@ angular.module('mm.core')
saveToCache: 0
};

// Reset clean Unicode to check if it's supported again.
site.cleanUnicode = false;

site.read('core_webservice_get_site_info', {}, preSets).then(deferred.resolve, function(error) {
site.read('moodle_webservice_get_siteinfo', {}, preSets).then(deferred.resolve, function(error) {
deferred.reject(error);
Expand Down Expand Up @@ -537,6 +541,16 @@ angular.module('mm.core')
preSets = angular.copy(preSets) || {};
preSets.wstoken = site.token;
preSets.siteurl = site.siteurl;
preSets.cleanUnicode = site.cleanUnicode;

if (preSets.cleanUnicode && $mmText.hasUnicodeData(data)) {
// Data will be cleaned, notify the user.
// @todo: Detect if the call is a syncing call and not notify.
$mmUtil.showToast('mm.core.unicodenotsupported', true, 3000);
} else {
// No need to clean data in this call.
preSets.cleanUnicode = false;
}

// Enable text filtering by default.
data.moodlewssettingfilter = preSets.filter === false ? false : true;
Expand Down Expand Up @@ -597,6 +611,14 @@ angular.module('mm.core')
// Site policy not agreed, trigger event.
$mmEvents.trigger(mmCoreEventSitePolicyNotAgreed, site.id);
return $mmLang.translateAndReject('mm.login.sitepolicynotagreederror');
} else if (error === mmCoreUnicodeNotSupported) {
if (!site.cleanUnicode) {
// Try again cleaning unicode.
site.cleanUnicode = true;
return site.request(method, data, preSets);
}
// This should not happen.
return $mmLang.translateAndReject('mm.core.unicodenotsupported');
} else if (typeof preSets.emergencyCache !== 'undefined' && !preSets.emergencyCache) {
$log.debug('WS call ' + method + ' failed. Emergency cache is forbidden, rejecting.');
return $q.reject(error);
Expand Down
61 changes: 61 additions & 0 deletions www/core/lib/text.js
Original file line number Diff line number Diff line change
Expand Up @@ -579,5 +579,66 @@ angular.module('mm.core')
return /<[a-z][\s\S]*>/i.test(text);
};

/**
* Check if a text contains Unicode long chars.
* Using as threshold Hex value D800
*
* @module mm.core
* @ngdoc method
* @name $mmText#hasUnicode
* @param {String} text Text to check.
* @return {Boolean} True if has Unicode chars, false otherwise.
*/
self.hasUnicode = function(text) {
for (var x = 0; x < text.length; x++) {
if (text.charCodeAt(x) > 55295) {
return true;
}
}
return false;
};

/**
* Check if an object has any long Unicode char.
*
* @module mm.core
* @ngdoc method
* @name $mmText#hasUnicodeData
* @param {Mixed} data Object to be checked.
* @return {Boolean} If the data has any long Unicode char on it.
*/
self.hasUnicodeData = function(data) {
for (var el in data) {
if (angular.isObject(data[el])) {
if (self.hasUnicodeData(data[el])) {
return true;
}
} else if (typeof data[el] == "string" && self.hasUnicode(data[el])) {
return true;
}
}
return false;
}

/**
* Strip Unicode long char of a given text.
* Using as threshold Hex value D800
*
* @module mm.core
* @ngdoc method
* @name $mmText#stripUnicode
* @param {String} text Text to check.
* @return {String} Without the Unicode chars.
*/
self.stripUnicode = function(text) {
var stripped = "";
for (var x = 0; x < text.length; x++) {
if (text.charCodeAt(x) <= 55295){
stripped += text.charAt(x);
}
}
return stripped;
};

return self;
});
3 changes: 2 additions & 1 deletion www/core/lib/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -1945,7 +1945,8 @@ angular.module('mm.core')
$translate.instant('mm.core.errorinvalidresponse'),
$translate.instant('mm.core.sitemaintenance'),
$translate.instant('mm.core.upgraderunning'),
$translate.instant('mm.core.nopasswordchangeforced')
$translate.instant('mm.core.nopasswordchangeforced'),
$translate.instant('mm.core.unicodenotsupported')
];
return error && localErrors.indexOf(error) == -1;
};
Expand Down
32 changes: 24 additions & 8 deletions www/core/lib/ws.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ angular.module('mm.core')
* @name $mmWS
*/
.factory('$mmWS', function($http, $q, $log, $mmLang, $cordovaFileTransfer, $mmApp, $mmFS, mmCoreSessionExpired, $translate, $window,
mmCoreUserDeleted, md5, $timeout, mmWSTimeout, mmCoreUserPasswordChangeForced, mmCoreUserNotFullySetup,
mmCoreSitePolicyNotAgreed) {
mmCoreUserDeleted, md5, $timeout, mmWSTimeout, mmCoreUserPasswordChangeForced, mmCoreUserNotFullySetup, $mmText,
mmCoreSitePolicyNotAgreed, mmCoreUnicodeNotSupported) {

$log = $log.getInstance('$mmWS');

Expand All @@ -49,14 +49,13 @@ angular.module('mm.core')
* - wstoken string The Webservice token.
* - responseExpected boolean Defaults to true. Set to false when the expected response is null.
* - typeExpected string Defaults to 'object'. Use it when you expect a type that's not an object|array.
* - cleanUnicode boolean Defaults to false. Clean multibyte Unicode chars from data.
* @return {Promise} Promise resolved with the response data in success and rejected with the error message if it fails.
*/
self.call = function(method, data, preSets) {

var siteurl;

data = convertValuesToString(data);

if (typeof preSets == 'undefined' || preSets === null ||
typeof preSets.wstoken == 'undefined' || typeof preSets.siteurl == 'undefined') {
return $mmLang.translateAndReject('mm.core.unexpectederror');
Expand All @@ -69,6 +68,13 @@ angular.module('mm.core')
preSets.responseExpected = true;
}

try {
data = convertValuesToString(data, preSets.cleanUnicode);
} catch (e) {
// Empty cleaned text found.
return $mmLang.translateAndReject('mm.core.unicodenotsupportedcleanerror');
}

data.wsfunction = method;
data.wstoken = preSets.wstoken;
siteurl = preSets.siteurl + '/webservice/rest/server.php?moodlewsrestformat=json';
Expand Down Expand Up @@ -133,6 +139,8 @@ angular.module('mm.core')
return $q.reject(mmCoreUserNotFullySetup);
} else if (data.errorcode === 'sitepolicynotagreed') {
return $q.reject(mmCoreSitePolicyNotAgreed);
} else if (data.errorcode === 'dmlwriteexception' && $mmText.hasUnicodeData(ajaxData)) {
return $q.reject(mmCoreUnicodeNotSupported);
} else {
return $q.reject(data.message);
}
Expand Down Expand Up @@ -280,19 +288,27 @@ angular.module('mm.core')
* Converts an objects values to strings where appropriate.
* Arrays (associative or otherwise) will be maintained.
*
* @param {Object} data The data that needs all the non-object values set to strings.
* @param {Object} data The data that needs all the non-object values set to strings.
* @param {Boolean} stripUnicode If Unicode long chars need to be stripped.
* @return {Object} The cleaned object, with multilevel array and objects preserved.
*/
function convertValuesToString(data) {
function convertValuesToString(data, stripUnicode) {
var result = [];
if (!angular.isArray(data) && angular.isObject(data)) {
result = {};
}
for (var el in data) {
if (angular.isObject(data[el])) {
result[el] = convertValuesToString(data[el]);
result[el] = convertValuesToString(data[el], stripUnicode);
} else {
result[el] = data[el] + '';
if (typeof data[el] == "string") {
result[el] = stripUnicode ? $mmText.stripUnicode(data[el]) : data[el];
if (stripUnicode && data[el] != result[el] && result[el].trim().length == 0) {
throw new Exception();
}
} else {
result[el] = data[el] + '';
}
}
}
return result;
Expand Down
1 change: 1 addition & 0 deletions www/core/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ angular.module('mm.core', ['pascalprecht.translate'])
.constant('mmCoreUserPasswordChangeForced', 'mmCoreUserPasswordChangeForced')
.constant('mmCoreUserNotFullySetup', 'mmCoreUserNotFullySetup')
.constant('mmCoreSitePolicyNotAgreed', 'mmCoreSitePolicyNotAgreed')
.constant('mmCoreUnicodeNotSupported', 'mmCoreUnicodeNotSupported')
.constant('mmCoreSecondsYear', 31536000)
.constant('mmCoreSecondsDay', 86400)
.constant('mmCoreSecondsHour', 3600)
Expand Down
1 change: 1 addition & 0 deletions www/core/scss/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -1099,6 +1099,7 @@ mm-timer {
.loading {
padding: 10px 20px;
border-radius: 25px;
margin: 0 10px;
}
}

Expand Down