account_creator.c 52.7 KB
Newer Older
1 2
/*
linphone
3
Copyright (C) 2010-2018 Belledonne Communications SARL
4 5 6 7 8 9 10 11 12 13 14 15 16

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
17
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18 19
*/

20
#include "linphone/account_creator.h"
21
#include "linphone/core.h"
22
#include "linphone/lpconfig.h"
23 24

#include "c-wrapper/c-wrapper.h"
25
#include "dial-plan/dial-plan.h"
26

27
#if !_WIN32
28
	#include "regex.h"
29
#endif
30

31 32
#include <bctoolbox/crypto.h>

33 34 35
// TODO: From coreapi. Remove me later.
#include "private.h"

36 37 38 39
// =============================================================================

using namespace LinphonePrivate;

40
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneAccountCreatorCbs);
41

42
BELLE_SIP_INSTANCIATE_VPTR(LinphoneAccountCreatorCbs, belle_sip_object_t,
43 44 45 46 47 48 49
	NULL, // destroy
	NULL, // clone
	NULL, // marshal
	FALSE
);

/************************** Start Misc **************************/
50 51 52 53 54 55
static const char* ha1_for_passwd(const char* username, const char* realm, const char* passwd) {
	static char ha1[33];
	sal_auth_compute_ha1(username, realm, passwd, ha1);
	return ha1;
}

Erwan Croze's avatar
Erwan Croze committed
56
static unsigned int validate_uri(const char* username, const char* domain, const char* display_name) {
57
	LinphoneAddress* addr;
Benjamin REIS's avatar
Benjamin REIS committed
58
	unsigned int status = 0;
Erwan Croze's avatar
Erwan Croze committed
59
	LinphoneProxyConfig* proxy = linphone_proxy_config_new();
60
	linphone_proxy_config_set_identity(proxy, "sip:?@domain.com");
61 62 63 64 65 66 67

	if (username) {
		addr = linphone_proxy_config_normalize_sip_uri(proxy, username);
	} else {
		addr = linphone_address_clone(linphone_proxy_config_get_identity_address(proxy));
	}

Erwan Croze's avatar
Erwan Croze committed
68 69 70 71
	if (addr == NULL) {
		status = 1;
		goto end;
	}
72

Erwan Croze's avatar
Erwan Croze committed
73 74
	if (domain && linphone_address_set_domain(addr, domain) != 0) {
		status = 1;
75 76
	}

Erwan Croze's avatar
Erwan Croze committed
77 78 79
	if (display_name && (!strlen(display_name) || linphone_address_set_display_name(addr, display_name) != 0)) {
		status = 1;
	}
80
	linphone_address_unref(addr);
Erwan Croze's avatar
Erwan Croze committed
81 82 83
end:
	linphone_proxy_config_destroy(proxy);
	return status;
84 85 86 87 88 89
}

static char* _get_identity(const LinphoneAccountCreator *creator) {
	char *identity = NULL;
	if ((creator->username || creator->phone_number)) {
		//we must escape username
90
		LinphoneProxyConfig* proxy = linphone_core_create_proxy_config(creator->core);
91 92 93
		LinphoneAddress* addr;

		addr = linphone_proxy_config_normalize_sip_uri(proxy, creator->username ? creator->username : creator->phone_number);
94 95 96 97 98 99 100 101 102 103 104 105
		if (addr == NULL) {
			if (creator->username && creator->domain) {
				char *url = ms_strdup_printf("sip:%s@%s", creator->username, creator->domain);
				addr = linphone_address_new(url);
				ms_free(url);
				if (addr == NULL) {
					goto end;
				}
			} else {
				goto end;
			}
		}
106 107 108

		identity = linphone_address_as_string(addr);
		linphone_address_unref(addr);
109 110
		end:
		linphone_proxy_config_destroy(proxy);
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
	}
	return identity;
}

static bool_t is_matching_regex(const char *entry, const char* regex) {
#if _WIN32
	return TRUE;
#else
	regex_t regex_pattern;
	char err_msg[256];
	int res;
	res = regcomp(&regex_pattern, regex, REG_EXTENDED | REG_NOSUB);
	if(res != 0) {
		regerror(res, &regex_pattern, err_msg, sizeof(err_msg));
		ms_error("Could not compile regex '%s: %s", regex, err_msg);
		return FALSE;
	}
	res = regexec(&regex_pattern, entry, 0, NULL, 0);
	regfree(&regex_pattern);
	return (res != REG_NOMATCH);
#endif
}

134
LinphoneProxyConfig * linphone_account_creator_create_proxy_config(const LinphoneAccountCreator *creator) {
135 136 137 138
	LinphoneAuthInfo *info;
	LinphoneProxyConfig *cfg = linphone_core_create_proxy_config(creator->core);
	char *identity_str = _get_identity(creator);
	LinphoneAddress *identity = linphone_address_new(identity_str);
139

140 141 142 143 144 145 146 147
	ms_free(identity_str);
	if (creator->display_name) {
		linphone_address_set_display_name(identity, creator->display_name);
	}
	linphone_proxy_config_set_identity_address(cfg, identity);
	if (creator->phone_country_code) {
		linphone_proxy_config_set_dial_prefix(cfg, creator->phone_country_code);
	} else if (creator->phone_number) {
148
		int dial_prefix_number = DialPlan::lookupCccFromE164(creator->phone_number);
149 150 151
		char buff[4];
		snprintf(buff, sizeof(buff), "%d", dial_prefix_number);
		linphone_proxy_config_set_dial_prefix(cfg, buff);
152 153 154
	}
	if (linphone_proxy_config_get_server_addr(cfg) == NULL && creator->domain != NULL) {
		linphone_proxy_config_set_server_addr(cfg, creator->domain);
155
	}
Erwan Croze's avatar
Erwan Croze committed
156

157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
	linphone_proxy_config_enable_register(cfg, TRUE);

	info = linphone_auth_info_new(linphone_address_get_username(identity), // username
								NULL, //user id
								creator->password, // passwd
								creator->password ? NULL : creator->ha1,  // ha1
								!creator->password && creator->ha1 ? linphone_address_get_domain(identity) : NULL,  // realm - assumed to be domain
								linphone_address_get_domain(identity) // domain
	);
	linphone_core_add_auth_info(creator->core, info);
	linphone_address_unref(identity);

	if (linphone_core_add_proxy_config(creator->core, cfg) != -1) {
		linphone_core_set_default_proxy(creator->core, cfg);
		return cfg;
	}

	linphone_core_remove_auth_info(creator->core, info);
	return NULL;
}
177 178 179 180

LinphoneProxyConfig * linphone_account_creator_configure(const LinphoneAccountCreator *creator) {
	return linphone_account_creator_create_proxy_config(creator);
}
181 182 183 184
/************************** End Misc **************************/

/************************** Start Account Creator Cbs **************************/

185 186
static LinphoneAccountCreatorCbs * linphone_account_creator_cbs_new(void) {
	return belle_sip_object_new(LinphoneAccountCreatorCbs);
187 188
}

189 190 191
LinphoneAccountCreatorCbs * linphone_account_creator_cbs_ref(LinphoneAccountCreatorCbs *cbs) {
	belle_sip_object_ref(cbs);
	return cbs;
192 193
}

194 195
void linphone_account_creator_cbs_unref(LinphoneAccountCreatorCbs *cbs) {
	belle_sip_object_unref(cbs);
196 197
}

198 199
void *linphone_account_creator_cbs_get_user_data(const LinphoneAccountCreatorCbs *cbs) {
	return cbs->user_data;
200 201
}

202 203
void linphone_account_creator_cbs_set_user_data(LinphoneAccountCreatorCbs *cbs, void *ud) {
	cbs->user_data = ud;
204 205
}

206 207
LinphoneAccountCreatorCbsStatusCb linphone_account_creator_cbs_get_create_account(const LinphoneAccountCreatorCbs *cbs) {
	return cbs->create_account_response_cb;
208 209
}

210 211
void linphone_account_creator_cbs_set_create_account(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsStatusCb cb) {
	cbs->create_account_response_cb = cb;
212 213
}

214 215
LinphoneAccountCreatorCbsStatusCb linphone_account_creator_cbs_get_is_account_exist(const LinphoneAccountCreatorCbs *cbs) {
	return cbs->is_account_exist_response_cb;
216 217
}

218 219
void linphone_account_creator_cbs_set_is_account_exist(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsStatusCb cb) {
	cbs->is_account_exist_response_cb = cb;
220 221
}

222 223
LinphoneAccountCreatorCbsStatusCb linphone_account_creator_cbs_get_activate_account(const LinphoneAccountCreatorCbs *cbs) {
	return cbs->activate_account_response_cb;
224 225
}

226 227
void linphone_account_creator_cbs_set_activate_account(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsStatusCb cb) {
	cbs->activate_account_response_cb = cb;
228 229
}

230 231
LinphoneAccountCreatorCbsStatusCb linphone_account_creator_cbs_get_is_account_activated(const LinphoneAccountCreatorCbs *cbs) {
	return cbs->is_account_activated_response_cb;
232 233
}

234 235
void linphone_account_creator_cbs_set_is_account_activated(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsStatusCb cb) {
	cbs->is_account_activated_response_cb = cb;
236 237
}

238 239
LinphoneAccountCreatorCbsStatusCb linphone_account_creator_cbs_get_link_account(const LinphoneAccountCreatorCbs *cbs) {
	return cbs->link_account_response_cb;
240 241
}

242 243
void linphone_account_creator_cbs_set_link_account(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsStatusCb cb) {
	cbs->link_account_response_cb = cb;
244 245
}

246 247
LinphoneAccountCreatorCbsStatusCb linphone_account_creator_cbs_get_activate_alias(const LinphoneAccountCreatorCbs *cbs) {
	return cbs->activate_alias_response_cb;
248
}
249

250 251
void linphone_account_creator_cbs_set_activate_alias(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsStatusCb cb) {
	cbs->activate_alias_response_cb = cb;
252 253
}

254 255
LinphoneAccountCreatorCbsStatusCb linphone_account_creator_cbs_get_is_alias_used(const LinphoneAccountCreatorCbs *cbs) {
	return cbs->is_alias_used_response_cb;
256 257
}

258 259
void linphone_account_creator_cbs_set_is_alias_used(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsStatusCb cb) {
	cbs->is_alias_used_response_cb = cb;
260 261
}

262 263
LinphoneAccountCreatorCbsStatusCb linphone_account_creator_cbs_get_is_account_linked(const LinphoneAccountCreatorCbs *cbs) {
	return cbs->is_account_linked_response_cb;
264
}
265

266 267
void linphone_account_creator_cbs_set_is_account_linked(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsStatusCb cb) {
	cbs->is_account_linked_response_cb = cb;
268 269
}

270 271
LinphoneAccountCreatorCbsStatusCb linphone_account_creator_cbs_get_recover_account(const LinphoneAccountCreatorCbs *cbs) {
	return cbs->recover_account_response_cb;
272 273
}

274 275
void linphone_account_creator_cbs_set_recover_account(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsStatusCb cb) {
	cbs->recover_account_response_cb = cb;
276 277
}

278 279
LinphoneAccountCreatorCbsStatusCb linphone_account_creator_cbs_get_update_account(const LinphoneAccountCreatorCbs *cbs) {
	return cbs->update_account_response_cb;
280 281
}

282 283
void linphone_account_creator_cbs_set_update_account(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsStatusCb cb) {
	cbs->update_account_response_cb = cb;
284 285 286 287
}
/************************** End Account Creator Cbs **************************/

/************************** Start Account Creator data **************************/
288
static void _linphone_account_creator_destroy(LinphoneAccountCreator *creator) {
289 290
	/*this will drop all pending requests if any*/
	if (creator->xmlrpc_session) linphone_xml_rpc_session_release(creator->xmlrpc_session);
291 292 293
	if (creator->service != NULL && linphone_account_creator_service_get_destructor_cb(creator->service) != NULL)
		linphone_account_creator_service_get_destructor_cb(creator->service)(creator);
	linphone_account_creator_cbs_unref(creator->cbs);
294
	linphone_proxy_config_unref(creator->proxy_cfg);
295
	linphone_account_creator_reset(creator);
296 297 298 299 300 301 302 303 304 305 306
}

BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneAccountCreator);

BELLE_SIP_INSTANCIATE_VPTR(LinphoneAccountCreator, belle_sip_object_t,
	(belle_sip_object_destroy_t)_linphone_account_creator_destroy,
	NULL, // clone
	NULL, // marshal
	FALSE
);

307
LinphoneAccountCreator * _linphone_account_creator_new(LinphoneCore *core, const char *xmlrpc_url) {
308
	LinphoneAccountCreator *creator;
Erwan Croze's avatar
Erwan Croze committed
309
	const char* domain = lp_config_get_string(core->config, "assistant", "domain", NULL);
310
	creator = belle_sip_object_new(LinphoneAccountCreator);
311 312
	creator->service = linphone_core_get_account_creator_service(core);
	creator->cbs = linphone_account_creator_cbs_new();
313
	creator->core = core;
314
	creator->transport = LinphoneTransportTcp;
315
	creator->xmlrpc_session = (xmlrpc_url) ? linphone_xml_rpc_session_new(core, xmlrpc_url) : NULL;
Erwan Croze's avatar
Erwan Croze committed
316 317 318
	if (domain) {
		linphone_account_creator_set_domain(creator, domain);
	}
319
	creator->proxy_cfg = linphone_core_create_proxy_config(core);
320 321
	if (creator->service != NULL && linphone_account_creator_service_get_constructor_cb(creator->service) != NULL)
		linphone_account_creator_service_get_constructor_cb(creator->service)(creator);
322 323 324
	return creator;
}

325 326 327 328
LinphoneAccountCreator * linphone_account_creator_new(LinphoneCore *core, const char *xmlrpc_url) {
	return _linphone_account_creator_new(core, xmlrpc_url);
}

329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350
#define _reset_field(field) \
	if (field) { \
		ms_free(field); \
		field = NULL; \
	}

void linphone_account_creator_reset(LinphoneAccountCreator *creator) {
	_reset_field(creator->username);
	_reset_field(creator->display_name);
	_reset_field(creator->password);
	_reset_field(creator->ha1);
	_reset_field(creator->phone_number);
	_reset_field(creator->phone_country_code);
	_reset_field(creator->email);
	_reset_field(creator->language);
	_reset_field(creator->activation_code);
	_reset_field(creator->domain);
	_reset_field(creator->route);
}

#undef _reset_field

