---
Makefile.am | 2 +-
db.c | 11 +++-----
dbmail-imapsession.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++-
dbmail-mailbox.c | 21 +++++++++++---
dbmailtypes.h | 1 +
dm_imaputil.c | 72 --------------------------------------------------
dm_imaputil.h | 5 ---
export.c | 56 ++++++++++++++++++++++++++++++++-------
imap4.c | 3 --
modules/dbmysql.c | 5 +++-
modules/dbpgsql.c | 5 +++-
modules/dbsqlite.c | 5 +++-
12 files changed, 150 insertions(+), 107 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 5f02ac6..aaa4d95 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -88,7 +88,7 @@ dbmail_util_LDADD = libdbmail.la
dbmail_users_SOURCES = user.c
dbmail_users_LDADD = libdbmail.la
-dbmail_export_SOURCES = export.c
+dbmail_export_SOURCES = export.c memblock.c dbmail-imapsession.c
dbmail_export_LDADD = libdbmail.la
dbmail_lmtpd_SOURCES = lmtp.c lmtpd.c
diff --git a/db.c b/db.c
index 55211c0..100c2bd 100644
--- a/db.c
+++ b/db.c
@@ -4368,14 +4368,11 @@ char *date2char_str(const char *column)
char *char2date_str(const char *date)
{
- unsigned len;
- char *s;
-
- len = strlen(db_get_sql(SQL_TO_DATE)) + MAX_DATE_LEN;
- if (! (s = g_new0(char,len)))
- return NULL;
+ char *s, *qs;
- snprintf(s, len, db_get_sql(SQL_TO_DATE), date);
+ qs = g_strdup_printf("'%s'", date);
+ s = g_strdup_printf(db_get_sql(SQL_TO_DATETIME), qs);
+ g_free(qs);
return s;
}
diff --git a/dbmail-imapsession.c b/dbmail-imapsession.c
index 88fe66b..ae20ad7 100644
--- a/dbmail-imapsession.c
+++ b/dbmail-imapsession.c
@@ -36,7 +36,7 @@ extern db_param_t _db_params;
#define DBPFX _db_params.pfx
/* cache */
-extern cache_t cached_msg;
+cache_t cached_msg;
extern const char *month_desc[];
/* returned by date_sql2imap() */
@@ -60,6 +60,75 @@ static void _fetch_envelopes(struct ImapSession *self);
static int _imap_show_body_section(body_fetch_t *bodyfetch, gpointer data);
+/*
+ * send_data()
+ *
+ * sends cnt bytes from a MEM structure to a FILE stream
+ * uses a simple buffering system
+ */
+static void send_data(FILE * to, MEM * from, int cnt)
+{
+ char buf[SEND_BUF_SIZE];
+
+ for (cnt -= SEND_BUF_SIZE; cnt >= 0; cnt -= SEND_BUF_SIZE) {
+ mread(buf, SEND_BUF_SIZE, from);
+ fwrite(buf, SEND_BUF_SIZE, 1, to);
+ }
+
+ if (cnt < 0) {
+ mread(buf, cnt + SEND_BUF_SIZE, from);
+ fwrite(buf, cnt + SEND_BUF_SIZE, 1, to);
+ }
+
+ fflush(to);
+}
+
+/*
+ * init cache
+ */
+static int init_cache(void)
+{
+ int serr;
+ cached_msg.dmsg = NULL;
+ cached_msg.num = -1;
+ cached_msg.msg_parsed = 0;
+ if (! (cached_msg.memdump = mopen())) {
+ serr = errno;
+ TRACE(TRACE_ERROR,"mopen() failed [%s]", strerror(serr));
+ errno = serr;
+ return -1;
+ }
+
+
+ if (! (cached_msg.tmpdump = mopen())) {
+ serr = errno;
+ TRACE(TRACE_ERROR,"mopen() failed [%s]", strerror(serr));
+ errno = serr;
+ mclose(&cached_msg.memdump);
+ return -1;
+ }
+
+ cached_msg.file_dumped = 0;
+ cached_msg.dumpsize = 0;
+ return 0;
+}
+/*
+ * closes the msg cache
+ */
+static void close_cache(void)
+{
+ if (cached_msg.dmsg)
+ dbmail_message_free(cached_msg.dmsg);
+
+ cached_msg.num = -1;
+ cached_msg.msg_parsed = 0;
+ mclose(&cached_msg.memdump);
+ mclose(&cached_msg.tmpdump);
+}
+
+
+
+
static u64_t get_dumpsize(body_fetch_t *bodyfetch, u64_t tmpdumpsize);
static void _imap_fetchitem_free(struct ImapSession * self)
diff --git a/dbmail-mailbox.c b/dbmail-mailbox.c
index 7a04c7e..9e472af 100644
--- a/dbmail-mailbox.c
+++ b/dbmail-mailbox.c
@@ -270,6 +270,7 @@ int dbmail_mailbox_dump(struct DbmailMailbox *self, FILE *file)
ostream = g_mime_stream_file_new(file);
ids = g_tree_keys(self->ids);
+
while (ids) {
cids = g_list_append(cids,g_strdup_printf("%llu", *(u64_t *)ids->data));
if (! g_list_next(ids))
@@ -1122,10 +1123,12 @@ static gboolean _do_sort(GNode *node, struct DbmailMailbox *self)
}
static GTree * mailbox_search(struct DbmailMailbox *self, search_key_t *s)
{
- unsigned i, rows, date;
+ unsigned i, rows;
+ char *qs, *date, *field;
u64_t *k, *v, *w;
u64_t id;
char gt_lt = 0;
+ const char *op;
GString *t;
GString *q;
@@ -1139,14 +1142,22 @@ static GTree * mailbox_search(struct DbmailMailbox *self, search_key_t *s)
case IST_HDRDATE_ON:
case IST_HDRDATE_SINCE:
case IST_HDRDATE_BEFORE:
+
+ field = g_strdup_printf(db_get_sql(SQL_TO_DATE), s->hdrfld);
+ qs = g_strdup_printf("'%s'", date_imap2sql(s->search));
+ date = g_strdup_printf(db_get_sql(SQL_TO_DATE), qs);
+ g_free(qs);
- date = num_from_imapdate(s->search);
if (s->type == IST_HDRDATE_SINCE)
- g_string_printf(t,"%s >= %d", s->hdrfld, date);
+ op = ">=";
else if (s->type == IST_HDRDATE_BEFORE)
- g_string_printf(t,"%s < %d", s->hdrfld, date);
+ op = "<";
else
- g_string_printf(t,"%s >= %d AND %s < %d", s->hdrfld, date, s->hdrfld, date+1);
+ op = "=";
+
+ g_string_printf(t,"%s %s %s", field, op, date);
+ g_free(date);
+ g_free(field);
g_string_printf(q,"SELECT message_idnr FROM %smessages m "
"JOIN %sphysmessage p ON m.physmessage_id=p.id "
diff --git a/dbmailtypes.h b/dbmailtypes.h
index 7ab17f1..52243c0 100644
--- a/dbmailtypes.h
+++ b/dbmailtypes.h
@@ -488,6 +488,7 @@ typedef enum {
typedef enum {
SQL_TO_DATE,
+ SQL_TO_DATETIME,
SQL_TO_CHAR,
SQL_CURRENT_TIMESTAMP,
SQL_REPLYCACHE_EXPIRE,
diff --git a/dm_imaputil.c b/dm_imaputil.c
index 8b2b72a..d1d8eb0 100644
--- a/dm_imaputil.c
+++ b/dm_imaputil.c
@@ -38,9 +38,6 @@
extern db_param_t _db_params;
#define DBPFX _db_params.pfx
-/* cache */
-extern cache_t cached_msg;
-
/* consts */
const char AcceptedChars[] =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
@@ -80,75 +77,6 @@ int checktag(const char *s)
return 1;
}
-/*
- * send_data()
- *
- * sends cnt bytes from a MEM structure to a FILE stream
- * uses a simple buffering system
- */
-void send_data(FILE * to, MEM * from, int cnt)
-{
- char buf[SEND_BUF_SIZE];
-
- for (cnt -= SEND_BUF_SIZE; cnt >= 0; cnt -= SEND_BUF_SIZE) {
- mread(buf, SEND_BUF_SIZE, from);
- fwrite(buf, SEND_BUF_SIZE, 1, to);
- }
-
- if (cnt < 0) {
- mread(buf, cnt + SEND_BUF_SIZE, from);
- fwrite(buf, cnt + SEND_BUF_SIZE, 1, to);
- }
-
- fflush(to);
-}
-
-
-
-/*
- * init cache
- */
-int init_cache()
-{
- int serr;
- cached_msg.dmsg = NULL;
- cached_msg.num = -1;
- cached_msg.msg_parsed = 0;
- if (! (cached_msg.memdump = mopen())) {
- serr = errno;
- TRACE(TRACE_ERROR,"mopen() failed [%s]", strerror(serr));
- errno = serr;
- return -1;
- }
-
-
- if (! (cached_msg.tmpdump = mopen())) {
- serr = errno;
- TRACE(TRACE_ERROR,"mopen() failed [%s]", strerror(serr));
- errno = serr;
- mclose(&cached_msg.memdump);
- return -1;
- }
-
- cached_msg.file_dumped = 0;
- cached_msg.dumpsize = 0;
- return 0;
-}
-/*
- * closes the msg cache
- */
-void close_cache()
-{
- if (cached_msg.dmsg)
- dbmail_message_free(cached_msg.dmsg);
-
- cached_msg.num = -1;
- cached_msg.msg_parsed = 0;
- mclose(&cached_msg.memdump);
- mclose(&cached_msg.tmpdump);
-}
-
-
/* unwrap strings */
int mime_unwrap(char *to, const char *from)
{
diff --git a/dm_imaputil.h b/dm_imaputil.h
index 96dc5b9..0cc100d 100644
--- a/dm_imaputil.h
+++ b/dm_imaputil.h
@@ -33,11 +33,6 @@ size_t stridx(const char *s, char ch);
int checktag(const char *s);
-void send_data(FILE * to, MEM * from, int cnt);
-
-int init_cache(void);
-void close_cache(void);
-
int mime_unwrap(char *to, const char *from);
#endif
diff --git a/export.c b/export.c
index 3536209..ae9ee2d 100644
--- a/export.c
+++ b/export.c
@@ -43,6 +43,7 @@ int do_showhelp(void) {
printf(" -u username specify a user\n");
printf(" -m mailbox specify a mailbox (default export all mailboxes)\n");
printf(" -o outfile specify the destination mbox (default ./user/mailbox)\n");
+ printf(" -s set specify the search criteria in IMAP SEARCH notation (default 1:*)\n");
printf("\n");
printf("Summary of options for all modes:\n");
printf("\n");
@@ -57,10 +58,11 @@ int do_showhelp(void) {
return 0;
}
-static int mailbox_dump(u64_t mailbox_idnr, const char *outfile)
+static int mailbox_dump(u64_t mailbox_idnr, const char *outfile, const char *search)
{
FILE *ostream;
struct DbmailMailbox *mb = NULL;
+ struct ImapSession *s;
char *dir;
/*
@@ -71,6 +73,26 @@ static int mailbox_dump(u64_t mailbox_idnr, const char *outfile)
*
* TODO: facilitate maildir type exports
*/
+ mb = dbmail_mailbox_new(mailbox_idnr);
+ if (search) {
+ s = dbmail_imap_session_new();
+ if (! (build_args_array_ext(s, search))) {
+ qerrorf("error parsing search string");
+ dbmail_imap_session_delete(s);
+ dbmail_mailbox_free(mb);
+ return 1;
+ }
+
+ if (dbmail_mailbox_build_imap_search(mb, s->args, &(s->args_idx), SEARCH_UNORDERED) < 0) {
+ qerrorf("invalid search string");
+ dbmail_imap_session_delete(s);
+ dbmail_mailbox_free(mb);
+ return 1;
+ }
+ dbmail_mailbox_search(mb);
+ dbmail_imap_session_delete(s);
+ }
+
dir = g_path_get_dirname(outfile);
if (g_mkdir_with_parents(dir,0700)) {
qerrorf("can't create directory [%s]\n", dir);
@@ -79,18 +101,20 @@ static int mailbox_dump(u64_t mailbox_idnr, const char *outfile)
}
g_free(dir);
- if (! (ostream = fopen(outfile,"a"))) {
+ if (strncmp(outfile,"-",1)==0) {
+ ostream = stdout;
+ } else if (! (ostream = fopen(outfile,"a"))) {
int err=errno;
qerrorf("opening [%s] failed [%s]\n", outfile, strerror(err));
return -1;
}
- mb = dbmail_mailbox_new(mailbox_idnr);
if (dbmail_mailbox_dump(mb,ostream) < 0)
qerrorf("exporing failed\n");
if (mb)
dbmail_mailbox_free(mb);
+
return 0;
}
@@ -100,7 +124,7 @@ int main(int argc, char *argv[])
int opt = 0, opt_prev = 0;
int show_help = 0;
int result = 0;
- char *user = NULL,*mailbox=NULL, *outfile=NULL;
+ char *user = NULL,*mailbox=NULL, *outfile=NULL, *search=NULL;
u64_t useridnr = 0, mailbox_idnr = 0;
openlog(PNAME, LOG_PID, LOG_MAIL);
@@ -111,7 +135,7 @@ int main(int argc, char *argv[])
/* get options */
opterr = 0; /* suppress error message from getopt() */
while ((opt = getopt(argc, argv,
- "-u:m:o:" /* Major modes */
+ "-u:m:o:s:" /* Major modes */
"f:qvVh" /* Common options */ )) != -1) {
/* The initial "-" of optstring allows unaccompanied
* options and reports them as the optarg to opt 1 (not '1') */
@@ -120,8 +144,7 @@ int main(int argc, char *argv[])
opt_prev = opt;
switch (opt) {
- /* Major modes of operation
- * (exactly one of these is required) */
+ /* export specific options */
case 'u':
if (optarg && strlen(optarg))
user = optarg;
@@ -135,6 +158,14 @@ int main(int argc, char *argv[])
if (optarg && strlen(optarg))
outfile = optarg;
break;
+ case 's':
+ if (optarg && strlen(optarg))
+ search = optarg;
+ else {
+ qprintf("dbmail-mailbox: -s requires a value\n\n");
+ result = 1;
+ }
+ break;
/* Common options */
case 'f':
@@ -168,7 +199,6 @@ int main(int argc, char *argv[])
printf("This is DBMail version %s\n\n%s\n", VERSION, COPYRIGHT);
result = 1;
break;
-
default:
/* printf("unrecognized option [%c], continuing...\n",optopt); */
break;
@@ -186,6 +216,12 @@ int main(int argc, char *argv[])
result = 1;
goto freeall;
}
+ if (search && (! mailbox) ) {
+ qerrorf("Mailbox required if search is specified.\n");
+ result = 1;
+ goto freeall;
+
+ }
/* read the config file */
if (config_read(configFile) == -1) {
qerrorf("Failed. Unable to read config file %s\n", configFile);
@@ -236,7 +272,7 @@ int main(int argc, char *argv[])
}
qerrorf(" export mailbox /%s/%s -> %s\n", user, mailbox, outfile);
- mailbox_dump(mailbox_idnr, outfile);
+ mailbox_dump(mailbox_idnr, outfile, search);
} else {
u64_t *children;
@@ -267,7 +303,7 @@ int main(int argc, char *argv[])
dumpfile = g_strdup_printf("%s/%s.mbox", user, mailbox);
qerrorf(" export mailbox /%s/%s -> %s/%s\n", user, mailbox, outfile, dumpfile);
- if (mailbox_dump(mailbox_idnr, dumpfile)) {
+ if (mailbox_dump(mailbox_idnr, dumpfile, NULL)) {
g_free(dumpfile);
goto freeall;
}
diff --git a/imap4.c b/imap4.c
index 6184dd8..32e5f64 100644
--- a/imap4.c
+++ b/imap4.c
@@ -30,9 +30,6 @@
#define THIS_MODULE "imap"
-/* cache */
-cache_t cached_msg;
-
const char *IMAP_COMMANDS[] = {
"", "capability", "noop", "logout",
"authenticate", "login",
diff --git a/modules/dbmysql.c b/modules/dbmysql.c
index a1151f6..5e92d29 100644
--- a/modules/dbmysql.c
+++ b/modules/dbmysql.c
@@ -39,7 +39,10 @@ const char * db_get_sql(sql_fragment_t frag)
return "DATE_FORMAT(%s, '%%Y-%%m-%%d %%T')";
break;
case SQL_TO_DATE:
- return "'%s'";
+ return "DATE(%s)";
+ break;
+ case SQL_TO_DATETIME:
+ return "TIMESTAMP(%s)";
break;
case SQL_CURRENT_TIMESTAMP:
return "CURRENT_TIMESTAMP";
diff --git a/modules/dbpgsql.c b/modules/dbpgsql.c
index 0986792..bd16fc9 100644
--- a/modules/dbpgsql.c
+++ b/modules/dbpgsql.c
@@ -37,7 +37,10 @@ const char * db_get_sql(sql_fragment_t frag)
return "TO_CHAR(%s, 'YYYY-MM-DD HH24:MI:SS' )";
break;
case SQL_TO_DATE:
- return "TO_TIMESTAMP('%s', 'YYYY-MM-DD HH:MI:SS')";
+ return "TO_DATE(%s,'YYYY-MM-DD')";
+ break;
+ case SQL_TO_DATETIME:
+ return "TO_TIMESTAMP(%s, 'YYYY-MM-DD HH24:MI:SS')";
break;
case SQL_CURRENT_TIMESTAMP:
return "CURRENT_TIMESTAMP";
diff --git a/modules/dbsqlite.c b/modules/dbsqlite.c
index 49370af..c2bc643 100644
--- a/modules/dbsqlite.c
+++ b/modules/dbsqlite.c
@@ -47,7 +47,10 @@ const char * db_get_sql(sql_fragment_t frag)
return "%s";
break;
case SQL_TO_DATE:
- return "'%s'";
+ return "DATE(%s)";
+ break;
+ case SQL_TO_DATETIME:
+ return "DATETIME(%s)";
break;
case SQL_CURRENT_TIMESTAMP:
return "STRFTIME('%Y-%m-%d %H:%M:%S','now','localtime')";
_______________________________________________
Dbmail-dev mailing list
[email protected]
http://twister.fastxs.net/mailman/listinfo/dbmail-dev