From 53a0f0399996f3be03c31b2e6939f4297bec4d66 Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Thu, 1 Oct 2015 15:56:51 +0200 Subject: [PATCH] account_creator: rework it to be error-friendly --- coreapi/account_creator.c | 130 ++++++++++++++++++++++++++++++++------ coreapi/account_creator.h | 66 ++++++++++++++----- coreapi/private.h | 7 +- 3 files changed, 165 insertions(+), 38 deletions(-) diff --git a/coreapi/account_creator.c b/coreapi/account_creator.c index 23cdffb28..cada4f110 100644 --- a/coreapi/account_creator.c +++ b/coreapi/account_creator.c @@ -17,9 +17,9 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "linphonecore.h" +#include "account_creator.h" #include "private.h" - +#include "regex.h" BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneAccountCreatorCbs); @@ -67,12 +67,12 @@ void linphone_account_creator_cbs_set_validation_tested(LinphoneAccountCreatorCb cbs->validation_tested = cb; } -LinphoneAccountCreatorCbsValidatedCb linphone_account_creator_cbs_get_validated(const LinphoneAccountCreatorCbs *cbs) { - return cbs->validated; +LinphoneAccountCreatorCbsCreateAccountCb linphone_account_creator_cbs_get_create_account(const LinphoneAccountCreatorCbs *cbs) { + return cbs->create_account; } -void linphone_account_creator_cbs_set_validated(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsValidatedCb cb) { - cbs->validated = cb; +void linphone_account_creator_cbs_set_create_account(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsCreateAccountCb cb) { + cbs->create_account = cb; } @@ -85,7 +85,6 @@ static void _linphone_account_creator_destroy(LinphoneAccountCreator *creator) { if (creator->route) ms_free(creator->route); if (creator->email) ms_free(creator->email); if (creator->display_name) ms_free(creator->display_name); - ms_free(creator); } BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneAccountCreator); @@ -124,48 +123,143 @@ void linphone_account_creator_set_user_data(LinphoneAccountCreator *creator, voi creator->user_data = ud; } -void linphone_account_creator_set_username(LinphoneAccountCreator *creator, const char *username) { +static LinphoneAccountCreatorStatus validate_uri(const char* username, const char* domain, const char* route, const char* display_name) { + LinphoneProxyConfig* proxy = linphone_proxy_config_new(); + LinphoneAddress* addr; + + linphone_proxy_config_set_identity(proxy, "sip:user@domain.com"); + + if (route && linphone_proxy_config_set_route(proxy, route) != 0) { + linphone_proxy_config_destroy(proxy); + return LinphoneAccountCreatorRouteInvalid; + } + + if (username) { + addr = linphone_proxy_config_normalize_sip_uri(proxy, username); + } else { + addr = linphone_address_clone(linphone_proxy_config_get_identity_address(proxy)); + } + linphone_proxy_config_destroy(proxy); + + if (addr == NULL) { + return LinphoneAccountCreatorUsernameInvalid; + } + + if (domain) { + ms_error("TODO: detect invalid domain"); + linphone_address_set_domain(addr, domain); + } + + if (display_name) { + ms_error("TODO: detect invalid display name"); + linphone_address_set_display_name(addr, display_name); + } + + linphone_address_unref(addr); + return LinphoneAccountCreatorOk; +} + +static bool_t is_matching_regex(const char *entry, const char* regex) { + regex_t regex_pattern; + int res; + regcomp(®ex_pattern, regex, 0); + res = regexec(®ex_pattern, entry, 0, NULL, 0); + regfree(®ex_pattern); + return (res != REG_NOMATCH); +} + +LinphoneAccountCreatorStatus linphone_account_creator_set_username(LinphoneAccountCreator *creator, const char *username) { + int min_length = lp_config_get_int(creator->core->config, "assistant", "username_min_length", 0); + int fixed_length = lp_config_get_int(creator->core->config, "assistant", "username_length", 0); + bool_t use_phone_number = lp_config_get_int(creator->core->config, "assistant", "use_phone_number", 0); + const char* regex = lp_config_get_string(creator->core->config, "assistant", "username_regex", 0); + LinphoneAccountCreatorStatus status; + if (min_length > 0 && strlen(username) < min_length) { + return LinphoneAccountCreatorUsernameTooShort; + } else if (fixed_length > 0 && strlen(username) != fixed_length) { + return LinphoneAccountCreatorUsernameInvalidSize; + } else if (use_phone_number && !linphone_proxy_config_is_phone_number(NULL, username)) { + return LinphoneAccountCreatorUsernameInvalid; + } else if (regex && !is_matching_regex(username, regex)) { + return LinphoneAccountCreatorUsernameInvalid; + } else if ((status = validate_uri(username, NULL, NULL, NULL)) != LinphoneAccountCreatorOk) { + return status; + } set_string(&creator->username, username); + return LinphoneAccountCreatorOk; } const char * linphone_account_creator_get_username(const LinphoneAccountCreator *creator) { return creator->username; } -void linphone_account_creator_set_password(LinphoneAccountCreator *creator, const char *password){ +LinphoneAccountCreatorStatus linphone_account_creator_set_password(LinphoneAccountCreator *creator, const char *password){ + int min_length = lp_config_get_int(creator->core->config, "assistant", "password_min_length", 0); + if (min_length > 0 && strlen(password) < min_length) { + return LinphoneAccountCreatorPasswordTooShort; + } set_string(&creator->password, password); + return LinphoneAccountCreatorOk; } const char * linphone_account_creator_get_password(const LinphoneAccountCreator *creator) { return creator->password; } -void linphone_account_creator_set_domain(LinphoneAccountCreator *creator, const char *domain){ +LinphoneAccountCreatorStatus linphone_account_creator_set_transport(LinphoneAccountCreator *creator, LinphoneTransportType transport){ + if (!linphone_core_sip_transport_supported(creator->core, transport)) { + return LinphoneAccountCreatorTransportNotSupported; + } + creator->transport = transport; + return LinphoneAccountCreatorOk; +} + +LinphoneTransportType linphone_account_creator_get_transport(const LinphoneAccountCreator *creator) { + return creator->transport; +} + +LinphoneAccountCreatorStatus linphone_account_creator_set_domain(LinphoneAccountCreator *creator, const char *domain){ + if (validate_uri(NULL, domain, NULL, NULL) != 0) { + return LinphoneAccountCreatorDomainInvalid; + } set_string(&creator->domain, domain); + return LinphoneAccountCreatorOk; } const char * linphone_account_creator_get_domain(const LinphoneAccountCreator *creator) { return creator->domain; } -void linphone_account_creator_set_route(LinphoneAccountCreator *creator, const char *route) { +LinphoneAccountCreatorStatus linphone_account_creator_set_route(LinphoneAccountCreator *creator, const char *route) { + if (validate_uri(NULL, NULL, route, NULL) != 0) { + return LinphoneAccountCreatorRouteInvalid; + } set_string(&creator->route, route); + return LinphoneAccountCreatorOk; } const char * linphone_account_creator_get_route(const LinphoneAccountCreator *creator) { return creator->route; } -void linphone_account_creator_set_display_name(LinphoneAccountCreator *creator, const char *display_name) { +LinphoneAccountCreatorStatus linphone_account_creator_set_display_name(LinphoneAccountCreator *creator, const char *display_name) { + if (validate_uri(NULL, NULL, NULL, display_name) != 0) { + return LinphoneAccountCreatorDisplayNameInvalid; + } set_string(&creator->display_name, display_name); + return LinphoneAccountCreatorOk; } const char * linphone_account_creator_get_display_name(const LinphoneAccountCreator *creator) { return creator->display_name; } -void linphone_account_creator_set_email(LinphoneAccountCreator *creator, const char *email) { +LinphoneAccountCreatorStatus linphone_account_creator_set_email(LinphoneAccountCreator *creator, const char *email) { + if (!is_matching_regex(email, ".+@.+\\.[A-Za-z]{2}[A-Za-z]*")) { + return LinphoneAccountCreatorEmailInvalid; + } set_string(&creator->email, email); + return LinphoneAccountCreatorOk; } const char * linphone_account_creator_get_email(const LinphoneAccountCreator *creator) { @@ -244,19 +338,19 @@ LinphoneAccountCreatorStatus linphone_account_creator_test_validation(LinphoneAc return LinphoneAccountCreatorOk; } -static void _validate_cb(LinphoneXmlRpcRequest *request) { +static void _create_account_cb(LinphoneXmlRpcRequest *request) { LinphoneAccountCreator *creator = (LinphoneAccountCreator *)linphone_xml_rpc_request_get_user_data(request); - if (creator->callbacks->validated != NULL) { + if (creator->callbacks->create_account != NULL) { LinphoneAccountCreatorStatus status = LinphoneAccountCreatorFailed; if ((linphone_xml_rpc_request_get_status(request) == LinphoneXmlRpcStatusOk) && (linphone_xml_rpc_request_get_int_response(request) == 0)) { status = LinphoneAccountCreatorOk; } - creator->callbacks->validated(creator, status); + creator->callbacks->create_account(creator, status); } } -LinphoneAccountCreatorStatus linphone_account_creator_validate(LinphoneAccountCreator *creator) { +LinphoneAccountCreatorStatus linphone_account_creator_create_account(LinphoneAccountCreator *creator) { LinphoneXmlRpcRequest *request; char *identity; @@ -270,7 +364,7 @@ LinphoneAccountCreatorStatus linphone_account_creator_validate(LinphoneAccountCr LinphoneXmlRpcArgInt, (creator->subscribe_to_newsletter == TRUE) ? 1 : 0, LinphoneXmlRpcArgNone); linphone_xml_rpc_request_set_user_data(request, creator); - linphone_xml_rpc_request_cbs_set_response(linphone_xml_rpc_request_get_callbacks(request), _validate_cb); + linphone_xml_rpc_request_cbs_set_response(linphone_xml_rpc_request_get_callbacks(request), _create_account_cb); linphone_xml_rpc_session_send_request(creator->xmlrpc_session, request); linphone_xml_rpc_request_unref(request); ms_free(identity); diff --git a/coreapi/account_creator.h b/coreapi/account_creator.h index f2231984a..87a31149e 100644 --- a/coreapi/account_creator.h +++ b/coreapi/account_creator.h @@ -25,6 +25,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. extern "C" { #endif +#include "linphonecore.h" /** * @addtogroup misc @@ -35,8 +36,18 @@ extern "C" { * Enum describing the status of a LinphoneAccountCreator operation. **/ typedef enum _LinphoneAccountCreatorStatus { - LinphoneAccountCreatorOk, - LinphoneAccountCreatorFailed + LinphoneAccountCreatorOk = 0, + LinphoneAccountCreatorFailed = 1 << 0, + + LinphoneAccountCreatorEmailInvalid = 1 << 1, + LinphoneAccountCreatorUsernameInvalid = 1 << 2, + LinphoneAccountCreatorUsernameTooShort = 1 << 3, + LinphoneAccountCreatorUsernameInvalidSize = 1 << 4, + LinphoneAccountCreatorPasswordTooShort = 1 << 5, + LinphoneAccountCreatorDomainInvalid = 1 << 6, + LinphoneAccountCreatorRouteInvalid = 1 << 7, + LinphoneAccountCreatorDisplayNameInvalid = 1 << 8, + LinphoneAccountCreatorTransportNotSupported = 1 << 9, } LinphoneAccountCreatorStatus; /** @@ -68,12 +79,12 @@ typedef void (*LinphoneAccountCreatorCbsValidationTestedCb)(LinphoneAccountCreat * @param[in] creator LinphoneAccountCreator object * @param[in] status The status of the LinphoneAccountCreator validate operation that has just finished **/ -typedef void (*LinphoneAccountCreatorCbsValidatedCb)(LinphoneAccountCreator *creator, LinphoneAccountCreatorStatus status); +typedef void (*LinphoneAccountCreatorCbsCreateAccountCb)(LinphoneAccountCreator *creator, LinphoneAccountCreatorStatus status); /** * Create a LinphoneAccountCreator. * @param[in] core The LinphoneCore used for the XML-RPC communication - * @param[in] xmlrpc_url The URL to the XML-RPC server + * @param[in] xmlrpc_url The URL to the XML-RPC server. Must be NON NULL. * @return The new LinphoneAccountCreator object **/ LINPHONE_PUBLIC LinphoneAccountCreator * linphone_account_creator_new(LinphoneCore *core, const char *xmlrpc_url); @@ -109,8 +120,9 @@ LINPHONE_PUBLIC void linphone_account_creator_set_user_data(LinphoneAccountCreat * Set the username. * @param[in] creator LinphoneAccountCreator object * @param[in] username The username to set + * @return LinphoneAccountCreatorOk if everything is OK, or a specific error otherwise. **/ -LINPHONE_PUBLIC void linphone_account_creator_set_username(LinphoneAccountCreator *creator, const char *username); +LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_set_username(LinphoneAccountCreator *creator, const char *username); /** * Get the username. @@ -123,8 +135,9 @@ LINPHONE_PUBLIC const char * linphone_account_creator_get_username(const Linphon * Set the password. * @param[in] creator LinphoneAccountCreator object * @param[in] password The password to set + * @return LinphoneAccountCreatorOk if everything is OK, or a specific error otherwise. **/ -LINPHONE_PUBLIC void linphone_account_creator_set_password(LinphoneAccountCreator *creator, const char *password); +LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_set_password(LinphoneAccountCreator *creator, const char *password); /** * Get the password. @@ -133,12 +146,28 @@ LINPHONE_PUBLIC void linphone_account_creator_set_password(LinphoneAccountCreato **/ LINPHONE_PUBLIC const char * linphone_account_creator_get_password(const LinphoneAccountCreator *creator); +/** + * Set the transport. + * @param[in] creator LinphoneAccountCreator object + * @param[in] transport The transport to set + * @return LinphoneAccountCreatorOk if everything is OK, or a specific error if given transport is not supported by linphone core. +**/ +LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_set_transport(LinphoneAccountCreator *creator, LinphoneTransportType transport); + +/** + * Get the transport. + * @param[in] creator LinphoneAccountCreator object + * @return The transport of the LinphoneAccountCreator +**/ +LINPHONE_PUBLIC LinphoneTransportType linphone_account_creator_get_transport(const LinphoneAccountCreator *creator); + /** * Set the domain. * @param[in] creator LinphoneAccountCreator object * @param[in] domain The domain to set + * @return LinphoneAccountCreatorOk if everything is OK, or a specific error otherwise. **/ -LINPHONE_PUBLIC void linphone_account_creator_set_domain(LinphoneAccountCreator *creator, const char *domain); +LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_set_domain(LinphoneAccountCreator *creator, const char *domain); /** * Get the domain. @@ -151,8 +180,9 @@ LINPHONE_PUBLIC const char * linphone_account_creator_get_domain(const LinphoneA * Set the route. * @param[in] creator LinphoneAccountCreator object * @param[in] route The route to set + * @return LinphoneAccountCreatorOk if everything is OK, or a specific error otherwise. **/ -LINPHONE_PUBLIC void linphone_account_creator_set_route(LinphoneAccountCreator *creator, const char *route); +LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_set_route(LinphoneAccountCreator *creator, const char *route); /** * Get the route. @@ -165,8 +195,9 @@ LINPHONE_PUBLIC const char * linphone_account_creator_get_route(const LinphoneAc * Set the email. * @param[in] creator LinphoneAccountCreator object * @param[in] display_name The display name to set + * @return LinphoneAccountCreatorOk if everything is OK, or a specific error otherwise. **/ -LINPHONE_PUBLIC void linphone_account_creator_set_display_name(LinphoneAccountCreator *creator, const char *display_name); +LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_set_display_name(LinphoneAccountCreator *creator, const char *display_name); /** * Get the email. @@ -179,8 +210,9 @@ LINPHONE_PUBLIC const char * linphone_account_creator_get_display_name(const Lin * Set the email. * @param[in] creator LinphoneAccountCreator object * @param[in] email The email to set + * @return LinphoneAccountCreatorOk if everything is OK, or a specific error otherwise. **/ -LINPHONE_PUBLIC void linphone_account_creator_set_email(LinphoneAccountCreator *creator, const char *email); +LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_set_email(LinphoneAccountCreator *creator, const char *email); /** * Get the email. @@ -229,7 +261,7 @@ LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_test_valid * @param[in] creator LinphoneAccountCreator object * @return LinphoneAccountCreatorOk if the request has been sent, LinphoneAccountCreatorFailed otherwise **/ -LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_validate(LinphoneAccountCreator *creator); +LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_create_account(LinphoneAccountCreator *creator); /** * Configure an account (create a proxy config and authentication info for it). @@ -295,18 +327,18 @@ LINPHONE_PUBLIC LinphoneAccountCreatorCbsValidationTestedCb linphone_account_cre LINPHONE_PUBLIC void linphone_account_creator_cbs_set_validation_tested(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsValidationTestedCb cb); /** - * Get the validated callback. + * Get the create account callback. * @param[in] cbs LinphoneAccountCreatorCbs object. - * @return The current validated callback. + * @return The current create account callback. **/ -LINPHONE_PUBLIC LinphoneAccountCreatorCbsValidatedCb linphone_account_creator_cbs_get_validated(const LinphoneAccountCreatorCbs *cbs); +LINPHONE_PUBLIC LinphoneAccountCreatorCbsCreateAccountCb linphone_account_creator_cbs_get_create_account(const LinphoneAccountCreatorCbs *cbs); /** - * Set the validated callback. + * Set the create account callback. * @param[in] cbs LinphoneAccountCreatorCbs object. - * @param[in] cb The validated callback to be used. + * @param[in] cb The create account callback to be used. **/ -LINPHONE_PUBLIC void linphone_account_creator_cbs_set_validated(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsValidatedCb cb); +LINPHONE_PUBLIC void linphone_account_creator_cbs_set_create_account(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsCreateAccountCb cb); /** * @} diff --git a/coreapi/private.h b/coreapi/private.h index 6ab74a9f3..f08d5ea39 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -136,11 +136,11 @@ struct _LinphoneCallParams{ bool_t avpf_enabled; /* RTCP feedback messages are enabled */ bool_t real_early_media; /*send real media even during early media (for outgoing calls)*/ bool_t in_conference; /*in conference mode */ - + bool_t low_bandwidth; bool_t no_user_consent;/*when set to TRUE an UPDATE request will be used instead of reINVITE*/ uint16_t avpf_rr_interval; /*in milliseconds*/ - + bool_t internal_call_update; /*use mark that call update was requested internally (might be by ice) - unused for the moment*/ bool_t video_multicast_enabled; bool_t audio_multicast_enabled; @@ -1123,7 +1123,7 @@ struct _LinphoneAccountCreatorCbs { void *user_data; LinphoneAccountCreatorCbsExistenceTestedCb existence_tested; LinphoneAccountCreatorCbsValidationTestedCb validation_tested; - LinphoneAccountCreatorCbsValidatedCb validated; + LinphoneAccountCreatorCbsCreateAccountCb create_account; }; BELLE_SIP_DECLARE_VPTR(LinphoneAccountCreatorCbs); @@ -1142,6 +1142,7 @@ struct _LinphoneAccountCreator { char *email; bool_t subscribe_to_newsletter; char *display_name; + LinphoneTransportType transport; }; BELLE_SIP_DECLARE_VPTR(LinphoneAccountCreator);