changeset 14511:f309a5b3f184

[gaim-migrate @ 17231] Switched from using libdbi to using sqlite3. Results in easier configuration (no need to setup database server/create database/add tables). Also Gtk Gaim no longer needs to link against libdbi. This should make the plugin more easily distributable and thus hopefully it can be included in binary releases of Gaim (fingers crossed). committer: Tailor Script <tailor@pidgin.im>
author Geoff Foster <g-off_>
date Mon, 11 Sep 2006 00:28:35 +0000
parents 1d73e11d8787
children 92817f33cefc
files configure.ac gtk/Makefile.am gtk/plugins/cap/Makefile.am gtk/plugins/cap/cap.c gtk/plugins/cap/cap.h
diffstat 5 files changed, 379 insertions(+), 718 deletions(-) [+]
line wrap: on
line diff
--- a/configure.ac	Sun Sep 10 22:33:28 2006 +0000
+++ b/configure.ac	Mon Sep 11 00:28:35 2006 +0000
@@ -324,12 +324,10 @@
 	fi
 
 	dnl #######################################################################
-	dnl # Check for libdbi (for the Contact Availability Prediction plugin)
+	dnl # Check for libsqlite3 (for the Contact Availability Prediction plugin)
 	dnl #######################################################################
 	if test "x$enable_cap" = "xyes"; then
-		AC_CHECK_HEADERS(dbi/dbi.h, , enable_cap="no")
-		AC_CHECK_LIB(dbi, dbi_result_field_is_null, CAP_LIBS="-ldbi", enable_cap="no")
-		AC_SUBST(CAP_LIBS)
+		PKG_CHECK_MODULES(SQLITE3, sqlite3 >= 3.3, , enable_cap="no")
 	fi
 
 else # GTK
--- a/gtk/Makefile.am	Sun Sep 10 22:33:28 2006 +0000
+++ b/gtk/Makefile.am	Mon Sep 11 00:28:35 2006 +0000
@@ -161,7 +161,6 @@
 	$(STARTUP_NOTIFICATION_LIBS) \
 	$(LIBXML_LIBS) \
 	$(GTK_LIBS) \
-	$(CAP_LIBS) \
 	$(top_builddir)/libgaim/libgaim.la
 
 AM_CPPFLAGS = \
--- a/gtk/plugins/cap/Makefile.am	Sun Sep 10 22:33:28 2006 +0000
+++ b/gtk/plugins/cap/Makefile.am	Mon Sep 11 00:28:35 2006 +0000
@@ -15,9 +15,7 @@
 
 endif
 
-CAP_LIBS = -ldl -ldbi
-
-cap_la_LIBADD = $(CAP_LIBS)
+cap_la_LIBADD = $(SQLITE3_LIBS)
 
 AM_CPPFLAGS = \
 	-DDATADIR=\"$(datadir)\" \
@@ -26,4 +24,4 @@
 	-I$(top_srcdir)/gtk \
 	$(DEBUG_CFLAGS) \
 	$(GTK_CFLAGS) \
-	$(CAP_CFLAGS)
+	$(SQLITE3_CFLAGS)
--- a/gtk/plugins/cap/cap.c	Sun Sep 10 22:33:28 2006 +0000
+++ b/gtk/plugins/cap/cap.c	Mon Sep 11 00:28:35 2006 +0000
@@ -21,29 +21,6 @@
 
 #include "cap.h"
 
