/* $Id$ */
#include <sqlite3.h>
#include "bbs.h"
#define EMAILDB_PATH BBSHOME "/emaildb.db"
// define FORK model to minimize memory usage.
#define FORK_MODEL
static int emaildb_open(sqlite3 **Db) {
int rc;
if ((rc = sqlite3_open(EMAILDB_PATH, Db)) != SQLITE_OK)
return rc;
// create table if it doesn't exist
rc = sqlite3_exec(*Db, "CREATE TABLE IF NOT EXISTS emaildb (userid TEXT, email TEXT, PRIMARY KEY (userid));"
"CREATE INDEX IF NOT EXISTS email ON emaildb (email);",
NULL, NULL, NULL);
return rc;
}
#ifndef INIT_MAIN
int emaildb_check_email(char * email, int email_len)
{
int count = -1;
pid_t pid = -1;
sqlite3 *Db = NULL;
sqlite3_stmt *Stmt = NULL;
#ifdef FORK_MODEL
switch((pid = fork()))
{
case -1: // error
break;
case 0: // child
break;
default:
waitpid(pid, &count, 0);
count = WEXITSTATUS(count);
// vmsgf(ANSI_RESET "found %d emails", count);
return count;
}
#endif
if (emaildb_open(&Db) != SQLITE_OK)
goto end;
if (sqlite3_prepare(Db, "SELECT userid FROM emaildb WHERE email LIKE lower(?);",
-1, &Stmt, NULL) != SQLITE_OK)
goto end;
if (sqlite3_bind_text(Stmt, 1, email, email_len, SQLITE_STATIC) != SQLITE_OK)
goto end;
count = 0;
while (sqlite3_step(Stmt) == SQLITE_ROW) {
char *result;
userec_t u;
if ((result = (char*)sqlite3_column_text(Stmt, 0)) == NULL)
break;
// ignore my self, because I may be the one going to
// use mail.
if (strcasecmp(result, cuser.userid) == 0)
continue;
// force update
u.email[0] = 0;
if (getuser(result, &u))
if (strcasecmp(email, u.email) == 0)
count++;
}
end:
if (Stmt != NULL)
if (sqlite3_finalize(Stmt) != SQLITE_OK)
count = -1;
if (Db != NULL)
sqlite3_close(Db);
if (pid == 0)
exit(count);
return count;
}
#endif
int emaildb_update_email(char * userid, int userid_len, char * email, int email_len)
{
int ret = -1;
pid_t pid = -1;
sqlite3 *Db = NULL;
sqlite3_stmt *Stmt = NULL;
#ifdef FORK_MODEL
switch((pid = fork()))
{
case -1: // error
break;
case 0: // child
break;
default:
waitpid(pid, &ret, 0);
ret = WEXITSTATUS(ret);
return ret;
}
#endif
if (emaildb_open(&Db) != SQLITE_OK)
goto end;
if (sqlite3_prepare(Db, "REPLACE INTO emaildb (userid, email) VALUES (lower(?),lower(?));",
-1, &Stmt, NULL) != SQLITE_OK)
goto end;
if (sqlite3_bind_text(Stmt, 1, userid, userid_len, SQLITE_STATIC) != SQLITE_OK)
goto end;
if (sqlite3_bind_text(Stmt, 2, email, email_len, SQLITE_STATIC) != SQLITE_OK)
goto end;
if (sqlite3_step(Stmt) == SQLITE_DONE)
ret = 0;
end:
if (Stmt != NULL)
sqlite3_finalize(Stmt);
if (Db != NULL)
sqlite3_close(Db);
if (pid == 0)
exit(ret);
return ret;
}
#ifdef INIT_MAIN
// standalone initialize builder
#define TRANSCATION_PERIOD (4096)
int main()
{
int fd = 0;
userec_t xuser;
off_t sz = 0, i = 0, valids = 0;
sqlite3 *Db = NULL;
sqlite3_stmt *Stmt = NULL, *tranStart = NULL, *tranEnd = NULL;
// init passwd
sz = dashs(FN_PASSWD);
fd = open(FN_PASSWD, O_RDONLY);
if (fd < 0 || sz <= 0)
{
fprintf(stderr, "cannot open ~/.PASSWDS.\n");
return 0;
}
sz /= sizeof(userec_t);
// init emaildb
if (emaildb_open(&Db) != SQLITE_OK)
{
fprintf(stderr, "cannot initialize emaildb.\n");
return 0;
}
if (sqlite3_prepare(Db, "REPLACE INTO emaildb (userid, email) VALUES (lower(?),lower(?));",
-1, &Stmt, NULL) != SQLITE_OK ||
sqlite3_prepare(Db, "BEGIN TRANSACTION;", -1, &tranStart, NULL) != SQLITE_OK ||
sqlite3_prepare(Db, "COMMIT;", -1, &tranEnd, NULL) != SQLITE_OK)
{
fprintf(stderr, "SQLite 3 internal error.\n");
return 0;
}
sqlite3_step(tranStart);
sqlite3_reset(tranStart);
while (read(fd, &xuser, sizeof(xuser)) == sizeof(xuser))
{
i++;
// got a record
if (strlen(xuser.userid) < 2 || strlen(xuser.userid) > IDLEN)
continue;
if (strlen(xuser.email) < 5)
continue;
if (sqlite3_bind_text(Stmt, 1, xuser.userid, strlen(xuser.userid),
SQLITE_STATIC) != SQLITE_OK)
{
fprintf(stderr, "\ncannot prepare userid param.\n");
break;
}
if (sqlite3_bind_text(Stmt, 2, xuser.email, strlen(xuser.email),
SQLITE_STATIC) != SQLITE_OK)
{
fprintf(stderr, "\ncannot prepare email param.\n");
break;
}
if (sqlite3_step(Stmt) != SQLITE_DONE)
{
fprintf(stderr, "\ncannot execute statement.\n");
break;
}
sqlite3_reset(Stmt);
valids ++;
if (valids % 10 == 0)
fprintf(stderr, "%d/%d (valid: %d)\r",
(int)i, (int)sz, (int)valids);
if (valids % TRANSCATION_PERIOD == 0)
{
sqlite3_step(tranEnd);
sqlite3_step(tranStart);
sqlite3_reset(tranEnd);
sqlite3_reset(tranStart);
}
}
if (valids % TRANSCATION_PERIOD)
sqlite3_step(tranEnd);
if (Stmt != NULL)
sqlite3_finalize(Stmt);
if (Db != NULL)
sqlite3_close(Db);
close(fd);
return 0;
}
#endif
// vim: sw=4