Commit be4e74d2 authored by Sylvain Berfini's avatar Sylvain Berfini 🎩

Wizard

parent f6d85a81
......@@ -401,6 +401,11 @@ if test "$has_sighandler_t" = "yes" ; then
AC_DEFINE( HAVE_SIGHANDLER_T, 1, [Define if sighandler_t available] )
fi
dnl check libsoup (needed for wizard)
PKG_CHECK_MODULES(LIBSOUP, [libsoup-2.4 >= 2.26])
AC_SUBST(LIBSOUP_CFLAGS)
AC_SUBST(LIBSOUP_LIBS)
##################################################
# Stricter build options (after external packages)
##################################################
......
......@@ -35,6 +35,7 @@ liblinphone_la_SOURCES=\
linphonecall.c \
sipsetup.c sipsetup.h \
siplogin.c \
sipwizard.c \
lsd.c linphonecore_utils.h \
ec-calibrator.c \
conference.c
......@@ -45,7 +46,8 @@ liblinphone_la_LDFLAGS= -version-info $(LIBLINPHONE_SO_VERSION) -no-undefined
liblinphone_la_LIBADD= \
$(EXOSIP_LIBS) \
$(MEDIASTREAMER_LIBS) \
$(ORTP_LIBS) $(OPENSSL_LIBS)
$(ORTP_LIBS) $(OPENSSL_LIBS) \
$(LIBSOUP_LIBS)
if BUILD_WIN32
liblinphone_la_LIBADD+=$(top_builddir)/oRTP/src/libortp.la
......@@ -69,8 +71,9 @@ AM_CFLAGS=$(STRICT_OPTIONS) -DIN_LINPHONE \
$(OSIP_CFLAGS) \
$(MEDIASTREAMER_CFLAGS) \
$(EXOSIP_CFLAGS) \
$(LIBSOUP_CFLAGS) \
-DENABLE_TRACE \
-DLOG_DOMAIN=\"LinphoneCore\" \
$(IPV6_CFLAGS) \
-DORTP_INET6 \
$(VIDEO_CFLAGS)
$(VIDEO_CFLAGS)
......@@ -404,6 +404,9 @@ typedef struct _LinphoneAccountCreator{
char *username;
char *password;
char *domain;
char *route;
char *email;
int suscribe;
bool_t succeeded;
}LinphoneAccountCreator;
......@@ -411,9 +414,13 @@ LinphoneAccountCreator *linphone_account_creator_new(struct _LinphoneCore *core,
void linphone_account_creator_set_username(LinphoneAccountCreator *obj, const char *username);
void linphone_account_creator_set_password(LinphoneAccountCreator *obj, const char *password);
void linphone_account_creator_set_domain(LinphoneAccountCreator *obj, const char *domain);
void linphone_account_creator_set_route(LinphoneAccountCreator *obj, const char *route);
void linphone_account_creator_set_email(LinphoneAccountCreator *obj, const char *email);
void linphone_account_creator_set_suscribe(LinphoneAccountCreator *obj, int suscribre);
const char * linphone_account_creator_get_username(LinphoneAccountCreator *obj);
const char * linphone_account_creator_get_domain(LinphoneAccountCreator *obj);
int linphone_account_creator_test_existence(LinphoneAccountCreator *obj);
int linphone_account_creator_test_validation(LinphoneAccountCreator *obj);
LinphoneProxyConfig * linphone_account_creator_validate(LinphoneAccountCreator *obj);
void linphone_account_creator_destroy(LinphoneAccountCreator *obj);
......
......@@ -780,6 +780,18 @@ void linphone_account_creator_set_domain(LinphoneAccountCreator *obj, const char
set_string(&obj->domain,domain);
}
void linphone_account_creator_set_route(LinphoneAccountCreator *obj, const char *route) {
set_string(&obj->route,route);
}
void linphone_account_creator_set_email(LinphoneAccountCreator *obj, const char *email) {
set_string(&obj->email,email);
}
void linphone_account_creator_set_suscribe(LinphoneAccountCreator *obj, int suscribe) {
obj->suscribe = suscribe;
}
const char * linphone_account_creator_get_username(LinphoneAccountCreator *obj){
return obj->username;
}
......@@ -796,10 +808,16 @@ int linphone_account_creator_test_existence(LinphoneAccountCreator *obj){
return err;
}
int linphone_account_creator_test_validation(LinphoneAccountCreator *obj) {
SipSetupContext *ssctx=obj->ssctx;
int err=sip_setup_context_account_validated(ssctx,obj->username);
return err;
}
LinphoneProxyConfig * linphone_account_creator_validate(LinphoneAccountCreator *obj){
SipSetupContext *ssctx=obj->ssctx;
char *uri=ms_strdup_printf("%s@%s",obj->username,obj->domain);
int err=sip_setup_context_create_account(ssctx,uri,obj->password);
int err=sip_setup_context_create_account(ssctx, uri, obj->password, obj->email, obj->suscribe);
ms_free(uri);
if (err==0) {
obj->succeeded=TRUE;
......
......@@ -24,9 +24,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "linphonecore.h"
extern SipSetup linphone_sip_login;
extern SipSetup linphone_sip_wizard;
static SipSetup *all_sip_setups[]={
&linphone_sip_login,
&linphone_sip_wizard,
NULL
};
......@@ -123,9 +125,9 @@ int sip_setup_context_get_capabilities(SipSetupContext *ctx){
return ctx->funcs->capabilities;
}
int sip_setup_context_create_account(SipSetupContext * ctx, const char *uri, const char *passwd){
int sip_setup_context_create_account(SipSetupContext * ctx, const char *uri, const char *passwd, const char *email, int suscribe){
if (ctx->funcs->create_account)
return ctx->funcs->create_account(ctx,uri, passwd);
return ctx->funcs->create_account(ctx, uri, passwd, email, suscribe);
else return -1;
}
......@@ -135,6 +137,12 @@ int sip_setup_context_account_exists(SipSetupContext *ctx, const char *uri){
return -1;
}
int sip_setup_context_account_validated(SipSetupContext *ctx, const char *uri){
if (ctx->funcs->account_validated)
return ctx->funcs->account_validated(ctx,uri);
return -1;
}
int sip_setup_context_login_account(SipSetupContext * ctx, const char *uri, const char *passwd){
LinphoneAddress *from=linphone_address_new(uri);
if (from==NULL) {
......
......@@ -97,7 +97,7 @@ struct _SipSetup{
void (*init_instance)(SipSetupContext *ctx);
void (*uninit_instance)(SipSetupContext *ctx);
int (*account_exists)(SipSetupContext *ctx, const char *uri);
int (*create_account)(SipSetupContext *ctx, const char *uri, const char *passwd);
int (*create_account)(SipSetupContext *ctx, const char *uri, const char *passwd, const char *email, int suscribe);
int (*login_account)(SipSetupContext *ctx, const char *uri, const char *passwd);
int (*get_proxy)(SipSetupContext *ctx, const char *domain, char *proxy, size_t sz);
int (*get_stun_servers)(SipSetupContext *ctx, char *stun1, char *stun2, size_t size);
......@@ -106,6 +106,7 @@ struct _SipSetup{
const char ** (*get_domains)(SipSetupContext *ctx);
int (*logout_account)(SipSetupContext *ctx);
BuddyLookupFuncs *buddy_lookup_funcs;
int (*account_validated)(SipSetupContext *ctx, const char *uri);
};
typedef struct _SipSetup SipSetup;
......@@ -131,7 +132,8 @@ unsigned int sip_setup_get_capabilities(SipSetup *s);
SipSetupContext * sip_setup_context_new(SipSetup *s, struct _LinphoneProxyConfig *cfg);
int sip_setup_context_account_exists(SipSetupContext *ctx, const char *uri);
int sip_setup_context_create_account(SipSetupContext *ctx, const char *uri, const char *passwd);
int sip_setup_context_account_validated(SipSetupContext *ctx, const char *uri);
int sip_setup_context_create_account(SipSetupContext *ctx, const char *uri, const char *passwd, const char *email, int suscribe);
int sip_setup_context_get_capabilities(SipSetupContext *ctx);
int sip_setup_context_login_account(SipSetupContext * ctx, const char *uri, const char *passwd);
int sip_setup_context_get_proxy(SipSetupContext *ctx, const char *domain, char *proxy, size_t sz);
......
/*
linphone
Copyright (C) 2011 Simon MORLAT (simon.morlat@linphone.org)
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
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "linphonecore.h"
#include "private.h"
#include <ctype.h>
#include <libsoup/soup.h>
typedef struct _BLReq{
int status;
int result;
SoupMessage *msg;
SoupSession *session;
ortp_thread_t th;
}BLReq;
const int XMLRPC_FAILED = -1;
const int XMLRPC_OK = 0;
const char *XMLRPC_URL = "https://www.linphone.org/wizard.php";
static void sip_wizard_init_instance(SipSetupContext *ctx){
LinphoneProxyConfig *cfg=sip_setup_context_get_proxy_config(ctx);
/*disable registration until the user logs in*/
linphone_proxy_config_enable_register(cfg,FALSE);
}
const char ** sip_wizard_get_domains(SipSetupContext *ctx) {
LinphoneProxyConfig *cfg=sip_setup_context_get_proxy_config(ctx);
const char **domains = (const char**) &cfg->reg_proxy;
return domains;
}
static SoupMessage * build_xmlrpc_check_account_request(const char *identity){
SoupMessage * msg;
msg=soup_xmlrpc_request_new(XMLRPC_URL,
"check_account",
G_TYPE_STRING, identity,
G_TYPE_INVALID);
if (!msg){
ms_error("Fail to create SoupMessage !");
}else{
SoupBuffer *sb=soup_message_body_flatten(msg->request_body);
ms_message("This is the XML-RPC request we are going to send:\n%s\n",sb->data);
soup_buffer_free(sb);
}
return msg;
}
static SoupMessage * build_xmlrpc_check_account_validated(const char *identity){
SoupMessage * msg;
msg=soup_xmlrpc_request_new(XMLRPC_URL,
"check_account_validated",
G_TYPE_STRING, identity,
G_TYPE_INVALID);
if (!msg){
ms_error("Fail to create SoupMessage !");
}else{
SoupBuffer *sb=soup_message_body_flatten(msg->request_body);
ms_message("This is the XML-RPC request we are going to send:\n%s\n",sb->data);
soup_buffer_free(sb);
}
return msg;
}
static SoupMessage * build_xmlrpc_create_account_request(const char *identity, const char *passwd, const char *email, int suscribe){
SoupMessage * msg;
msg=soup_xmlrpc_request_new(XMLRPC_URL,
"create_account",
G_TYPE_STRING, identity,
G_TYPE_STRING, passwd,
G_TYPE_STRING, email,
G_TYPE_INT, suscribe,
G_TYPE_INVALID);
if (!msg){
ms_error("Fail to create SoupMessage !");
}else{
SoupBuffer *sb=soup_message_body_flatten(msg->request_body);
ms_message("This is the XML-RPC request we are going to send:\n%s\n",sb->data);
soup_buffer_free(sb);
}
return msg;
}
static int xml_rpc_parse_response(BLReq *blreq, SoupMessage *sm){
SoupBuffer *sb;
GValue retval;
GError *error=NULL;
sb=soup_message_body_flatten(sm->response_body);
ms_message("This the xml-rpc response:\n%s\n",sb->data);
if (soup_xmlrpc_parse_method_response(sb->data,sb->length,&retval,&error)==FALSE){
if (error!=NULL){
ms_error("xmlrpc fault: %s",error->message);
g_error_free(error);
}else{
ms_error("Could not parse xml-rpc response !");
}
blreq->status=XMLRPC_FAILED;
}else{
ms_message("Extracting values from return type...");
blreq->result = g_value_get_int(&retval);
g_value_unset(&retval);
blreq->status=XMLRPC_OK;
}
soup_buffer_free(sb);
return blreq->status;
}
static void got_headers(BLReq *blreq, SoupMessage*msg){
ms_message("Got headers !");
blreq->status=XMLRPC_OK;
}
#if SERIALIZE_HTTPS
/*on windows libsoup support for threads with gnutls is not yet functionnal (only in git)
This will come in next release of libsoup, probably.
In the meantime, we are forced to serialize all soup https processing with a big
ugly global mutex...*/
static GStaticMutex big_mutex = G_STATIC_MUTEX_INIT;
#endif
static void * process_xml_rpc_request(void *up){
BLReq *blreq=(BLReq*)up;
SoupMessage *sm=blreq->msg;
int code;
g_signal_connect_swapped(G_OBJECT(sm),"got-headers",(GCallback)got_headers,blreq);
blreq->status=XMLRPC_OK;
#if SERIALIZE_HTTPS
g_static_mutex_lock(&big_mutex);
#endif
code=soup_session_send_message(blreq->session,sm);
if (code==200){
ms_message("Got a response from server, yeah !");
xml_rpc_parse_response(blreq,sm);
}else{
ms_error("request failed, error-code=%i (%s)",code,soup_status_get_phrase(code));
blreq->status=XMLRPC_FAILED;
}
#if SERIALIZE_HTTPS
g_static_mutex_unlock(&big_mutex);
#endif
return NULL;
}
int sip_wizard_account_exists(SipSetupContext *ctx, const char *uri) {
/*
* Return 1 if account already exists
* 0 if account doesn't exists
* -1 if information isn't available
*/
SoupMessage *sm;
BLReq *req=ms_new0(BLReq, 1);
req->session=soup_session_sync_new();
sm=build_xmlrpc_check_account_request(uri);
req->msg=sm;
process_xml_rpc_request(req);
if (req->status == XMLRPC_OK) {
return req->result;
} else {
return -1;
}
}
int sip_wizard_account_validated(SipSetupContext *ctx, const char *uri) {
/*
* Return 1 if account already exists
* 0 if account doesn't exists
* -1 if information isn't available
*/
SoupMessage *sm;
BLReq *req=ms_new0(BLReq, 1);
req->session=soup_session_sync_new();
sm=build_xmlrpc_check_account_validated(uri);
req->msg=sm;
process_xml_rpc_request(req);
if (req->status == XMLRPC_OK) {
return req->result;
} else {
return -1;
}
}
int sip_wizard_create_account(SipSetupContext *ctx, const char *uri, const char *passwd, const char *email, int suscribe) {
/*
* Return 0 if account successfully created
* Else return -1
*/
SoupMessage *sm;
BLReq *req=ms_new0(BLReq, 1);
req->session=soup_session_sync_new();
sm=build_xmlrpc_create_account_request(uri, passwd, email, suscribe);
req->msg=sm;
process_xml_rpc_request(req);
if (req->status == XMLRPC_OK) {
return req->result;
} else {
return -1;
}
}
static void guess_display_name(LinphoneAddress *from){
char *dn=(char*)ms_malloc(strlen(linphone_address_get_username(from))+3);
const char *it;
char *wptr=dn;
bool_t begin=TRUE;
bool_t surname=0;
for(it=linphone_address_get_username(from);*it!='\0';++it){
if (begin){
*wptr=toupper(*it);
begin=FALSE;
}else if (*it=='.'){
if (surname) break;
*wptr=' ';
begin=TRUE;
surname=TRUE;
}else *wptr=*it;
wptr++;
}
linphone_address_set_display_name(from,dn);
ms_free(dn);
}
static int sip_wizard_do_login(SipSetupContext * ctx, const char *uri, const char *passwd){
LinphoneProxyConfig *cfg=sip_setup_context_get_proxy_config(ctx);
LinphoneCore *lc=linphone_proxy_config_get_core(cfg);
LinphoneAuthInfo *auth;
LinphoneAddress *parsed_uri;
char *tmp;
parsed_uri=linphone_address_new(uri);
if (parsed_uri==NULL){
return -1;
}
if (linphone_address_get_display_name(parsed_uri)!=NULL){
guess_display_name(parsed_uri);
}
tmp=linphone_address_as_string(parsed_uri);
linphone_proxy_config_set_identity(cfg,tmp);
if (passwd) {
auth=linphone_auth_info_new(linphone_address_get_username(parsed_uri),NULL,passwd,NULL,NULL);
linphone_core_add_auth_info(lc,auth);
}
linphone_proxy_config_enable_register(cfg,TRUE);
linphone_proxy_config_done(cfg);
ms_free(tmp);
linphone_address_destroy(parsed_uri);
return 0;
}
/* a simple SipSetup built-in plugin to allow creating accounts at runtime*/
#ifndef _MSC_VER
SipSetup linphone_sip_wizard={
.name="SipWizard",
.capabilities=SIP_SETUP_CAP_ACCOUNT_MANAGER,
.init_instance=sip_wizard_init_instance,
.account_exists=sip_wizard_account_exists,
.create_account=sip_wizard_create_account,
.login_account=sip_wizard_do_login,
.get_domains=sip_wizard_get_domains,
.account_validated=sip_wizard_account_validated
};
#else
SipSetup linphone_sip_wizard={
"SipWizard",
SIP_SETUP_CAP_ACCOUNT_MANAGER,
0,
NULL,
NULL,
sip_wizard_init_instance,
NULL,
sip_wizard_account_exists,
sip_wizard_create_account,
sip_wizard_do_login,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
sip_wizard_get_domains,
NULL,
NULL,
sip_wizard_account_validated
};
#endif
......@@ -56,6 +56,7 @@ GdkPixbuf *_gdk_pixbuf_new_from_memory_at_scale(const void *data, gint len, gint
GtkWidget *linphone_gtk_create_window(const char *window_name);
GtkWidget *linphone_gtk_get_widget(GtkWidget *window, const char *name);
GtkWidget *linphone_gtk_create_widget(const char *filename, const char *widget_name);
GtkWidget * linphone_gtk_create_assistant(void);
LinphoneCore *linphone_gtk_get_core(void);
GtkWidget *linphone_gtk_get_main_window();
......
......@@ -50,6 +50,7 @@ const char *this_program_ident_string="linphone_ident_string=" LINPHONE_VERSION;
static LinphoneCore *the_core=NULL;
static GtkWidget *the_ui=NULL;
GtkWidget *the_wizard=NULL;
static void linphone_gtk_registration_state_changed(LinphoneCore *lc, LinphoneProxyConfig *cfg, LinphoneRegistrationState rs, const char *msg);
static void linphone_gtk_notify_recv(LinphoneCore *lc, LinphoneFriend * fid);
......@@ -1416,8 +1417,9 @@ static void linphone_gtk_configure_main_window(){
g_object_unref(G_OBJECT(pbuf));
}
}
if (linphone_gtk_can_manage_accounts())
if (linphone_gtk_can_manage_accounts()) {
gtk_widget_show(linphone_gtk_get_widget(w,"assistant_item"));
}
if (update_check_menu){
gtk_widget_show(linphone_gtk_get_widget(w,"versioncheck_item"));
}
......@@ -1561,6 +1563,13 @@ static void linphone_gtk_check_soundcards(){
}
}
// Display the account wizard
void linphone_gtk_display_wizard() {
if (the_wizard == NULL || !gtk_widget_get_visible(the_wizard)) { // Only one instance of the wizard at the same time
the_wizard = linphone_gtk_create_assistant();
}
}
static void linphone_gtk_quit(void){
linphone_gtk_uninit_instance();
linphone_gtk_destroy_log_window();
......@@ -1699,6 +1708,12 @@ int main(int argc, char *argv[]){
gtk_timeout_add(30,(GtkFunction)linphone_gtk_iterate,(gpointer)linphone_gtk_get_core());
gtk_timeout_add(30,(GtkFunction)linphone_gtk_check_logs,(gpointer)NULL);
linphone_gtk_init_main_window();
// Veryfing if at least one sip account is configured. If not, show wizard
if (linphone_core_get_proxy_config_list(linphone_gtk_get_core()) == NULL) {
linphone_gtk_display_wizard();
}
#ifndef HAVE_GTK_OSX
linphone_gtk_init_status_icon();
#endif
......
......@@ -333,6 +333,11 @@
<property name="can_focus">False</property>
<property name="stock">gtk-clear</property>
</object>
<object class="GtkImage" id="image12">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-connect</property>
</object>
<object class="GtkImage" id="image2">
<property name="visible">True</property>
<property name="can_focus">False</property>
......@@ -504,6 +509,16 @@
<signal name="activate" handler="linphone_gtk_check_for_new_version" swapped="no"/>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="assistant_item">
<property name="label" translatable="yes">Account assistant</property>
<property name="can_focus">False</property>
<property name="use_action_appearance">False</property>
<property name="image">image12</property>
<property name="use_stock">False</property>
<signal name="activate" handler="linphone_gtk_display_wizard" swapped="no"/>
</object>
</child>
</object>
</child>
</object>
......
This diff is collapsed.
This diff is collapsed.
......@@ -14,6 +14,8 @@ status-offline.png \
contact-orange.png dialer-orange.png history-orange.png\
startcall-green.png stopcall-red.png addcall-green.png linphone.icns \
contact_starred.png contact_unstarred.png \
speaker.png
speaker.png \
ok.png \
notok.png
EXTRA_DIST=$(pixmap_DATA)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment