message_storage.c 19.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*
message_storage.c
Copyright (C) 2012  Belledonne Communications, Grenoble, France

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 "private.h"
#include "linphonecore.h"

#ifdef MSG_STORAGE_ENABLED
Sylvain Berfini's avatar
Sylvain Berfini committed
24 25 26
#ifndef PRIu64
#define PRIu64 "I64u"
#endif
27 28 29

#include "sqlite3.h"

Sylvain Berfini's avatar
Sylvain Berfini committed
30
static ORTP_INLINE LinphoneChatMessage* get_transient_message(LinphoneChatRoom* cr, unsigned int storage_id){
31 32 33 34 35 36 37 38 39 40 41 42
	MSList* transients = cr->transient_messages;
	LinphoneChatMessage* chat;
	while( transients ){
		chat = (LinphoneChatMessage*)transients->data;
		if(chat->storage_id == storage_id){
			return linphone_chat_message_ref(chat);
		}
		transients = transients->next;
	}
	return NULL;
}

43 44 45 46 47 48 49 50 51 52 53 54
/* DB layout:
 * | 0  | storage_id
 * | 1  | type
 * | 2  | subtype
 * | 3  | name
 * | 4  | encoding
 * | 5  | size
 * | 6  | data
 */
// Callback for sql request when getting linphone content
static int callback_content(void *data, int argc, char **argv, char **colName) {
	LinphoneChatMessage *message = (LinphoneChatMessage *)data;
55

56 57 58 59 60 61 62
	if (message->file_transfer_information) {
		linphone_content_uninit(message->file_transfer_information);
		ms_free(message->file_transfer_information);
		message->file_transfer_information = NULL;
	}
	message->file_transfer_information = (LinphoneContent *)malloc(sizeof(LinphoneContent));
	memset(message->file_transfer_information, 0, sizeof(*(message->file_transfer_information)));
63

64 65 66 67 68
	message->file_transfer_information->type = argv[1] ? ms_strdup(argv[1]) : NULL;
	message->file_transfer_information->subtype = argv[2] ? ms_strdup(argv[2]) : NULL;
	message->file_transfer_information->name = argv[3] ? ms_strdup(argv[3]) : NULL;
	message->file_transfer_information->encoding = argv[4] ? ms_strdup(argv[4]) : NULL;
	message->file_transfer_information->size = (size_t) atoi(argv[5]);
69

70 71 72 73 74 75 76
	return 0;
}

static void fetch_content_from_database(sqlite3 *db, LinphoneChatMessage *message, int content_id) {
	char* errmsg = NULL;
	int ret;
	char * buf;
77

78 79 80 81 82 83 84 85
	buf = sqlite3_mprintf("SELECT * FROM content WHERE id = %i", content_id);
	ret = sqlite3_exec(db, buf, callback_content, message, &errmsg);
	if (ret != SQLITE_OK) {
		ms_error("Error in creation: %s.", errmsg);
		sqlite3_free(errmsg);
	}
	sqlite3_free(buf);
}
86 87 88 89 90 91 92 93 94 95 96 97 98

/* DB layout:
 * | 0  | storage_id
 * | 1  | localContact
 * | 2  | remoteContact
 * | 3  | direction flag
 * | 4  | message
 * | 5  | time (unused now, used to be string-based timestamp)
 * | 6  | read flag
 * | 7  | status
 * | 8  | external body url
 * | 9  | utc timestamp
 * | 10 | app data text
99
 * | 11 | linphone content
100
 */
