account_creator.c 52.9 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

Simon Morlat's avatar
Simon Morlat committed
24

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

Simon Morlat's avatar
Simon Morlat committed
28 29 30

#include "bctoolbox/crypto.h"
#include "bctoolbox/regex.h"
31

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

35 36 37 38
// =============================================================================

using namespace LinphonePrivate;

39
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneAccountCreatorCbs);
40

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

/************************** Start Misc **************************/
49 50 51 52 53 54
static const char *_get_domain(LinphoneAccountCreator *creator) {
	if (creator->domain)
		return creator->domain;
	return linphone_proxy_config_get_domain(creator->proxy_cfg);
}

55 56 57 58 59 60
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
61
static unsigned int validate_uri(const char* username, const char* domain, const char* display_name) {
62
	LinphoneAddress* addr;
Benjamin REIS's avatar
Benjamin REIS committed
63
	unsigned int status = 0;
Erwan Croze's avatar
Erwan Croze committed
64
	LinphoneProxyConfig* proxy = linphone_proxy_config_new();
65
	linphone_proxy_config_set_identity(proxy, "sip:?@domain.com");
66 67 68 69 70 71 72

	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
73 74 75 76
	if (addr == NULL) {
		status = 1;
		goto end;
	}
77

Erwan Croze's avatar
Erwan Croze committed
78 79
	if (domain && linphone_address_set_domain(addr, domain) != 0) {
		status = 1;
80 81
	}

Erwan Croze's avatar
Erwan Croze committed
82 83 84
	if (display_name && (!strlen(display_name) || linphone_address_set_display_name(addr, display_name) != 0)) {
		status = 1;
	}
85
	linphone_address_unref(addr);
Erwan Croze's avatar
Erwan Croze committed
86 87 88
end:
	linphone_proxy_config_destroy(proxy);
	return status;
89 90 91 92 93 94
}

static char* _get_identity(const LinphoneAccountCreator *creator) {
	char *identity = NULL;
	if ((creator->username || creator->phone_number)) {
		//we must escape username
95
		LinphoneProxyConfig* proxy = linphone_core_create_proxy_config(creator->core);
96 97 98
		LinphoneAddress* addr;

		addr = linphone_proxy_config_normalize_sip_uri(proxy, creator->username ? creator->username : creator->phone_number);
99 100 101
		if (addr == NULL || (creator->domain && strcmp(linphone_address_get_domain(addr), creator->domain) != 0)) {
			if ((creator->username || creator->phone_number) && creator->domain) {
                char *url = ms_strdup_printf("sip:%s@%s", creator->username ? creator->username : creator->phone_number, creator->domain);
102 103 104 105 106 107 108 109 110
				addr = linphone_address_new(url);
				ms_free(url);
				if (addr == NULL) {
					goto end;
				}
			} else {
				goto end;
			}
		}
111 112 113

		identity = linphone_address_as_string(addr);
		linphone_address_unref(addr);
114 115
		end:
		linphone_proxy_config_destroy(proxy);
116 117 118 119
	}
	return identity;
}

120 121 122 123 124 125 126
static inline void resetField (char **field) {
	if (*field) {
		bctbx_free(*field);
		*field = nullptr;
	}
}

127
LinphoneProxyConfig * linphone_account_creator_create_proxy_config(const LinphoneAccountCreator *creator) {
128 129 130 131
	LinphoneAuthInfo *info;
	LinphoneProxyConfig *cfg = linphone_core_create_proxy_config(creator->core);
	char *identity_str = _get_identity(creator);
	LinphoneAddress *identity = linphone_address_new(identity_str);
132

133 134 135 136 137 138 139 140
	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) {
141
		int dial_prefix_number = DialPlan::lookupCccFromE164(creator->phone_number);
142 143 144
		char buff[4];
		snprintf(buff, sizeof(buff), "%d", dial_prefix_number);
		linphone_proxy_config_set_dial_prefix(cfg, buff);
145 146 147
	}
	if (linphone_proxy_config_get_server_addr(cfg) == NULL && creator->domain != NULL) {
		linphone_proxy_config_set_server_addr(cfg, creator->domain);
148
	}
Erwan Croze's avatar
Erwan Croze committed
149

150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
	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);
168
	linphone_auth_info_unref(info);
169 170
	return NULL;
}
171 172 173 174

LinphoneProxyConfig * linphone_account_creator_configure(const LinphoneAccountCreator *creator) {
	return linphone_account_creator_create_proxy_config(creator);
}
175 176 177 178
/************************** End Misc **************************/

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

179 180
static LinphoneAccountCreatorCbs * linphone_account_creator_cbs_new(void) {
	return belle_sip_object_new(LinphoneAccountCreatorCbs);
181 182
}