-static char * quote_string(const char *str) {
-	gchar *quoted_str = NULL;
-	quoted_str = g_strdup(str);
-	dbi_driver_quote_string(_driver, &quoted_str);
-	return quoted_str;
-}
-
-static void generate_minute_stats(CapStatistics *statistics) {
-	gchar *buddy_name = quote_string(statistics->buddy->name);
-	gchar *protocol_id = quote_string(gaim_account_get_protocol_id(statistics->buddy->account));
-	gchar *account_id = quote_string(gaim_account_get_username(statistics->buddy->account));
-	dbi_result result = dbi_conn_queryf(_conn, "select minute_val, success_count, failed_count from cap_msg_count where buddy=%s account=%s and protocol=%s;", buddy_name, account_id, protocol_id);
-
-	while(dbi_result_next_row(result)) {
-		int minute_val = dbi_result_get_int(result, "minute_val");
-		int success_count = dbi_result_get_int(result, "success_count");
-		int failed_count = dbi_result_get_int(result, "failed_count");
-		double ratio = ((double)success_count/(double)(success_count + failed_count));
-		statistics->minute_stats[minute_val] = ratio;
-	}
-	dbi_result_free(result);
-}
-
 static void generate_prediction(CapStatistics *statistics) {
 	if(statistics->buddy) {
 		if(statistics->prediction == NULL)
@@ -56,86 +33,67 @@
 static double generate_prediction_for(GaimBuddy *buddy) {
 	double prediction = 1.0f;
 	gboolean generated = FALSE;
-	gchar *buddy_name = quote_string(buddy->name);
-	gchar *protocol_id = quote_string(gaim_account_get_protocol_id(buddy->account));
-	gchar *account_id = quote_string(gaim_account_get_username(buddy->account));
-	gchar *status_id = quote_string(gaim_status_get_id(get_status_for(buddy)));
+	gchar *buddy_name = buddy->name;
+	const gchar *protocol_id = gaim_account_get_protocol_id(buddy->account);
+	const gchar *account_id = gaim_account_get_username(buddy->account);
+	const gchar *status_id = gaim_status_get_id(get_status_for(buddy));
 	time_t t = time(NULL);
 	struct tm *current_time = localtime(&t);
 	int current_minute = current_time->tm_min + current_time->tm_hour * 60;
 	int threshold = gaim_prefs_get_int("/plugins/gtk/cap/threshold");
 	int min_minute = (current_minute - threshold) % 1440;
 	int max_minute = (current_minute + threshold) % 1440;
-	dbi_result result;
-
-	result = dbi_conn_queryf(_conn, "select success_count, failed_count from cap_msg_count where buddy=%s and account=%s and protocol=%s and minute_val>=%d and minute_val<=%d;", buddy_name, account_id, protocol_id, min_minute, max_minute);
-	if(result) {
-		int successes = 0;
-		int failures = 0;
-		while(dbi_result_next_row(result)) {
-			if(!dbi_result_field_is_null(result, "success_count"))
-				successes += dbi_result_get_int(result, "success_count");
-
-			if(!dbi_result_field_is_null(result, "failed_count"))
-				failures += dbi_result_get_int(result, "failed_count");
-		}
-		if(failures + successes > 0) {
-			prediction *= ((double)successes/((double)(successes + failures)));
-			generated = TRUE;
-		}
-		dbi_result_free(result);
-	}
+	char *sql;
+	sqlite3_stmt *stmt = NULL;
+	const char *tail = NULL;
+	int rc;
 
 
-/*
- * Note to self: apparently when using a function like sum results in not being able to get
- * the values for fields using libdbi...why? the way I'm doing it above sucks, find a fix.
-	result = dbi_conn_queryf(_conn, "select sum(success_count) as successes, sum(failed_count) as failures from cap_msg_count where buddy=%s and account=%s and protocol=%s and minute_val>=%d and minute_val<=%d;", buddy_name, account_id, protocol_id, min_minute, max_minute);
-	gaim_debug_info("cap", "select sum(success_count) as successes, sum(failed_count) as failures from cap_msg_count where buddy=%s and account=%s and protocol=%s and minute_val>=%d and minute_val<=%d;\n", buddy_name, account_id, protocol_id, min_minute, max_minute);
-
-	if(result) {
-		int failures;
-		int successes;
-		int rc = dbi_result_get_numrows(result);
-		dbi_result_next_row(result);
-		gaim_debug_info("cap", "Result code: %d\n", rc);
-		failures = dbi_result_get_int_idx(result, 1);//"failures");
-		successes = dbi_result_get_int_idx(result, 2); //"successes");
-		gaim_debug_info("cap", "Successes = %d; Failures = %d\n", successes, failures);
-		dbi_result_get_fields(result, "successes.%i failures.%i", &successes, &failures);
-		gaim_debug_info("cap", "Successes = %d; Failures = %d\n", successes, failures);
-		if(failures + successes > 0.0)
-			prediction *= ((double)successes/((double)(successes + failures)));
-		gaim_debug_info("cap", "After message value prediction is %0.4f.\n", prediction);
-		dbi_result_free(result);
-	}
-*/	
-	
-	result = dbi_conn_queryf(_conn, "select success_count, failed_count from cap_status_count where buddy=%s and account=%s and protocol=%s and status=%s;", buddy_name, account_id, protocol_id, status_id);
-	if(result) {
+	sql = sqlite3_mprintf("select sum(success_count) as successes, sum(failed_count) as failures "
+		"from cap_msg_count where "
+		"buddy=%Q and account=%Q and protocol=%Q and minute_val>=%d and minute_val<=%d;",
+		buddy_name,	account_id,	protocol_id, min_minute, max_minute);
+	rc = sqlite3_prepare(_db, sql, -1, &stmt, &tail);
+	if(rc == SQLITE_OK) {
 		int successes = 0;
 		int failures = 0;
-		
-		dbi_result_next_row(result);
-
-		if(!dbi_result_field_is_null(result, "success_count"))
-			successes = dbi_result_get_int(result, "success_count");
-
-		if(!dbi_result_field_is_null(result, "failed_count"))
-			failures = dbi_result_get_int(result, "failed_count");
+		if(stmt != NULL) {
+			if(sqlite3_step(stmt) == SQLITE_ROW) {
+				successes = sqlite3_column_int(stmt, 0);
+				failures = sqlite3_column_int(stmt, 1);
+				if(failures + successes > 0) {
+					prediction *= ((double)successes/((double)(successes+failures)));
+					generated = TRUE;
+				}
+			}
+			sqlite3_finalize(stmt);
+		}
+	}
+	sqlite3_free(sql);
 
-		if(successes + failures > 0) {
-			prediction *= ((double)successes/(double)(successes + failures));
-			generated = TRUE;
+	sql = sqlite3_mprintf("select sum(success_count) as successes, sum(failed_count) as failures "
+		"from cap_status_count where "
+		"buddy=%Q and account=%Q and protocol=%Q and status=%Q;",
+		buddy_name,	account_id,	protocol_id, status_id);
+	rc = sqlite3_prepare(_db, sql, -1, &stmt, &tail);
+	if(rc == SQLITE_OK) {
+		int successes = 0;
+		int failures = 0;
+		if(stmt != NULL) {
+			if(sqlite3_step(stmt) == SQLITE_ROW) {
+				successes = sqlite3_column_int(stmt, 0);
+				failures = sqlite3_column_int(stmt, 1);
+				if(failures + successes > 0) {
+					prediction *= ((double)successes/((double)(successes+failures)));
+					generated = TRUE;
+				}
+			}
+			sqlite3_finalize(stmt);
 		}
-		dbi_result_free(result);
 	}
+	sqlite3_free(sql);
 
-	free(buddy_name);
-	free(account_id);
-	free(protocol_id);
-	free(status_id);
-
+	
 	if(strcmp(gaim_status_get_id(get_status_for(buddy)), "offline") == 0) {
 		//This is kind of stupid, change it.
 		if(prediction == 1.0f)
@@ -150,12 +108,10 @@
 
 static CapStatistics * get_stats_for(GaimBuddy *buddy) {
 	gchar *buddy_name;
-	gchar *q_buddy_name = quote_string(buddy->name);
 	CapStatistics *stats;
 	buddy_name = g_strdup(buddy->name);
 	stats = g_hash_table_lookup(_buddy_stats, buddy_name);
 	if(!stats) {
-		dbi_result result;
 		stats = g_malloc(sizeof(CapStatistics));
 		stats->last_message = -1;
 		stats->last_message_status_id = NULL;
@@ -163,37 +119,11 @@
 		stats->prediction = NULL;
 		g_hash_table_insert(_buddy_stats, buddy_name, stats);
 		stats->buddy = buddy;
-		/* Setup the last seen online time from database or -1 if no time available. */
-		result = dbi_conn_queryf(_conn,
-			//"select max(event_time) as last_event_time from cap_status where buddy=\'%s\' and status!=\'offline\';",
-			"select event_time from cap_status where buddy=\'%s\' and status!=\'offline\' order by event_time desc;",
-			q_buddy_name);
-		if(result && dbi_result_get_numrows(result) > 0) {
-			dbi_result_next_row(result);
-			stats->last_seen = dbi_result_get_datetime(result, "event_time");
-		} else {
-			stats->last_seen = -1;
-		}
-		dbi_result_free(result);
-		/* Setup the last messaged time to be a 'useable' value for comparisons. */
-		//result = dbi_conn_queryf(conn, "", );
-		/* Setup the last status id to nothing */
-		// --> Better approach would be to get the last status available in db and use it.
-		result = dbi_conn_queryf(_conn,
-			"select status, max(event_time) from cap_status where buddy=\'%s\' group by status;",
-			buddy->name);
-		if(result && dbi_result_get_numrows(result) > 0) {
-			dbi_result_next_row(result);
-			stats->last_status_id = dbi_result_get_string_copy(result, "status");
-		} else {
-			stats->last_status_id = "";
-		}
-		dbi_result_free(result);
-		//TODO: populate stats from database
+		stats->last_seen = -1;
+		stats->last_status_id = "";
 	} else {
 		g_free(buddy_name);
 	}
-	free(q_buddy_name);
 	generate_prediction(stats);
 	return stats;
 }
@@ -206,43 +136,161 @@
 	g_free(stats);
 }
 
-static gboolean remove_stats_for(GaimBuddy *buddy) {
-	gboolean success = TRUE;
-	//GString *buddy_name = g_string_new(buddy->name);
-	gchar *buddy_name = g_strdup(buddy->name);
-	success = g_hash_table_remove(_buddy_stats, buddy_name);
-	g_free(buddy_name);
-	return success;
-}
+static void
+insert_cap_msg_count_success(const char *buddy_name, const char *account, const char *protocol, int minute) {
+	int rc;
+	sqlite3_stmt *stmt;
+	const char *tail;
+	char *sql_select = sqlite3_mprintf("SELECT * FROM cap_msg_count WHERE "
+		"buddy=%Q AND account=%Q AND protocol=%Q AND minute_val=%d;",
+		buddy_name, account, protocol, minute);
+	char *sql_ins_up = NULL;
+
+	gaim_debug_info("cap", "%s\n", sql_select);
+
+	sqlite3_prepare(_db, sql_select, -1, &stmt, &tail);
+	
+	rc = sqlite3_step(stmt);
 
-static dbi_result insert_cap_msg_count_success(const char *buddy_name, const char *account, const char *protocol, int minute) {
-	gaim_debug_info("cap", "Insert cap_msg_count success: %s %s %s %d\n", buddy_name, account, protocol, minute);
-	return dbi_conn_queryf(_conn, "insert into cap_msg_count (buddy, account, protocol, minute_val, success_count, failed_count) values (%s, %s, %s, %d, %d, %d) on duplicate key update success_count=success_count+1;", buddy_name, account, protocol, minute, 1, 0);
+	if(rc == SQLITE_DONE) {
+		sql_ins_up = sqlite3_mprintf("INSERT INTO cap_msg_count VALUES (%Q, %Q, %Q, %d, %d, %d);",
+			buddy_name, account, protocol, minute, 1, 0);
+	} else if(rc == SQLITE_ROW) {
+		sql_ins_up = sqlite3_mprintf("UPDATE cap_msg_count SET success_count=success_count+1 WHERE "
+			"buddy=%Q AND account=%Q AND protocol=%Q AND minute_val=%d;",
+			buddy_name, account, protocol, minute);
+	} else {
+		gaim_debug_info("cap", "%d\n", rc);
+		sqlite3_finalize(stmt);
+		sqlite3_free(sql_select);
+		return;
+	}
+
+	sqlite3_finalize(stmt);
+	sqlite3_free(sql_select);
+
+	sqlite3_exec(_db, sql_ins_up, NULL, NULL, NULL);
+	sqlite3_free(sql_ins_up);
 }
 
-static dbi_result insert_cap_status_count_success(const char *buddy_name, const char *account, const char *protocol, const char *status_id) {
-	gaim_debug_info("cap", "Insert cap_status_count success: %s %s %s %s\n", buddy_name, account, protocol, status_id);
-	return dbi_conn_queryf(_conn, "insert into cap_status_count (buddy, account, protocol, status, success_count, failed_count) values(%s, %s, %s, %s, %d, %d) on duplicate key update success_count=success_count+1;", buddy_name, account, protocol, status_id, 1, 0);
+static void
+insert_cap_status_count_success(const char *buddy_name, const char *account, const char *protocol, const char *status_id) {
+	int rc;
+	sqlite3_stmt *stmt;
+	const char *tail;
+	char *sql_select = sqlite3_mprintf("SELECT * FROM cap_status_count WHERE "
+		"buddy=%Q AND account=%Q AND protocol=%Q AND status=%Q;",
+		buddy_name, account, protocol, status_id);
+	char *sql_ins_up = NULL;
+
+	gaim_debug_info("cap", "%s\n", sql_select);
+
+	sqlite3_prepare(_db, sql_select, -1, &stmt, &tail);
+	
+	rc = sqlite3_step(stmt);
+
+	if(rc == SQLITE_DONE) {
+		sql_ins_up = sqlite3_mprintf("INSERT INTO cap_status_count VALUES (%Q, %Q, %Q, %Q, %d, %d);",
+			buddy_name, account, protocol, status_id, 1, 0);
+	} else if(rc == SQLITE_ROW) {
+		sql_ins_up = sqlite3_mprintf("UPDATE cap_status_count SET success_count=success_count+1 WHERE "
+			"buddy=%Q AND account=%Q AND protocol=%Q AND status=%Q;",
+			buddy_name, account, protocol, status_id);
+	} else {
+		gaim_debug_info("cap", "%d\n", rc);
+		sqlite3_finalize(stmt);
+		sqlite3_free(sql_select);
+		return;
+	}
+
+	sqlite3_finalize(stmt);
+	sqlite3_free(sql_select);
+
+	sqlite3_exec(_db, sql_ins_up, NULL, NULL, NULL);
+	sqlite3_free(sql_ins_up);
 }
 
-static dbi_result insert_cap_msg_count_failed(const char *buddy_name, const char *account, const char *protocol, int minute) {
-	gaim_debug_info("cap", "Insert cap_msg_count failed: %s %s %s %d\n", buddy_name, account, protocol, minute);
-	return dbi_conn_queryf(_conn, "insert into cap_msg_count (buddy, account, protocol, minute_val, success_count, failed_count) values (%s, %s, %s, %d, %d, %d) on duplicate key update failed_count=failed_count+1;", buddy_name, account, protocol, minute, 0, 1);
+static void
+insert_cap_msg_count_failed(const char *buddy_name, const char *account, const char *protocol, int minute) {
+	int rc;
+	sqlite3_stmt *stmt;
+	const char *tail;
+	char *sql_select = sqlite3_mprintf("SELECT * FROM cap_msg_count WHERE "
+		"buddy=%Q AND account=%Q AND protocol=%Q AND minute_val=%d;",
+		buddy_name, account, protocol, minute);
+	char *sql_ins_up = NULL;
+
+	gaim_debug_info("cap", "%s\n", sql_select);
+
+	sqlite3_prepare(_db, sql_select, -1, &stmt, &tail);
+	
+	rc = sqlite3_step(stmt);
+
+	if(rc == SQLITE_DONE) {
+		sql_ins_up = sqlite3_mprintf("INSERT INTO cap_msg_count VALUES (%Q, %Q, %Q, %d, %d, %d);",
+			buddy_name, account, protocol, minute, 0, 1);
+	} else if(rc == SQLITE_ROW) {
+		sql_ins_up = sqlite3_mprintf("UPDATE cap_msg_count SET failed_count=failed_count+1 WHERE "
+			"buddy=%Q AND account=%Q AND protocol=%Q AND minute_val=%d;",
+			buddy_name, account, protocol, minute);
+	} else {
+		gaim_debug_info("cap", "%d\n", rc);
+		sqlite3_finalize(stmt);
+		sqlite3_free(sql_select);
+		return;
+	}
+
+	sqlite3_finalize(stmt);
+	sqlite3_free(sql_select);
+
+	sqlite3_exec(_db, sql_ins_up, NULL, NULL, NULL);
+	sqlite3_free(sql_ins_up);
 }
 
-static dbi_result insert_cap_status_count_failed(const char *buddy_name, const char *account, const char *protocol, const char *status_id) {
-	gaim_debug_info("cap", "Insert cap_status_count failed: %s %s %s %s\n", buddy_name, account, protocol, status_id);
-	return dbi_conn_queryf(_conn, "insert into cap_status_count (buddy, account, protocol, status, success_count, failed_count) values(%s, %s, %s, %s, %d, %d) on duplicate key update failed_count=failed_count+1;", buddy_name, account, protocol, status_id, 0, 1);
+static void
+insert_cap_status_count_failed(const char *buddy_name, const char *account, const char *protocol, const char *status_id) {
+	int rc;
+	sqlite3_stmt *stmt;
+	const char *tail;
+	char *sql_select = sqlite3_mprintf("SELECT * FROM cap_status_count WHERE "
+		"buddy=%Q AND account=%Q AND protocol=%Q AND status=%Q;",
+		buddy_name, account, protocol, status_id);
+	char *sql_ins_up = NULL;
+
+	gaim_debug_info("cap", "%s\n", sql_select);
+
+	sqlite3_prepare(_db, sql_select, -1, &stmt, &tail);
+	
+	rc = sqlite3_step(stmt);
+
+	if(rc == SQLITE_DONE) {
+		sql_ins_up = sqlite3_mprintf("INSERT INTO cap_status_count VALUES (%Q, %Q, %Q, %Q, %d, %d);",
+			buddy_name, account, protocol, status_id, 0, 1);
+	} else if(rc == SQLITE_ROW) {
+		sql_ins_up = sqlite3_mprintf("UPDATE cap_status_count SET failed_count=failed_count+1 WHERE "
+			"buddy=%Q AND account=%Q AND protocol=%Q AND status=%Q;",
+			buddy_name, account, protocol, status_id);
+	} else {
+		gaim_debug_info("cap", "%d\n", rc);
+		sqlite3_finalize(stmt);
+		sqlite3_free(sql_select);
+		return;
+	}
+
+	sqlite3_finalize(stmt);
+	sqlite3_free(sql_select);
+
+	sqlite3_exec(_db, sql_ins_up, NULL, NULL, NULL);
+	sqlite3_free(sql_ins_up);
 }
 
 static void insert_cap_success(CapStatistics *stats) {
-	dbi_result result;
-	gchar *buddy_name = quote_string(stats->buddy->name);
-	gchar *protocol_id = quote_string(gaim_account_get_protocol_id(stats->buddy->account));
-	gchar *account_id = quote_string(gaim_account_get_username(stats->buddy->account));
-	gchar *status_id = (stats->last_message_status_id) ?
-		quote_string(stats->last_message_status_id) :
-		quote_string(gaim_status_get_id(get_status_for(stats->buddy)));
+	gchar *buddy_name = stats->buddy->name;
+	const gchar *protocol_id = gaim_account_get_protocol_id(stats->buddy->account);
+	const gchar *account_id = gaim_account_get_username(stats->buddy->account);
+	const gchar *status_id = (stats->last_message_status_id) ?
+		stats->last_message_status_id :
+		gaim_status_get_id(get_status_for(stats->buddy));
 	struct tm *current_time;
 	int minute;
 	
@@ -254,49 +302,30 @@
 	}
 	minute = current_time->tm_min + current_time->tm_hour * 60;
 
-	result = insert_cap_msg_count_success(buddy_name, account_id, protocol_id, minute);
-	if(result)
-		dbi_result_free(result);
+	insert_cap_msg_count_success(buddy_name, account_id, protocol_id, minute);
 	
-	result = insert_cap_status_count_success(buddy_name, account_id, protocol_id, status_id);
-	if(result)
-		dbi_result_free(result);
+	insert_cap_status_count_success(buddy_name, account_id, protocol_id, status_id);
 
 	stats->last_message = -1;
 	stats->last_message_status_id = NULL;
-
-	free(status_id);
-	free(protocol_id);
-	free(account_id);
-	free(buddy_name);
 }
 
 static void insert_cap_failure(CapStatistics *stats) {
-	dbi_result result;
-	gchar *buddy_name = quote_string(stats->buddy->name);
-	gchar *protocol_id = quote_string(gaim_account_get_protocol_id(stats->buddy->account));
-	gchar *account_id = quote_string(gaim_account_get_username(stats->buddy->account));
-	gchar *status_id = (stats->last_message_status_id) ?
-		quote_string(stats->last_message_status_id) :
-		quote_string(gaim_status_get_id(get_status_for(stats->buddy)));
+	gchar *buddy_name = stats->buddy->name;
+	const gchar *protocol_id = gaim_account_get_protocol_id(stats->buddy->account);
+	const gchar *account_id = gaim_account_get_username(stats->buddy->account);
+	const gchar *status_id = (stats->last_message_status_id) ?
+		stats->last_message_status_id :
+		gaim_status_get_id(get_status_for(stats->buddy));
 	struct tm *current_time = localtime(&stats->last_message);
 	int minute = current_time->tm_min + current_time->tm_hour * 60;
 
-	result = insert_cap_msg_count_failed(buddy_name, account_id, protocol_id, minute);
-	if(result)
-		dbi_result_free(result);
+	insert_cap_msg_count_failed(buddy_name, account_id, protocol_id, minute);
 	
-	result = insert_cap_status_count_failed(buddy_name, account_id, protocol_id, status_id);
-	if(result)
-		dbi_result_free(result);
+	insert_cap_status_count_failed(buddy_name, account_id, protocol_id, status_id);
 	
 	stats->last_message = -1;
 	stats->last_message_status_id = NULL;
-
-	free(status_id);
-	free(protocol_id);
-	free(account_id);
-	free(buddy_name);
 }
 
 static gboolean max_message_difference_cb(gpointer data) {
@@ -326,10 +355,10 @@
 }
 
 //received-im-msg
-static void received_im_msg(GaimAccount *account, char *sender, char *message,
-		GaimConversation *conv, GaimMessageFlags flags) {
+static void
+received_im_msg(GaimAccount *account, char *sender, char *message, GaimConversation *conv, GaimMessageFlags flags) {
 	GaimBuddy *buddy = gaim_find_buddy(account, sender);
-	guint words = word_count(message);
+	//guint words = word_count(message);
 	CapStatistics *stats = get_stats_for(buddy);
 
 	//insert_word_count(sender, buddy_name, words);
@@ -407,7 +436,8 @@
 		CapStatistics *stats = get_stats_for(buddy);
 		// get the probability that this buddy will respond and add to the tooltip
 		if(stats->prediction->probability >= 0.0) {
-			g_string_append_printf(text, "\n<b>%s</b> %0.4f", _("Response Probability:"), stats->prediction->probability);
+			g_string_append_printf(text, "\n<b>%s</b> %3.0f %%", _("Response Probability:"),
+				100 * stats->prediction->probability);
 		} else {
 			g_string_append_printf(text, "\n<b>%s</b> ???", _("Response Probability:"));
 		}
@@ -421,13 +451,13 @@
 	gchar *my_name = g_strdup(my_gaim_name);
 	time_t *last_offline = g_hash_table_lookup(_my_offline_times, my_name);
 
-	gchar *account_id = quote_string(gaim_account_get_username(account));
-	gchar *protocol_id = quote_string(gaim_account_get_protocol_id(account));
-	dbi_result result;
+	const gchar *account_id = gaim_account_get_username(account);
+	const gchar *protocol_id = gaim_account_get_protocol_id(account);
+	char *sql;
 
-	result = dbi_conn_queryf(_conn, "insert into cap_my_usage values(%s, %s, %d, now());", account_id, protocol_id, 1);
-	if(result)
-		dbi_result_free(result);
+	sql = sqlite3_mprintf("insert into cap_my_usage values(%Q, %Q, %d, now());", account_id, protocol_id, 1);
+	sqlite3_exec(_db, sql, NULL, NULL, NULL);
+	sqlite3_free(sql);
 
 	if(last_offline) {
 		if(difftime(*last_offline, time(NULL)) > gaim_prefs_get_int("/plugins/gtk/cap/max_seen_difference") * 60) {
@@ -448,39 +478,18 @@
 	const char *my_gaim_name = gaim_account_get_username(account);
 	gchar *my_name = g_strdup(my_gaim_name);
 	time_t *offline_time = g_malloc(sizeof(time_t));
-	gchar *account_id = quote_string(gaim_account_get_username(account));
-	gchar *protocol_id = quote_string(gaim_account_get_protocol_id(account));
-	dbi_result result;
+	const gchar *account_id = gaim_account_get_username(account);
+	const gchar *protocol_id = gaim_account_get_protocol_id(account);
+	char *sql;
 
-	result = dbi_conn_queryf(_conn, "insert into cap_my_usage values(%s, %s, %d, now());", account_id, protocol_id, 0);
-	if(result)
-		dbi_result_free(result);
+	sql = sqlite3_mprintf("insert into cap_my_usage values(%Q, %Q, %d, now());", account_id, protocol_id, 0);
+	sqlite3_exec(_db, sql, NULL, NULL, NULL);
+	sqlite3_free(sql);
 
 	time(offline_time);
 	g_hash_table_insert(_my_offline_times, my_name, offline_time);
 }
 
-static const gchar * get_error_msg() {
-	if(error_msg)
-		return error_msg->str;
-	else
-		return NULL;
-}
-
-static void set_error_msg(const gchar *msg) {
-	if(!error_msg)
-		error_msg = g_string_new(msg);
-	else
-		g_string_assign(error_msg, msg);
-}
-
-static void append_error_msg(const gchar *msg) {
-	if(!error_msg)
-		set_error_msg(msg);
-	else
-		g_string_append(error_msg, msg);
-}
-
 static void reset_all_last_message_times(gpointer key, gpointer value, gpointer user_data) {
 	CapStatistics *stats = value;
 	stats->last_message = -1;
@@ -493,52 +502,89 @@
 }
 
 static void create_tables() {
+	int rc;
+	rc = sqlite3_exec(_db,
+		"CREATE TABLE IF NOT EXISTS cap_status ("
+		"	buddy varchar(60) not null,"
+		"	account varchar(60) not null,"
+		"	protocol varchar(60) not null,"
+		"	status varchar(60) not null,"
+		"	event_time datetime not null,"
+		"	primary key (buddy, account, protocol, event_time)"
+		");",
+		NULL, NULL, NULL);
+
+	rc = sqlite3_exec(_db,
+		"create table if not exists cap_message ("
+		"	sender varchar(60) not null,"
+		"	receiver varchar(60) not null,"
+		"	account varchar(60) not null,"
+		"	protocol varchar(60) not null,"
+		"	word_count integer not null,"
+		"	event_time datetime not null,"
+		"	primary key (sender, account, protocol, receiver, event_time)"
+		");",
+		NULL, NULL, NULL);
+
+	rc = sqlite3_exec(_db,
+		"create table if not exists cap_msg_count ("
+		"	buddy varchar(60) not null,"
+		"	account varchar(60) not null,"
+		"	protocol varchar(60) not null,"
+		"	minute_val int not null,"
+		"	success_count int not null,"
+		"	failed_count int not null,"
+		"	primary key (buddy, account, protocol, minute_val)"
+		");",
+	NULL, NULL, NULL);
+
+	rc = sqlite3_exec(_db,
+		"create table if not exists cap_status_count ("
+		"	buddy varchar(60) not null,"
+		"	account varchar(60) not null,"
+		"	protocol varchar(60) not null,"
+		"	status varchar(60) not null,"
+		"	success_count int not null,"
+		"	failed_count int not null,"
+		"	primary key (buddy, account, protocol, status)"
+		");",
+	NULL, NULL, NULL);
+
+	rc = sqlite3_exec(_db,
+		"create table if not exists cap_my_usage ("
+		"	account varchar(60) not null,"
+		"	protocol varchar(60) not null,"
+		"	online tinyint not null,"
+		"	event_time datetime not null,"
+		"	primary key(account, protocol, online, event_time)"
+		");",
+	NULL, NULL, NULL);
 }
 
 static gboolean create_database_connection() {
+	GString *path;
 	int rc;
-	int driver_type;
 
-	if(_conn)
+	if(_db)
 		return TRUE;
 
 	//make database connection here
-	_conn = dbi_conn_new(gaim_prefs_get_string("/plugins/gtk/cap/db_driver"));
-	if(!_conn)
+	path = g_string_new(gaim_user_dir());
+	g_string_append(path, "/cap.db");
+	rc = sqlite3_open(path->str, &_db);
+	if(rc != SQLITE_OK)
 		return FALSE;
 	
-	_driver = dbi_conn_get_driver(_conn);
-	gaim_debug_info("cap", "Using driver: %s\n", gaim_prefs_get_string("/plugins/gtk/cap/db_driver"));
-	if(strcmp(gaim_prefs_get_string("/plugins/gtk/cap/db_driver"), "mysql") == 0) {
-		driver_type = MYSQL;
-		dbi_conn_set_option(_conn, "host", gaim_prefs_get_string("/plugins/gtk/cap/mysql/db_host"));
-		dbi_conn_set_option(_conn, "username", gaim_prefs_get_string("/plugins/gtk/cap/mysql/db_user"));
-		dbi_conn_set_option(_conn, "password", gaim_prefs_get_string("/plugins/gtk/cap/mysql/db_password"));
-		dbi_conn_set_option(_conn, "dbname", gaim_prefs_get_string("/plugins/gtk/cap/mysql/db_name"));
-		dbi_conn_set_option(_conn, "encoding", "auto");
-		dbi_conn_set_option_numeric(_conn, "port", gaim_prefs_get_int("/plugins/gtk/cap/mysql/db_port"));
-	}
-	if(dbi_conn_connect(_conn) < 0) {
-		const char *err_msg = "";
-		//rc = dbi_conn_error(_conn, &err_msg);
-		rc = dbi_conn_error(_conn, NULL);
-		gaim_debug_error("cap", "CAP could not create database connection. %d\n", rc);
-		//set_error_msg(_("Could not create database connection. Reason: "));
-		//append_error_msg(err_msg);
-		_conn = NULL;
-		return FALSE;
-	} else {
-		//Add tables here
-		create_tables();
-	}
+	//Add tables here
+	create_tables();
 	gaim_debug_info("cap", "Database connection successfully made.\n");
 	return TRUE;
 }
 static void destroy_database_connection() {
-	if(_conn)
-		dbi_conn_close(_conn);
+	if(_db)
+		sqlite3_close(_db);
 
-	_conn = NULL;
+	_db = NULL;
 }
 
 static guint word_count(const gchar *string) {
@@ -551,53 +597,17 @@
 	return count;
 }
 
-/* If the difference in time between the present time and the time that
- * you last sent a message to a buddy is less than some value then return
- * true, otherwise return false.
- * The difference can either be + or - the max_difference.
- * max_difference is in seconds
- */
-static gboolean last_message_time_in_range(CapStatistics *statistics, gdouble max_difference) {
-	time_t now = time(NULL);
-	gdouble difference = 0.0;
-	//If there is no last_message time then it is considered in range
-	if(statistics->last_message == -1) {
-		return TRUE;
-	}
-	//Compute the difference between now and the last_message
-	difference = difftime(statistics->last_message, now);
-	//Absolute value
-	difference = (difference < 0.0) ? -difference : difference;
-	//If the difference is less than the maximum then we are good and its in range, otherwise not
-	if(difference <= max_difference)
-		return TRUE;
-	else
-		return FALSE;
-}
-
-static gboolean last_seen_time_in_range(CapStatistics *statistics, gdouble max_difference) {
-	time_t now = time(NULL);
-	gdouble difference = 0.0;
-	if(statistics->last_seen == -1)
-		return FALSE;
-	difference = difftime(statistics->last_seen, now);
-	difference = (difference < 0.0) ? -difference : difference;
-	if(difference < max_difference)
-		return TRUE;
-	else
-		return FALSE;
-}
-
 static void insert_status_change(CapStatistics *statistics) {
 	insert_status_change_from_gaim_status(statistics, get_status_for(statistics->buddy));
 }
 
 static void insert_status_change_from_gaim_status(CapStatistics *statistics, GaimStatus *status) {
-	dbi_result result;
-	gchar *status_id;
-	gchar *buddy_name;
-	gchar *protocol_id;
-	gchar *account_id;
+	char *sql;
+	int rc;
+	const gchar *status_id;
+	const gchar *buddy_name;
+	const gchar *protocol_id;
+	const gchar *account_id;
 
 	/* It would seem that some protocols receive periodic updates of the buddies status.
 	 * Check to make sure the last status is not the same as current status to prevent
@@ -605,27 +615,18 @@
 	if(strcmp(statistics->last_status_id, gaim_status_get_id(status)) == 0)
 		return;
 
-	status_id = quote_string(gaim_status_get_id(status));
-	buddy_name = quote_string(statistics->buddy->name);
-	protocol_id = quote_string(gaim_account_get_protocol_id(statistics->buddy->account));
-	account_id = quote_string(gaim_account_get_username(statistics->buddy->account));
+	status_id = gaim_status_get_id(status);
+	buddy_name = statistics->buddy->name;
+	protocol_id = gaim_account_get_protocol_id(statistics->buddy->account);
+	account_id = gaim_account_get_username(statistics->buddy->account);
 
 	statistics->last_status_id = gaim_status_get_id(status);
+
 	gaim_debug_info("cap", "Executing: insert into cap_status (buddy, account, protocol, status, event_time) values(%s, %s, %s, %s, now());\n", buddy_name, account_id, protocol_id, status_id);
 
-	result = dbi_conn_queryf(_conn, "insert into cap_status (buddy, account, protocol, status, event_time) values(%s, %s, %s, %s, now());", buddy_name, account_id, protocol_id, status_id);
-	if(result)
-		dbi_result_free(result);
-	else {
-		const char *err = "";
-		dbi_conn_error(_conn, &err);
-		gaim_debug_error("cap", "Could not insert status change event into database. %s\n", err);
-	}
-
-	free(status_id);
-	free(buddy_name);
-	free(protocol_id);
-	free(account_id);
+	sql = sqlite3_mprintf("insert into cap_status values (%Q, %Q, %Q, %Q, now());", buddy_name, account_id, protocol_id, status_id);
+	rc = sqlite3_exec(_db, sql, NULL, NULL, NULL);
+	sqlite3_free(sql);
 }
 
 static void insert_word_count(const char *sender, const char *receiver, guint count) {
@@ -658,24 +659,8 @@
 	 */
 	_my_offline_times = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
 
-	if(gaim_prefs_exists("/plugins/gtk/cap/libdbi_drivers"))
-		_num_drivers = dbi_initialize(gaim_prefs_get_string("/plugins/gtk/cap/libdbi_drivers"));
-	else
-		_num_drivers = dbi_initialize(NULL);
-
-	if(_num_drivers == -1) {
-		gaim_debug_error("cap", "Error initializing dbi.\n");
-		gaim_prefs_set_bool("/plugins/gtk/cap/configured", FALSE);
-		_dbi_initialized = FALSE;
-	} else {
-		_dbi_initialized = TRUE;
-	}
-
-
-	if(gaim_prefs_get_bool("/plugins/gtk/cap/configured") && gaim_prefs_get_bool("/plugins/gtk/cap/connected")) {
-		if(create_database_connection()) {
-			add_plugin_functionality(plugin);
-		}
+	if(create_database_connection()) {
+		add_plugin_functionality(plugin);
 	}
 	return TRUE;
 }
@@ -788,71 +773,18 @@
 	}
 	 
 	 //close database connection
-	 dbi_conn_close(_conn);
-	 _conn = NULL;
-	 dbi_shutdown();
+	 destroy_database_connection();
 
 	return TRUE;
 }
 
-static GtkWidget * get_config_frame(GaimPlugin *plugin) {
-	CapPrefsUI *ui = create_cap_prefs_ui();
-
-	/* Since we are editing the database setup we will disable the plugin.
-	 * This will prevent database updates from occuring while there is potentially
-	 * no connection to the database.
-	 */
-	remove_plugin_functionality(_plugin_pointer);
-
-	return ui->ret;
-}
-
-static void cap_prefs_ui_destroy_cb(GtkObject *object, gpointer user_data) {
-	CapPrefsUI *ui = user_data;
-	if(_conn) {
-		add_plugin_functionality(_plugin_pointer);
-	}
-	g_free(ui);
-}
-
 static CapPrefsUI * create_cap_prefs_ui() {
 	CapPrefsUI *ui = g_malloc(sizeof(CapPrefsUI));
 
 	ui->ret = gtk_vbox_new(FALSE, 18);
 	gtk_container_set_border_width(GTK_CONTAINER(ui->ret), 10);
-	ui->db_vbox = gaim_gtk_make_frame(ui->ret, _("Database Configuration"));
 	ui->cap_vbox = gaim_gtk_make_frame(ui->ret, _("Statistics Configuration"));
 
-	/* dbd path input folder selector button */
-	ui->dbd_label = gtk_label_new(_("libdbi driver path:"));
-	gtk_misc_set_alignment(GTK_MISC(ui->dbd_label), 0, 0.5);
-	ui->dbd_input = gtk_file_chooser_button_new(_("libdbi Drivers Path"), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
-	ui->dbd_button = gtk_button_new_with_label(_("Verify"));
-	ui->dbd_hbox = gtk_hbox_new(FALSE, 18);
-	gtk_box_pack_start(GTK_BOX(ui->dbd_hbox), ui->dbd_label, FALSE, FALSE, 0);
-	gtk_box_pack_start(GTK_BOX(ui->dbd_hbox), ui->dbd_input, FALSE, FALSE, 0);
-	gtk_box_pack_start(GTK_BOX(ui->dbd_hbox), ui->dbd_button, FALSE, FALSE, 0);
-
-	/* Setup the driver selection widget */
-	ui->driver_choice = gtk_combo_box_new_text();
-	
-	ui->driver_vbox = gtk_vbox_new(FALSE, 18);
-	ui->driver_label = gtk_label_new(_("Driver:"));
-	gtk_misc_set_alignment(GTK_MISC(ui->driver_label), 0, 0.5);
-	ui->driver_select_hbox = gtk_hbox_new(FALSE, 18);
-	ui->driver_connect_button = gtk_toggle_button_new_with_label(_("Connected"));
-
-	gtk_box_pack_start(GTK_BOX(ui->driver_select_hbox), ui->driver_label, FALSE, FALSE, 0);
-	gtk_box_pack_start(GTK_BOX(ui->driver_select_hbox), ui->driver_choice, FALSE, FALSE, 0);
-	gtk_box_pack_start(GTK_BOX(ui->driver_select_hbox), ui->driver_connect_button, FALSE, FALSE, 0);
-
-	ui->driver_config = gtk_expander_new_with_mnemonic(_("Configure"));
-	ui->driver_config_hbox = gtk_hbox_new(FALSE, 18);
-	gtk_box_pack_start(GTK_BOX(ui->driver_config_hbox), ui->driver_config, FALSE, FALSE, 0);
-
-	gtk_box_pack_start(GTK_BOX(ui->driver_vbox), ui->driver_select_hbox, FALSE, FALSE, 0);
-	gtk_box_pack_start(GTK_BOX(ui->driver_vbox), ui->driver_config_hbox, FALSE, FALSE, 0);
-
 	/* msg_difference spinner */
 	ui->msg_difference_label = gtk_label_new(_("Maximum response timeout:"));
 	gtk_misc_set_alignment(GTK_MISC(ui->msg_difference_label), 0, 0.5);
@@ -914,16 +846,11 @@
 
 
 	/* Config window - lay it out */
-	gtk_box_pack_start(GTK_BOX(ui->db_vbox), ui->dbd_hbox, FALSE, FALSE, 0);
-	gtk_box_pack_start(GTK_BOX(ui->db_vbox), ui->driver_vbox, FALSE, FALSE, 0);
 	gtk_box_pack_start(GTK_BOX(ui->cap_vbox), ui->table_layout, FALSE, FALSE, 0);
 
 	/* Set the input areas to contain the configuration values from
 	 * gaim prefs.
 	 */
-	if(gaim_prefs_exists("/plugins/gtk/cap/libdbi_drivers")) {
-		gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(ui->dbd_input), gaim_prefs_get_string("/plugins/gtk/cap/libdbi_drivers"));
-	}
 	if(gaim_prefs_exists("/plugins/gtk/cap/max_msg_difference")) {
 		int max_msg_diff = gaim_prefs_get_int("/plugins/gtk/cap/max_msg_difference");
 		gtk_spin_button_set_value(GTK_SPIN_BUTTON(ui->msg_difference_input),  max_msg_diff);
@@ -941,15 +868,6 @@
 	g_signal_connect(G_OBJECT(ui->ret), "destroy",
 		G_CALLBACK(cap_prefs_ui_destroy_cb), ui);
 
-	g_signal_connect(G_OBJECT(ui->driver_choice), "changed",
-		G_CALLBACK(driver_choice_changed_cb), ui);	
-	
-	g_signal_connect(G_OBJECT(ui->driver_config), "notify::expanded",
-		G_CALLBACK(driver_config_expanded_cb), ui);
-
-	g_signal_connect(G_OBJECT(ui->driver_connect_button), "toggled",
-		G_CALLBACK(connect_toggled_cb), ui);
-
 	g_signal_connect(G_OBJECT(ui->msg_difference_input), "value-changed",
 		G_CALLBACK(numeric_spinner_prefs_cb), "/plugins/gtk/cap/max_msg_difference");
 	
@@ -959,244 +877,21 @@
 	g_signal_connect(G_OBJECT(ui->threshold_input), "value-changed",
 		G_CALLBACK(numeric_spinner_prefs_cb), "/plugins/gtk/cap/threshold");
 	
-	g_signal_connect(G_OBJECT(ui->dbd_button), "clicked",
-		G_CALLBACK(driver_location_verify_cb), ui);
-	
-	/* libdbi was not successfully initialized so disable the driver selection.
-	 * Also disable the configuration for the database.
-	 */
-	if(!_dbi_initialized || _num_drivers <= 0) {
-		/* Since DBI is not available disable database configuration */
-		gtk_widget_set_sensitive(ui->driver_choice, FALSE);
-		gtk_widget_set_sensitive(ui->driver_config, FALSE);
-		gtk_widget_set_sensitive(ui->driver_connect_button, FALSE);
-	} else {
-		set_driver_choice_options(GTK_COMBO_BOX(ui->driver_choice));
-	}
-	
-	if(_conn) {
-		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ui->driver_connect_button), TRUE);
-		gtk_widget_set_sensitive(ui->driver_choice, FALSE);
-		gtk_widget_set_sensitive(ui->driver_config, FALSE);
-	} else {
-		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ui->driver_connect_button), FALSE);
-	}
-
 	return ui;
 }
 
-static void driver_choice_changed_cb(GtkComboBox *widget, gpointer user_data) {
+static void cap_prefs_ui_destroy_cb(GtkObject *object, gpointer user_data) {
 	CapPrefsUI *ui = user_data;
-	if(strcmp(gtk_combo_box_get_active_text(GTK_COMBO_BOX(ui->driver_choice)), "mysql") == 0) {
-		gtk_widget_set_sensitive(ui->driver_config, TRUE);
-		gtk_widget_set_sensitive(ui->driver_connect_button, TRUE);
-	} else {
-		gtk_widget_set_sensitive(ui->driver_config, FALSE);
-		gtk_widget_set_sensitive(ui->driver_connect_button, FALSE);
-	}
-}
-
-static void driver_config_expanded_cb(GObject *object, GParamSpec *param_spec, gpointer user_data) {
-	CapPrefsUI *ui = user_data;
-	GtkExpander *expander;
-	gchar *driver = gtk_combo_box_get_active_text(GTK_COMBO_BOX(ui->driver_choice));
-	expander = GTK_EXPANDER(object);
-	if(gtk_expander_get_expanded(expander)) {
-		if(strcmp(driver, "mysql") == 0) {
-			gtk_container_add(GTK_CONTAINER(expander), get_mysql_config());
-		}
-	} else {
-		gtk_container_remove(GTK_CONTAINER(expander), gtk_bin_get_child(GTK_BIN(expander)));
+	if(_db) {
+		add_plugin_functionality(_plugin_pointer);
 	}
-}
-
-static void connect_toggled_cb(GtkToggleButton *togglebutton, gpointer user_data) {
-	CapPrefsUI *ui = user_data;
-	if(gtk_toggle_button_get_active(togglebutton)) {
-		//connect
-		if(create_database_connection()) {
-			gtk_widget_set_sensitive(GTK_WIDGET(ui->driver_choice), FALSE);
-			gtk_widget_set_sensitive(GTK_WIDGET(ui->driver_config), FALSE);
-			gtk_widget_set_sensitive(GTK_WIDGET(ui->dbd_input), FALSE);
-			gtk_widget_set_sensitive(GTK_WIDGET(ui->dbd_button), FALSE);
-			gaim_prefs_set_bool("/plugins/gtk/cap/connected", TRUE);
-		} else {
-			gtk_toggle_button_set_active(togglebutton, FALSE);
-		}
-	} else {
-		//disconnect
-		destroy_database_connection();
-		gtk_widget_set_sensitive(GTK_WIDGET(ui->driver_choice), TRUE);
-		gtk_widget_set_sensitive(GTK_WIDGET(ui->driver_config), TRUE);
-		gtk_widget_set_sensitive(GTK_WIDGET(ui->dbd_input), TRUE);
-		gtk_widget_set_sensitive(GTK_WIDGET(ui->dbd_button), TRUE);
-		gaim_prefs_set_bool("/plugins/gtk/cap/connected", FALSE);
-	}
+	g_free(ui);
 }
 
 static void numeric_spinner_prefs_cb(GtkSpinButton *spinbutton, gpointer user_data) {
 	gaim_prefs_set_int(user_data, gtk_spin_button_get_value_as_int(spinbutton));
 }
 
-static void driver_location_verify_cb(GtkButton *button, gpointer user_data) {
-	CapPrefsUI *ui = user_data;
-	gchar *path = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(ui->dbd_input));
-	
-	if(_dbi_initialized)
-		dbi_shutdown();
-
-	gaim_prefs_set_string("/plugins/gtk/cap/libdbi_drivers", path);
-	_num_drivers = dbi_initialize(path);
-	if(_num_drivers == -1) {
-		_dbi_initialized = FALSE;
-	} else {
-		_dbi_initialized = TRUE;
-	}
-	if(_num_drivers > 0) {
-		gtk_widget_set_sensitive(GTK_WIDGET(ui->driver_choice), TRUE);
-		gtk_widget_set_sensitive(GTK_WIDGET(ui->driver_config), TRUE);
-		gtk_widget_set_sensitive(GTK_WIDGET(ui->driver_connect_button), TRUE);
-		set_driver_choice_options(GTK_COMBO_BOX(ui->driver_choice));
-	} else {
-		gtk_widget_set_sensitive(GTK_WIDGET(ui->driver_choice), FALSE);
-		gtk_widget_set_sensitive(GTK_WIDGET(ui->driver_config), FALSE);
-		gtk_expander_set_expanded(GTK_EXPANDER(ui->driver_config), FALSE);
-		gtk_widget_set_sensitive(GTK_WIDGET(ui->driver_connect_button), FALSE);
-	}
-}
-
-static gboolean text_entry_prefs_cb(GtkWidget *widget, GdkEventFocus *event, gpointer user_data) {
-	gaim_prefs_set_string(user_data, gtk_entry_get_text(GTK_ENTRY(widget)));
-	return FALSE;
-}
-
-void set_driver_choice_options(GtkComboBox *chooser) {
-	dbi_driver driver = NULL;
-	GtkListStore *list_store;
-	gint index = 0;
-	gint selected = 0;
-
-	list_store = GTK_LIST_STORE(gtk_combo_box_get_model(chooser));
-	gtk_list_store_clear(list_store);
-
-	if(!_dbi_initialized)
-		return;
-	
-	while((driver = dbi_driver_list(driver)) != NULL) {
-		gtk_combo_box_append_text(chooser, dbi_driver_get_name(driver));
-		if(strcmp(dbi_driver_get_name(driver), gaim_prefs_get_string("/plugins/gtk/cap/db_driver")) == 0) {
-			selected = index;
-		}
-		++index;
-	}
-	gtk_combo_box_set_active(chooser, selected);
-}
-
-static GtkWidget * get_mysql_config() {
-	GtkWidget *config_area = gtk_table_new(5, 2, FALSE);
-	GtkWidget *username_label = gtk_label_new(_("Username:"));
-	GtkWidget *username_input = gtk_entry_new();
-	GtkWidget *password_label = gtk_label_new(_("Password:"));
-	GtkWidget *password_input = gtk_entry_new();
-	GtkWidget *host_label = gtk_label_new(_("Host:"));
-	GtkWidget *host_input = gtk_entry_new();
-	GtkWidget *db_label = gtk_label_new(_("Database:"));
-	GtkWidget *db_input = gtk_entry_new();
-	GtkWidget *port_label = gtk_label_new(_("Port:"));
-	GtkWidget *port_input = gtk_spin_button_new_with_range(0, 10000, 1);
-
-	gtk_entry_set_visibility(GTK_ENTRY(password_input), FALSE);
-
-	gtk_misc_set_alignment(GTK_MISC(username_label), 0, 0.5);
-	gtk_misc_set_padding(GTK_MISC(username_label), 10, 0);
-
-	gtk_misc_set_alignment(GTK_MISC(password_label), 0, 0.5);
-	gtk_misc_set_padding(GTK_MISC(password_label), 10, 0);
-
-	gtk_misc_set_alignment(GTK_MISC(host_label), 0, 0.5);
-	gtk_misc_set_padding(GTK_MISC(host_label), 10, 0);
-
-	gtk_misc_set_alignment(GTK_MISC(db_label), 0, 0.5);
-	gtk_misc_set_padding(GTK_MISC(db_label), 10, 0);
-
-	gtk_misc_set_alignment(GTK_MISC(port_label), 0, 0.5);
-	gtk_misc_set_padding(GTK_MISC(port_label), 10, 0);
-
-	gtk_table_attach(GTK_TABLE(config_area), host_label, 0, 1, 0, 1,
-		(GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
-		(GtkAttachOptions) (0), 0, 0);
-	gtk_table_attach(GTK_TABLE(config_area), host_input, 1, 2, 0, 1,
-		(GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
-		(GtkAttachOptions) (0), 0, 0);
-	gtk_table_attach(GTK_TABLE(config_area), port_label, 0, 1, 1, 2,
-		(GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
-		(GtkAttachOptions) (0), 0, 0);
-	gtk_table_attach(GTK_TABLE(config_area), port_input, 1, 2, 1, 2,
-		(GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
-		(GtkAttachOptions) (0), 0, 0);
-	gtk_table_attach(GTK_TABLE(config_area), db_label, 0, 1, 2, 3,
-		(GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
-		(GtkAttachOptions) (0), 0, 0);
-	gtk_table_attach(GTK_TABLE(config_area), db_input, 1, 2, 2, 3,
-		(GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
-		(GtkAttachOptions) (0), 0, 0);
-	gtk_table_attach(GTK_TABLE(config_area), username_label, 0, 1, 3, 4,
-		(GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
-		(GtkAttachOptions) (0), 0, 0);
-	gtk_table_attach(GTK_TABLE(config_area), username_input, 1, 2, 3, 4,
-		(GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
-		(GtkAttachOptions) (0), 0, 0);
-	gtk_table_attach(GTK_TABLE(config_area), password_label, 0, 1, 4, 5,
-		(GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
-		(GtkAttachOptions) (0), 0, 0);
-	gtk_table_attach(GTK_TABLE(config_area), password_input, 1, 2, 4, 5,
-		(GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
-		(GtkAttachOptions) (0), 0, 0);
-
-	//Initialize with data
-	if(gaim_prefs_exists("/plugins/gtk/cap/mysql/db_host")) {
-		gtk_entry_set_text(GTK_ENTRY(host_input), gaim_prefs_get_string("/plugins/gtk/cap/mysql/db_host"));
-	} else {
-		gtk_entry_set_text(GTK_ENTRY(host_input), "localhost");
-	}
-	if(gaim_prefs_exists("/plugins/gtk/cap/mysql/db_port")) {
-		gtk_spin_button_set_value(GTK_SPIN_BUTTON(port_input), gaim_prefs_get_int("/plugins/gtk/cap/mysql/db_port"));
-	} else {
-		gtk_spin_button_set_value(GTK_SPIN_BUTTON(port_input), 3306);
-	}
-	if(gaim_prefs_exists("/plugins/gtk/cap/mysql/db_user")) {
-		gtk_entry_set_text(GTK_ENTRY(username_input), gaim_prefs_get_string("/plugins/gtk/cap/mysql/db_user"));
-	} else {
-		gtk_entry_set_text(GTK_ENTRY(username_input), "root");
-	}
-	if(gaim_prefs_exists("/plugins/gtk/cap/mysql/db_password")) {
-		gtk_entry_set_text(GTK_ENTRY(password_input), gaim_prefs_get_string("/plugins/gtk/cap/mysql/db_password"));
-	} else {
-		gtk_entry_set_text(GTK_ENTRY(password_input), "");
-	}
-	if(gaim_prefs_exists("/plugins/gtk/cap/mysql/db_name")) {
-		gtk_entry_set_text(GTK_ENTRY(db_input), gaim_prefs_get_string("/plugins/gtk/cap/mysql/db_name"));
-	} else {
-		gtk_entry_set_text(GTK_ENTRY(db_input), "cap");
-	}
-
-	//Add callbacks
-	g_signal_connect(G_OBJECT(host_input), "focus-out-event",
-		G_CALLBACK(text_entry_prefs_cb), "/plugins/gtk/cap/mysql/db_host");
-	g_signal_connect(G_OBJECT(port_input), "value-changed",
-		G_CALLBACK(numeric_spinner_prefs_cb), "/plugins/gtk/cap/mysql/db_port");
-	g_signal_connect(G_OBJECT(username_input), "focus-out-event",
-		G_CALLBACK(text_entry_prefs_cb), "/plugins/gtk/cap/mysql/db_user");
-	g_signal_connect(G_OBJECT(password_input), "focus-out-event",
-		G_CALLBACK(text_entry_prefs_cb), "/plugins/gtk/cap/mysql/db_password");
-	g_signal_connect(G_OBJECT(db_input), "focus-out-event",
-		G_CALLBACK(text_entry_prefs_cb), "/plugins/gtk/cap/mysql/db_name");
-
-	gtk_widget_show_all(config_area);
-
-	return config_area;
-}
-
 static GaimGtkPluginUiInfo ui_info = {
 	get_config_frame,
 	0 /* page_num (reserved) */
@@ -1228,19 +923,22 @@
 	NULL
 };
 
+static GtkWidget * get_config_frame(GaimPlugin *plugin) {
+	CapPrefsUI *ui = create_cap_prefs_ui();
+
+	/*
+	 * Prevent database stuff from occuring since we are editing values
+	 */
+	remove_plugin_functionality(_plugin_pointer);
+
+	return ui->ret;
+}
+
 static void init_plugin(GaimPlugin *plugin) {
 	gaim_prefs_add_none("/plugins/gtk/cap");
 	gaim_prefs_add_int("/plugins/gtk/cap/max_seen_difference", 1);
 	gaim_prefs_add_int("/plugins/gtk/cap/max_msg_difference", 10);
 	gaim_prefs_add_int("/plugins/gtk/cap/threshold", 5);
-	gaim_prefs_add_bool("/plugins/gtk/cap/configured", FALSE);
-	gaim_prefs_add_string("/plugins/gtk/cap/db_driver", "mysql");
-	gaim_prefs_add_none("/plugins/gtk/cap/mysql");
-	gaim_prefs_add_string("/plugins/gtk/cap/mysql/db_host", "localhost");
-	gaim_prefs_add_int("/plugins/gtk/cap/mysql/db_port", 3306);
-	gaim_prefs_add_string("/plugins/gtk/cap/mysql/db_user", "root");
-	gaim_prefs_add_string("/plugins/gtk/cap/mysql/db_password", "");
-	gaim_prefs_add_string("/plugins/gtk/cap/mysql/db_name", "cap");
 }
 
 GAIM_INIT_PLUGIN(cap, init_plugin, info);
--- a/gtk/plugins/cap/cap.h	Sun Sep 10 22:33:28 2006 +0000
+++ b/gtk/plugins/cap/cap.h	Mon Sep 11 00:28:35 2006 +0000
@@ -39,100 +39,30 @@
 
 #include "util.h"
 
-#include <dbi/dbi.h>
 #include <glib.h>
 #include <time.h>
+#include <sqlite3.h>
 #include "cap_statistics.h"
 
 #define CAP_PLUGIN_ID "gtk-g-off_-cap"
 
 /* Variables used throughout lifetime of the plugin */
 GaimPlugin *_plugin_pointer;
-dbi_conn _conn = NULL; /**< The database connection */
-dbi_driver _driver = NULL; /**< The database driver */
+sqlite3 *_db; /**< The database */
+
 GHashTable *_buddy_stats = NULL;
 GHashTable *_my_offline_times = NULL;
-GString *error_msg = NULL;
 gboolean _signals_connected;
-gboolean _dbi_initialized;
-int _num_drivers;
-
-enum driver_types {MYSQL};
-
-/* Function definitions */
-static char * quote_string(const char *str);
-static gboolean plugin_load(GaimPlugin *plugin);
-static void add_plugin_functionality(GaimPlugin *plugin);
-static void cancel_conversation_timeouts(gpointer key, gpointer value, gpointer user_data);
-static void remove_plugin_functionality(GaimPlugin *plugin);
-static gboolean plugin_unload(GaimPlugin *plugin);
-static void init_plugin(GaimPlugin *plugin);
-static void generate_prediction(CapStatistics *statistics);
-static double generate_prediction_for(GaimBuddy *buddy);
-static CapStatistics * get_stats_for(GaimBuddy *buddy);
-static void destroy_stats(gpointer data);
-static gboolean remove_stats_for(GaimBuddy *buddy);
-static dbi_result insert_cap_msg_count_success(const char *buddy_name, const char *account, const char *protocol, int minute);
-static dbi_result insert_cap_status_count_success(const char *buddy_name, const char *account, const char *protocol, const char *status_id);
-static dbi_result insert_cap_msg_count_failed(const char *buddy_name, const char *account, const char *protocol, int minute);
-static dbi_result insert_cap_status_count_failed(const char *buddy_name, const char *account, const char *protocol, const char *status_id);
-static void insert_cap_success(CapStatistics *stats);
-static void insert_cap_failure(CapStatistics *stats);
-static gboolean max_message_difference_cb(gpointer data);
-
-/* Various CAP helper functions */
-static const gchar * get_error_msg(void);
-static void set_error_msg(const gchar *msg);
-static void reset_all_last_message_times(gpointer key, gpointer value, gpointer user_data);
-static GaimStatus * get_status_for(GaimBuddy *buddy);
-static void create_tables(void);
-static gboolean create_database_connection(void);
-static void destroy_database_connection(void);
-static guint word_count(const gchar *string);
-static gboolean last_message_time_in_range(CapStatistics *statistics, gdouble max_difference);
-static gboolean last_seen_time_in_range(CapStatistics *statistics, gdouble max_difference);
-static void insert_status_change(CapStatistics *statistics);
-static void insert_status_change_from_gaim_status(CapStatistics *statistics, GaimStatus *status);
-static void insert_word_count(const char *sender, const char *receiver, guint count);
-
-/* Gaim Signal Handlers */
-static void sent_im_msg(GaimAccount *account, const char *receiver, const char *message);
-static void received_im_msg(GaimAccount *account, char *sender, char *message,
-		GaimConversation *conv, GaimMessageFlags flags);
-static void buddy_status_changed(GaimBuddy *buddy, GaimStatus *old_status, GaimStatus *status);
-static void buddy_signed_on(GaimBuddy *buddy);
-static void buddy_signed_off(GaimBuddy *buddy);
-static void buddy_idle(GaimBuddy *buddy, gboolean old_idle, gboolean idle);
-static void blist_node_extended_menu(GaimBlistNode *node, GList **menu);
-static void drawing_tooltip(GaimBlistNode *node, GString *text, gboolean full);
-static void signed_on(GaimConnection *gc);
-static void signed_off(GaimConnection *gc);
-
-/* Call backs */
-void display_statistics_action_cb(GaimBlistNode *node, gpointer data);
+gboolean _sqlite_initialized;
 
 /* Prefs UI */
 typedef struct _CapPrefsUI CapPrefsUI;
 
-struct _CapPrefsUI {
+struct _CapPrefsUI { 
 	GtkWidget *ret;
-	GtkWidget *db_vbox;
 	GtkWidget *cap_vbox;
 	GtkWidget *table_layout;
 
-	GtkWidget *driver_vbox;
-	GtkWidget *driver_select_hbox;
-	GtkWidget *driver_choice;
-	GtkWidget *driver_label;
-	GtkWidget *driver_config_hbox;
-	GtkWidget *driver_config;
-	GtkWidget *driver_connect_button;
-
-	GtkWidget *dbd_label;
-	GtkWidget *dbd_input;
-	GtkWidget *dbd_hbox;
-	GtkWidget *dbd_button;
-
 	GtkWidget *threshold_label;
 	GtkWidget *threshold_input;
 	GtkWidget *threshold_minutes_label;
@@ -146,18 +76,56 @@
 	GtkWidget *last_seen_minutes_label;
 };
 
-static GtkWidget * get_config_frame(GaimPlugin *plugin);
+static void generate_prediction(CapStatistics *statistics);
+static double generate_prediction_for(GaimBuddy *buddy);
+static CapStatistics * get_stats_for(GaimBuddy *buddy);
+static void destroy_stats(gpointer data);
+static void insert_cap_msg_count_success(const char *buddy_name, const char *account, const char *protocol, int minute);
+static void insert_cap_status_count_success(const char *buddy_name, const char *account, const char *protocol, const char *status_id);
+static void insert_cap_msg_count_failed(const char *buddy_name, const char *account, const char *protocol, int minute);
+static void insert_cap_status_count_failed(const char *buddy_name, const char *account, const char *protocol, const char *status_id);
+static void insert_cap_success(CapStatistics *stats);
+static void insert_cap_failure(CapStatistics *stats);
+static gboolean max_message_difference_cb(gpointer data);
+/* Gaim Signal Handlers */
+//sent-im-msg
+static void sent_im_msg(GaimAccount *account, const char *receiver, const char *message);
+//received-im-msg
+static void received_im_msg(GaimAccount *account, char *sender, char *message, GaimConversation *conv, GaimMessageFlags flags);
+//buddy-status-changed
+static void buddy_status_changed(GaimBuddy *buddy, GaimStatus *old_status, GaimStatus *status);
+//buddy-signed-on
+static void buddy_signed_on(GaimBuddy *buddy);
+//buddy-signed-off
+static void buddy_signed_off(GaimBuddy *buddy);
+static void buddy_idle(GaimBuddy *buddy, gboolean old_idle, gboolean idle);
+static void blist_node_extended_menu(GaimBlistNode *node, GList **menu);
+//drawing-tooltip
+static void drawing_tooltip(GaimBlistNode *node, GString *text, gboolean full);
+//signed-on
+static void signed_on(GaimConnection *gc);
+//signed-off
+static void signed_off(GaimConnection *gc);
+static void reset_all_last_message_times(gpointer key, gpointer value, gpointer user_data);
+static GaimStatus * get_status_for(GaimBuddy *buddy);
+static void create_tables();
+static gboolean create_database_connection();
+static void destroy_database_connection();
+static guint word_count(const gchar *string);
+static void insert_status_change(CapStatistics *statistics);
+static void insert_status_change_from_gaim_status(CapStatistics *statistics, GaimStatus *status);
+static void insert_word_count(const char *sender, const char *receiver, guint count);
+void display_statistics_action_cb(GaimBlistNode *node, gpointer data);
+static gboolean plugin_load(GaimPlugin *plugin);
+static void add_plugin_functionality(GaimPlugin *plugin);
+static void cancel_conversation_timeouts(gpointer key, gpointer value, gpointer user_data);
+static void remove_plugin_functionality(GaimPlugin *plugin);
+static void write_stats_on_unload(gpointer key, gpointer value, gpointer user_data);
+static gboolean plugin_unload(GaimPlugin *plugin);
+static CapPrefsUI * create_cap_prefs_ui();
 static void cap_prefs_ui_destroy_cb(GtkObject *object, gpointer user_data);
-static CapPrefsUI * create_cap_prefs_ui(void);
-
-static void driver_choice_changed_cb(GtkComboBox *widget, gpointer user_data);
-static void driver_config_expanded_cb(GObject *object, GParamSpec *param_spec, gpointer user_data);
-static void connect_toggled_cb(GtkToggleButton *togglebutton, gpointer user_data);
 static void numeric_spinner_prefs_cb(GtkSpinButton *spinbutton, gpointer user_data);
-static void driver_location_verify_cb(GtkButton *button, gpointer user_data);
-static gboolean text_entry_prefs_cb(GtkWidget *widget, GdkEventFocus *event, gpointer user_data);
-
-static void set_driver_choice_options(GtkComboBox *chooser); 
-static GtkWidget * get_mysql_config(void);
+static GtkWidget * get_config_frame(GaimPlugin *plugin);
+static void init_plugin(GaimPlugin *plugin);
 
 #endif