101 102 103
static void create_chat_message(char **argv, void *data){
	LinphoneChatRoom *cr = (LinphoneChatRoom *)data;
	LinphoneAddress *from;
104
	LinphoneAddress *to;
105 106 107 108 109 110 111 112 113 114 115

	unsigned int storage_id = atoi(argv[0]);

	// check if the message exists in the transient list, in which case we should return that one.
	LinphoneChatMessage* new_message = get_transient_message(cr, storage_id);
	if( new_message == NULL ){
		new_message = linphone_chat_room_create_message(cr, argv[4]);

		if(atoi(argv[3])==LinphoneChatMessageIncoming){
			new_message->dir=LinphoneChatMessageIncoming;
			from=linphone_address_new(argv[2]);
116
			to=linphone_address_new(argv[1]);
117 118 119
		} else {
			new_message->dir=LinphoneChatMessageOutgoing;
			from=linphone_address_new(argv[1]);
120
			to=linphone_address_new(argv[2]);
121 122 123
		}
		linphone_chat_message_set_from(new_message,from);
		linphone_address_destroy(from);
124 125 126 127
		if (to){
			linphone_chat_message_set_to(new_message,to);
			linphone_address_destroy(to);
		}
128 129 130 131 132 133 134 135 136 137

		if( argv[9] != NULL ){
			new_message->time = (time_t)atol(argv[9]);
		} else {
			new_message->time = time(NULL);
		}

		new_message->is_read=atoi(argv[6]);
		new_message->state=atoi(argv[7]);
		new_message->storage_id=storage_id;
138 139
		new_message->external_body_url= argv[8] ? ms_strdup(argv[8])  : NULL;
		new_message->appdata          = argv[10]? ms_strdup(argv[10]) : NULL;
140

141 142 143 144 145 146
		if (argv[11] != NULL) {
			int id = atoi(argv[11]);
			if (id >= 0) {
				fetch_content_from_database(cr->lc->db, new_message, id);
			}
		}
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
	}
	cr->messages_hist=ms_list_prepend(cr->messages_hist,new_message);
}

// Called when fetching all conversations from database
static int callback_all(void *data, int argc, char **argv, char **colName){
	LinphoneCore* lc = (LinphoneCore*) data;
	char* address = argv[0];
	linphone_core_get_or_create_chat_room(lc, address);
	return 0;
}

static int callback(void *data, int argc, char **argv, char **colName){
	create_chat_message(argv,data);
	return 0;
}

void linphone_sql_request_message(sqlite3 *db,const char *stmt,LinphoneChatRoom *cr){
	char* errmsg=NULL;
	int ret;
	ret=sqlite3_exec(db,stmt,callback,cr,&errmsg);
	if(ret != SQLITE_OK) {
169
		ms_error("Error in creation: %s.", errmsg);
170 171 172 173
		sqlite3_free(errmsg);
	}
}

174
int linphone_sql_request(sqlite3* db,const char *stmt){
175 176 177 178
	char* errmsg=NULL;
	int ret;
	ret=sqlite3_exec(db,stmt,NULL,NULL,&errmsg);
	if(ret != SQLITE_OK) {
179
		ms_error("linphone_sql_request: statement %s -> error sqlite3_exec(): %s.", stmt, errmsg);
180 181
		sqlite3_free(errmsg);
	}
182
	return ret;
183 184 185 186 187 188 189 190
}

// Process the request to fetch all chat contacts
void linphone_sql_request_all(sqlite3* db,const char *stmt, LinphoneCore* lc){
	char* errmsg=NULL;
	int ret;
	ret=sqlite3_exec(db,stmt,callback_all,lc,&errmsg);
	if(ret != SQLITE_OK) {
191
		ms_error("linphone_sql_request_all: error sqlite3_exec(): %s.", errmsg);
192 193 194 195
		sqlite3_free(errmsg);
	}
}

196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
static int linphone_chat_message_store_content(LinphoneChatMessage *msg) {
	LinphoneCore *lc = linphone_chat_room_get_lc(msg->chat_room);
	int id = -1;
	if (lc->db) {
		LinphoneContent *content = msg->file_transfer_information;
		char *buf = sqlite3_mprintf("INSERT INTO content VALUES(NULL,%Q,%Q,%Q,%Q,%i,%Q);",
						content->type,
						content->subtype,
						content->name,
						content->encoding,
						content->size,
						NULL
 					);
		linphone_sql_request(lc->db, buf);
		sqlite3_free(buf);
		id = (unsigned int) sqlite3_last_insert_rowid (lc->db);
	}
	return id;
}