183 184 185
LinphoneAccountCreatorCbs * linphone_account_creator_cbs_ref(LinphoneAccountCreatorCbs *cbs) {
	belle_sip_object_ref(cbs);
	return cbs;
186 187
}

188 189
void linphone_account_creator_cbs_unref(LinphoneAccountCreatorCbs *cbs) {
	belle_sip_object_unref(cbs);
190 191
}

192 193
void *linphone_account_creator_cbs_get_user_data(const LinphoneAccountCreatorCbs *cbs) {
	return cbs->user_data;
194 195
}

196 197
void linphone_account_creator_cbs_set_user_data(LinphoneAccountCreatorCbs *cbs, void *ud) {
	cbs->user_data = ud;
198 199
}

200 201
LinphoneAccountCreatorCbsStatusCb linphone_account_creator_cbs_get_create_account(const LinphoneAccountCreatorCbs *cbs) {
	return cbs->create_account_response_cb;
202 203
}

204 205
void linphone_account_creator_cbs_set_create_account(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsStatusCb cb) {
	cbs->create_account_response_cb = cb;
206 207
}

208 209
LinphoneAccountCreatorCbsStatusCb linphone_account_creator_cbs_get_is_account_exist(const LinphoneAccountCreatorCbs *cbs) {
	return cbs->is_account_exist_response_cb;
210 211
}

212 213
void linphone_account_creator_cbs_set_is_account_exist(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsStatusCb cb) {
	cbs->is_account_exist_response_cb = cb;
214 215
}

216 217
LinphoneAccountCreatorCbsStatusCb linphone_account_creator_cbs_get_activate_account(const LinphoneAccountCreatorCbs *cbs) {
	return cbs->activate_account_response_cb;
218 219
}

220 221
void linphone_account_creator_cbs_set_activate_account(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsStatusCb cb) {
	cbs->activate_account_response_cb = cb;
222 223
}

224 225
LinphoneAccountCreatorCbsStatusCb linphone_account_creator_cbs_get_is_account_activated(const LinphoneAccountCreatorCbs *cbs) {
	return cbs->is_account_activated_response_cb;
226 227
}

228 229
void linphone_account_creator_cbs_set_is_account_activated(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsStatusCb cb) {
	cbs->is_account_activated_response_cb = cb;
230 231
}

232 233
LinphoneAccountCreatorCbsStatusCb linphone_account_creator_cbs_get_link_account(const LinphoneAccountCreatorCbs *cbs) {
	return cbs->link_account_response_cb;
234 235
}

236 237
void linphone_account_creator_cbs_set_link_account(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsStatusCb cb) {
	cbs->link_account_response_cb = cb;
238 239
}

240 241
LinphoneAccountCreatorCbsStatusCb linphone_account_creator_cbs_get_activate_alias(const LinphoneAccountCreatorCbs *cbs) {
	return cbs->activate_alias_response_cb;
242
}
243

244 245
void linphone_account_creator_cbs_set_activate_alias(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsStatusCb cb) {
	cbs->activate_alias_response_cb = cb;
246 247
}

248 249
LinphoneAccountCreatorCbsStatusCb linphone_account_creator_cbs_get_is_alias_used(const LinphoneAccountCreatorCbs *cbs) {
	return cbs->is_alias_used_response_cb;
250 251
}

252 253
void linphone_account_creator_cbs_set_is_alias_used(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsStatusCb cb) {
	cbs->is_alias_used_response_cb = cb;
254 255
}

256 257
LinphoneAccountCreatorCbsStatusCb linphone_account_creator_cbs_get_is_account_linked(const LinphoneAccountCreatorCbs *cbs) {
	return cbs->is_account_linked_response_cb;
258
}
259

260 261
void linphone_account_creator_cbs_set_is_account_linked(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsStatusCb cb) {
	cbs->is_account_linked_response_cb = cb;
262 263
}

264 265
LinphoneAccountCreatorCbsStatusCb linphone_account_creator_cbs_get_recover_account(const LinphoneAccountCreatorCbs *cbs) {
	return cbs->recover_account_response_cb;
266 267
}

268 269
void linphone_account_creator_cbs_set_recover_account(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsStatusCb cb) {
	cbs->recover_account_response_cb = cb;
270 271
}

272 273
LinphoneAccountCreatorCbsStatusCb linphone_account_creator_cbs_get_update_account(const LinphoneAccountCreatorCbs *cbs) {
	return cbs->update_account_response_cb;
274 275
}

276 277
void linphone_account_creator_cbs_set_update_account(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsStatusCb cb) {
	cbs->update_account_response_cb = cb;
278 279 280 281
}
/************************** End Account Creator Cbs **************************/

