From: Simon Morlat Date: Sat, 9 Mar 2013 09:34:32 +0000 (+0100) Subject: clean message storage API X-Git-Url: http://sjero.net/git/?p=linphone;a=commitdiff_plain;h=ad7114171eceab0116a7568367633c7808c9aa00 clean message storage API relax requirement for sqlite3 --- diff --git a/configure.ac b/configure.ac index 9cb828e8..ae2d5938 100644 --- a/configure.ac +++ b/configure.ac @@ -670,21 +670,31 @@ if test x$enable_tunnel = xtrue; then fi AC_ARG_ENABLE(msg-storage, - [AS_HELP_STRING([--enable-msg-storage=[yes/no]], [Turn on compilation of message storage (default=yes)])], + [AS_HELP_STRING([--enable-msg-storage=[yes/no]], [Turn on compilation of message storage (default=auto)])], [case "${enableval}" in yes) enable_msg_storage=true ;; no) enable_msg_storage=false ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-msg-storage) ;; esac], - [enable_msg_storage=true] + [enable_msg_storage=auto] ) + +echo "enable_msg_storage = $enable_msg_storage" + AM_CONDITIONAL(BUILD_MSG_STORAGE, test x$enable_msg_storage = xtrue) -if test x$enable_msg_storage = xtrue; then - PKG_CHECK_MODULES(SQLITE3,[ sqlite3 >= 3.7.0],[],[ - AC_MSG_ERROR([sqlite3 required for message storage not found.])] ) - SQLITE3_CFLAGS+="-DMSG_STORAGE_ENABLED" - AC_SUBST(SQLITE3_CFLAGS) - AC_SUBST(SQLITE3_LIBS) +if test x$enable_msg_storage != xfalse; then + PKG_CHECK_MODULES(SQLITE3,[ sqlite3 >= 3.7.0],[ + SQLITE3_CFLAGS+="-DMSG_STORAGE_ENABLED" + AC_SUBST(SQLITE3_CFLAGS) + AC_SUBST(SQLITE3_LIBS) + enable_msg_storage=true + ],[ + if test x$enable_msg_storage = xtrue; then + AC_MSG_ERROR([sqlite3 required for message storage not found.]) + fi + enable_msg_storage=false + ] ) + fi diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index d65e5367..dd5ab7ed 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -934,10 +934,11 @@ static void text_delivery_update(SalOp *op, SalTextDeliveryStatus status){ LinphoneChatMessage *chat_msg=(LinphoneChatMessage* )sal_op_get_user_pointer(op); const MSList* calls = linphone_core_get_calls(chat_msg->chat_room->lc); - linphone_core_set_message_state(chat_msg->chat_room,chat_msg->message,chatStatusSal2Linphone(status),chat_msg->time); + chat_msg->state=chatStatusSal2Linphone(status); + linphone_chat_message_store_state(chat_msg); if (chat_msg && chat_msg->cb) { chat_msg->cb(chat_msg - ,chatStatusSal2Linphone(status) + ,chat_msg->state ,chat_msg->cb_ud); } linphone_chat_message_destroy(chat_msg); diff --git a/coreapi/chat.c b/coreapi/chat.c index 046c3473..69893217 100644 --- a/coreapi/chat.c +++ b/coreapi/chat.c @@ -62,16 +62,7 @@ void linphone_chat_room_destroy(LinphoneChatRoom *cr){ ms_free(cr->peer); } -#ifdef WIN32 -static inline char *my_ctime_r(const time_t *t, char *buf){ - strcpy(buf,ctime(t)); - return buf; -} - -#else -#define my_ctime_r ctime_r -#endif static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage* msg){ const char *route=NULL; @@ -80,8 +71,6 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatM LinphoneCall *call; char* content_type; time_t t=time(NULL); - char buf[26]; - char *to; if (lp_config_get_int(cr->lc->config,"sip","chat_use_call_dialogs",0)){ if((call = linphone_core_get_call_by_remote_address(cr->lc,cr->peer))!=NULL){ @@ -109,15 +98,14 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatM } if (msg->external_body_url) { content_type=ms_strdup_printf("message/external-body; access-type=URL; URL=\"%s\"",msg->external_body_url); - sal_message_send(op,identity,cr->peer,content_type, NULL,my_ctime_r(&t,buf)); + sal_message_send(op,identity,cr->peer,content_type, NULL); ms_free(content_type); } else { - sal_text_send(op, identity, cr->peer,msg->message,my_ctime_r(&t,buf)); + sal_text_send(op, identity, cr->peer,msg->message); } - to=linphone_address_as_string_uri_only (cr->peer_url); - linphone_core_set_history_message(cr,identity,to,OUTGOING,msg->message, - my_ctime_r(&t,buf),READ,LinphoneChatMessageStateInProgress); - ms_free(to); + msg->dir=LinphoneChatMessageOutgoing; + msg->from=linphone_address_new(identity); + linphone_chat_message_store(msg); } /** @@ -144,27 +132,37 @@ void linphone_chat_room_message_received(LinphoneChatRoom *cr, LinphoneCore *lc, } -void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessage *sal_msg){ +/** + * Retrieve an existing chat room whose peer is the supplied address, if exists. + * @param lc the linphone core + * @param add a linphone address. + * @returns the matching chatroom, or NULL if no such chatroom exists. +**/ +LinphoneChatRoom *linphone_core_get_chat_room(LinphoneCore *lc, const LinphoneAddress *addr){ + LinphoneChatRoom *cr=NULL; MSList *elem; + for(elem=lc->chatrooms;elem!=NULL;elem=ms_list_next(elem)){ + cr=(LinphoneChatRoom*)elem->data; + if (linphone_chat_room_matches(cr,addr)){ + break; + } + cr=NULL; + } + return cr; +} + +void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessage *sal_msg){ + LinphoneChatRoom *cr=NULL; LinphoneAddress *addr; char *cleanfrom; - const char *to; char *from; LinphoneChatMessage* msg; const SalCustomHeader *ch; - char buf[26]; addr=linphone_address_new(sal_msg->from); linphone_address_clean(addr); - for(elem=lc->chatrooms;elem!=NULL;elem=ms_list_next(elem)){ - cr=(LinphoneChatRoom*)elem->data; - if (linphone_chat_room_matches(cr,addr)){ - break; - } - cr=NULL; - } - to=linphone_core_get_identity(lc); + cr=linphone_core_get_chat_room(lc,addr); cleanfrom=linphone_address_as_string(addr); from=linphone_address_as_string_uri_only(addr); if (cr==NULL){ @@ -173,8 +171,16 @@ void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessag } msg = linphone_chat_room_create_message(cr, sal_msg->text); linphone_chat_message_set_from(msg, cr->peer_url); + + { + LinphoneAddress *to; + to=sal_op_get_to(op) ? linphone_address_new(sal_op_get_to(op)) : linphone_address_new(linphone_core_get_identity(lc)); + msg->to=to; + } + msg->time=sal_msg->time; msg->state=LinphoneChatMessageStateDelivered; + msg->is_read=FALSE; ch=sal_op_get_custom_header(op); if (ch) msg->custom_headers=sal_custom_header_clone(ch); @@ -182,9 +188,7 @@ void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessag linphone_chat_message_set_external_body_url(msg, sal_msg->url); } linphone_address_destroy(addr); - linphone_core_set_history_message(cr,to,from,INCOMING, - msg->message,my_ctime_r(&msg->time,buf),NOT_READ, - LinphoneChatMessageStateDelivered); + linphone_chat_message_store(msg); linphone_chat_room_message_received(cr,lc,msg); ms_free(cleanfrom); ms_free(from); @@ -230,6 +234,7 @@ LinphoneChatMessage* linphone_chat_room_create_message(LinphoneChatRoom *cr, con LinphoneChatMessage* msg = ms_new0(LinphoneChatMessage,1); msg->chat_room=(LinphoneChatRoom*)cr; msg->message=message?ms_strdup(message):NULL; + msg->is_read=TRUE; return msg; } @@ -327,10 +332,32 @@ void linphone_chat_message_set_from(LinphoneChatMessage* message, const Linphone *@param message #LinphoneChatMessage obj *@return #LinphoneAddress */ -LinphoneAddress* linphone_chat_message_get_from(const LinphoneChatMessage* message) { +const LinphoneAddress* linphone_chat_message_get_from(const LinphoneChatMessage* message) { return message->from; } +/** + * Get destination of the message + *@param message #LinphoneChatMessage obj + *@return #LinphoneAddress + */ +const LinphoneAddress* linphone_chat_message_get_to(const LinphoneChatMessage* message){ + if (message->to) return message->to; + if (message->dir==LinphoneChatMessageOutgoing){ + return message->chat_room->peer_url; + } + return NULL; +} + +/** + * Returns the origin address of a message if it was a outgoing message, or the destination address if it was an incoming message. + *@param message #LinphoneChatMessage obj + *@return #LinphoneAddress + */ +LinphoneAddress *linphone_chat_message_get_local_address(const LinphoneChatMessage* message){ + return message->dir==LinphoneChatMessageOutgoing ? message->from : message->to; +} + /** * Get the time the message was sent. */ diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index bdf2193c..2bb9fab3 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -1306,9 +1306,6 @@ static void linphone_core_init (LinphoneCore * lc, const LinphoneCoreVTable *vta #ifdef TUNNEL_ENABLED lc->tunnel=linphone_core_tunnel_new(lc); if (lc->tunnel) linphone_tunnel_configure(lc->tunnel); -#endif -#ifdef MSG_STORAGE_ENABLED - lc->db=linphone_message_storage_init(); #endif if (lc->vtable.display_status) lc->vtable.display_status(lc,_("Ready")); @@ -5265,6 +5262,8 @@ static void linphone_core_uninit(LinphoneCore *lc) } linphone_core_free_payload_types(lc); + + linphone_core_message_storage_close(lc); ortp_exit(); linphone_core_set_state(lc,LinphoneGlobalOff,"Off"); #ifdef TUNNEL_ENABLED @@ -5795,3 +5794,24 @@ void linphone_core_set_video_dscp(LinphoneCore *lc, int dscp){ int linphone_core_get_video_dscp(const LinphoneCore *lc){ return lp_config_get_int(lc->config,"rtp","video_dscp",0x2e); } + + +/** + * Sets the database filename where chat messages will be stored. + * If the file does not exist, it will be created. + * @ingroup initializing + * @param lc the linphone core + * @param path filesystem path +**/ +void linphone_core_set_chat_database_path(LinphoneCore *lc, const char *path){ + if (lc->chat_db_file){ + ms_free(lc->chat_db_file); + lc->chat_db_file=NULL; + } + if (path) { + lc->chat_db_file=ms_strdup(path); + linphone_core_message_storage_init(lc); + } +} + + diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index 49074db3..7212f26c 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -663,12 +663,17 @@ typedef enum _LinphoneChatMessageStates { */ typedef void (*LinphoneChatMessageStateChangeCb)(LinphoneChatMessage* msg,LinphoneChatMessageState state,void* ud); +void linphone_core_set_chat_database_path(LinphoneCore *lc, const char *path); LinphoneChatRoom * linphone_core_create_chat_room(LinphoneCore *lc, const char *to); +LinphoneChatRoom *linphone_core_get_chat_room(LinphoneCore *lc, const LinphoneAddress *addr); void linphone_chat_room_destroy(LinphoneChatRoom *cr); LinphoneChatMessage* linphone_chat_room_create_message(LinphoneChatRoom *cr,const char* message); const LinphoneAddress* linphone_chat_room_get_peer_address(LinphoneChatRoom *cr); void linphone_chat_room_send_message(LinphoneChatRoom *cr, const char *msg); void linphone_chat_room_send_message2(LinphoneChatRoom *cr, LinphoneChatMessage* msg,LinphoneChatMessageStateChangeCb status_cb,void* ud); +MSList *linphone_chat_room_get_history(LinphoneChatRoom *cr,int nb_message); +void linphone_chat_room_mark_as_read(LinphoneChatRoom *cr); +void linphone_chat_room_delete_history(LinphoneChatRoom *cr); LinphoneCore* linphone_chat_room_get_lc(LinphoneChatRoom *cr); void linphone_chat_room_set_user_data(LinphoneChatRoom *cr, void * ud); void * linphone_chat_room_get_user_data(LinphoneChatRoom *cr); @@ -677,7 +682,8 @@ LinphoneChatMessageState linphone_chat_message_get_state(const LinphoneChatMessa const char* linphone_chat_message_state_to_string(const LinphoneChatMessageState state); LinphoneChatMessage* linphone_chat_message_clone(const LinphoneChatMessage* message); void linphone_chat_message_set_from(LinphoneChatMessage* message, const LinphoneAddress* from); -LinphoneAddress* linphone_chat_message_get_from(const LinphoneChatMessage* message); +const LinphoneAddress* linphone_chat_message_get_from(const LinphoneChatMessage* message); +const LinphoneAddress* linphone_chat_message_get_to(const LinphoneChatMessage* message); const char* linphone_chat_message_get_external_body_url(const LinphoneChatMessage* message); void linphone_chat_message_set_external_body_url(LinphoneChatMessage* message,const char* url); const char * linphone_chat_message_get_text(const LinphoneChatMessage* message); @@ -686,6 +692,7 @@ void* linphone_chat_message_get_user_data(const LinphoneChatMessage* message); void linphone_chat_message_set_user_data(LinphoneChatMessage* message,void*); LinphoneChatRoom* linphone_chat_message_get_chat_room(LinphoneChatMessage *msg); const LinphoneAddress* linphone_chat_message_get_peer_address(LinphoneChatMessage *msg); +LinphoneAddress *linphone_chat_message_get_local_address(const LinphoneChatMessage* message); void linphone_chat_message_add_custom_header(LinphoneChatMessage* message, const char *header_name, const char *header_value); const char * linphone_chat_message_get_custom_header(LinphoneChatMessage* message, const char *header_name); @@ -1418,9 +1425,7 @@ int linphone_core_get_audio_dscp(const LinphoneCore *lc); void linphone_core_set_video_dscp(LinphoneCore *lc, int dscp); int linphone_core_get_video_dscp(const LinphoneCore *lc); -MSList *linphone_chat_room_get_history(const char *to,LinphoneChatRoom *cr,int nb_message); -void linphone_core_set_messages_flag_read(LinphoneChatRoom *cr,const char *from, int read); -void linphone_core_delete_history(LinphoneCore *lc,const char *from); + #ifdef __cplusplus } diff --git a/coreapi/message_storage.c b/coreapi/message_storage.c index 3d6c45d9..c62fa1dd 100644 --- a/coreapi/message_storage.c +++ b/coreapi/message_storage.c @@ -38,44 +38,22 @@ static inline char *my_ctime_r(const time_t *t, char *buf){ static const char *days[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; static const char *months[]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}; -#define CONFIG_FILE ".linphone-history.db" - -char *linphone_message_storage_get_config_file(const char *filename){ - const int path_max=1024; - char *config_file=(char *)malloc(path_max*sizeof(char)); - if (filename==NULL) filename=CONFIG_FILE; - /*try accessing a local file first if exists*/ - if (access(CONFIG_FILE,F_OK)==0){ - snprintf(config_file,path_max,"%s",filename); - }else{ -#ifdef WIN32 - const char *appdata=getenv("APPDATA"); - if (appdata){ - snprintf(config_file,path_max,"%s\\%s",appdata,LINPHONE_CONFIG_DIR); - CreateDirectory(config_file,NULL); - snprintf(config_file,path_max,"%s\\%s\\%s",appdata,LINPHONE_CONFIG_DIR,filename); - } -#else - const char *home=getenv("HOME"); - if (home==NULL) home="."; - snprintf(config_file,path_max,"%s/%s",home,filename); -#endif - } - return config_file; -} -void create_chat_message(char **argv, void *data){ +static void create_chat_message(char **argv, void *data){ LinphoneChatRoom *cr = (LinphoneChatRoom *)data; LinphoneChatMessage* new_message = linphone_chat_room_create_message(cr,argv[4]); + LinphoneAddress *from; struct tm ret={0}; char tmp1[80]={0}; char tmp2[80]={0}; - if(atoi(argv[3])==INCOMING){ - linphone_chat_message_set_from(new_message,linphone_address_new(argv[2])); + if(atoi(argv[3])==LinphoneChatMessageIncoming){ + from=linphone_address_new(argv[2]); } else { - linphone_chat_message_set_from(new_message,linphone_address_new(argv[1])); + from=linphone_address_new(argv[1]); } + linphone_chat_message_set_from(new_message,from); + linphone_address_destroy(from); if(argv[5]!=NULL){ int i,j; @@ -91,7 +69,7 @@ void create_chat_message(char **argv, void *data){ } new_message->time=argv[5]!=NULL ? mktime(&ret) : time(NULL); new_message->state=atoi(argv[7]); - cr->messages_hist=ms_list_prepend(cr->messages_hist,(void *)new_message); + cr->messages_hist=ms_list_prepend(cr->messages_hist,new_message); } static int callback(void *data, int argc, char **argv, char **colName){ @@ -99,58 +77,84 @@ static int callback(void *data, int argc, char **argv, char **colName){ return 0; } -void linphone_sql_request_message(sqlite3 *db,const char *stmt,void *data){ +void linphone_sql_request_message(sqlite3 *db,const char *stmt,LinphoneChatRoom *cr){ char* errmsg; int ret; - ret=sqlite3_exec(db,stmt,callback,data,&errmsg); + ret=sqlite3_exec(db,stmt,callback,cr,&errmsg); if(ret != SQLITE_OK) { printf("Error in creation: %s.\n", errmsg); } } void linphone_sql_request(sqlite3* db,const char *stmt){ - char* errmsg; + char* errmsg=NULL; int ret; ret=sqlite3_exec(db,stmt,0,0,&errmsg); if(ret != SQLITE_OK) { - printf("Error in creation: %s.\n", errmsg); + ms_error("linphone_sql_request: error sqlite3_exec(): %s.\n", errmsg); + sqlite3_free(errmsg); } } -void linphone_core_set_history_message(LinphoneChatRoom *cr,const char *local_contact,const char *remote_contact, - int direction, const char *message,const char *date, int read, int state){ - LinphoneCore *lc=linphone_chat_room_get_lc(cr); - char *buf=sqlite3_mprintf("insert into history values(NULL,%Q,%Q,%i,%Q,%Q,%i,%i);", - local_contact,remote_contact,direction,message,date,read,state); - linphone_sql_request(lc->db,buf); +void linphone_chat_message_store(LinphoneChatMessage *msg){ + LinphoneCore *lc=linphone_chat_room_get_lc(msg->chat_room); + if (lc->db){ + const char *peer=msg->chat_room->peer; + char *local_contact=linphone_address_as_string_uri_only(linphone_chat_message_get_local_address(msg)); + char datebuf[26]; + char *buf=sqlite3_mprintf("insert into history values(NULL,%Q,%Q,%i,%Q,%Q,%i,%i);", + local_contact,peer,msg->dir,msg->message,my_ctime_r(&msg->time,datebuf),msg->is_read,msg->state); + linphone_sql_request(lc->db,buf); + sqlite3_free(buf); + ms_free(local_contact); + } } -void linphone_core_set_message_state(LinphoneChatRoom *cr,const char *message, int state, time_t date){ - LinphoneCore *lc=linphone_chat_room_get_lc(cr); - char time_str[26]; - char *buf=sqlite3_mprintf("update history set status=%i where message = %Q and time = %Q;", - state,message,my_ctime_r(&date,time_str)); - linphone_sql_request(lc->db,buf); +void linphone_chat_message_store_state(LinphoneChatMessage *msg){ + LinphoneCore *lc=msg->chat_room->lc; + if (lc->db){ + char time_str[26]; + char *buf=sqlite3_mprintf("update history set status=%i where message = %Q and time = %Q;", + msg->state,msg->message,my_ctime_r(&msg->time,time_str)); + linphone_sql_request(lc->db,buf); + sqlite3_free(buf); + } } -void linphone_core_set_messages_flag_read(LinphoneChatRoom *cr,const char *from, int read){ +void linphone_chat_room_mark_as_read(LinphoneChatRoom *cr){ LinphoneCore *lc=linphone_chat_room_get_lc(cr); + int read=1; + + if (lc->db==NULL) return ; + char *buf=sqlite3_mprintf("update history set read=%i where remoteContact = %Q;", - read,from); + read,cr->peer); linphone_sql_request(lc->db,buf); + sqlite3_free(buf); } -void linphone_core_delete_history(LinphoneCore *lc,const char *from){ - char *buf=sqlite3_mprintf("delete from history where remoteContact = %Q;",from); +void linphone_chat_room_delete_history(LinphoneChatRoom *cr){ + LinphoneCore *lc=cr->lc; + + if (lc->db==NULL) return ; + char *buf=sqlite3_mprintf("delete from history where remoteContact = %Q;",cr->peer); linphone_sql_request(lc->db,buf); + sqlite3_free(buf); } -MSList *linphone_chat_room_get_history(const char *to,LinphoneChatRoom *cr,int nb_message){ +MSList *linphone_chat_room_get_history(LinphoneChatRoom *cr,int nb_message){ LinphoneCore *lc=linphone_chat_room_get_lc(cr); + MSList *ret; + + if (lc->db==NULL) return NULL; + cr->messages_hist = NULL; - char *buf=sqlite3_mprintf("select * from history where remoteContact = %Q order by id DESC limit %i ;",to,nb_message); - linphone_sql_request_message(lc->db,buf,(void *)cr); - return cr->messages_hist; + char *buf=sqlite3_mprintf("select * from history where remoteContact = %Q order by id DESC limit %i ;",cr->peer,nb_message); + linphone_sql_request_message(lc->db,buf,cr); + sqlite3_free(buf); + ret=cr->messages_hist; + cr->messages_hist=NULL; + return ret; } void linphone_close_storage(sqlite3* db){ @@ -167,36 +171,49 @@ void linphone_create_table(sqlite3* db){ } } -sqlite3 * linphone_message_storage_init(){ +void linphone_core_message_storage_init(LinphoneCore *lc){ int ret; - char *errmsg; + char *errmsg=NULL; sqlite3 *db; - char *filename; - filename=linphone_message_storage_get_config_file(NULL); - ret=sqlite3_open(filename,&db); + ret=sqlite3_open(lc->chat_db_file,&db); if(ret != SQLITE_OK) { printf("Error in the opening: %s.\n", errmsg); sqlite3_close(db); + sqlite3_free(errmsg); } linphone_create_table(db); - return db; + lc->db=db; +} + +void linphone_core_message_storage_close(LinphoneCore *lc){ + if (lc->db){ + sqlite3_close(lc->db); + lc->db=NULL; + } } + #else -void linphone_core_set_history_message(LinphoneChatRoom *cr,const char *local_contact,const char *remote_contact, - int direction, const char *message,const char *date, int read, int state){ +void linphone_chat_message_store(LinphoneChatMessage *cr){ } -void linphone_core_set_message_state(LinphoneChatRoom *cr,const char *message, int state, time_t date){ +void linphone_chat_message_store_state(LinphoneChatMessage *cr){ } -void linphone_core_set_messages_flag_read(LinphoneChatRoom *cr,const char *from, int read){ +void linphone_chat_room_mark_as_read(LinphoneChatRoom *cr){ } -MSList *linphone_chat_room_get_history(const char *to,LinphoneChatRoom *cr,int nb_message){ +MSList *linphone_chat_room_get_history(LinphoneChatRoom *cr,int nb_message){ return NULL; } -void linphone_core_delete_history(LinphoneCore *lc,const char *from){ +void linphone_chat_room_delete_history(LinphoneChatRoom *cr){ +} + +void linphone_core_message_storage_init(LinphoneCore *lc){ } -#endif \ No newline at end of file + +void linphone_core_message_storage_close(LinphoneCore *lc){ +} + +#endif diff --git a/coreapi/private.h b/coreapi/private.h index 35578604..78344ee7 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -119,17 +119,25 @@ typedef struct _CallCallbackObj static const int linphone_call_magic=0x3343; +typedef enum _LinphoneChatMessageDir{ + LinphoneChatMessageIncoming, + LinphoneChatMessageOutgoing +} LinphoneChatMessageDir; + struct _LinphoneChatMessage { - char* message; LinphoneChatRoom* chat_room; + LinphoneChatMessageDir dir; + char* message; LinphoneChatMessageStateChangeCb cb; void* cb_ud; void* message_userdata; char* external_body_url; - LinphoneAddress* from; + LinphoneAddress *from; + LinphoneAddress *to; time_t time; SalCustomHeader *custom_headers; LinphoneChatMessageState state; + bool_t is_read; }; typedef struct StunCandidate{ @@ -616,6 +624,7 @@ struct _LinphoneCore LinphoneTunnel *tunnel; char* device_id; MSList *last_recv_msg_ids; + char *chat_db_file; #ifdef MSG_STORAGE_ENABLED sqlite3 *db; #endif @@ -700,19 +709,13 @@ void linphone_call_params_uninit(LinphoneCallParams *params); int linphone_upnp_init(LinphoneCore *lc); void linphone_upnp_destroy(LinphoneCore *lc); -#define OUTGOING 0 -#define INCOMING 1 - -#define NOT_READ 0 -#define READ 1 - #ifdef MSG_STORAGE_ENABLED sqlite3 * linphone_message_storage_init(); #endif -void linphone_core_set_history_message(LinphoneChatRoom *cr,const char *local_contact,const char *remote_contact, - int direction, const char *message,const char *date, int read, int state); -void linphone_core_set_message_state(LinphoneChatRoom *cr,const char *message, int state,time_t date); - +void linphone_chat_message_store(LinphoneChatMessage *msg); +void linphone_chat_message_store_state(LinphoneChatMessage *msg); +void linphone_core_message_storage_init(LinphoneCore *lc); +void linphone_core_message_storage_close(LinphoneCore *lc); #ifdef __cplusplus } diff --git a/coreapi/sal.h b/coreapi/sal.h index ba232cca..25d8d20b 100644 --- a/coreapi/sal.h +++ b/coreapi/sal.h @@ -430,8 +430,8 @@ int sal_register_refresh(SalOp *op, int expires); int sal_unregister(SalOp *h); /*Messaging */ -int sal_text_send(SalOp *op, const char *from, const char *to, const char *text, const char*t); -int sal_message_send(SalOp *op, const char *from, const char *to, const char* content_type, const char *msg, const char*t); +int sal_text_send(SalOp *op, const char *from, const char *to, const char *text); +int sal_message_send(SalOp *op, const char *from, const char *to, const char* content_type, const char *msg); /*presence Subscribe/notify*/ int sal_subscribe_presence(SalOp *op, const char *from, const char *to); diff --git a/coreapi/sal_eXosip2_presence.c b/coreapi/sal_eXosip2_presence.c index 2670af47..356d2a9f 100644 --- a/coreapi/sal_eXosip2_presence.c +++ b/coreapi/sal_eXosip2_presence.c @@ -81,8 +81,23 @@ void sal_remove_in_subscribe(Sal *sal, SalOp *op){ sal->in_subscribes=ms_list_remove(sal->in_subscribes,op); } -int sal_message_send(SalOp *op, const char *from, const char *to, const char* content_type, const char *msg, const char *t){ +#ifdef WIN32 + +static inline char *my_ctime_r(const time_t *t, char *buf){ + strcpy(buf,ctime(t)); + return buf; +} + +#else +#define my_ctime_r ctime_r +#endif + +int sal_message_send(SalOp *op, const char *from, const char *to, const char* content_type, const char *msg){ osip_message_t *sip=NULL; + char t[26]; + time_t curtime=time(NULL); + + my_ctime_r(&curtime,t); if(op->cid == -1) { @@ -120,6 +135,8 @@ int sal_message_send(SalOp *op, const char *from, const char *to, const char* co eXosip_unlock(); return -1; } + sal_exosip_add_custom_headers(sip,op->base.custom_headers); + osip_message_set_date(sip,t); osip_message_set_content_type(sip,content_type); if (msg) osip_message_set_body(sip,msg,strlen(msg)); eXosip_call_send_request(op->did,sip); @@ -128,8 +145,8 @@ int sal_message_send(SalOp *op, const char *from, const char *to, const char* co return 0; } -int sal_text_send(SalOp *op, const char *from, const char *to, const char *msg,const char *t) { - return sal_message_send(op,from,to,"text/plain",msg,t); +int sal_text_send(SalOp *op, const char *from, const char *to, const char *msg) { + return sal_message_send(op,from,to,"text/plain",msg); } /*presence Subscribe/notify*/ int sal_subscribe_presence(SalOp *op, const char *from, const char *to){ diff --git a/gtk/chat.c b/gtk/chat.c index b3a5ecfd..6a65cd9f 100644 --- a/gtk/chat.c +++ b/gtk/chat.c @@ -25,6 +25,37 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define NB_MSG_HIST 250 +#define CONFIG_FILE ".linphone-history.db" + +const char *linphone_gtk_message_storage_get_db_file(const char *filename){ + const int path_max=1024; + static char *db_file=NULL; + + if (db_file) return db_file; + + db_file=(char *)malloc(path_max*sizeof(char)); + if (filename==NULL) filename=CONFIG_FILE; + /*try accessing a local file first if exists*/ + if (access(CONFIG_FILE,F_OK)==0){ + snprintf(db_file,path_max,"%s",filename); + }else{ +#ifdef WIN32 + const char *appdata=getenv("APPDATA"); + if (appdata){ + snprintf(db_file,path_max,"%s\\%s",appdata,LINPHONE_CONFIG_DIR); + CreateDirectory(db_file,NULL); + snprintf(db_file,path_max,"%s\\%s\\%s",appdata,LINPHONE_CONFIG_DIR,filename); + } +#else + const char *home=getenv("HOME"); + if (home==NULL) home="."; + snprintf(db_file,path_max,"%s/%s",home,filename); +#endif + } + return db_file; +} + + void linphone_gtk_quit_chatroom(LinphoneChatRoom *cr) { GtkWidget *main_window=linphone_gtk_get_main_window (); GtkWidget *nb=linphone_gtk_get_widget(main_window,"viewswitch"); @@ -92,16 +123,16 @@ void udpate_tab_chat_header(GtkWidget *chat_view,const LinphoneAddress *uri,Linp void linphone_gtk_push_text(GtkWidget *w, const LinphoneAddress *from, gboolean me,LinphoneChatRoom *cr,LinphoneChatMessage *msg, gboolean hist){ - GtkTextView *text=GTK_TEXT_VIEW(linphone_gtk_get_widget(w,"textview")); - GtkTextBuffer *buffer=gtk_text_view_get_buffer(text); - GtkTextIter iter,begin; + GtkTextView *text=GTK_TEXT_VIEW(linphone_gtk_get_widget(w,"textview")); + GtkTextBuffer *buffer=gtk_text_view_get_buffer(text); + GtkTextIter iter,begin; int off; char *from_str=linphone_address_as_string_uri_only(from); char *from_message=(char *)g_object_get_data(G_OBJECT(w),"from_message"); GList *list=g_object_get_data(G_OBJECT(w),"list"); time_t t; - gtk_text_buffer_get_start_iter(buffer,&begin); + gtk_text_buffer_get_start_iter(buffer,&begin); gtk_text_buffer_get_end_iter(buffer,&iter); off=gtk_text_iter_get_offset(&iter); if(g_strcmp0(from_message,from_str)!=0){ @@ -148,7 +179,7 @@ void linphone_gtk_push_text(GtkWidget *w, const LinphoneAddress *from, gtk_text_buffer_get_end_iter(buffer,&iter); gtk_text_buffer_insert(buffer,&iter,"\n",-1); GtkTextMark *mark=gtk_text_buffer_create_mark(buffer,NULL,&iter,FALSE); - gtk_text_view_scroll_mark_onscreen(text,mark); + gtk_text_view_scroll_mark_onscreen(text,mark); } const LinphoneAddress* linphone_gtk_get_used_identity(){ @@ -160,8 +191,8 @@ const LinphoneAddress* linphone_gtk_get_used_identity(){ } void update_chat_state_message(LinphoneChatMessageState state,LinphoneChatMessage *msg){ - GtkWidget *main_window=linphone_gtk_get_main_window(); - GtkWidget *friendlist=linphone_gtk_get_widget(main_window,"contact_list"); + GtkWidget *main_window=linphone_gtk_get_main_window(); + GtkWidget *friendlist=linphone_gtk_get_widget(main_window,"contact_list"); GtkWidget *page=(GtkWidget*)g_object_get_data(G_OBJECT(friendlist),"chatview"); GList *list=g_object_get_data(G_OBJECT(page),"list"); @@ -277,7 +308,7 @@ GtkWidget* linphone_gtk_init_chatroom(LinphoneChatRoom *cr, const LinphoneAddres colorb.blue = 61952; with_str=linphone_address_as_string_uri_only(with); - linphone_core_set_messages_flag_read(cr,with_str,1); + linphone_chat_room_mark_as_read(cr); gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text),GTK_WRAP_WORD_CHAR); gtk_text_view_set_editable(GTK_TEXT_VIEW(text),FALSE); gtk_notebook_append_page(notebook,chat_view,create_tab_chat_header(cr,with)); @@ -304,7 +335,7 @@ GtkWidget* linphone_gtk_init_chatroom(LinphoneChatRoom *cr, const LinphoneAddres "margin","indent",10,NULL); gtk_text_buffer_create_tag(gtk_text_view_get_buffer(GTK_TEXT_VIEW(text)), "bg","paragraph-background-gdk",&colorb,NULL); - messages = linphone_chat_room_get_history(with_str,cr,NB_MSG_HIST); + messages = linphone_chat_room_get_history(cr,NB_MSG_HIST); display_history_message(chat_view,messages,with); button = linphone_gtk_get_widget(chat_view,"send"); g_signal_connect_swapped(G_OBJECT(button),"clicked",(GCallback)linphone_gtk_send_text,NULL); @@ -325,23 +356,22 @@ void linphone_gtk_load_chatroom(LinphoneChatRoom *cr,const LinphoneAddress *uri, LinphoneChatRoom *cr2=(LinphoneChatRoom *)g_object_get_data(G_OBJECT(chat_view),"cr"); char *from_str=linphone_address_as_string(linphone_chat_room_get_peer_address (cr2)); char *uri_str=linphone_address_as_string(uri); - char *uri_only=linphone_address_as_string_uri_only(uri); MSList *messages=NULL; - linphone_core_set_messages_flag_read(cr,uri_only,1); - if(g_strcmp0(from_str,uri_str)!=0){ - GtkTextView *text_view=GTK_TEXT_VIEW(linphone_gtk_get_widget(chat_view,"textview")); - GtkTextIter start; - GtkTextIter end; + linphone_chat_room_mark_as_read(cr); + if(g_strcmp0(from_str,uri_str)!=0){ + GtkTextView *text_view=GTK_TEXT_VIEW(linphone_gtk_get_widget(chat_view,"textview")); + GtkTextIter start; + GtkTextIter end; GtkTextBuffer *text_buffer; - text_buffer=gtk_text_view_get_buffer(text_view); - gtk_text_buffer_get_bounds(text_buffer, &start, &end); - gtk_text_buffer_delete (text_buffer, &start, &end); + text_buffer=gtk_text_view_get_buffer(text_view); + gtk_text_buffer_get_bounds(text_buffer, &start, &end); + gtk_text_buffer_delete (text_buffer, &start, &end); udpate_tab_chat_header(chat_view,uri,cr); g_object_set_data(G_OBJECT(chat_view),"cr",cr); g_object_set_data(G_OBJECT(linphone_gtk_get_widget(main_window,"contact_list")),"chatview",(gpointer)chat_view); - messages = linphone_chat_room_get_history(uri_only,cr,NB_MSG_HIST); + messages = linphone_chat_room_get_history(cr,NB_MSG_HIST); g_object_set_data(G_OBJECT(chat_view),"from_message",uri_str); display_history_message(chat_view,messages,uri); } diff --git a/gtk/friendlist.c b/gtk/friendlist.c index 4ae86dfa..fc2c2f4b 100644 --- a/gtk/friendlist.c +++ b/gtk/friendlist.c @@ -174,8 +174,10 @@ void linphone_gtk_delete_history(GtkWidget *button){ select = gtk_tree_view_get_selection(GTK_TREE_VIEW(linphone_gtk_get_widget(w,"contact_list"))); if (gtk_tree_selection_get_selected (select, &model, &iter)) { + LinphoneChatRoom *cr; gtk_tree_model_get (model, &iter,FRIEND_ID , &lf, -1); - linphone_core_delete_history(linphone_gtk_get_core(),linphone_address_as_string_uri_only(linphone_friend_get_address(lf))); + cr=linphone_core_get_chat_room(linphone_gtk_get_core(),linphone_friend_get_address(lf)); + linphone_chat_room_delete_history(cr); linphone_gtk_show_friends(); } } diff --git a/gtk/linphone.h b/gtk/linphone.h index f9597849..aaa021a2 100644 --- a/gtk/linphone.h +++ b/gtk/linphone.h @@ -58,6 +58,8 @@ 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); + +const char *linphone_gtk_message_storage_get_db_file(const char *filename); void linphone_gtk_show_assistant(void); void linphone_gtk_close_assistant(void); diff --git a/gtk/main.c b/gtk/main.c index b1dab3d6..c6065241 100644 --- a/gtk/main.c +++ b/gtk/main.c @@ -216,7 +216,7 @@ static const char *linphone_gtk_get_factory_config_file(){ } static void linphone_gtk_init_liblinphone(const char *config_file, - const char *factory_config_file) { + const char *factory_config_file, const char *db_file) { LinphoneCoreVTable vtable={0}; gchar *secrets_file=linphone_gtk_get_config_file(SECRETS_FILE); @@ -248,6 +248,7 @@ static void linphone_gtk_init_liblinphone(const char *config_file, _linphone_gtk_enable_video(FALSE); linphone_gtk_set_ui_config_int("videoselfview",0); } + if (db_file) linphone_core_set_chat_database_path(the_core,db_file); } LinphoneCore *linphone_gtk_get_core(void){ @@ -1840,6 +1841,7 @@ int main(int argc, char *argv[]){ GdkPixbuf *pbuf; const char *app_name="Linphone"; LpConfig *factory; + const char *db_file; #if !GLIB_CHECK_VERSION(2, 31, 0) g_thread_init(NULL); @@ -1946,7 +1948,8 @@ int main(int argc, char *argv[]){ linphone_gtk_create_log_window(); linphone_core_enable_logs_with_cb(linphone_gtk_log_handler); - linphone_gtk_init_liblinphone(config_file, factory_config_file); + db_file=linphone_gtk_message_storage_get_db_file(NULL); + linphone_gtk_init_liblinphone(config_file, factory_config_file, db_file); g_set_application_name(app_name); pbuf=create_pixbuf(linphone_gtk_get_ui_config("icon",LINPHONE_ICON));