351 352 353 354
LinphoneAccountCreator * linphone_core_create_account_creator(LinphoneCore *core, const char *xmlrpc_url) {
	return _linphone_account_creator_new(core, xmlrpc_url);
}

355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371
LinphoneAccountCreator * linphone_account_creator_ref(LinphoneAccountCreator *creator) {
	belle_sip_object_ref(creator);
	return creator;
}

void linphone_account_creator_unref(LinphoneAccountCreator *creator) {
	belle_sip_object_unref(creator);
}

void *linphone_account_creator_get_user_data(const LinphoneAccountCreator *creator) {
	return creator->user_data;
}

void linphone_account_creator_set_user_data(LinphoneAccountCreator *creator, void *ud) {
	creator->user_data = ud;
}

372
LinphoneAccountCreatorUsernameStatus linphone_account_creator_set_username(LinphoneAccountCreator *creator, const char *username) {
373 374
	int min_length = lp_config_get_int(creator->core->config, "assistant", "username_min_length", -1);
	int max_length = lp_config_get_int(creator->core->config, "assistant", "username_max_length", -1);
375
	bool_t use_phone_number = !!lp_config_get_int(creator->core->config, "assistant", "use_phone_number", 0);
376
	const char* regex = lp_config_get_string(creator->core->config, "assistant", "username_regex", 0);
377 378
	if (!username) {
		creator->username = NULL;
379
		return LinphoneAccountCreatorUsernameStatusOk;
380
	} else if (min_length > 0 && strlen(username) < (size_t)min_length) {
381
		return LinphoneAccountCreatorUsernameStatusTooShort;
382
	} else if (max_length > 0 && strlen(username) > (size_t)max_length) {
383
		return LinphoneAccountCreatorUsernameStatusTooLong;
384
	} else if (use_phone_number && !linphone_proxy_config_is_phone_number(NULL, username)) {
385
		return LinphoneAccountCreatorUsernameStatusInvalid;
386
	} else if (regex && !is_matching_regex(username, regex)) {
387
		return LinphoneAccountCreatorUsernameStatusInvalidCharacters;
Erwan Croze's avatar
Erwan Croze committed
388
	} else if (validate_uri(username, NULL, NULL) != 0) {
389
		return LinphoneAccountCreatorUsernameStatusInvalid;
390
	}
391

392
	set_string(&creator->username, username, TRUE);
393
	return LinphoneAccountCreatorUsernameStatusOk;
394 395 396 397 398 399
}

const char * linphone_account_creator_get_username(const LinphoneAccountCreator *creator) {
	return creator->username;
}

400
LinphoneAccountCreatorPhoneNumberStatusMask linphone_account_creator_set_phone_number(LinphoneAccountCreator *creator, const char *phone_number, const char *country_code) {
401
	char *normalized_phone_number;
402
	LinphoneAccountCreatorPhoneNumberStatusMask return_status = 0;
403
	if (!phone_number || !country_code) {
404 405
		if (!phone_number && !country_code) {
			creator->phone_number = NULL;
406
			creator->phone_country_code = NULL;
407
			return (LinphoneAccountCreatorPhoneNumberStatusMask)LinphoneAccountCreatorPhoneNumberStatusOk;
408
		} else {
409
			return (LinphoneAccountCreatorPhoneNumberStatusMask)LinphoneAccountCreatorPhoneNumberStatusInvalid;
410
		}
411
	} else {
412
		LinphoneProxyConfig *numCfg = creator->proxy_cfg;
413 414
		creator->phone_country_code = ms_strdup(country_code[0] == '+' ? &country_code[1] : country_code);
		linphone_proxy_config_set_dial_prefix(numCfg, creator->phone_country_code);
415 416
		normalized_phone_number = linphone_proxy_config_normalize_phone_number(numCfg, phone_number);
		if (!normalized_phone_number) {
417
			return LinphoneAccountCreatorPhoneNumberStatusInvalid;
418 419 420 421
		}

		// if phone is valid, we lastly want to check that length is OK
		{
422
			const DialPlan &plan = DialPlan::findByCcc(creator->phone_country_code);
423
			int size = (int)strlen(phone_number);
424
			if (plan.isGeneric()) {
425
				return_status = LinphoneAccountCreatorPhoneNumberStatusInvalidCountryCode;
426
			}
427
			if (size < plan.getNationalNumberLength() - 1) {
428
				return_status += LinphoneAccountCreatorPhoneNumberStatusTooShort;
Erwan Croze's avatar
Erwan Croze committed
429
				goto end;
430
			} else if (size > plan.getNationalNumberLength() + 1) {
431
				return_status += LinphoneAccountCreatorPhoneNumberStatusTooLong;
432
				goto end;
433
			} else if (return_status & LinphoneAccountCreatorPhoneNumberStatusInvalidCountryCode) {
Erwan Croze's avatar
Erwan Croze committed
434
				goto end;
435 436 437
			}
		}
	}
438
	set_string(&creator->phone_number, normalized_phone_number, TRUE);
439
	return_status = LinphoneAccountCreatorPhoneNumberStatusOk;
Erwan Croze's avatar
Erwan Croze committed
440 441 442
end:
	ms_free(normalized_phone_number);
	return return_status;
443 444 445 446 447 448
}

const char * linphone_account_creator_get_phone_number(const LinphoneAccountCreator *creator) {
	return creator->phone_number;
}

449
LinphoneAccountCreatorPasswordStatus linphone_account_creator_set_password(LinphoneAccountCreator *creator, const char *password) {
450 451
	int min_length = lp_config_get_int(creator->core->config, "assistant", "password_min_length", -1);
	int max_length = lp_config_get_int(creator->core->config, "assistant", "password_max_length", -1);
452 453
	if (!password) {
		creator->password = NULL;
454
		return LinphoneAccountCreatorPasswordStatusTooShort;
455
	}
456
	if (min_length > 0 && strlen(password) < (size_t)min_length) {
457
		return LinphoneAccountCreatorPasswordStatusTooShort;
458
	} else if (max_length > 0 && strlen(password) > (size_t)max_length) {
459
		return LinphoneAccountCreatorPasswordStatusTooLong;
460
	}
461
	set_string(&creator->password, password, FALSE);
462
	return LinphoneAccountCreatorPasswordStatusOk;
463 464 465 466 467 468
}

const char * linphone_account_creator_get_password(const LinphoneAccountCreator *creator) {
	return creator->password;
}

469
LinphoneAccountCreatorPasswordStatus linphone_account_creator_set_ha1(LinphoneAccountCreator *creator, const char *ha1){
470
	set_string(&creator->ha1, ha1, FALSE);
471
	return LinphoneAccountCreatorPasswordStatusOk;
472 473 474 475 476 477
}

const char * linphone_account_creator_get_ha1(const LinphoneAccountCreator *creator) {
	return creator->ha1;
}

478
LinphoneAccountCreatorActivationCodeStatus linphone_account_creator_set_activation_code(LinphoneAccountCreator *creator, const char *activation_code){
479
	set_string(&creator->activation_code, activation_code, FALSE);
480
	return LinphoneAccountCreatorActivationCodeStatusOk;
481 482
}

483 484 485 486
const char * linphone_account_creator_get_activation_code(const LinphoneAccountCreator *creator) {
	return creator->activation_code;
}

487
LinphoneAccountCreatorLanguageStatus linphone_account_creator_set_language(LinphoneAccountCreator *creator, const char *lang) {
488
	set_string(&creator->language, lang, FALSE);
489
	return LinphoneAccountCreatorLanguageStatusOk;
490 491 492 493
}