/************************** Start Account Creator data **************************/
282
static void _linphone_account_creator_destroy(LinphoneAccountCreator *creator) {
283 284
	/*this will drop all pending requests if any*/
	if (creator->xmlrpc_session) linphone_xml_rpc_session_release(creator->xmlrpc_session);
285 286 287 288 289
	if (creator->service != NULL ) {
			if (linphone_account_creator_service_get_destructor_cb(creator->service) != NULL)
				linphone_account_creator_service_get_destructor_cb(creator->service)(creator);
			linphone_account_creator_service_unref(creator->service);
	}
290

291
	linphone_account_creator_cbs_unref(creator->cbs);
292
	linphone_proxy_config_unref(creator->proxy_cfg);
293
	linphone_account_creator_reset(creator);
294 295 296 297 298 299 300 301 302 303 304
}

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
);

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

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

328
void linphone_account_creator_reset(LinphoneAccountCreator *creator) {
329 330 331 332 333 334 335 336 337 338 339
	resetField(&creator->username);
	resetField(&creator->display_name);
	resetField(&creator->password);
	resetField(&creator->ha1);
	resetField(&creator->phone_number);
	resetField(&creator->phone_country_code);
	resetField(&creator->email);
	resetField(&creator->language);
	resetField(&creator->activation_code);
	resetField(&creator->domain);
	resetField(&creator->route);
340 341
}

342 343 344 345
LinphoneAccountCreator * linphone_core_create_account_creator(LinphoneCore *core, const char *xmlrpc_url) {
	return _linphone_account_creator_new(core, xmlrpc_url);
}

346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362
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;
}

363
LinphoneAccountCreatorUsernameStatus linphone_account_creator_set_username(LinphoneAccountCreator *creator, const char *username) {
364 365
	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);
366
	bool_t use_phone_number = !!lp_config_get_int(creator->core->config, "assistant", "use_phone_number", 0);
367
	const char* regex = lp_config_get_string(creator->core->config, "assistant", "username_regex", 0);
368
	if (!username) {
369
		resetField(&creator->username);
370
		return LinphoneAccountCreatorUsernameStatusOk;
371
	} else if (min_length > 0 && strlen(username) < (size_t)min_length) {
372
		return LinphoneAccountCreatorUsernameStatusTooShort;
373
	} else if (max_length > 0 && strlen(username) > (size_t)max_length) {
374
		return LinphoneAccountCreatorUsernameStatusTooLong;
375
	} else if (use_phone_number && !linphone_proxy_config_is_phone_number(NULL, username)) {
376
		return LinphoneAccountCreatorUsernameStatusInvalid;
377
	} else if (regex && !bctbx_is_matching_regex(username, regex)) {
378
		return LinphoneAccountCreatorUsernameStatusInvalidCharacters;
Erwan Croze's avatar
Erwan Croze committed
379
	} else if (validate_uri(username, NULL, NULL) != 0) {
380
		return LinphoneAccountCreatorUsernameStatusInvalid;
381
	}
382

383
	set_string(&creator->username, username, TRUE);
384
	return LinphoneAccountCreatorUsernameStatusOk;
385 386 387 388 389 390
}

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

391
LinphoneAccountCreatorPhoneNumberStatusMask linphone_account_creator_set_phone_number(LinphoneAccountCreator *creator, const char *phone_number, const char *country_code) {
392
	char *normalized_phone_number;
393
	LinphoneAccountCreatorPhoneNumberStatusMask return_status = 0;
394
	if (!phone_number || !country_code) {
395 396
		if (!phone_number && !country_code) {
			creator->phone_number = NULL;
397
			creator->phone_country_code = NULL;
398
			return (LinphoneAccountCreatorPhoneNumberStatusMask)LinphoneAccountCreatorPhoneNumberStatusOk;
399
		} else {
400
			return (LinphoneAccountCreatorPhoneNumberStatusMask)LinphoneAccountCreatorPhoneNumberStatusInvalid;
401
		}
402
	} else {
403
		LinphoneProxyConfig *numCfg = creator->proxy_cfg;
404 405
		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);
406 407
		normalized_phone_number = linphone_proxy_config_normalize_phone_number(numCfg, phone_number);
		if (!normalized_phone_number) {
408
			return LinphoneAccountCreatorPhoneNumberStatusInvalid;
409 410 411 412
		}

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

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

440
LinphoneAccountCreatorPasswordStatus linphone_account_creator_set_password(LinphoneAccountCreator *creator, const char *password) {
441 442
	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);
443
	if (!password) {
444
		resetField(&creator->password);
445
		return LinphoneAccountCreatorPasswordStatusTooShort;
446
	}
447
	if (min_length > 0 && strlen(password) < (size_t)min_length) {
448
		return LinphoneAccountCreatorPasswordStatusTooShort;
449
	} else if (max_length > 0 && strlen(password) > (size_t)max_length) {
450
		return LinphoneAccountCreatorPasswordStatusTooLong;
451
	}
452
	set_string(&creator->password, password, FALSE);
453
	return LinphoneAccountCreatorPasswordStatusOk;
454 455 456 457 458 459
}

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