216 217
unsigned int linphone_chat_message_store(LinphoneChatMessage *msg){
	LinphoneCore *lc=linphone_chat_room_get_lc(msg->chat_room);
218
	int id = 0;
219 220

	if (lc->db){
221
		int content_id = -1;
222 223 224
		char *peer;
		char *local_contact;
		char *buf;
225 226 227
		if (msg->file_transfer_information) {
			content_id = linphone_chat_message_store_content(msg);
		}
228 229 230

		peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(msg->chat_room));
		local_contact=linphone_address_as_string_uri_only(linphone_chat_message_get_local_address(msg));
Sylvain Berfini's avatar
Sylvain Berfini committed
231
		buf = sqlite3_mprintf("INSERT INTO history VALUES(NULL,%Q,%Q,%i,%Q,%Q,%i,%i,%Q,%lld,%Q,%i);",
232
						local_contact,
233 234 235 236 237 238 239
						peer,
						msg->dir,
						msg->message,
						"-1", /* use UTC field now */
						msg->is_read,
						msg->state,
						msg->external_body_url,
Simon Morlat's avatar
Simon Morlat committed
240
						(int64_t)msg->time,
241 242 243
						msg->appdata,
						content_id
 					);
244 245 246 247 248 249 250 251 252 253 254 255
		linphone_sql_request(lc->db,buf);
		sqlite3_free(buf);
		ms_free(local_contact);
		ms_free(peer);
		id = (unsigned int) sqlite3_last_insert_rowid (lc->db);
	}
	return id;
}

void linphone_chat_message_store_state(LinphoneChatMessage *msg){
	LinphoneCore *lc=msg->chat_room->lc;
	if (lc->db){
256 257
		char *buf=sqlite3_mprintf("UPDATE history SET status=%i WHERE (id = %i);",
								  msg->state,msg->storage_id);
258
		linphone_sql_request(lc->db,buf);
259 260 261 262 263 264 265 266 267 268 269
		sqlite3_free(buf);
	}

	if( msg->state == LinphoneChatMessageStateDelivered
			|| msg->state == LinphoneChatMessageStateNotDelivered ){
		// message is not transient anymore, we can remove it from our transient list:
		msg->chat_room->transient_messages = ms_list_remove(msg->chat_room->transient_messages, msg);
		linphone_chat_message_unref(msg);
	}
}

270 271 272 273 274 275 276 277 278 279
void linphone_chat_message_store_appdata(LinphoneChatMessage* msg){
	LinphoneCore *lc=msg->chat_room->lc;
	if (lc->db){
		char *buf=sqlite3_mprintf("UPDATE history SET appdata=%Q WHERE id=%i;",
								  msg->appdata,msg->storage_id);
		linphone_sql_request(lc->db,buf);
		sqlite3_free(buf);
	}
}

280 281 282
void linphone_chat_room_mark_as_read(LinphoneChatRoom *cr){
	LinphoneCore *lc=linphone_chat_room_get_lc(cr);
	int read=1;
283 284
	char *peer;
	char *buf;
285 286 287

	if (lc->db==NULL) return ;

288 289
	peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr));
	buf=sqlite3_mprintf("UPDATE history SET read=%i WHERE remoteContact = %Q;",
290 291 292 293 294 295 296 297
				   read,peer);
	linphone_sql_request(lc->db,buf);
	sqlite3_free(buf);
	ms_free(peer);
}

void linphone_chat_room_update_url(LinphoneChatRoom *cr, LinphoneChatMessage *msg) {
	LinphoneCore *lc=linphone_chat_room_get_lc(cr);
298
	char *buf;
299 300 301

	if (lc->db==NULL) return ;

302
	buf=sqlite3_mprintf("UPDATE history SET url=%Q WHERE id=%i;",msg->external_body_url,msg->storage_id);
303 304 305 306
	linphone_sql_request(lc->db,buf);
	sqlite3_free(buf);
}

307
static int linphone_chat_room_get_messages_count(LinphoneChatRoom *cr, bool_t unread_only){
308 309
	LinphoneCore *lc=linphone_chat_room_get_lc(cr);
	int numrows=0;
310 311 312 313
	char *peer;
	char *buf;
	sqlite3_stmt *selectStatement;
	int returnValue;
314 315 316

	if (lc->db==NULL) return 0;

317 318 319
	peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr));
	buf=sqlite3_mprintf("SELECT count(*) FROM history WHERE remoteContact = %Q %s;",peer,unread_only?"AND read = 0":"");
	returnValue = sqlite3_prepare_v2(lc->db,buf,-1,&selectStatement,NULL);
320 321 322 323 324 325 326 327 328 329 330
	if (returnValue == SQLITE_OK){
		if(sqlite3_step(selectStatement) == SQLITE_ROW){
			numrows= sqlite3_column_int(selectStatement, 0);
		}
	}
	sqlite3_finalize(selectStatement);
	sqlite3_free(buf);
	ms_free(peer);
	return numrows;
}