const char * linphone_account_creator_get_language(const LinphoneAccountCreator *creator) {
	return creator->language;
494 495
}

496
LinphoneAccountCreatorUsernameStatus linphone_account_creator_set_display_name(LinphoneAccountCreator *creator, const char *display_name) {
Erwan Croze's avatar
Erwan Croze committed
497
	if (validate_uri(NULL, display_name, NULL) != 0) {
498
		return LinphoneAccountCreatorUsernameStatusInvalid;
499
	}
500
	set_string(&creator->display_name, display_name, FALSE);
501
	return LinphoneAccountCreatorUsernameStatusOk;
502 503
}

504 505
const char * linphone_account_creator_get_display_name(const LinphoneAccountCreator *creator) {
	return creator->display_name;
506 507
}

508
LinphoneAccountCreatorEmailStatus linphone_account_creator_set_email(LinphoneAccountCreator *creator, const char *email) {
509
	if (!email || !is_matching_regex(email, "^.+@.+\\..*$")) {
510
		return LinphoneAccountCreatorEmailStatusMalformed;
511 512
	}
	if (!is_matching_regex(email, "^.+@.+\\.[A-Za-z]{2}[A-Za-z]*$")) {
513
		return LinphoneAccountCreatorEmailStatusInvalidCharacters;
514
	}
515
	set_string(&creator->email, email, TRUE);
516
	return LinphoneAccountCreatorEmailStatusOk;
517 518
}

519 520
const char * linphone_account_creator_get_email(const LinphoneAccountCreator *creator) {
	return creator->email;
521 522
}

523
LinphoneAccountCreatorDomainStatus linphone_account_creator_set_domain(LinphoneAccountCreator *creator, const char *domain) {
Erwan Croze's avatar
Erwan Croze committed
524
	if (domain && validate_uri(NULL, domain, NULL) != 0) {
525
		return LinphoneAccountCreatorDomainInvalid;
Erwan Croze's avatar
Erwan Croze committed
526 527 528
	}

	set_string(&creator->domain, domain, TRUE);
529
	return LinphoneAccountCreatorDomainOk;
Erwan Croze's avatar
Erwan Croze committed
530 531 532 533 534 535
 }

const char * linphone_account_creator_get_domain(const LinphoneAccountCreator *creator) {
	return creator->domain;
}

536
LinphoneAccountCreatorTransportStatus linphone_account_creator_set_transport(LinphoneAccountCreator *creator, LinphoneTransportType transport) {
537
	if (!linphone_core_sip_transport_supported(creator->core, transport)) {
538
		return LinphoneAccountCreatorTransportUnsupported;
539 540
	}
	creator->transport = transport;
541
	return LinphoneAccountCreatorTransportOk;
542 543 544 545 546 547
}

LinphoneTransportType linphone_account_creator_get_transport(const LinphoneAccountCreator *creator) {
	return creator->transport;
}

548
LinphoneAccountCreatorStatus linphone_account_creator_set_route(LinphoneAccountCreator *creator, const char *route) {
Erwan Croze's avatar
Erwan Croze committed
549
	if (!route || linphone_proxy_config_set_route(creator->proxy_cfg, route) != 0)
550
		return LinphoneAccountCreatorStatusRequestFailed;
Erwan Croze's avatar
Erwan Croze committed
551 552

	set_string(&creator->route, route, TRUE);
553
	return LinphoneAccountCreatorStatusRequestOk;
Erwan Croze's avatar
Erwan Croze committed
554 555 556 557 558 559
}

const char * linphone_account_creator_get_route(const LinphoneAccountCreator *creator) {
	return creator->route;
}

560 561
LinphoneAccountCreatorCbs * linphone_account_creator_get_callbacks(const LinphoneAccountCreator *creator) {
	return creator->cbs;
562 563
}

564 565
LinphoneAccountCreatorService * linphone_account_creator_get_service(const LinphoneAccountCreator *creator) {
	return creator->service;
566 567
}

568 569 570 571
LinphoneAccountCreatorStatus linphone_account_creator_is_account_exist(LinphoneAccountCreator *creator) {
	if (creator->service->is_account_exist_request_cb == NULL
		|| creator->cbs->is_account_exist_response_cb == NULL) {
		return LinphoneAccountCreatorStatusMissingCallbacks;
572
	}
573

574
	return creator->service->is_account_exist_request_cb(creator);
575 576
}

577 578 579 580
LinphoneAccountCreatorStatus linphone_account_creator_create_account(LinphoneAccountCreator *creator) {
	if (creator->service->create_account_request_cb == NULL
		|| creator->cbs->create_account_response_cb == NULL) {
		return LinphoneAccountCreatorStatusMissingCallbacks;
581
	}
582

583
	return creator->service->create_account_request_cb(creator);
584 585
}

586 587 588 589
LinphoneAccountCreatorStatus linphone_account_creator_is_account_activated(LinphoneAccountCreator *creator) {
	if (creator->service->is_account_activated_request_cb == NULL
		|| creator->cbs->is_account_activated_response_cb == NULL) {
		return LinphoneAccountCreatorStatusMissingCallbacks;
590 591
	}

592
	return creator->service->is_account_activated_request_cb(creator);
593 594
}

595 596 597 598
LinphoneAccountCreatorStatus linphone_account_creator_activate_account(LinphoneAccountCreator *creator) {
	if (creator->service->activate_account_request_cb == NULL
		|| creator->cbs->activate_account_response_cb == NULL) {
		return LinphoneAccountCreatorStatusMissingCallbacks;
599 600
	}

601
	return creator->service->activate_account_request_cb(creator);
602 603
}

604 605 606 607
LinphoneAccountCreatorStatus linphone_account_creator_link_account(LinphoneAccountCreator *creator) {
	if (creator->service->link_account_request_cb == NULL
		|| creator->cbs->link_account_response_cb == NULL) {
		return LinphoneAccountCreatorStatusMissingCallbacks;
608
	}
609

610
	return creator->service->link_account_request_cb(creator);
611 612
}

613 614 615 616
LinphoneAccountCreatorStatus linphone_account_creator_activate_alias(LinphoneAccountCreator *creator) {
	if (creator->service->activate_alias_request_cb == NULL
		|| creator->cbs->activate_alias_response_cb == NULL) {
		return LinphoneAccountCreatorStatusMissingCallbacks;
617
	}
618

619
	return creator->service->activate_alias_request_cb(creator);
620 621
}

622 623 624 625
LinphoneAccountCreatorStatus linphone_account_creator_is_alias_used(LinphoneAccountCreator *creator) {
	if (creator->service->is_alias_used_request_cb == NULL
		|| creator->cbs->is_alias_used_response_cb == NULL) {
		return LinphoneAccountCreatorStatusMissingCallbacks;
626
	}
627

628
	return creator->service->is_alias_used_request_cb(creator);
629 630
}

631 632 633 634
LinphoneAccountCreatorStatus linphone_account_creator_is_account_linked(LinphoneAccountCreator *creator) {
	if (creator->service->is_account_linked_request_cb == NULL
		|| creator->cbs->is_account_linked_response_cb == NULL) {
		return LinphoneAccountCreatorStatusMissingCallbacks;
635
	}
636

637
	return creator->service->is_account_linked_request_cb(creator);
638 639
}