460
LinphoneAccountCreatorPasswordStatus linphone_account_creator_set_ha1(LinphoneAccountCreator *creator, const char *ha1){
461
	set_string(&creator->ha1, ha1, FALSE);
462
	return LinphoneAccountCreatorPasswordStatusOk;
463 464 465 466 467 468
}

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

469
LinphoneAccountCreatorActivationCodeStatus linphone_account_creator_set_activation_code(LinphoneAccountCreator *creator, const char *activation_code){
470
	set_string(&creator->activation_code, activation_code, FALSE);
471
	return LinphoneAccountCreatorActivationCodeStatusOk;
472 473
}

474 475 476 477
const char * linphone_account_creator_get_activation_code(const LinphoneAccountCreator *creator) {
	return creator->activation_code;
}

478
LinphoneAccountCreatorLanguageStatus linphone_account_creator_set_language(LinphoneAccountCreator *creator, const char *lang) {
479
	set_string(&creator->language, lang, FALSE);
480
	return LinphoneAccountCreatorLanguageStatusOk;
481 482 483 484
}

const char * linphone_account_creator_get_language(const LinphoneAccountCreator *creator) {
	return creator->language;
485 486
}

487
LinphoneAccountCreatorUsernameStatus linphone_account_creator_set_display_name(LinphoneAccountCreator *creator, const char *display_name) {
Erwan Croze's avatar
Erwan Croze committed
488
	if (validate_uri(NULL, display_name, NULL) != 0) {
489
		return LinphoneAccountCreatorUsernameStatusInvalid;
490
	}
491
	set_string(&creator->display_name, display_name, FALSE);
492
	return LinphoneAccountCreatorUsernameStatusOk;
493 494
}

495 496
const char * linphone_account_creator_get_display_name(const LinphoneAccountCreator *creator) {
	return creator->display_name;
497 498
}

499
LinphoneAccountCreatorEmailStatus linphone_account_creator_set_email(LinphoneAccountCreator *creator, const char *email) {
500
	if (!email || !bctbx_is_matching_regex(email, "^.+@.+\\..*$")) {
501
		return LinphoneAccountCreatorEmailStatusMalformed;
502
	}
503
	if (!bctbx_is_matching_regex(email, "^.+@.+\\.[A-Za-z]{2}[A-Za-z]*$")) {
504
		return LinphoneAccountCreatorEmailStatusInvalidCharacters;
505
	}
506
	set_string(&creator->email, email, TRUE);
507
	return LinphoneAccountCreatorEmailStatusOk;
508 509
}

510 511
const char * linphone_account_creator_get_email(const LinphoneAccountCreator *creator) {
	return creator->email;
512 513
}

514
LinphoneAccountCreatorDomainStatus linphone_account_creator_set_domain(LinphoneAccountCreator *creator, const char *domain) {
Erwan Croze's avatar
Erwan Croze committed
515
	if (domain && validate_uri(NULL, domain, NULL) != 0) {
516
		return LinphoneAccountCreatorDomainInvalid;
Erwan Croze's avatar
Erwan Croze committed
517 518 519
	}

	set_string(&creator->domain, domain, TRUE);
520
	return LinphoneAccountCreatorDomainOk;
Erwan Croze's avatar
Erwan Croze committed
521 522 523 524 525 526
 }

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

527
LinphoneAccountCreatorTransportStatus linphone_account_creator_set_transport(LinphoneAccountCreator *creator, LinphoneTransportType transport) {
528
	if (!linphone_core_sip_transport_supported(creator->core, transport)) {
529
		return LinphoneAccountCreatorTransportUnsupported;
530 531
	}
	creator->transport = transport;
532
	return LinphoneAccountCreatorTransportOk;
533 534 535 536 537 538
}

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

539
LinphoneAccountCreatorStatus linphone_account_creator_set_route(LinphoneAccountCreator *creator, const char *route) {
Erwan Croze's avatar
Erwan Croze committed
540
	if (!route || linphone_proxy_config_set_route(creator->proxy_cfg, route) != 0)
541
		return LinphoneAccountCreatorStatusRequestFailed;
Erwan Croze's avatar
Erwan Croze committed
542 543

	set_string(&creator->route, route, TRUE);
544
	return LinphoneAccountCreatorStatusRequestOk;
Erwan Croze's avatar
Erwan Croze committed
545 546 547 548 549 550
}

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

