jabber_autobuddy.c [plain text]
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sqlite3.h>
#include <syslog.h>
#define MAX_USERNAME_LEN 256
#define MAX_HOSTNAME_LEN 256
#define MAX_JID_LEN 512
#define MAX_PASS_LEN 256
#define MAX_LOG_LINE 1024
short int g_debug = 0;
typedef struct sqlite3 sqlite3;
static const char *_log_level[] =
{
"emergency",
"alert",
"critical",
"error",
"warning",
"notice",
"info",
"debug"
};
void _log(int level, const char *msgfmt, ...)
{
va_list ap;
char message[MAX_LOG_LINE];
time_t t;
int sz;
char *pos;
va_start(ap, msgfmt);
vsyslog(level, msgfmt, ap);
va_end(ap);
if ((! g_debug) && (level > LOG_WARNING)) {
return;
}
t = time(NULL);
pos = (char *)ctime(&t);
sz = strlen(pos);
pos[sz-1]=' ';
snprintf(message, MAX_LOG_LINE, "%s[%s] ", pos, _log_level[level]);
for (pos = message; *pos != '\0'; pos++);
sz = pos - message;
va_start(ap, msgfmt);
vsnprintf(pos, MAX_LOG_LINE - sz, msgfmt, ap);
va_end(ap);
fprintf(stderr, "%s\n", message);
fflush(stderr);
return;
}
void usage() {
fprintf(stderr, "Usage: jabber_autobuddy [options] <command> [command args]\n");
fprintf(stderr, "Options:\n");
fprintf(stderr, " -D : Debug mode; verbose output to standard error.\n");
fprintf(stderr, " -v, -h, -?: Display this usage information.\n\n");
fprintf(stderr, "Commands:\n");
fprintf(stderr, " -i JID: Initialize user's data store in SQLite database.\n");
fprintf(stderr, " This is a prerequisite for -a and -d.\n");
fprintf(stderr, " -d JID: Delete user's data store in SQLite database.\n");
fprintf(stderr, " -a JID: Add specified user to the buddy list of all other users.\n");
fprintf(stderr, " -m : Make all existing users buddies\n");
fprintf(stderr, " -r JID: Delete specified user from all buddy lists.\n\n");
fprintf(stderr, "Notes:\n");
fprintf(stderr, " - JID is of the format <username>@<hostname>. The username should be a valid\n");
fprintf(stderr, " Open Directory user's short name. The hostname should be a domain (or realm) that\n");
fprintf(stderr, " the local jabberd service is configured to host.\n");
fprintf(stderr, " - You may specify one (and only one) command per execution.\n");
fprintf(stderr, "\n\n");
exit(0);
}
int init_user(char *input_jid, sqlite3 *db)
{
char query[MAX_JID_LEN+128];
time_t t;
int ret;
sqlite3_stmt *stmt;
snprintf(query, sizeof(query)-1, "select \"collection-owner\" from active where \"collection-owner\" = \"%s\"", input_jid);
ret = sqlite3_prepare_v2(db, (const char *)query, strlen(query), &stmt, NULL);
if (ret != SQLITE_OK) {
_log(LOG_ERR, "Error: (sqlite3_prepare_v2): %s", sqlite3_errmsg(db));
return 1;
}
ret = sqlite3_step(stmt);
switch(ret) {
case SQLITE_ROW:
_log(LOG_ERR, "Error: %s already exists in the active table. Skipping init.", input_jid);
return 1;
case SQLITE_DONE:
break;
default:
_log(LOG_ERR, "Error: Unknown status of query (sqlite3_step): %s", sqlite3_errmsg(db));
return 1;
}
sqlite3_finalize(stmt);
t = time(NULL);
snprintf(query, sizeof(query)-1, "insert into active (\"collection-owner\", \"time\") values (\"%s\", \"%d\")", input_jid, t);
ret = sqlite3_prepare_v2(db, (const char *)query, strlen(query), &stmt, NULL);
if (ret != SQLITE_OK) {
_log(LOG_ERR, "Error: (sqlite3_prepare_v2): %s", sqlite3_errmsg(db));
return 1;
}
ret = sqlite3_step(stmt);
switch(ret) {
case SQLITE_DONE:
case SQLITE_OK:
break;
default:
_log(LOG_ERR, "Error: Unknown status of query (sqlite3_step): %s", sqlite3_errmsg(db));
return 1;
}
sqlite3_finalize(stmt);
snprintf(query, sizeof(query)-1, "insert into vcard (\"collection-owner\", \"fn\", \"nickname\", \"url\", \"tel\", \"email\", \"title\", \"role\", \"bday\", \"desc\", \"n-given\", \"n-family\", \"adr-street\", \"adr-extadd\", \"adr-locality\", \"adr-region\", \"adr-pcode\", \"adr-country\", \"org-orgname\", \"org-orgunit\", \"photo-type\", \"photo-binval\") values (\"%s\", NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL)", input_jid);
ret = sqlite3_prepare_v2(db, (const char *)query, strlen(query), &stmt, NULL);
if (ret != SQLITE_OK) {
_log(LOG_ERR, "Error: (sqlite3_prepare_v2): %s", sqlite3_errmsg(db));
return 1;
}
ret = sqlite3_step(stmt);
switch(ret) {
case SQLITE_DONE:
case SQLITE_OK:
break;
default:
_log(LOG_ERR, "Error: Unknown status of query (sqlite3_step): %s", sqlite3_errmsg(db));
return 1;
}
sqlite3_finalize(stmt);
return 0;
}
int delete_user(char *input_jid, sqlite3 *db)
{
int i;
char query[MAX_JID_LEN+128];
time_t t;
int ret;
sqlite3_stmt *stmt;
snprintf(query, sizeof(query)-1, "delete from active where \"collection-owner\" = \"%s\"", input_jid);
ret = sqlite3_prepare_v2(db, (const char *)query, strlen(query), &stmt, NULL);
if (ret != SQLITE_OK) {
_log(LOG_ERR, "Error: (sqlite3_prepare_v2): %s", sqlite3_errmsg(db));
return 1;
}
ret = sqlite3_step(stmt);
switch(ret) {
case SQLITE_DONE:
case SQLITE_OK:
break;
default:
_log(LOG_ERR, "Error: Unknown status of query (sqlite3_step): %s", sqlite3_errmsg(db));
return 1;
}
sqlite3_finalize(stmt);
snprintf(query, sizeof(query)-1, "delete from vcard where \"collection-owner\" = \"%s\"", input_jid);
ret = sqlite3_prepare_v2(db, (const char *)query, strlen(query), &stmt, NULL);
if (ret != SQLITE_OK) {
_log(LOG_ERR, "Error: (sqlite3_prepare_v2): %s", sqlite3_errmsg(db));
return 1;
}
ret = sqlite3_step(stmt);
switch(ret) {
case SQLITE_DONE:
case SQLITE_OK:
break;
default:
_log(LOG_ERR, "Error: Unknown status of query (sqlite3_step): %s", sqlite3_errmsg(db));
return 1;
}
sqlite3_finalize(stmt);
snprintf(query, sizeof(query)-1, "delete from \"disco-items\" where \"collection-owner\" = \"%s\"", input_jid);
ret = sqlite3_prepare_v2(db, (const char *)query, strlen(query), &stmt, NULL);
if (ret != SQLITE_OK) {
_log(LOG_ERR, "Error: (sqlite3_prepare_v2): %s", sqlite3_errmsg(db));
return 1;
}
ret = sqlite3_step(stmt);
switch(ret) {
case SQLITE_DONE:
case SQLITE_OK:
break;
default:
_log(LOG_ERR, "Error: Unknown status of query (sqlite3_step): %s", sqlite3_errmsg(db));
return 1;
}
sqlite3_finalize(stmt);
snprintf(query, sizeof(query)-1, "delete from \"privacy-default\" where \"collection-owner\" = \"%s\"", input_jid);
ret = sqlite3_prepare_v2(db, (const char *)query, strlen(query), &stmt, NULL);
if (ret != SQLITE_OK) {
_log(LOG_ERR, "Error: (sqlite3_prepare_v2): %s", sqlite3_errmsg(db));
return 1;
}
ret = sqlite3_step(stmt);
switch(ret) {
case SQLITE_DONE:
case SQLITE_OK:
break;
default:
_log(LOG_ERR, "Error: Unknown status of query (sqlite3_step): %s", sqlite3_errmsg(db));
return 1;
}
sqlite3_finalize(stmt);
snprintf(query, sizeof(query)-1, "delete from \"privacy-items\" where \"collection-owner\" = \"%s\"", input_jid);
ret = sqlite3_prepare_v2(db, (const char *)query, strlen(query), &stmt, NULL);
if (ret != SQLITE_OK) {
_log(LOG_ERR, "Error: (sqlite3_prepare_v2): %s", sqlite3_errmsg(db));
return 1;
}
ret = sqlite3_step(stmt);
switch(ret) {
case SQLITE_DONE:
case SQLITE_OK:
break;
default:
_log(LOG_ERR, "Error: Unknown status of query (sqlite3_step): %s", sqlite3_errmsg(db));
return 1;
}
sqlite3_finalize(stmt);
snprintf(query, sizeof(query)-1, "delete from \"private\" where \"collection-owner\" = \"%s\"", input_jid);
ret = sqlite3_prepare_v2(db, (const char *)query, strlen(query), &stmt, NULL);
if (ret != SQLITE_OK) {
_log(LOG_ERR, "Error: (sqlite3_prepare_v2): %s", sqlite3_errmsg(db));
return 1;
}
ret = sqlite3_step(stmt);
switch(ret) {
case SQLITE_DONE:
case SQLITE_OK:
break;
default:
_log(LOG_ERR, "Error: Unknown status of query (sqlite3_step): %s", sqlite3_errmsg(db));
return 1;
}
sqlite3_finalize(stmt);
snprintf(query, sizeof(query)-1, "delete from \"queue\" where \"collection-owner\" = \"%s\"", input_jid);
ret = sqlite3_prepare_v2(db, (const char *)query, strlen(query), &stmt, NULL);
if (ret != SQLITE_OK) {
_log(LOG_ERR, "Error: (sqlite3_prepare_v2): %s", sqlite3_errmsg(db));
return 1;
}
ret = sqlite3_step(stmt);
switch(ret) {
case SQLITE_DONE:
case SQLITE_OK:
break;
default:
_log(LOG_ERR, "Error: Unknown status of query (sqlite3_step): %s", sqlite3_errmsg(db));
return 1;
}
sqlite3_finalize(stmt);
snprintf(query, sizeof(query)-1, "delete from \"roster-groups\" where \"collection-owner\" = \"%s\"", input_jid);
ret = sqlite3_prepare_v2(db, (const char *)query, strlen(query), &stmt, NULL);
if (ret != SQLITE_OK) {
_log(LOG_ERR, "Error: (sqlite3_prepare_v2): %s", sqlite3_errmsg(db));
return 1;
}
ret = sqlite3_step(stmt);
switch(ret) {
case SQLITE_DONE:
case SQLITE_OK:
break;
default:
_log(LOG_ERR, "Error: Unknown status of query (sqlite3_step): %s", sqlite3_errmsg(db));
return 1;
}
sqlite3_finalize(stmt);
snprintf(query, sizeof(query)-1, "delete from \"roster-groups\" where jid = \"%s\"", input_jid);
ret = sqlite3_prepare_v2(db, (const char *)query, strlen(query), &stmt, NULL);
if (ret != SQLITE_OK) {
_log(LOG_ERR, "Error: (sqlite3_prepare_v2): %s", sqlite3_errmsg(db));
return 1;
}
ret = sqlite3_step(stmt);
switch(ret) {
case SQLITE_DONE:
case SQLITE_OK:
break;
default:
_log(LOG_ERR, "Error: Unknown status of query (sqlite3_step): %s", sqlite3_errmsg(db));
return 1;
}
sqlite3_finalize(stmt);
snprintf(query, sizeof(query)-1, "delete from \"roster-items\" where \"collection-owner\" = \"%s\"", input_jid);
ret = sqlite3_prepare_v2(db, (const char *)query, strlen(query), &stmt, NULL);
if (ret != SQLITE_OK) {
_log(LOG_ERR, "Error: (sqlite3_prepare_v2): %s", sqlite3_errmsg(db));
return 1;
}
ret = sqlite3_step(stmt);
switch(ret) {
case SQLITE_DONE:
case SQLITE_OK:
break;
default:
_log(LOG_ERR, "Error: Unknown status of query (sqlite3_step): %s", sqlite3_errmsg(db));
return 1;
}
sqlite3_finalize(stmt);
snprintf(query, sizeof(query)-1, "delete from \"roster-items\" where jid = \"%s\"", input_jid);
ret = sqlite3_prepare_v2(db, (const char *)query, strlen(query), &stmt, NULL);
if (ret != SQLITE_OK) {
_log(LOG_ERR, "Error: (sqlite3_prepare_v2): %s", sqlite3_errmsg(db));
return 1;
}
ret = sqlite3_step(stmt);
switch(ret) {
case SQLITE_DONE:
case SQLITE_OK:
break;
default:
_log(LOG_ERR, "Error: Unknown status of query (sqlite3_step): %s", sqlite3_errmsg(db));
return 1;
}
sqlite3_finalize(stmt);
snprintf(query, sizeof(query)-1, "delete from \"vacation-settings\" where \"collection-owner\" = \"%s\"", input_jid);
ret = sqlite3_prepare_v2(db, (const char *)query, strlen(query), &stmt, NULL);
if (ret != SQLITE_OK) {
_log(LOG_ERR, "Error: (sqlite3_prepare_v2): %s", sqlite3_errmsg(db));
return 1;
}
ret = sqlite3_step(stmt);
switch(ret) {
case SQLITE_DONE:
case SQLITE_OK:
break;
default:
_log(LOG_ERR, "Error: Unknown status of query (sqlite3_step): %s", sqlite3_errmsg(db));
return 1;
}
sqlite3_finalize(stmt);
return 0;
}
int add_user_to_rosters(char *input_jid, sqlite3 *db)
{
int ret, ret2, ret3;
sqlite3_stmt *stmt;
int i;
char query[MAX_JID_LEN+128];
const unsigned char *elem;
sqlite3_stmt *stmt2;
const char *errmsg;
snprintf(query, sizeof(query)-1, "select \"collection-owner\" FROM active where \"collection-owner\" = \"%s\"", input_jid);
ret = sqlite3_prepare_v2(db, (const char *)query, strlen(query), &stmt, NULL);
if (ret != SQLITE_OK) {
_log(LOG_ERR, "Error: (sqlite3_prepare_v2): %s", sqlite3_errmsg(db));
sqlite3_finalize(stmt);
return 1;
}
_log(LOG_INFO, "Issuing SQL command: %s", query);
ret = sqlite3_step(stmt);
switch(ret) {
case SQLITE_ROW:
break;
case SQLITE_DONE:
_log(LOG_ERR, "Error: Could not find input JID in database. Use -i argument to initialize user.", query);
sqlite3_finalize(stmt);
return 1;
default:
_log(LOG_ERR, "Error: Unknown status of query (sqlite3_step): %s", sqlite3_errmsg(db));
sqlite3_finalize(stmt);
return 1;
}
sqlite3_finalize(stmt);
snprintf(query, sizeof(query)-1, "select \"collection-owner\" from active");
ret = sqlite3_prepare_v2(db, (const char *)query, strlen(query), &stmt, NULL);
if (ret != SQLITE_OK) {
_log(LOG_ERR, "Error: (sqlite3_prepare_v2): %s", sqlite3_errmsg(db));
sqlite3_finalize(stmt);
return 1;
}
_log(LOG_INFO, "Issuing SQL command: %s", query);
ret = sqlite3_step(stmt);
switch(ret) {
case SQLITE_DONE:
case SQLITE_OK:
_log(LOG_NOTICE, "Error: Did not find any collection-owner items in active table");
sqlite3_finalize(stmt);
return 1;
case SQLITE_ROW:
break;
default:
_log(LOG_ERR, "Error: Unknown status of query (sqlite3_step): %s", sqlite3_errmsg(db));
sqlite3_finalize(stmt);
return 1;
}
while (ret != SQLITE_DONE) {
if (ret != SQLITE_ROW) {
_log(LOG_ERR, "Error: Unknown status of query (sqlite3_step): %s", sqlite3_errmsg(db));
sqlite3_finalize(stmt);
return 1;
}
elem = sqlite3_column_text(stmt, 0);
if (strlen((char *)elem) > MAX_JID_LEN)
{
_log(LOG_ERR, "Error: JID larger than MAX_JID_LEN, skipping (%s)", elem);
ret = sqlite3_step(stmt);
continue;
}
if (! (strncmp((char *)elem, input_jid, MAX_JID_LEN))) {
ret = sqlite3_step(stmt);
continue;
}
snprintf(query, sizeof(query)-1, "select \"collection-owner\" from \"roster-items\" where \"collection-owner\" = \"%s\" and jid = \"%s\"", elem, input_jid);
ret2 = sqlite3_prepare_v2(db, (const char *)query, strlen(query), &stmt2, NULL);
if (ret2 != SQLITE_OK) {
_log(LOG_ERR, "Error: (sqlite3_prepare_v2): %s", sqlite3_errmsg(db));
sqlite3_finalize(stmt2);
sqlite3_finalize(stmt);
return 1;
}
ret2 = sqlite3_step(stmt2);
errmsg = sqlite3_errmsg(db);
sqlite3_finalize(stmt2);
if (ret2 == SQLITE_DONE) {
snprintf(query, sizeof(query)-1, "insert into \"roster-items\" (\"collection-owner\", \"jid\", \"name\", \"to\", \"from\", \"ask\") values (\"%s\", \"%s\", \"\", \"1\", \"1\", \"0\")", elem, input_jid);
ret3 = sqlite3_prepare_v2(db, (const char *)query, strlen(query), &stmt2, NULL);
if (ret3 != SQLITE_OK) {
_log(LOG_ERR, "Error: (sqlite3_prepare_v2): %s", sqlite3_errmsg(db));
sqlite3_finalize(stmt2);
sqlite3_finalize(stmt);
return 1;
}
_log(LOG_INFO, "Issuing SQL command: %s", query);
ret3 = sqlite3_step(stmt2);
switch(ret3) {
case SQLITE_OK:
case SQLITE_DONE:
break;
default:
_log(LOG_ERR, "Error: Unknown status of query (sqlite3_step): %s", sqlite3_errmsg(db));
sqlite3_finalize(stmt2);
sqlite3_finalize(stmt);
return 1;
}
sqlite3_finalize(stmt2);
}
snprintf(query, sizeof(query)-1, "select \"collection-owner\" from \"roster-items\" where \"collection-owner\" = \"%s\" and jid = \"%s\"", input_jid, elem);
ret2 = sqlite3_prepare_v2(db, (const char *)query, strlen(query), &stmt2, NULL);
if (ret2 != SQLITE_OK) {
_log(LOG_ERR, "Error: (sqlite3_prepare_v2): %s", sqlite3_errmsg(db));
sqlite3_finalize(stmt2);
sqlite3_finalize(stmt);
return 1;
}
ret2 = sqlite3_step(stmt2);
errmsg = sqlite3_errmsg(db);
sqlite3_finalize(stmt2);
if (ret2 == SQLITE_DONE) {
snprintf(query, sizeof(query)-1, "insert into \"roster-items\" (\"collection-owner\", \"jid\", \"name\", \"to\", \"from\", \"ask\") values (\"%s\", \"%s\", \"\", \"1\", \"1\", \"0\")", input_jid, elem);
ret3 = sqlite3_prepare_v2(db, (const char *)query, strlen(query), &stmt2, NULL);
if (ret3 != SQLITE_OK) {
_log(LOG_ERR, "Error: (sqlite3_prepare_v2): %s", sqlite3_errmsg(db));
sqlite3_finalize(stmt2);
sqlite3_finalize(stmt);
return 1;
}
_log(LOG_INFO, "Issuing SQL command: %s", query);
ret3 = sqlite3_step(stmt2);
switch(ret3) {
case SQLITE_OK:
case SQLITE_DONE:
break;
default:
_log(LOG_ERR, "Error: Unknown status of query (sqlite3_step): %s", sqlite3_errmsg(db));
sqlite3_finalize(stmt2);
sqlite3_finalize(stmt);
return 1;
}
sqlite3_finalize(stmt2);
}
ret = sqlite3_step(stmt);
}
sqlite3_finalize(stmt);
return 0;
}
int delete_user_from_rosters(char *input_jid, sqlite3 *db)
{
char query[MAX_JID_LEN+128];
int ret;
sqlite3_stmt *stmt;
snprintf(query, sizeof(query)-1, "delete from \"roster-items\" where \"collection-owner\" = \"%s\"", input_jid);
ret = sqlite3_prepare_v2(db, (const char *)query, strlen(query), &stmt, NULL);
if (ret != SQLITE_OK) {
_log(LOG_ERR, "Error: (sqlite3_prepare_v2): %s", sqlite3_errmsg(db));
return 1;
}
ret = sqlite3_step(stmt);
switch(ret) {
case SQLITE_DONE:
case SQLITE_OK:
break;
default:
_log(LOG_ERR, "Error: Unknown status of query (sqlite3_step): %s", sqlite3_errmsg(db));
return 1;
}
sqlite3_finalize(stmt);
snprintf(query, sizeof(query)-1, "delete from \"roster-items\" where \"jid\" = \"%s\"", input_jid);
ret = sqlite3_prepare_v2(db, (const char *)query, strlen(query), &stmt, NULL);
if (ret != SQLITE_OK) {
_log(LOG_ERR, "Error: (sqlite3_prepare_v2): %s", sqlite3_errmsg(db));
return 1;
}
ret = sqlite3_step(stmt);
switch(ret) {
case SQLITE_DONE:
case SQLITE_OK:
break;
default:
_log(LOG_ERR, "Error: Unknown status of query (sqlite3_step): %s", sqlite3_errmsg(db));
return 1;
}
sqlite3_finalize(stmt);
snprintf(query, sizeof(query)-1, "delete from \"roster-groups\" where \"collection-owner\" = \"%s\"", input_jid);
ret = sqlite3_prepare_v2(db, (const char *)query, strlen(query), &stmt, NULL);
if (ret != SQLITE_OK) {
_log(LOG_ERR, "Error: (sqlite3_prepare_v2): %s", sqlite3_errmsg(db));
return 1;
}
ret = sqlite3_step(stmt);
switch(ret) {
case SQLITE_DONE:
case SQLITE_OK:
break;
default:
_log(LOG_ERR, "Error: Unknown status of query (sqlite3_step): %s", sqlite3_errmsg(db));
return 1;
}
sqlite3_finalize(stmt);
snprintf(query, sizeof(query)-1, "delete from \"roster-groups\" where \"jid\" = \"%s\"", input_jid);
ret = sqlite3_prepare_v2(db, (const char *)query, strlen(query), &stmt, NULL);
if (ret != SQLITE_OK) {
_log(LOG_ERR, "Error: (sqlite3_prepare_v2): %s", sqlite3_errmsg(db));
return 1;
}
ret = sqlite3_step(stmt);
switch(ret) {
case SQLITE_DONE:
case SQLITE_OK:
break;
default:
_log(LOG_ERR, "Error: Unknown status of query (sqlite3_step): %s", sqlite3_errmsg(db));
return 1;
}
sqlite3_finalize(stmt);
return 0;
}
int make_all_users_buddies(sqlite3 *db)
{
int ret;
sqlite3_stmt *stmt;
char query[MAX_JID_LEN+128];
const unsigned char *elem;
snprintf(query, sizeof(query)-1, "select \"collection-owner\" from \"active\"");
ret = sqlite3_prepare_v2(db, (const char *)query, strlen(query), &stmt, NULL);
if (ret != SQLITE_OK) {
_log(LOG_ERR, "Error: (sqlite3_prepare_v2): %s", sqlite3_errmsg(db));
sqlite3_finalize(stmt);
return 1;
}
_log(LOG_INFO, "Issuing SQL command: %s", query);
ret = sqlite3_step(stmt);
switch(ret) {
case SQLITE_DONE:
case SQLITE_OK:
return 0;
case SQLITE_ROW:
break;
default:
_log(LOG_ERR, "Error: Unknown status of query (sqlite3_step): %s", sqlite3_errmsg(db));
sqlite3_finalize(stmt);
return 1;
}
while (ret != SQLITE_DONE) {
if (ret != SQLITE_ROW) {
_log(LOG_ERR, "Error: Unknown status of query (sqlite3_step): %s", sqlite3_errmsg(db));
sqlite3_finalize(stmt);
return 1;
}
elem = sqlite3_column_text(stmt, 0);
if ((add_user_to_rosters((char *)elem, db)) != 0) {
_log(LOG_ERR, "Error: add_user_to_rosters() failed for %s", elem);
}
ret = sqlite3_step(stmt);
}
sqlite3_finalize(stmt);
return 0;
}
static int db_busy_cb(void *unused, int count) {
const int max_tries = 100;
const int sleep_ms = 100;
_log(LOG_NOTICE, "Database is busy, attempt %i of %i, sleeping for %i ms...", count, max_tries, sleep_ms);
usleep(sleep_ms);
return count<100;
}
int main (int argc, char * const argv[]) {
enum operations {
INIT_USER = 1,
ADD_BUDDY,
REMOVE_BUDDY,
DELETE_USER,
MAKE_ALL_USERS_BUDDIES
};
int opt;
int operation = 0;
char input_jid[MAX_JID_LEN+1];
char jid[MAX_JID_LEN+1];
char dbname[256];
extern char* optarg;
sqlite3 *db;
int ret;
while ((opt = getopt(argc, argv, "a:d:i:r:n:mvD?h")) != EOF)
{
switch(opt)
{
case 'a':
if (operation) {
fprintf(stderr, "Error: You may only specify one operation at a time.\n");
exit(1);
}
operation = ADD_BUDDY;
strncpy(input_jid, optarg, MAX_JID_LEN);
break;
case 'r':
if (operation) {
fprintf(stderr, "Error: You may only specify one operation at a time.\n");
exit(1);
}
operation = REMOVE_BUDDY;
strncpy(input_jid, optarg, MAX_JID_LEN);
break;
case 'd':
if (operation) {
fprintf(stderr, "Error: You may only specify one operation at a time.\n");
exit(1);
}
operation = DELETE_USER;
strncpy(input_jid, optarg, MAX_JID_LEN);
break;
case 'i':
if (operation) {
fprintf(stderr, "Error: You may only specify one operation at a time.\n");
exit(1);
}
operation = INIT_USER;
strncpy(input_jid, optarg, MAX_JID_LEN);
break;
case 'm':
if (operation) {
fprintf(stderr, "Error: You may only specify one operation at a time.\n");
exit(1);
}
operation = MAKE_ALL_USERS_BUDDIES;
break;
case 'D':
g_debug = 1;
break;
case 'h':
case 'v':
case '?':
default:
usage();
break;
}
}
strncpy(dbname, "/private/var/jabberd/sqlite/jabberd2.db", sizeof(dbname)-1);
ret = sqlite3_open((const char*)dbname, &db);
if (ret != SQLITE_OK) {
_log(LOG_ERR, "Error: (sqlite3_open): %s", sqlite3_errmsg(db));
sqlite3_close(db);
return 1;
}
#if SQLITE_VERSION_NUMBER >= 3003008
sqlite3_extended_result_codes(db, 1);
#endif
sqlite3_busy_handler(db, db_busy_cb, dbname);
switch (operation) {
case ADD_BUDDY:
if ((add_user_to_rosters(input_jid, db)) == 0)
{
_log(LOG_INFO, "Operation completed. %s added to all jabber buddy lists.", input_jid);
} else {
_log(LOG_ERR, "Error: failed to add user to rosters, input_jid = %s", input_jid);
}
break;
case REMOVE_BUDDY:
if ((delete_user_from_rosters(input_jid, db)) == 0)
{
_log(LOG_INFO, "Operation completed. %s removed from all jabber buddy lists.", input_jid);
} else {
_log(LOG_ERR, "Error: failed to remove user from rosters. input_jid = %s", input_jid);
}
break;
case INIT_USER:
if ((init_user(input_jid, db)) == 0)
{
_log(LOG_INFO, "Operation completed. %s is now listed in the jabberd active table.", input_jid);
} else {
_log(LOG_ERR, "Error: failed to init user in jabberd database. input_jid = %s", input_jid);
}
break;
case DELETE_USER:
if ((delete_user(input_jid, db)) == 0)
{
_log(LOG_INFO, "Operation completed. %s has been removed from the jabberd database.", input_jid);
} else {
_log(LOG_ERR, "Error: failed to delete user from jabberd database. input_jid = %s", input_jid);
}
break;
case MAKE_ALL_USERS_BUDDIES:
if ((make_all_users_buddies(db)) == 0)
{
_log(LOG_INFO, "Operation completed. All users are buddies.");
} else {
_log(LOG_ERR, "Error: failed to make all active users buddies.");
}
break;
default:
fprintf(stderr, "Error: You must choose 1 operation to perform.\n\n");
usage; }
ret = sqlite3_close(db);
if (ret != SQLITE_OK) {
_log(LOG_ERR, "Error: (sqlite3_close): %s", sqlite3_errmsg(db));
}
return 0;
}