331 332 333 334 335 336 337 338
int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr){
	return linphone_chat_room_get_messages_count(cr, TRUE);
}

int linphone_chat_room_get_history_size(LinphoneChatRoom *cr){
	return linphone_chat_room_get_messages_count(cr, FALSE);
}

339 340
void linphone_chat_room_delete_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg) {
	LinphoneCore *lc=cr->lc;
341
	char *buf;
342 343 344

	if (lc->db==NULL) return ;

345
	buf=sqlite3_mprintf("DELETE FROM history WHERE id = %i;", msg->storage_id);
346 347 348 349 350 351
	linphone_sql_request(lc->db,buf);
	sqlite3_free(buf);
}

void linphone_chat_room_delete_history(LinphoneChatRoom *cr){
	LinphoneCore *lc=cr->lc;
352 353
	char *peer;
	char *buf;
354 355 356

	if (lc->db==NULL) return ;

357 358
	peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr));
	buf=sqlite3_mprintf("DELETE FROM history WHERE remoteContact = %Q;",peer);
359 360 361 362 363
	linphone_sql_request(lc->db,buf);
	sqlite3_free(buf);
	ms_free(peer);
}

364
MSList *linphone_chat_room_get_history_range(LinphoneChatRoom *cr, int startm, int endm){
365 366
	LinphoneCore *lc=linphone_chat_room_get_lc(cr);
	MSList *ret;
367
	char *buf,*buf2;
368 369
	char *peer;
	uint64_t begin,end;
370
	int buf_max_size = 512;
371 372

	if (lc->db==NULL) return NULL;
373 374
	peer = linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr));

375
	cr->messages_hist = NULL;
376 377 378 379 380

	/*since we want to append query parameters depending on arguments given, we use malloc instead of sqlite3_mprintf*/
	buf=ms_malloc(buf_max_size);
	buf=sqlite3_snprintf(buf_max_size-1,buf,"SELECT * FROM history WHERE remoteContact = %Q ORDER BY id DESC",peer);

381

382 383
	if (startm<0) startm=0;

384
	if (endm>0&&endm>=startm){
385 386 387
		buf2=ms_strdup_printf("%s LIMIT %i ",buf,endm+1-startm);
		ms_free(buf);
		buf = buf2;
388
	}else if(startm>0){
389 390 391 392
		ms_message("%s(): end is lower than start (%d < %d). Assuming no end limit.",__FUNCTION__,endm,startm);
		buf2=ms_strdup_printf("%s LIMIT -1",buf);
		ms_free(buf);
		buf = buf2;
393 394 395
	}

	if (startm>0){
396 397 398
		buf2=ms_strdup_printf("%s OFFSET %i ",buf,startm);
		ms_free(buf);
		buf = buf2;
399 400
	}

401 402 403
	begin=ortp_get_cur_time_ms();
	linphone_sql_request_message(lc->db,buf,cr);
	end=ortp_get_cur_time_ms();
404 405
	ms_message("%s(): completed in %i ms",__FUNCTION__, (int)(end-begin));
	ms_free(buf);
406 407 408 409 410 411
	ret=cr->messages_hist;
	cr->messages_hist=NULL;
	ms_free(peer);
	return ret;
}

412
MSList *linphone_chat_room_get_history(LinphoneChatRoom *cr,int nb_message){
413
	return linphone_chat_room_get_history_range(cr, 0, nb_message-1);
414 415 416
}


417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467
void linphone_close_storage(sqlite3* db){
	sqlite3_close(db);
}