551 552
LinphoneAccountCreatorCbs * linphone_account_creator_get_callbacks(const LinphoneAccountCreator *creator) {
	return creator->cbs;
553 554
}

555 556
LinphoneAccountCreatorService * linphone_account_creator_get_service(const LinphoneAccountCreator *creator) {
	return creator->service;
557 558
}

559 560 561 562
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;
563
	}
564

565
	return creator->service->is_account_exist_request_cb(creator);
566 567
}

568 569 570 571
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;
572
	}
573

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

577 578 579 580
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;
581 582
	}

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

586 587 588 589
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;
590 591
	}

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

595 596 597 598
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;
599
	}
600

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

604 605 606 607
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;
608
	}
609

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

613 614 615 616
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;
617
	}
618

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

622 623 624 625
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;
626
	}
627

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

631 632 633 634
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;
635 636
	}

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

640 641 642 643
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;
644 645
	}

646
	return creator->service->update_account_request_cb(creator);
647
}
648 649 650
/************************** End Account Creator data **************************/

/************************** Start Account Creator Linphone **************************/
651

652
LinphoneAccountCreatorStatus linphone_account_creator_constructor_linphone(LinphoneAccountCreator *creator) {
653
	LinphoneAddress *addr;
654 655 656 657 658 659 660 661
	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");
662 663
	linphone_proxy_config_set_identity_address(creator->proxy_cfg, addr);
	linphone_address_unref(addr);
664
	return LinphoneAccountCreatorStatusRequestOk;
Erwan Croze's avatar
Erwan Croze committed
665 666
}

667
/****************** START OF ACCOUNT USED SECTION *****************************/
668
static void _is_account_exist_response_cb(LinphoneXmlRpcRequest *request) {
669
	LinphoneAccountCreator *creator = (LinphoneAccountCreator *)linphone_xml_rpc_request_get_user_data(request);
670 671
	if (creator->cbs->is_account_exist_response_cb != NULL) {
		LinphoneAccountCreatorStatus status = LinphoneAccountCreatorStatusRequestFailed;
672
		const char* resp = linphone_xml_rpc_request_get_string_response(request);
673
		if (linphone_xml_rpc_request_get_status(request) == LinphoneXmlRpcStatusOk) {
674 675 676 677
			status = (strcmp(resp, "ERROR_ACCOUNT_DOESNT_EXIST") == 0) ? LinphoneAccountCreatorStatusAccountNotExist : (
							(strcmp(resp, "ERROR_ALIAS_DOESNT_EXIST") == 0) ? LinphoneAccountCreatorStatusAccountExist :
														LinphoneAccountCreatorStatusAccountExistWithAlias);
			if (status == LinphoneAccountCreatorStatusAccountExistWithAlias) {
678 679
				set_string(&creator->phone_number, resp, FALSE);
			}
680
		}
681
		creator->cbs->is_account_exist_response_cb(creator, status, resp);
682 683 684
	}
}

685
LinphoneAccountCreatorStatus linphone_account_creator_is_account_exist_linphone(LinphoneAccountCreator *creator) {
686
	LinphoneXmlRpcRequest *request = NULL;
687
	if (!creator->username && !creator->phone_number) {
688 689
		if (creator->cbs->is_account_exist_response_cb != NULL) {
			creator->cbs->is_account_exist_response_cb(creator, LinphoneAccountCreatorStatusMissingArguments, "Missing required parameters");
690
		}
691
		return LinphoneAccountCreatorStatusMissingArguments;
692
	}
693

694 695 696 697
	if (creator->xmlrpc_session) {
		ms_debug("Account creator: is_account_exist (%s=%s, domain=%s)",
			(creator->username) ? "username" : "phone number",
			(creator->username) ? creator->username : creator->phone_number,
698
			_get_domain(creator));
699 700
		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);
701
		linphone_xml_rpc_request_add_string_arg(request, _get_domain(creator));
702 703 704 705 706 707 708 709
		linphone_xml_rpc_request_set_user_data(request, creator);
		linphone_xml_rpc_request_cbs_set_response(linphone_xml_rpc_request_get_callbacks(request), _is_account_exist_response_cb);
		linphone_xml_rpc_session_send_request(creator->xmlrpc_session, request);
		linphone_xml_rpc_request_unref(request);

		return LinphoneAccountCreatorStatusRequestOk;
	}
	return LinphoneAccountCreatorStatusRequestFailed;
710
}
711
/****************** END OF CREATE ACCOUNT USED SECTION ************************/
712