640 641 642 643
LinphoneAccountCreatorStatus linphone_account_creator_recover_account(LinphoneAccountCreator *creator) {
	if (creator->service->recover_account_request_cb == NULL
		|| creator->cbs->recover_account_response_cb == NULL) {
		return LinphoneAccountCreatorStatusMissingCallbacks;
644 645
	}

646
	return creator->service->recover_account_request_cb(creator);
647
}
648

649 650 651 652
LinphoneAccountCreatorStatus linphone_account_creator_update_account(LinphoneAccountCreator *creator) {
	if (creator->service->update_account_request_cb == NULL
		|| creator->cbs->update_account_response_cb == NULL) {
		return LinphoneAccountCreatorStatusMissingCallbacks;
653 654
	}

655
	return creator->service->update_account_request_cb(creator);
656
}
657 658 659
/************************** End Account Creator data **************************/

/************************** Start Account Creator Linphone **************************/
660

661
LinphoneAccountCreatorStatus linphone_account_creator_constructor_linphone(LinphoneAccountCreator *creator) {
662
	LinphoneAddress *addr;
663 664 665 666 667 668 669 670
	const char *identity = lp_config_get_default_string(creator->core->config, "proxy", "reg_identity", NULL);
	const char *proxy = lp_config_get_default_string(creator->core->config, "proxy", "reg_proxy", NULL);
	const char *route = lp_config_get_default_string(creator->core->config, "proxy", "reg_route", NULL);
	const char *realm = lp_config_get_default_string(creator->core->config, "proxy", "realm", NULL);
	linphone_proxy_config_set_realm(creator->proxy_cfg, realm ? realm : "sip.linphone.org");
	linphone_proxy_config_set_route(creator->proxy_cfg, route ? route : "sip.linphone.org");
	linphone_proxy_config_set_server_addr(creator->proxy_cfg, proxy ? proxy : "sip.linphone.org");
	addr = linphone_address_new(identity ? identity : "sip:username@sip.linphone.org");
671 672
	linphone_proxy_config_set_identity_address(creator->proxy_cfg, addr);
	linphone_address_unref(addr);
673
	return LinphoneAccountCreatorStatusRequestOk;
Erwan Croze's avatar
Erwan Croze committed
674 675
}

676
/****************** START OF ACCOUNT USED SECTION *****************************/
677
static void _is_account_exist_response_cb(LinphoneXmlRpcRequest *request) {
678
	LinphoneAccountCreator *creator = (LinphoneAccountCreator *)linphone_xml_rpc_request_get_user_data(request);
679 680
	if (creator->cbs->is_account_exist_response_cb != NULL) {
		LinphoneAccountCreatorStatus status = LinphoneAccountCreatorStatusRequestFailed;
681
		const char* resp = linphone_xml_rpc_request_get_string_response(request);
682
		if (linphone_xml_rpc_request_get_status(request) == LinphoneXmlRpcStatusOk) {
683 684 685 686
			status = (strcmp(resp, "ERROR_ACCOUNT_DOESNT_EXIST") == 0) ? LinphoneAccountCreatorStatusAccountNotExist : (
							(strcmp(resp, "ERROR_ALIAS_DOESNT_EXIST") == 0) ? LinphoneAccountCreatorStatusAccountExist :
														LinphoneAccountCreatorStatusAccountExistWithAlias);
			if (status == LinphoneAccountCreatorStatusAccountExistWithAlias) {
687 688
				set_string(&creator->phone_number, resp, FALSE);
			}
689
		}
690
		creator->cbs->is_account_exist_response_cb(creator, status, resp);
691 692 693
	}
}

694
LinphoneAccountCreatorStatus linphone_account_creator_is_account_exist_linphone(LinphoneAccountCreator *creator) {
695
	LinphoneXmlRpcRequest *request;
696
	if (!creator->username && !creator->phone_number) {
697 698
		if (creator->cbs->is_account_exist_response_cb != NULL) {
			creator->cbs->is_account_exist_response_cb(creator, LinphoneAccountCreatorStatusMissingArguments, "Missing required parameters");
699
		}
700
		return LinphoneAccountCreatorStatusMissingArguments;
701
	}
702

703 704 705 706
	ms_debug("Account creator: is_account_exist (%s=%s, domain=%s)",
		(creator->username) ? "username" : "phone number",
		(creator->username) ? creator->username : creator->phone_number,
		linphone_proxy_config_get_domain(creator->proxy_cfg));
707 708 709
	request = linphone_xml_rpc_request_new(LinphoneXmlRpcArgString, "get_phone_number_for_account");
	linphone_xml_rpc_request_add_string_arg(request, creator->username ? creator->username : creator->phone_number);
	linphone_xml_rpc_request_add_string_arg(request, linphone_proxy_config_get_domain(creator->proxy_cfg));
710
	linphone_xml_rpc_request_set_user_data(request, creator);
711
	linphone_xml_rpc_request_cbs_set_response(linphone_xml_rpc_request_get_callbacks(request), _is_account_exist_response_cb);
712 713
	linphone_xml_rpc_session_send_request(creator->xmlrpc_session, request);
	linphone_xml_rpc_request_unref(request);
714

715
	return LinphoneAccountCreatorStatusRequestOk;
716
}
717
/****************** END OF CREATE ACCOUNT USED SECTION ************************/
718

719
/****************** START OF CREATE ACCOUNT SECTION ***************************/
720
static void _create_account_cb_custom(LinphoneXmlRpcRequest *request) {
721
	LinphoneAccountCreator *creator = (LinphoneAccountCreator *)linphone_xml_rpc_request_get_user_data(request);
722 723
	if (creator->cbs->create_account_response_cb != NULL) {
		LinphoneAccountCreatorStatus status = LinphoneAccountCreatorStatusRequestFailed;
724
		const char* resp = linphone_xml_rpc_request_get_string_response(request);
725
		if (linphone_xml_rpc_request_get_status(request) == LinphoneXmlRpcStatusOk) {
726 727 728 729 730
			status = (strcmp(resp, "OK") == 0) ? LinphoneAccountCreatorStatusAccountCreated
			: (strcmp(resp, "ERROR_CANNOT_SEND_SMS") == 0) ? LinphoneAccountCreatorStatusServerError
			: (strcmp(resp, "ERROR_ACCOUNT_ALREADY_IN_USE") == 0) ? LinphoneAccountCreatorStatusAccountExist
			: (strcmp(resp, "ERROR_ALIAS_ALREADY_IN_USE") == 0) ? LinphoneAccountCreatorStatusAccountExistWithAlias
			:LinphoneAccountCreatorStatusAccountNotCreated;
731
		}
732
		creator->cbs->create_account_response_cb(creator, status, resp);
733 734 735
	}
}