void linphone_create_table(sqlite3* db){
	char* errmsg=NULL;
	int ret;
	ret=sqlite3_exec(db,"CREATE TABLE IF NOT EXISTS history ("
							 "id            INTEGER PRIMARY KEY AUTOINCREMENT,"
							 "localContact  TEXT NOT NULL,"
							 "remoteContact TEXT NOT NULL,"
							 "direction     INTEGER,"
							 "message       TEXT,"
							 "time          TEXT NOT NULL,"
							 "read          INTEGER,"
							 "status        INTEGER"
						");",
			0,0,&errmsg);
	if(ret != SQLITE_OK) {
		ms_error("Error in creation: %s.\n", errmsg);
		sqlite3_free(errmsg);
	}
}


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"};
static time_t parse_time_from_db( const char* time ){
	/* messages used to be stored in the DB by using string-based time */
	struct tm ret={0};
	char tmp1[80]={0};
	char tmp2[80]={0};
	int i,j;
	time_t parsed = 0;

	if( sscanf(time,"%3c %3c%d%d:%d:%d %d",tmp1,tmp2,&ret.tm_mday,
			   &ret.tm_hour,&ret.tm_min,&ret.tm_sec,&ret.tm_year) == 7 ){
		ret.tm_year-=1900;
		for(i=0;i<7;i++) {
			if(strcmp(tmp1,days[i])==0) ret.tm_wday=i;
		}
		for(j=0;j<12;j++) {
			if(strcmp(tmp2,months[j])==0) ret.tm_mon=j;
		}
		ret.tm_isdst=-1;
		parsed = mktime(&ret);
	}
	return parsed;
}


468
static int migrate_messages_timestamp(void* data,int argc, char** argv, char** column_names) {
469 470 471
	time_t new_time = parse_time_from_db(argv[1]);
	if( new_time ){
		/* replace 'time' by -1 and set 'utc' to the timestamp */
Sylvain Berfini's avatar
Sylvain Berfini committed
472
		char *buf =	sqlite3_mprintf("UPDATE history SET utc=%lld,time='-1' WHERE id=%i;", new_time, atoi(argv[0]));
473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489
		if( buf) {
			linphone_sql_request((sqlite3*)data, buf);
			sqlite3_free(buf);
		}
	} else {
		ms_warning("Cannot parse time %s from id %s", argv[1], argv[0]);
	}
	return 0;
}

static void linphone_migrate_timestamps(sqlite3* db){
	int ret;
	char* errmsg = NULL;
	uint64_t begin=ortp_get_cur_time_ms();

	linphone_sql_request(db,"BEGIN TRANSACTION");

490
	ret = sqlite3_exec(db,"SELECT id,time,direction FROM history WHERE time != '-1';", migrate_messages_timestamp, db, &errmsg);
491 492 493 494 495
	if( ret != SQLITE_OK ){
		ms_warning("Error migrating outgoing messages: %s.\n", errmsg);
		sqlite3_free(errmsg);
		linphone_sql_request(db, "ROLLBACK");
	} else {
496
		uint64_t end;
497
		linphone_sql_request(db, "COMMIT");
498
		end=ortp_get_cur_time_ms();
Simon Morlat's avatar
Simon Morlat committed
499
		ms_message("Migrated message timestamps to UTC in %lu ms",(unsigned long)(end-begin));
500 501 502 503 504 505 506 507 508 509 510 511 512
	}
}

void linphone_update_table(sqlite3* db) {
	char* errmsg=NULL;
	int ret;

	// for image url storage
	ret=sqlite3_exec(db,"ALTER TABLE history ADD COLUMN url TEXT;",NULL,NULL,&errmsg);
	if(ret != SQLITE_OK) {
		ms_message("Table already up to date: %s.", errmsg);
		sqlite3_free(errmsg);
	} else {
513
		ms_debug("Table history updated successfully for URL.");
514 515 516 517 518 519 520 521
	}

	// for UTC timestamp storage
	ret = sqlite3_exec(db, "ALTER TABLE history ADD COLUMN utc INTEGER;", NULL,NULL,&errmsg);
	if( ret != SQLITE_OK ){
		ms_message("Table already up to date: %s.", errmsg);
		sqlite3_free(errmsg);
	} else {
522
		ms_debug("Table history updated successfully for UTC.");
523 524 525
		// migrate from old text-based timestamps to unix time-based timestamps
		linphone_migrate_timestamps(db);
	}
526 527 528 529 530 531 532

	// new field for app-specific storage
	ret=sqlite3_exec(db,"ALTER TABLE history ADD COLUMN appdata TEXT;",NULL,NULL,&errmsg);
	if(ret != SQLITE_OK) {
		ms_message("Table already up to date: %s.", errmsg);
		sqlite3_free(errmsg);
	} else {
533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558
		ms_debug("Table history updated successfully for app-specific data.");
	}

	// new field for linphone content storage
	ret=sqlite3_exec(db,"ALTER TABLE history ADD COLUMN content INTEGER;",NULL,NULL,&errmsg);
	if(ret != SQLITE_OK) {
		ms_message("Table already up to date: %s.", errmsg);
		sqlite3_free(errmsg);
	} else {
		ms_debug("Table history updated successfully for content data.");
		ret = sqlite3_exec(db,"CREATE TABLE IF NOT EXISTS content ("
							"id INTEGER PRIMARY KEY AUTOINCREMENT,"
							"type TEXT,"
							"subtype TEXT,"
							"name TEXT,"
							"encoding TEXT,"
							"size INTEGER,"
							"data BLOB"
						");",
			0,0,&errmsg);
		if(ret != SQLITE_OK) {
			ms_error("Error in creation: %s.\n", errmsg);
			sqlite3_free(errmsg);
		} else {
			ms_debug("Table content successfully created.");
		}
559
	}
560 561 562 563 564 565 566 567 568 569 570
}