713
/****************** START OF CREATE ACCOUNT SECTION ***************************/
714
static void _create_account_cb_custom(LinphoneXmlRpcRequest *request) {
715
	LinphoneAccountCreator *creator = (LinphoneAccountCreator *)linphone_xml_rpc_request_get_user_data(request);
716 717
	if (creator->cbs->create_account_response_cb != NULL) {
		LinphoneAccountCreatorStatus status = LinphoneAccountCreatorStatusRequestFailed;
718
		const char* resp = linphone_xml_rpc_request_get_string_response(request);
719
		if (linphone_xml_rpc_request_get_status(request) == LinphoneXmlRpcStatusOk) {
720 721 722 723 724
			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;
725
		}
726
		creator->cbs->create_account_response_cb(creator, status, resp);
727 728 729
	}
}

730
static LinphoneXmlRpcRequest * _create_account_with_phone_custom(LinphoneAccountCreator *creator) {
731 732 733
	LinphoneXmlRpcRequest *request;
	if (!creator->phone_number) {
		return NULL;
734
	}
735 736 737
	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,
738
		_get_domain(creator),
739 740
		creator->language);

741 742 743 744
	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 ?
745
		ha1_for_passwd(creator->username ? creator->username : creator->phone_number, _get_domain(creator), creator->password) : "");
746
	linphone_xml_rpc_request_add_string_arg(request, linphone_core_get_user_agent(creator->core));
747
	linphone_xml_rpc_request_add_string_arg(request, _get_domain(creator));
748
	linphone_xml_rpc_request_add_string_arg(request, creator->language);
749
	return request;
750 751
}

752
static LinphoneXmlRpcRequest * _create_account_with_email_custom(LinphoneAccountCreator *creator) {
753
	LinphoneXmlRpcRequest *request;
754
	if (!creator->username || !creator->email || !creator->password) {
755 756
		return NULL;
	}
757 758 759
	ms_debug("Account creator: create_account_with_email (username=%s, email=%s, domain=%s)",
		creator->username,
		creator->email,
760
		_get_domain(creator));
761

762 763 764 765
	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,
766
		ha1_for_passwd(creator->username ? creator->username : creator->phone_number, _get_domain(creator), creator->password));
767
	linphone_xml_rpc_request_add_string_arg(request, linphone_core_get_user_agent(creator->core));
768
	linphone_xml_rpc_request_add_string_arg(request, _get_domain(creator));
769
	return request;
770 771
}

772
LinphoneAccountCreatorStatus linphone_account_creator_create_account_linphone(LinphoneAccountCreator *creator) {
773
	LinphoneXmlRpcRequest *request = NULL;
774
	char *identity = _get_identity(creator);
775 776
	if (!identity || (!(request = _create_account_with_phone_custom(creator))
		&& !(request = _create_account_with_email_custom(creator)))) {
777 778
		if (creator->cbs->create_account_response_cb != NULL) {
			creator->cbs->create_account_response_cb(creator, LinphoneAccountCreatorStatusMissingArguments, "Missing required parameters");
779
		}
780
		if (identity) ms_free(identity);
781
		return LinphoneAccountCreatorStatusMissingArguments;
782
	}
783

784 785 786 787 788 789 790 791
	if (creator->xmlrpc_session) {
		linphone_xml_rpc_request_set_user_data(request, creator);
		linphone_xml_rpc_request_cbs_set_response(linphone_xml_rpc_request_get_callbacks(request), _create_account_cb_custom);
		linphone_xml_rpc_session_send_request(creator->xmlrpc_session, request);
		linphone_xml_rpc_request_unref(request);
		ms_free(identity);
		return LinphoneAccountCreatorStatusRequestOk;
	}
792
	ms_free(identity);
793
	return LinphoneAccountCreatorStatusRequestFailed;
794
}
795
/****************** END OF CREATE ACCOUNT SECTION *****************************/
796

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

817
LinphoneAccountCreatorStatus linphone_account_creator_activate_account_linphone(LinphoneAccountCreator *creator) {
818
	LinphoneXmlRpcRequest *request = NULL;
819
	if (!creator->phone_number || !creator->activation_code) {
820 821
		if (creator->cbs->is_account_activated_response_cb != NULL) {
			creator->cbs->is_account_activated_response_cb(creator, LinphoneAccountCreatorStatusMissingArguments, "Missing required parameters");
822
		}
823
		return LinphoneAccountCreatorStatusMissingArguments;
824
	}
825

826 827 828 829 830
	if (creator->xmlrpc_session) {
		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,
831
			_get_domain(creator));
832 833 834 835 836

		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);
837
		linphone_xml_rpc_request_add_string_arg(request, _get_domain(creator));
838 839 840 841 842 843 844
		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;
	}
	return LinphoneAccountCreatorStatusRequestFailed;
845 846 847
}

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

856 857 858 859
	if (creator->xmlrpc_session) {
		ms_debug("Account creator: activate_account_email (username=%s, activation code=%s, domain=%s)",
			creator->username,
			creator->activation_code,
860
			_get_domain(creator));
861 862 863 864

		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);