736
static LinphoneXmlRpcRequest * _create_account_with_phone_custom(LinphoneAccountCreator *creator) {
737 738 739
	LinphoneXmlRpcRequest *request;
	if (!creator->phone_number) {
		return NULL;
740
	}
741 742 743 744 745 746
	ms_debug("Account creator: create_account_with_phone (phone number=%s, username=%s, domain=%s, language=%s)",
		creator->phone_number,
		(creator->username) ? creator->username : creator->phone_number,
		linphone_proxy_config_get_domain(creator->proxy_cfg),
		creator->language);

747 748 749 750 751 752 753 754
	request = linphone_xml_rpc_request_new(LinphoneXmlRpcArgString, "create_phone_account");
	linphone_xml_rpc_request_add_string_arg(request, creator->phone_number);
	linphone_xml_rpc_request_add_string_arg(request, creator->username ? creator->username : creator->phone_number);
	linphone_xml_rpc_request_add_string_arg(request, creator->password ?
		ha1_for_passwd(creator->username ? creator->username : creator->phone_number, linphone_proxy_config_get_domain(creator->proxy_cfg), creator->password) : "");
	linphone_xml_rpc_request_add_string_arg(request, linphone_core_get_user_agent(creator->core));
	linphone_xml_rpc_request_add_string_arg(request, linphone_proxy_config_get_domain(creator->proxy_cfg));
	linphone_xml_rpc_request_add_string_arg(request, creator->language);
755
	return request;
756 757
}

758
static LinphoneXmlRpcRequest * _create_account_with_email_custom(LinphoneAccountCreator *creator) {
759
	LinphoneXmlRpcRequest *request;
760
	if (!creator->username || !creator->email || !creator->password) {
761 762
		return NULL;
	}
763 764 765 766 767
	ms_debug("Account creator: create_account_with_email (username=%s, email=%s, domain=%s)",
		creator->username,
		creator->email,
		linphone_proxy_config_get_domain(creator->proxy_cfg));

768 769 770 771 772 773 774
	request = linphone_xml_rpc_request_new(LinphoneXmlRpcArgString, "create_email_account");
	linphone_xml_rpc_request_add_string_arg(request, creator->username);
	linphone_xml_rpc_request_add_string_arg(request, creator->email);
	linphone_xml_rpc_request_add_string_arg(request,
		ha1_for_passwd(creator->username ? creator->username : creator->phone_number, linphone_proxy_config_get_domain(creator->proxy_cfg), creator->password));
	linphone_xml_rpc_request_add_string_arg(request, linphone_core_get_user_agent(creator->core));
	linphone_xml_rpc_request_add_string_arg(request, linphone_proxy_config_get_domain(creator->proxy_cfg));
775
	return request;
776 777
}

778
LinphoneAccountCreatorStatus linphone_account_creator_create_account_linphone(LinphoneAccountCreator *creator) {
779
	LinphoneXmlRpcRequest *request;
780
	char *identity = _get_identity(creator);
781 782
	if (!identity || (!(request = _create_account_with_phone_custom(creator))
		&& !(request = _create_account_with_email_custom(creator)))) {
783 784
		if (creator->cbs->create_account_response_cb != NULL) {
			creator->cbs->create_account_response_cb(creator, LinphoneAccountCreatorStatusMissingArguments, "Missing required parameters");
785
		}
786
		if (identity) ms_free(identity);
787
		return LinphoneAccountCreatorStatusMissingArguments;
788
	}
789

790
	linphone_xml_rpc_request_set_user_data(request, creator);
791
	linphone_xml_rpc_request_cbs_set_response(linphone_xml_rpc_request_get_callbacks(request), _create_account_cb_custom);
792 793 794
	linphone_xml_rpc_session_send_request(creator->xmlrpc_session, request);
	linphone_xml_rpc_request_unref(request);
	ms_free(identity);
795
	return LinphoneAccountCreatorStatusRequestOk;
796
}
797
/****************** END OF CREATE ACCOUNT SECTION *****************************/
798

799
/****************** START OF VALIDATE ACCOUNT SECTION *************************/
800
static void _activate_account_cb_custom(LinphoneXmlRpcRequest *request) {
801
	LinphoneAccountCreator *creator = (LinphoneAccountCreator *)linphone_xml_rpc_request_get_user_data(request);
802 803
	if (creator->cbs->activate_account_response_cb != NULL) {
		LinphoneAccountCreatorStatus status = LinphoneAccountCreatorStatusRequestFailed;
804
		const char* resp = linphone_xml_rpc_request_get_string_response(request);
805
		if (linphone_xml_rpc_request_get_status(request) == LinphoneXmlRpcStatusOk) {
806
			if (strcmp(resp, "ERROR_ACCOUNT_ALREADY_ACTIVATED") == 0) {
807
				status = LinphoneAccountCreatorStatusAccountAlreadyActivated;
808
			} else if (strstr(resp, "ERROR_") == resp) {
809
				status = LinphoneAccountCreatorStatusAccountNotActivated;
810
			} else {
811
				status = LinphoneAccountCreatorStatusAccountActivated;
812 813
				set_string(&creator->ha1, resp, FALSE);
			}
814
		}
815
		creator->cbs->activate_account_response_cb(creator, status, resp);
816 817 818
	}
}

819
LinphoneAccountCreatorStatus linphone_account_creator_activate_account_linphone(LinphoneAccountCreator *creator) {
820
	LinphoneXmlRpcRequest *request;
821
	if (!creator->phone_number || !creator->activation_code) {
822 823
		if (creator->cbs->is_account_activated_response_cb != NULL) {
			creator->cbs->is_account_activated_response_cb(creator, LinphoneAccountCreatorStatusMissingArguments, "Missing required parameters");
824
		}
825
		return LinphoneAccountCreatorStatusMissingArguments;
826
	}
827 828 829 830 831
	ms_debug("Account creator: activate_account_phone (phone number=%s, username=%s, activation code=%s, domain=%s)",
		creator->phone_number,
		creator->username ? creator->username : creator->phone_number,
		creator->activation_code,
		linphone_proxy_config_get_domain(creator->proxy_cfg));
832

833 834 835 836 837
	request = linphone_xml_rpc_request_new(LinphoneXmlRpcArgString, "activate_phone_account");
	linphone_xml_rpc_request_add_string_arg(request, creator->phone_number);
	linphone_xml_rpc_request_add_string_arg(request, creator->username ? creator->username : creator->phone_number);
	linphone_xml_rpc_request_add_string_arg(request, creator->activation_code);
	linphone_xml_rpc_request_add_string_arg(request, linphone_proxy_config_get_domain(creator->proxy_cfg));
838 839 840 841 842 843 844 845 846
	linphone_xml_rpc_request_set_user_data(request, creator);
	linphone_xml_rpc_request_cbs_set_response(linphone_xml_rpc_request_get_callbacks(request), _activate_account_cb_custom);
	linphone_xml_rpc_session_send_request(creator->xmlrpc_session, request);
	linphone_xml_rpc_request_unref(request);
	return LinphoneAccountCreatorStatusRequestOk;
}

LinphoneAccountCreatorStatus linphone_account_creator_activate_email_account_linphone(LinphoneAccountCreator *creator) {
	LinphoneXmlRpcRequest *request;
847
	if (!creator->activation_code || !creator->username) {
848 849 850 851 852 853
		if (creator->cbs->is_account_activated_response_cb != NULL) {
			creator->cbs->is_account_activated_response_cb(creator, LinphoneAccountCreatorStatusMissingArguments, "Missing required parameters");
		}
		return LinphoneAccountCreatorStatusMissingArguments;
	}

854 855 856 857 858
	ms_debug("Account creator: activate_account_email (username=%s, activation code=%s, domain=%s)",
		creator->username,
		creator->activation_code,
		linphone_proxy_config_get_domain(creator->proxy_cfg));

859 860 861 862
	request = linphone_xml_rpc_request_new(LinphoneXmlRpcArgString, "activate_email_account");
	linphone_xml_rpc_request_add_string_arg(request, creator->username);
	linphone_xml_rpc_request_add_string_arg(request, creator->activation_code);
	linphone_xml_rpc_request_add_string_arg(request, linphone_proxy_config_get_domain(creator->proxy_cfg));
863
	linphone_xml_rpc_request_set_user_data(request, creator);
864
	linphone_xml_rpc_request_cbs_set_response(linphone_xml_rpc_request_get_callbacks(request), _activate_account_cb_custom);
865 866
	linphone_xml_rpc_session_send_request(creator->xmlrpc_session, request);
	linphone_xml_rpc_request_unref(request);
867
	return LinphoneAccountCreatorStatusRequestOk;
868
}
869
/****************** END OF CREATE VALIDATE ACCOUNT SECTION ********************/
870

