diff --git a/js/api.js b/js/api.js
index 908e9a50013a..39d57c86c78b 100644
--- a/js/api.js
+++ b/js/api.js
@@ -87,6 +87,28 @@ window.textsecure.api = function() {
code = -1;
var e = new Error(code);
e.name = "HTTPError";
+ switch (code) {
+ case -1:
+ e.human_error = "Failed to connect to the server, please check your network connection.";
+ break;
+ case 413:
+ e.human_error = "Rate limit exceeded, please try again later.";
+ break;
+ case 403:
+ e.human_error = "Invalid code, please try again.";
+ break;
+ case 417:
+ e.human_error = "Number already registered"; // TODO: This shouldn't be a thing?, but its in the API doc?
+ break;
+ case 401:
+ e.human_error = "Invalid authentication, most likely someone re-registered and invalidated our registration";
+ break;
+ case 404:
+ e.human_error = "Number is not registered with TextSecure..";
+ break;
+ default:
+ e.human_error = "The server rejected our query, please file a bug report.";
+ }
reject(e);
}
});
@@ -108,28 +130,21 @@ window.textsecure.api = function() {
};
self.confirmCode = function(code, number, password,
- signaling_key, registrationId, single_device,
- success_callback, error_callback) {
- var call = single_device ? 'accounts' : 'devices';
- var urlPrefix = single_device ? '/code/' : '/';
+ signaling_key, registrationId, single_device) {
+ var call = single_device ? 'accounts' : 'devices';
+ var urlPrefix = single_device ? '/code/' : '/';
- doAjax({
- call : call,
- httpType : 'PUT',
- urlParameters : urlPrefix + code,
- user : number,
- password : password,
- jsonData : { signalingKey : btoa(getString(signaling_key)),
- supportsSms : false,
- fetchesMessages : true,
- registrationId : registrationId},
- }).then(function(response) {
- if (success_callback !== undefined)
- success_callback(response);
- }).catch(function(code) {
- if (error_callback !== undefined)
- error_callback(code);
- });
+ return doAjax({
+ call : call,
+ httpType : 'PUT',
+ urlParameters : urlPrefix + code,
+ user : number,
+ password : password,
+ jsonData : { signalingKey : btoa(getString(signaling_key)),
+ supportsSms : false,
+ fetchesMessages : true,
+ registrationId : registrationId},
+ });
};
self.registerKeys = function(keys, success_callback, error_callback) {
diff --git a/js/helpers.js b/js/helpers.js
index 4e5381ab1d6e..45107990bee9 100644
--- a/js/helpers.js
+++ b/js/helpers.js
@@ -207,45 +207,41 @@ window.textsecure.utils = function() {
return [number.substr(1, 1), number.substr(2)]; //XXX
}
- function numberValid(number) {
- return true; //XXX
+ function validateNumber(number, countryCode) {
+ return isNumeric(number) && number.length > 3 && number.length < 11; //XXX
}
- function countryCodeValid(number) {
- return true; //XXX
+ function validateCountryCode(countryCode) {
+ return isNumeric(countryCode) && countryCode.length < 4 && countryCode.length > 0;
}
self.verifyNumber = function(number, countryCode) {
+ //XXX: All verifyNumber stuff needs to match the server-side verification
var countryCodeValid = true;
var numberValid = true;
- if (countryCode !== undefined) {
- var match = countryCode.match(/[0-9]{3}-?[0-9]{3}/g)
- if (match == null || match.length == 1 || match[0] == countryCode) {
- countryCodeValid = false;
- countryCode = '1'; // Continue testing number with a fake countryCode
- }
- }
- if (!isNumeric(number)) {
- if (countryCode !== undefined || !number.startsWith('+') || !isNumeric(number.substr(1))) {
- numberValid = false;
- number = '2222222222'; // Continue testing countryCode with a fake number
- } else {
+ if (number.substr(0, 1) == '+') {
+ if (countryCode === undefined) {
var numberCCPair = splitPrefixedNumber(number);
- countryCode = numberCCPair[0];
- number = numberCCPair[1];
- }
- }
-
- if (numberValid && !verifyNumber(number))
+ if (numberCCPair != null) {
+ countryCode = numberCCPair[0];
+ number = numberCCPair[1];
+ } else
+ numberValid = false;
+ } else
+ numberValid = false;
+ } else if (countryCode === undefined)
numberValid = false;
- if (countryCodeValid && !verifyCountryCode(countryCode))
- countryCodeValid = false;
+
+ if (numberValid && !validateNumber(number, countryCode))
+ numberValid = false;
+ if (countryCode !== undefined)
+ countryCodeValid = validateCountryCode(countryCode);
if (!countryCodeValid || !numberValid)
throw { countryCodeValid: countryCodeValid, numberValid: numberValid };
- return '+' + country_code + number;
+ return '+' + countryCode + number;
}
self.unencodeNumber = function(number) {
@@ -615,6 +611,41 @@ window.textsecure.sendMessage = function() {
}
}();
+window.textsecure.register = function() {
+ return function(number, verificationCode, singleDevice, stepDone) {
+ var signalingKey = textsecure.crypto.getRandomBytes(32 + 20);
+ textsecure.storage.putEncrypted('signaling_key', signalingKey);
+
+ var password = btoa(getString(textsecure.crypto.getRandomBytes(16)));
+ password = password.substring(0, password.length - 2);
+ textsecure.storage.putEncrypted("password", password);
+
+ var registrationId = new Uint16Array(textsecure.crypto.getRandomBytes(2))[0];
+ registrationId = registrationId & 0x3fff;
+ textsecure.storage.putUnencrypted("registrationId", registrationId);
+
+ return textsecure.api.confirmCode(number, verificationCode, password, signalingKey, registrationId, singleDevice).then(function(response) {
+ if (singleDevice)
+ response = 1;
+ var numberId = number + "." + response;
+ textsecure.storage.putUnencrypted("number_id", numberId);
+ stepDone(1);
+
+ if (!singleDevice) {
+ //TODO: Do things???
+ stepDone(2);
+ }
+
+ return textsecure.crypto.generateKeys().then(function(keys) {
+ stepDone(3);
+ return textsecure.api.registerKeys(keys).then(function() {
+ stepDone(4);
+ });
+ });
+ });
+ }
+}();
+
function requestIdentityPrivKeyFromMasterDevice(number, identityKey) {
//TODO
}
diff --git a/js/options.js b/js/options.js
index 50832a8e0c23..e0082f985fea 100644
--- a/js/options.js
+++ b/js/options.js
@@ -14,16 +14,16 @@
* along with this program. If not, see