865
		linphone_xml_rpc_request_add_string_arg(request, _get_domain(creator));
866 867 868 869 870 871 872
		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;
	}
	return LinphoneAccountCreatorStatusRequestFailed;
873
}
874
/****************** END OF CREATE VALIDATE ACCOUNT SECTION ********************/
875

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

889
LinphoneAccountCreatorStatus linphone_account_creator_is_account_activated_linphone(LinphoneAccountCreator *creator) {
890
	LinphoneXmlRpcRequest *request = NULL;
891 892
	char *identity = _get_identity(creator);
	if (!identity) {
893 894
		if (creator->cbs->is_account_activated_response_cb != NULL) {
			creator->cbs->is_account_activated_response_cb(creator, LinphoneAccountCreatorStatusMissingArguments, "Missing required parameters");
895
		}
896
		return LinphoneAccountCreatorStatusMissingArguments;
897
	}
898

899 900 901
	if (creator->xmlrpc_session) {
		ms_debug("Account creator: is_account_activated (username=%s, domain=%s)",
			creator->username ? creator->username : creator->phone_number,
902
			_get_domain(creator));
903 904 905

		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);
906
		linphone_xml_rpc_request_add_string_arg(request, _get_domain(creator));
907 908 909 910 911 912 913
		linphone_xml_rpc_request_set_user_data(request, creator);
		linphone_xml_rpc_request_cbs_set_response(linphone_xml_rpc_request_get_callbacks(request), _is_account_activated_cb_custom);
		linphone_xml_rpc_session_send_request(creator->xmlrpc_session, request);
		linphone_xml_rpc_request_unref(request);
		ms_free(identity);
		return LinphoneAccountCreatorStatusRequestOk;
	}
914
	ms_free(identity);
915
	return LinphoneAccountCreatorStatusRequestFailed;
916 917
}
/****************** END OF CREATE ACCOUNT VALIDATED SECTION********************/
918

919 920
/****************** START OF PHONE NUMBER VALIDATED SECTION *******************/

921
static void _is_phone_number_used_cb_custom(LinphoneXmlRpcRequest *request) {
922
	LinphoneAccountCreator *creator = (LinphoneAccountCreator *)linphone_xml_rpc_request_get_user_data(request);
923 924
	if (creator->cbs->is_alias_used_response_cb != NULL) {
		LinphoneAccountCreatorStatus status = LinphoneAccountCreatorStatusRequestFailed;
925 926
		const char* resp = linphone_xml_rpc_request_get_string_response(request);
		if (linphone_xml_rpc_request_get_status(request) == LinphoneXmlRpcStatusOk) {
927 928 929
			status = (strcmp(resp, "OK_ACCOUNT") == 0) ? LinphoneAccountCreatorStatusAliasIsAccount
			: (strcmp(resp, "OK_ALIAS") == 0) ? LinphoneAccountCreatorStatusAliasExist
			: LinphoneAccountCreatorStatusAliasNotExist;
930
		}
931
		creator->cbs->is_alias_used_response_cb(creator, status, resp);
932 933 934
	}
}

935
LinphoneAccountCreatorStatus linphone_account_creator_is_phone_number_used_linphone(LinphoneAccountCreator *creator) {
936
	LinphoneXmlRpcRequest *request = NULL;
937 938
	char *identity = _get_identity(creator);
	if (!identity) {
939 940
		if (creator->cbs->is_alias_used_response_cb != NULL) {
			creator->cbs->is_alias_used_response_cb(creator, LinphoneAccountCreatorStatusMissingArguments, "Missing required parameters");
941
		}
942
		return LinphoneAccountCreatorStatusMissingArguments;
943
	}
944

945 946 947
	if (creator->xmlrpc_session) {
		ms_debug("Account creator: is_phone_number_used (phone number=%s, domain=%s)",
			creator->phone_number,
948
			_get_domain(creator));
949 950 951

		request = linphone_xml_rpc_request_new(LinphoneXmlRpcArgString, "is_phone_number_used");
		linphone_xml_rpc_request_add_string_arg(request, creator->phone_number);
952
		linphone_xml_rpc_request_add_string_arg(request, _get_domain(creator));
953 954 955 956 957 958 959
		linphone_xml_rpc_request_set_user_data(request, creator);
		linphone_xml_rpc_request_cbs_set_response(linphone_xml_rpc_request_get_callbacks(request), _is_phone_number_used_cb_custom);
		linphone_xml_rpc_session_send_request(creator->xmlrpc_session, request);
		linphone_xml_rpc_request_unref(request);
		ms_free(identity);
		return LinphoneAccountCreatorStatusRequestOk;
	}
960
	ms_free(identity);
961
	return LinphoneAccountCreatorStatusRequestFailed;
962 963 964 965
}

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