void linphone_message_storage_init_chat_rooms(LinphoneCore *lc) {
	char *buf;

	if (lc->db==NULL) return;
	buf=sqlite3_mprintf("SELECT remoteContact FROM history GROUP BY remoteContact;");
	linphone_sql_request_all(lc->db,buf,lc);
	sqlite3_free(buf);
}

571
static void _linphone_message_storage_profile(void*data,const char*statement, sqlite3_uint64 duration){
Simon Morlat's avatar
Simon Morlat committed
572
	ms_warning("SQL statement '%s' took %" PRIu64 " microseconds", statement, (uint64_t)(duration / 1000LL) );
573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591
}

static void linphone_message_storage_activate_debug(sqlite3* db, bool_t debug){
	if( debug  ){
		sqlite3_profile(db, _linphone_message_storage_profile, NULL );
	} else {
		sqlite3_profile(db, NULL, NULL );
	}
}

void linphone_core_message_storage_set_debug(LinphoneCore *lc, bool_t debug){

	lc->debug_storage = debug;

	if( lc->db ){
		linphone_message_storage_activate_debug(lc->db, debug);
	}
}

592 593 594 595 596 597 598 599 600 601 602 603 604
void linphone_core_message_storage_init(LinphoneCore *lc){
	int ret;
	const char *errmsg;
	sqlite3 *db;

	linphone_core_message_storage_close(lc);

	ret=sqlite3_open(lc->chat_db_file,&db);
	if(ret != SQLITE_OK) {
		errmsg=sqlite3_errmsg(db);
		ms_error("Error in the opening: %s.\n", errmsg);
		sqlite3_close(db);
	}
605 606 607

	linphone_message_storage_activate_debug(db, lc->debug_storage);

608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631
	linphone_create_table(db);
	linphone_update_table(db);
	lc->db=db;

	// Create a chatroom for each contact in the chat history
	linphone_message_storage_init_chat_rooms(lc);
}

void linphone_core_message_storage_close(LinphoneCore *lc){
	if (lc->db){
		sqlite3_close(lc->db);
		lc->db=NULL;
	}
}

#else

unsigned int linphone_chat_message_store(LinphoneChatMessage *cr){
	return 0;
}

void linphone_chat_message_store_state(LinphoneChatMessage *cr){
}

632 633 634
void linphone_chat_message_store_appdata(LinphoneChatMessage *msg){
}

635 636 637 638 639 640 641
void linphone_chat_room_mark_as_read(LinphoneChatRoom *cr){
}

MSList *linphone_chat_room_get_history(LinphoneChatRoom *cr,int nb_message){
	return NULL;
}

642 643 644 645
LINPHONE_PUBLIC MSList *linphone_chat_room_get_history_range(LinphoneChatRoom *cr, int begin, int end){
	return NULL;
}

646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667
void linphone_chat_room_delete_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg) {
}

void linphone_chat_room_delete_history(LinphoneChatRoom *cr){
}

void linphone_message_storage_init_chat_rooms(LinphoneCore *lc) {
}

void linphone_core_message_storage_init(LinphoneCore *lc){
}

void linphone_core_message_storage_close(LinphoneCore *lc){
}

void linphone_chat_room_update_url(LinphoneChatRoom *cr, LinphoneChatMessage *msg) {
}

int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr){
	return 0;
}

668 669 670 671
int linphone_chat_room_get_history_size(LinphoneChatRoom *cr){
	return 0;
}

672
#endif