871
/****************** START OF ACCOUNT VALIDATED SECTION ************************/
872
static void _is_account_activated_cb_custom(LinphoneXmlRpcRequest *request) {
873
	LinphoneAccountCreator *creator = (LinphoneAccountCreator *)linphone_xml_rpc_request_get_user_data(request);
874 875
	if (creator->cbs->is_account_activated_response_cb != NULL) {
		LinphoneAccountCreatorStatus status = LinphoneAccountCreatorStatusRequestFailed;
876
		const char* resp = linphone_xml_rpc_request_get_string_response(request);
877
		if (linphone_xml_rpc_request_get_status(request) == LinphoneXmlRpcStatusOk) {
878
			status = (strcmp(resp, "OK") == 0) ? LinphoneAccountCreatorStatusAccountActivated : LinphoneAccountCreatorStatusAccountNotActivated;
879
		}
880
		creator->cbs->is_account_activated_response_cb(creator, status, resp);
881
	}
882 883
}

884
LinphoneAccountCreatorStatus linphone_account_creator_is_account_activated_linphone(LinphoneAccountCreator *creator) {
885 886 887
	LinphoneXmlRpcRequest *request;
	char *identity = _get_identity(creator);
	if (!identity) {
888 889
		if (creator->cbs->is_account_activated_response_cb != NULL) {
			creator->cbs->is_account_activated_response_cb(creator, LinphoneAccountCreatorStatusMissingArguments, "Missing required parameters");
890
		}
891
		return LinphoneAccountCreatorStatusMissingArguments;
892
	}
893 894 895 896
	ms_debug("Account creator: is_account_activated (username=%s, domain=%s)",
		creator->username ? creator->username : creator->phone_number,
		linphone_proxy_config_get_domain(creator->proxy_cfg));

897 898 899
	request = linphone_xml_rpc_request_new(LinphoneXmlRpcArgString, "is_account_activated");
	linphone_xml_rpc_request_add_string_arg(request, creator->username ? creator->username : creator->phone_number);
	linphone_xml_rpc_request_add_string_arg(request, linphone_proxy_config_get_domain(creator->proxy_cfg));
900
	linphone_xml_rpc_request_set_user_data(request, creator);
901
	linphone_xml_rpc_request_cbs_set_response(linphone_xml_rpc_request_get_callbacks(request), _is_account_activated_cb_custom);
902 903 904
	linphone_xml_rpc_session_send_request(creator->xmlrpc_session, request);
	linphone_xml_rpc_request_unref(request);
	ms_free(identity);
905
	return LinphoneAccountCreatorStatusRequestOk;
906 907
}
/****************** END OF CREATE ACCOUNT VALIDATED SECTION********************/
908

909 910
/****************** START OF PHONE NUMBER VALIDATED SECTION *******************/

911
static void _is_phone_number_used_cb_custom(LinphoneXmlRpcRequest *request) {
912
	LinphoneAccountCreator *creator = (LinphoneAccountCreator *)linphone_xml_rpc_request_get_user_data(request);
913 914
	if (creator->cbs->is_alias_used_response_cb != NULL) {
		LinphoneAccountCreatorStatus status = LinphoneAccountCreatorStatusRequestFailed;
915 916
		const char* resp = linphone_xml_rpc_request_get_string_response(request);
		if (linphone_xml_rpc_request_get_status(request) == LinphoneXmlRpcStatusOk) {
917 918 919
			status = (strcmp(resp, "OK_ACCOUNT") == 0) ? LinphoneAccountCreatorStatusAliasIsAccount
			: (strcmp(resp, "OK_ALIAS") == 0) ? LinphoneAccountCreatorStatusAliasExist
			: LinphoneAccountCreatorStatusAliasNotExist;
920
		}
921
		creator->cbs->is_alias_used_response_cb(creator, status, resp);
922 923 924
	}
}

925
LinphoneAccountCreatorStatus linphone_account_creator_is_phone_number_used_linphone(LinphoneAccountCreator *creator) {
926 927 928
	LinphoneXmlRpcRequest *request;
	char *identity = _get_identity(creator);
	if (!identity) {
929 930
		if (creator->cbs->is_alias_used_response_cb != NULL) {
			creator->cbs->is_alias_used_response_cb(creator, LinphoneAccountCreatorStatusMissingArguments, "Missing required parameters");
931
		}
932
		return LinphoneAccountCreatorStatusMissingArguments;
933
	}
934 935 936 937 938

	ms_debug("Account creator: is_phone_number_used (phone number=%s, domain=%s)",
		creator->phone_number,
		linphone_proxy_config_get_domain(creator->proxy_cfg));

939 940 941
	request = linphone_xml_rpc_request_new(LinphoneXmlRpcArgString, "is_phone_number_used");
	linphone_xml_rpc_request_add_string_arg(request, creator->phone_number);
	linphone_xml_rpc_request_add_string_arg(request, linphone_proxy_config_get_domain(creator->proxy_cfg));
942
	linphone_xml_rpc_request_set_user_data(request, creator);
943
	linphone_xml_rpc_request_cbs_set_response(linphone_xml_rpc_request_get_callbacks(request), _is_phone_number_used_cb_custom);
944 945 946
	linphone_xml_rpc_session_send_request(creator->xmlrpc_session, request);
	linphone_xml_rpc_request_unref(request);
	ms_free(identity);
947
	return LinphoneAccountCreatorStatusRequestOk;
948 949 950 951
}

/****************** END OF PHONE NUMBER VALIDATED SECTION *********************/

952
/****************** START OF LINK PHONE NUMBER WITH ACCOUNT SECTION ***********/
953
static void _link_phone_number_with_account_cb_custom(LinphoneXmlRpcRequest *request) {
954
	LinphoneAccountCreator *creator = (LinphoneAccountCreator *)linphone_xml_rpc_request_get_user_data(request);
955 956
	if (creator->cbs->link_account_response_cb != NULL) {
		LinphoneAccountCreatorStatus status = LinphoneAccountCreatorStatusRequestFailed;
957
		const char* resp = linphone_xml_rpc_request_get_string_response(request);
958
		if (linphone_xml_rpc_request_get_status(request) == LinphoneXmlRpcStatusOk) {
959
			status = (strcmp(resp, "OK") == 0) ? LinphoneAccountCreatorStatusRequestOk : LinphoneAccountCreatorStatusAccountNotLinked;
960
		}
961
		creator->cbs->link_account_response_cb(creator, status, resp);
962
	}
963
}
964