966
/****************** START OF LINK PHONE NUMBER WITH ACCOUNT SECTION ***********/
967
static void _link_phone_number_with_account_cb_custom(LinphoneXmlRpcRequest *request) {
968
	LinphoneAccountCreator *creator = (LinphoneAccountCreator *)linphone_xml_rpc_request_get_user_data(request);
969 970
	if (creator->cbs->link_account_response_cb != NULL) {
		LinphoneAccountCreatorStatus status = LinphoneAccountCreatorStatusRequestFailed;
971
		const char* resp = linphone_xml_rpc_request_get_string_response(request);
972
		if (linphone_xml_rpc_request_get_status(request) == LinphoneXmlRpcStatusOk) {
973
			status = (strcmp(resp, "OK") == 0) ? LinphoneAccountCreatorStatusRequestOk : LinphoneAccountCreatorStatusAccountNotLinked;
974
		}
975
		creator->cbs->link_account_response_cb(creator, status, resp);
976
	}
977
}
978

979
LinphoneAccountCreatorStatus linphone_account_creator_link_phone_number_with_account_linphone(LinphoneAccountCreator *creator) {
980
	LinphoneXmlRpcRequest *request = NULL;
981
	if (!creator->phone_number || !creator->username) {
982 983
		if (creator->cbs->link_account_response_cb != NULL) {
			creator->cbs->link_account_response_cb(creator, LinphoneAccountCreatorStatusMissingArguments, "Missing required parameters");
984
		}
985
		return LinphoneAccountCreatorStatusMissingArguments;
986
	}
987

988 989 990 991
	if (creator->xmlrpc_session) {
		ms_debug("Account creator: link_phone_number_with_account (phone number=%s, username=%s, domain=%s, language=%s)",
			creator->phone_number,
			creator->username,
992
			_get_domain(creator),
993 994 995 996 997
			creator->language);

		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);
998
		linphone_xml_rpc_request_add_string_arg(request, _get_domain(creator));
999 1000 1001 1002 1003 1004 1005 1006
		linphone_xml_rpc_request_add_string_arg(request, creator->language);
		linphone_xml_rpc_request_set_user_data(request, creator);
		linphone_xml_rpc_request_cbs_set_response(linphone_xml_rpc_request_get_callbacks(request), _link_phone_number_with_account_cb_custom);
		linphone_xml_rpc_session_send_request(creator->xmlrpc_session, request);
		linphone_xml_rpc_request_unref(request);
		return LinphoneAccountCreatorStatusRequestOk;
	}
	return LinphoneAccountCreatorStatusRequestFailed;
1007
}
1008

1009
static void _get_phone_number_for_account_cb_custom(LinphoneXmlRpcRequest *request) {
1010
	LinphoneAccountCreator *creator = (LinphoneAccountCreator *)linphone_xml_rpc_request_get_user_data(request);
1011 1012
	if (creator->cbs->is_account_linked_response_cb != NULL) {
		LinphoneAccountCreatorStatus status = LinphoneAccountCreatorStatusRequestFailed;
1013 1014 1015 1016
		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
1017
				|| strcmp(resp, "ERROR_ALIAS_DOESNT_EXIST") == 0) ? LinphoneAccountCreatorStatusAccountNotLinked : LinphoneAccountCreatorStatusAccountLinked;
1018
		}
1019
		creator->cbs->is_account_linked_response_cb(creator, status, resp);
1020 1021 1022
	}
}

1023
LinphoneAccountCreatorStatus linphone_account_creator_is_account_linked_linphone(LinphoneAccountCreator *creator) {
1024
	LinphoneXmlRpcRequest *request = NULL;
1025
	if (!creator->username || !_get_domain(creator)) {
1026
		return LinphoneAccountCreatorStatusMissingArguments;
1027
	}
1028

1029 1030 1031
	if (creator->xmlrpc_session) {
		ms_debug("Account creator: is_account_linked (username=%s, domain=%s)",
			creator->username,
1032
			_get_domain(creator));
1033 1034 1035

		request = linphone_xml_rpc_request_new(LinphoneXmlRpcArgString, "get_phone_number_for_account");
		linphone_xml_rpc_request_add_string_arg(request, creator->username);
1036
		linphone_xml_rpc_request_add_string_arg(request, _get_domain(creator));
1037 1038 1039 1040 1041 1042 1043
		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;
	}
	return LinphoneAccountCreatorStatusRequestFailed;
1044
}
1045
/****************** END OF LINK PHONE NUMBER WITH ACCOUNT SECTION *************/
1046

1047
/****************** START OF ACTIVE PHONE NUMBER LINK **************************/