965
LinphoneAccountCreatorStatus linphone_account_creator_link_phone_number_with_account_linphone(LinphoneAccountCreator *creator) {
966 967
	LinphoneXmlRpcRequest *request;
	if (!creator->phone_number || !creator->username) {
968 969
		if (creator->cbs->link_account_response_cb != NULL) {
			creator->cbs->link_account_response_cb(creator, LinphoneAccountCreatorStatusMissingArguments, "Missing required parameters");
970
		}
971
		return LinphoneAccountCreatorStatusMissingArguments;
972
	}
973 974 975 976 977 978 979

	ms_debug("Account creator: link_phone_number_with_account (phone number=%s, username=%s, domain=%s, language=%s)",
		creator->phone_number,
		creator->username,
		linphone_proxy_config_get_domain(creator->proxy_cfg),
		creator->language);

980 981 982 983 984
	request = linphone_xml_rpc_request_new(LinphoneXmlRpcArgString, "link_phone_number_with_account");
	linphone_xml_rpc_request_add_string_arg(request, creator->phone_number);
	linphone_xml_rpc_request_add_string_arg(request, creator->username);
	linphone_xml_rpc_request_add_string_arg(request, linphone_proxy_config_get_domain(creator->proxy_cfg));
	linphone_xml_rpc_request_add_string_arg(request, creator->language);
985
	linphone_xml_rpc_request_set_user_data(request, creator);
986
	linphone_xml_rpc_request_cbs_set_response(linphone_xml_rpc_request_get_callbacks(request), _link_phone_number_with_account_cb_custom);
987 988
	linphone_xml_rpc_session_send_request(creator->xmlrpc_session, request);
	linphone_xml_rpc_request_unref(request);
989
	return LinphoneAccountCreatorStatusRequestOk;
990
}
991

992
static void _get_phone_number_for_account_cb_custom(LinphoneXmlRpcRequest *request) {
993
	LinphoneAccountCreator *creator = (LinphoneAccountCreator *)linphone_xml_rpc_request_get_user_data(request);
994 995
	if (creator->cbs->is_account_linked_response_cb != NULL) {
		LinphoneAccountCreatorStatus status = LinphoneAccountCreatorStatusRequestFailed;
996 997 998 999
		const char* resp = linphone_xml_rpc_request_get_string_response(request);
		if (linphone_xml_rpc_request_get_status(request) == LinphoneXmlRpcStatusOk) {
			status = (strcmp(resp, "ERROR_USERNAME_PARAMETER_NOT_FOUND") == 0
				|| strcmp(resp, "ERROR_ACCOUNT_DOESNT_EXIST") == 0
1000
				|| strcmp(resp, "ERROR_ALIAS_DOESNT_EXIST") == 0) ? LinphoneAccountCreatorStatusAccountNotLinked : LinphoneAccountCreatorStatusAccountLinked;
1001
		}
1002
		creator->cbs->is_account_linked_response_cb(creator, status, resp);
1003 1004 1005
	}
}

1006
LinphoneAccountCreatorStatus linphone_account_creator_is_account_linked_linphone(LinphoneAccountCreator *creator) {
1007 1008
	LinphoneXmlRpcRequest *request;
	if (!creator->username || !linphone_proxy_config_get_domain(creator->proxy_cfg)) {
1009
		return LinphoneAccountCreatorStatusMissingArguments;
1010
	}
1011 1012 1013 1014 1015

	ms_debug("Account creator: is_account_linked (username=%s, domain=%s)",
		creator->username,
		linphone_proxy_config_get_domain(creator->proxy_cfg));

1016 1017 1018
	request = linphone_xml_rpc_request_new(LinphoneXmlRpcArgString, "get_phone_number_for_account");
	linphone_xml_rpc_request_add_string_arg(request, creator->username);
	linphone_xml_rpc_request_add_string_arg(request, linphone_proxy_config_get_domain(creator->proxy_cfg));
1019 1020 1021 1022 1023
	linphone_xml_rpc_request_set_user_data(request, creator);
	linphone_xml_rpc_request_cbs_set_response(linphone_xml_rpc_request_get_callbacks(request), _get_phone_number_for_account_cb_custom);
	linphone_xml_rpc_session_send_request(creator->xmlrpc_session, request);
	linphone_xml_rpc_request_unref(request);
	return LinphoneAccountCreatorStatusRequestOk;
1024
}
1025
/****************** END OF LINK PHONE NUMBER WITH ACCOUNT SECTION *************/
1026

1027
/****************** START OF ACTIVE PHONE NUMBER LINK **************************/
1028
static void _activate_phone_number_link_cb_custom(LinphoneXmlRpcRequest *request) {
1029
	LinphoneAccountCreator *creator = (LinphoneAccountCreator *)linphone_xml_rpc_request_get_user_data(request);
1030 1031
	if (creator->cbs->activate_alias_response_cb != NULL) {
		LinphoneAccountCreatorStatus status = LinphoneAccountCreatorStatusRequestFailed;
1032
		const char* resp = linphone_xml_rpc_request_get_string_response(request);
1033
		if (linphone_xml_rpc_request_get_status(request) == LinphoneXmlRpcStatusOk) {
1034
			status = (strstr(resp, "ERROR_") == resp) ? LinphoneAccountCreatorStatusAccountNotActivated : LinphoneAccountCreatorStatusAccountActivated;
1035
		}
1036
		creator->cbs->activate_alias_response_cb(creator, status, resp);
1037
	}
1038
}
1039

1040
LinphoneAccountCreatorStatus linphone_account_creator_activate_phone_number_link_linphone(LinphoneAccountCreator *creator) {
1041
	LinphoneXmlRpcRequest *request;
1042
	if (!creator->phone_number || !creator->username || !creator->activation_code || (!creator->password && !creator->ha1) || !linphone_proxy_config_get_domain(creator->proxy_cfg)) {
1043 1044
		if (creator->cbs->activate_alias_response_cb != NULL) {
			creator->cbs->activate_alias_response_cb(creator, LinphoneAccountCreatorStatusMissingArguments, "Missing required parameters");
1045
		}
1046
		return LinphoneAccountCreatorStatusMissingArguments;
1047
	}
1048 1049 1050 1051

	ms_debug("Account creator: activate_phone_number_link (phone number=%s, username=%s, activation code=%s, domain=%s)",
		creator->phone_number,
		creator->username,
Erwan Croze's avatar
Erwan Croze committed
1052
		creator->activation_code,
1053 1054
		linphone_proxy_config_get_domain(creator->proxy_cfg));

1055 1056 1057 1058 1059 1060
	request = linphone_xml_rpc_request_new(LinphoneXmlRpcArgString, "activate_phone_number_link");
	linphone_xml_rpc_request_add_string_arg(request, creator->phone_number);
	linphone_xml_rpc_request_add_string_arg(request, creator->username);
	linphone_xml_rpc_request_add_string_arg(request, creator->activation_code);
	linphone_xml_rpc_request_add_string_arg(request, creator->ha1 ? creator->ha1 : ha1_for_passwd(creator->username, linphone_proxy_config_get_domain(creator->proxy_cfg), creator->password));
	linphone_xml_rpc_request_add_string_arg(request, linphone_proxy_config_get_domain(creator->proxy_cfg));
1061
	linphone_xml_rpc_request_set_user_data(request, creator);
1062
	linphone_xml_rpc_request_cbs_set_response(linphone_xml_rpc_request_get_callbacks(request), _activate_phone_number_link_cb_custom);
1063 1064
	linphone_xml_rpc_session_send_request(creator->xmlrpc_session, request);
	linphone_xml_rpc_request_unref(request);