search.c (mairix-0.23) | : | search.c (mairix-0.24) | ||
---|---|---|---|---|
skipping to change at line 47 | skipping to change at line 47 | |||
* set of .h files (Solaris, FreeBSD so far). Probably grossly oversized but | * set of .h files (Solaris, FreeBSD so far). Probably grossly oversized but | |||
* it'll do. */ | * it'll do. */ | |||
#if !defined(NAME_MAX) | #if !defined(NAME_MAX) | |||
#define NAME_MAX 4096 | #define NAME_MAX 4096 | |||
#endif | #endif | |||
#include "mairix.h" | #include "mairix.h" | |||
#include "reader.h" | #include "reader.h" | |||
#include "memmac.h" | #include "memmac.h" | |||
#include "imapinterface.h" | ||||
static void mark_hits_in_table(struct read_db *db, struct toktable_db *tt, int h it_tok, char *hits)/*{{{*/ | static void mark_hits_in_table(struct read_db *db, struct toktable_db *tt, int h it_tok, char *hits)/*{{{*/ | |||
{ | { | |||
/* mark files containing matched token */ | /* mark files containing matched token */ | |||
int idx; | int idx; | |||
unsigned char *j, *first_char; | unsigned char *j, *first_char; | |||
idx = 0; | idx = 0; | |||
first_char = (unsigned char *) db->data + tt->enc_offsets[hit_tok]; | first_char = (unsigned char *) db->data + tt->enc_offsets[hit_tok]; | |||
for (j = first_char; *j != 0xff; ) { | for (j = first_char; *j != 0xff; ) { | |||
idx += read_increment(&j); | idx += read_increment(&j); | |||
skipping to change at line 696 | skipping to change at line 697 | |||
if (data) { | if (data) { | |||
fprintf(out, "From mairix@mairix Mon Jan 1 12:34:56 1970\n"); | fprintf(out, "From mairix@mairix Mon Jan 1 12:34:56 1970\n"); | |||
fprintf(out, "X-source-folder: %s\n", path); | fprintf(out, "X-source-folder: %s\n", path); | |||
fwrite (data, sizeof(unsigned char), len, out); | fwrite (data, sizeof(unsigned char), len, out); | |||
mbox_terminate(data, len, out); | mbox_terminate(data, len, out); | |||
free_ro_mapping(data, len); | free_ro_mapping(data, len); | |||
} | } | |||
return; | return; | |||
} | } | |||
/*}}}*/ | /*}}}*/ | |||
static void append_data_to_mbox(const char *data, size_t len, void *arg)/*{{{*/ | ||||
{ | ||||
FILE *out = (FILE *)arg; | ||||
fprintf(out, "From mairix@mairix Mon Jan 1 12:34:56 1970\n"); | ||||
fwrite (data, sizeof(unsigned char), len, out); | ||||
fputc('\n', out); | ||||
return; | ||||
} | ||||
/*}}}*/ | ||||
static void write_to_file(const char *data, size_t len, void *arg)/*{{{*/ | ||||
{ | ||||
FILE *fp; | ||||
if (!(fp = fopen((char *)arg, "w"))) { | ||||
fprintf(stderr, "Cannot write matched message to \"%s\": %s\n", (char *)arg, | ||||
strerror(errno)); | ||||
return; | ||||
} | ||||
fwrite(data, 1, len, fp); | ||||
fclose(fp); | ||||
} | ||||
/*}}}*/ | ||||
static int had_failed_checksum; | static int had_failed_checksum; | |||
static void get_validated_mbox_msg(struct read_db *db, int msg_index,/*{{{*/ | static void get_validated_mbox_msg(struct read_db *db, int msg_index,/*{{{*/ | |||
int *mbox_index, | int *mbox_index, | |||
unsigned char **mbox_data, int *mbox_len, | unsigned char **mbox_data, int *mbox_len, | |||
unsigned char **msg_data, int *msg_len) | unsigned char **msg_data, int *msg_len) | |||
{ | { | |||
/* msg_data==NULL if checksum mismatches */ | /* msg_data==NULL if checksum mismatches */ | |||
unsigned char *start; | unsigned char *start; | |||
skipping to change at line 811 | skipping to change at line 832 | |||
} | } | |||
static void string_tolower(char *str) | static void string_tolower(char *str) | |||
{ | { | |||
char *p; | char *p; | |||
for (p=str; *p; p++) { | for (p=str; *p; p++) { | |||
*p = tolower(*(unsigned char *)p); | *p = tolower(*(unsigned char *)p); | |||
} | } | |||
} | } | |||
static int do_search(struct read_db *db, char **args, char *output_path, int sho w_threads, enum folder_type ft, int verbose)/*{{{*/ | static int do_search(struct read_db *db, char **args, char *output_path, int sho w_threads, enum folder_type ft, int verbose, const char *imap_pipe, const char * imap_server, const char *imap_username, const char *imap_password, int please_cl ear)/*{{{*/ | |||
{ | { | |||
char *colon, *start_words; | char *colon, *start_words; | |||
int do_body, do_subject, do_from, do_to, do_cc, do_date, do_size; | int do_body, do_subject, do_from, do_to, do_cc, do_date, do_size; | |||
int do_att_name; | int do_att_name; | |||
int do_flags; | int do_flags; | |||
int do_path, do_msgid; | int do_path, do_msgid; | |||
char *key; | char *key; | |||
char *hit0, *hit1, *hit2, *hit3; | char *hit0, *hit1, *hit2, *hit3; | |||
int i; | int i; | |||
int n_hits; | int n_hits; | |||
int left_anchor; | int left_anchor; | |||
int imap_tried = 0; | ||||
struct imap_ll *imapc; | ||||
#define GET_IMAP if (!imap_tried) {\ | ||||
imap_tried = 1;\ | ||||
if (imap_pipe || imap_server) {\ | ||||
imapc = imap_start(imap_pipe, imap_server, imap_username, imap_pa | ||||
ssword);\ | ||||
} else {\ | ||||
fprintf(stderr, "[No IMAP settings]\n");\ | ||||
imapc = NULL;\ | ||||
}\ | ||||
} | ||||
had_failed_checksum = 0; | had_failed_checksum = 0; | |||
hit0 = new_array(char, db->n_msgs); | hit0 = new_array(char, db->n_msgs); | |||
hit1 = new_array(char, db->n_msgs); | hit1 = new_array(char, db->n_msgs); | |||
hit2 = new_array(char, db->n_msgs); | hit2 = new_array(char, db->n_msgs); | |||
hit3 = new_array(char, db->n_msgs); | hit3 = new_array(char, db->n_msgs); | |||
/* Argument structure is | /* Argument structure is | |||
* x:tokena+tokenb,~tokenc,tokend+tokene | * x:tokena+tokenb,~tokenc,tokend+tokene | |||
skipping to change at line 931 | skipping to change at line 964 | |||
} else { | } else { | |||
/*{{{ Scan over separate words within this argument */ | /*{{{ Scan over separate words within this argument */ | |||
do { | do { | |||
/* / = 'or' separator | /* / = 'or' separator | |||
* , = 'and' separator */ | * , = 'and' separator */ | |||
char *orsep; | char *orsep; | |||
char *andsep; | char *andsep; | |||
char *word, *orig_word, *lower_word; | char *word, *orig_word, *lower_word; | |||
char *equal; | char *equal; | |||
char *p; | ||||
int negate; | int negate; | |||
int had_orsep; | int had_orsep; | |||
int max_errors; | int max_errors; | |||
orsep = strchr(start_words, '/'); | orsep = strchr(start_words, '/'); | |||
andsep = strchr(start_words, ','); | andsep = strchr(start_words, ','); | |||
had_orsep = 0; | had_orsep = 0; | |||
if (andsep && (!orsep || (andsep < orsep))) { | if (andsep && (!orsep || (andsep < orsep))) { | |||
char *p, *q; | char *p, *q; | |||
skipping to change at line 984 | skipping to change at line 1016 | |||
} | } | |||
if (word[0] == '^') { | if (word[0] == '^') { | |||
left_anchor = 1; | left_anchor = 1; | |||
word++; | word++; | |||
} else { | } else { | |||
left_anchor = 0; | left_anchor = 0; | |||
} | } | |||
equal = strchr(word, '='); | equal = strchr(word, '='); | |||
if (equal) { | if (equal && (equal[1] == '\0' || isdigit(equal[1]))) { | |||
*equal = 0; | *equal = 0; | |||
max_errors = atoi(equal + 1); | max_errors = atoi(equal + 1); | |||
/* Extend this to do anchoring etc */ | /* Extend this to do anchoring etc */ | |||
} else { | } else { | |||
equal = NULL; | ||||
max_errors = 0; /* keep GCC quiet */ | max_errors = 0; /* keep GCC quiet */ | |||
} | } | |||
/* Canonicalise search string to lowercase, since the database has all | /* Canonicalise search string to lowercase, since the database has all | |||
* tokens handled that way. But not for path search! */ | * tokens handled that way. But not for path search! */ | |||
lower_word = new_string(word); | lower_word = new_string(word); | |||
string_tolower(lower_word); | string_tolower(lower_word); | |||
memset(hit0, 0, db->n_msgs); | memset(hit0, 0, db->n_msgs); | |||
if (equal) { | if (equal) { | |||
skipping to change at line 1092 | skipping to change at line 1125 | |||
char *message_path; | char *message_path; | |||
int is_in_new; | int is_in_new; | |||
message_path = db->data + db->path_offsets[i]; | message_path = db->data + db->path_offsets[i]; | |||
is_in_new = looks_like_maildir_new_p(message_path); | is_in_new = looks_like_maildir_new_p(message_path); | |||
target_path = mk_maildir_path(i, output_path, is_in_new, is_seen , is_replied, is_flagged); | target_path = mk_maildir_path(i, output_path, is_in_new, is_seen , is_replied, is_flagged); | |||
create_symlink(message_path, target_path); | create_symlink(message_path, target_path); | |||
free(target_path); | free(target_path); | |||
++n_hits; | ++n_hits; | |||
} | } | |||
break; | break; | |||
case DB_MSG_IMAP: | ||||
{ | ||||
char *target_path; | ||||
target_path = mk_maildir_path(i, output_path, 0, is_seen, is_rep | ||||
lied, is_flagged); | ||||
GET_IMAP; | ||||
if (imapc) imap_fetch_message_raw(db->data + db->path_offsets[i] | ||||
, imapc, write_to_file, target_path); | ||||
free(target_path); | ||||
++n_hits; | ||||
} | ||||
break; | ||||
case DB_MSG_MBOX: | case DB_MSG_MBOX: | |||
{ | { | |||
char *target_path = mk_maildir_path(i, output_path, !is_seen, is _seen, is_replied, is_flagged); | char *target_path = mk_maildir_path(i, output_path, !is_seen, is _seen, is_replied, is_flagged); | |||
try_copy_to_path(db, i, target_path); | try_copy_to_path(db, i, target_path); | |||
free(target_path); | free(target_path); | |||
++n_hits; | ++n_hits; | |||
} | } | |||
break; | break; | |||
case DB_MSG_DEAD: | case DB_MSG_DEAD: | |||
break; | break; | |||
skipping to change at line 1119 | skipping to change at line 1162 | |||
if (hit3[i]) { | if (hit3[i]) { | |||
switch (rd_msg_type(db, i)) { | switch (rd_msg_type(db, i)) { | |||
case DB_MSG_FILE: | case DB_MSG_FILE: | |||
{ | { | |||
char *target_path = mk_mh_path(i, output_path); | char *target_path = mk_mh_path(i, output_path); | |||
create_symlink(db->data + db->path_offsets[i], target_path); | create_symlink(db->data + db->path_offsets[i], target_path); | |||
free(target_path); | free(target_path); | |||
++n_hits; | ++n_hits; | |||
} | } | |||
break; | break; | |||
case DB_MSG_IMAP: | ||||
{ | ||||
char *target_path = mk_mh_path(i, output_path); | ||||
GET_IMAP; | ||||
if (imapc) imap_fetch_message_raw(db->data + db->path_offsets[i] | ||||
, imapc, write_to_file, target_path); | ||||
free(target_path); | ||||
++n_hits; | ||||
} | ||||
break; | ||||
case DB_MSG_MBOX: | case DB_MSG_MBOX: | |||
{ | { | |||
char *target_path = mk_mh_path(i, output_path); | char *target_path = mk_mh_path(i, output_path); | |||
try_copy_to_path(db, i, target_path); | try_copy_to_path(db, i, target_path); | |||
free(target_path); | free(target_path); | |||
++n_hits; | ++n_hits; | |||
} | } | |||
break; | break; | |||
case DB_MSG_DEAD: | case DB_MSG_DEAD: | |||
break; | break; | |||
skipping to change at line 1152 | skipping to change at line 1204 | |||
for (i=0; i<db->n_msgs; i++) { | for (i=0; i<db->n_msgs; i++) { | |||
if (hit3[i]) { | if (hit3[i]) { | |||
switch (rd_msg_type(db, i)) { | switch (rd_msg_type(db, i)) { | |||
case DB_MSG_FILE: | case DB_MSG_FILE: | |||
{ | { | |||
append_file_to_mbox(db->data + db->path_offsets[i], out); | append_file_to_mbox(db->data + db->path_offsets[i], out); | |||
++n_hits; | ++n_hits; | |||
} | } | |||
break; | break; | |||
case DB_MSG_IMAP: | ||||
{ | ||||
GET_IMAP; | ||||
if (imapc) imap_fetch_message_raw(db->data + db->path_offsets[ | ||||
i], imapc, append_data_to_mbox, out); | ||||
++n_hits; | ||||
} | ||||
break; | ||||
case DB_MSG_MBOX: | case DB_MSG_MBOX: | |||
{ | { | |||
append_mboxmsg_to_mbox(db, i, out); | append_mboxmsg_to_mbox(db, i, out); | |||
++n_hits; | ++n_hits; | |||
} | } | |||
break; | break; | |||
case DB_MSG_DEAD: | case DB_MSG_DEAD: | |||
break; | break; | |||
} | } | |||
} | } | |||
skipping to change at line 1173 | skipping to change at line 1232 | |||
fclose(out); | fclose(out); | |||
} | } | |||
break; | break; | |||
/*}}}*/ | /*}}}*/ | |||
case FT_RAW:/*{{{*/ | case FT_RAW:/*{{{*/ | |||
for (i=0; i<db->n_msgs; i++) { | for (i=0; i<db->n_msgs; i++) { | |||
if (hit3[i]) { | if (hit3[i]) { | |||
switch (rd_msg_type(db, i)) { | switch (rd_msg_type(db, i)) { | |||
case DB_MSG_FILE: | case DB_MSG_FILE: | |||
case DB_MSG_IMAP: | ||||
{ | { | |||
++n_hits; | ++n_hits; | |||
printf("%s\n", db->data + db->path_offsets[i]); | printf("%s\n", db->data + db->path_offsets[i]); | |||
} | } | |||
break; | break; | |||
case DB_MSG_MBOX: | case DB_MSG_MBOX: | |||
{ | { | |||
unsigned int mbix, msgix; | unsigned int mbix, msgix; | |||
int start, len, after_end; | int start, len, after_end; | |||
start = db->mtime_table[i]; | start = db->mtime_table[i]; | |||
skipping to change at line 1212 | skipping to change at line 1272 | |||
case DB_MSG_FILE: | case DB_MSG_FILE: | |||
{ | { | |||
char *filename; | char *filename; | |||
++n_hits; | ++n_hits; | |||
printf("---------------------------------\n"); | printf("---------------------------------\n"); | |||
filename = db->data + db->path_offsets[i]; | filename = db->data + db->path_offsets[i]; | |||
printf("%s\n", filename); | printf("%s\n", filename); | |||
parsed = make_rfc822(filename); | parsed = make_rfc822(filename); | |||
} | } | |||
break; | break; | |||
case DB_MSG_IMAP: | ||||
{ | ||||
char *filename; | ||||
++n_hits; | ||||
printf("---------------------------------\n"); | ||||
filename = db->data + db->path_offsets[i]; | ||||
printf("%s\n", filename); | ||||
GET_IMAP; | ||||
parsed = imapc ? make_rfc822_from_imap(filename, imapc) : NULL; | ||||
} | ||||
break; | ||||
case DB_MSG_MBOX: | case DB_MSG_MBOX: | |||
{ | { | |||
unsigned int mbix, msgix; | unsigned int mbix, msgix; | |||
int start, len, after_end; | int start, len, after_end; | |||
unsigned char *mbox_start, *msg_start; | unsigned char *mbox_start, *msg_start; | |||
int mbox_len, msg_len; | int mbox_len, msg_len; | |||
int mbox_index; | int mbox_index; | |||
start = db->mtime_table[i]; | start = db->mtime_table[i]; | |||
len = db->size_table[i]; | len = db->size_table[i]; | |||
skipping to change at line 1253 | skipping to change at line 1324 | |||
if (parsed) { | if (parsed) { | |||
char datebuf[64]; | char datebuf[64]; | |||
struct tm *thetm; | struct tm *thetm; | |||
if (parsed->hdrs.to) printf(" To: %s\n", parsed->hdrs. to); | if (parsed->hdrs.to) printf(" To: %s\n", parsed->hdrs. to); | |||
if (parsed->hdrs.cc) printf(" Cc: %s\n", parsed->hdrs. cc); | if (parsed->hdrs.cc) printf(" Cc: %s\n", parsed->hdrs. cc); | |||
if (parsed->hdrs.from) printf(" From: %s\n", parsed->hdrs. from); | if (parsed->hdrs.from) printf(" From: %s\n", parsed->hdrs. from); | |||
if (parsed->hdrs.subject) printf(" Subject: %s\n", parsed->hdrs. subject); | if (parsed->hdrs.subject) printf(" Subject: %s\n", parsed->hdrs. subject); | |||
if (parsed->hdrs.message_id) | if (parsed->hdrs.message_id) | |||
printf(" Message-ID: %s\n", parsed->hdrs. message_id); | printf(" Message-ID: %s\n", parsed->hdrs. message_id); | |||
if (parsed->hdrs.in_reply_to) | ||||
printf(" In-Reply-To:%s\n", parsed->hdrs. | ||||
in_reply_to); | ||||
thetm = gmtime(&parsed->hdrs.date); | thetm = gmtime(&parsed->hdrs.date); | |||
strftime(datebuf, sizeof(datebuf), "%a, %d %b %Y", thetm); | strftime(datebuf, sizeof(datebuf), "%a, %d %b %Y", thetm); | |||
printf(" Date: %s\n", datebuf); | printf(" Date: %s\n", datebuf); | |||
free_rfc822(parsed); | free_rfc822(parsed); | |||
} | } | |||
} | } | |||
} | } | |||
break; | break; | |||
/*}}}*/ | /*}}}*/ | |||
case FT_IMAP:/*{{{*/ | ||||
GET_IMAP; | ||||
if (!imapc) break; | ||||
if (please_clear) { | ||||
imap_clear_folder(imapc, output_path); | ||||
} | ||||
for (i=0; i<db->n_msgs; i++) { | ||||
if (hit3[i]) { | ||||
int is_seen, is_replied, is_flagged; | ||||
get_flags_from_file(db, i, &is_seen, &is_replied, &is_flagged); | ||||
switch (rd_msg_type(db, i)) { | ||||
case DB_MSG_FILE: | ||||
{ | ||||
int len; | ||||
unsigned char *data; | ||||
create_ro_mapping(db->data + db->path_offsets[i], &data, &len); | ||||
if (data) { | ||||
imap_append_new_message(imapc, output_path, data, len, is_seen | ||||
, is_replied, is_flagged); | ||||
free_ro_mapping(data, len); | ||||
} | ||||
++n_hits; | ||||
} | ||||
break; | ||||
case DB_MSG_IMAP: | ||||
{ | ||||
imap_copy_message(imapc, db->data + db->path_offsets[i], output_ | ||||
path); | ||||
++n_hits; | ||||
} | ||||
break; | ||||
case DB_MSG_MBOX: | ||||
{ | ||||
unsigned char *start, *data; | ||||
int mbox_len, msg_len, mbi; | ||||
get_validated_mbox_msg(db, i, &mbi, &data, &mbox_len, &start, &m | ||||
sg_len); | ||||
imap_append_new_message(imapc, output_path, start, msg_len, is_s | ||||
een, is_replied, is_flagged); | ||||
if (data) { | ||||
free_ro_mapping(data, mbox_len); | ||||
} | ||||
++n_hits; | ||||
} | ||||
break; | ||||
case DB_MSG_DEAD: | ||||
break; | ||||
} | ||||
} | ||||
} | ||||
break; | ||||
/*}}}*/ | ||||
default: | default: | |||
assert(0); | assert(0); | |||
break; | break; | |||
} | } | |||
free(hit0); | free(hit0); | |||
free(hit1); | free(hit1); | |||
free(hit2); | free(hit2); | |||
free(hit3); | free(hit3); | |||
if ((ft != FT_RAW) && (ft != FT_EXCERPT)) { | if ((ft != FT_RAW) && (ft != FT_EXCERPT)) { | |||
skipping to change at line 1428 | skipping to change at line 1549 | |||
free(fpath); | free(fpath); | |||
} | } | |||
/*}}}*/ | /*}}}*/ | |||
static void clear_mbox_folder(char *path)/*{{{*/ | static void clear_mbox_folder(char *path)/*{{{*/ | |||
{ | { | |||
unlink(path); | unlink(path); | |||
} | } | |||
/*}}}*/ | /*}}}*/ | |||
int search_top(int do_threads, int do_augment, char *database_path, char *comple te_mfolder, char **argv, enum folder_type ft, int verbose)/*{{{*/ | int search_top(int do_threads, int do_augment, char *database_path, char *comple te_mfolder, char **argv, enum folder_type ft, int verbose, const char *imap_pipe , const char *imap_server, const char *imap_username, const char *imap_password) /*{{{*/ | |||
{ | { | |||
struct read_db *db; | struct read_db *db; | |||
int result; | int result; | |||
int please_clear = 0; | ||||
db = open_db(database_path); | db = open_db(database_path); | |||
switch (ft) { | switch (ft) { | |||
case FT_MAILDIR: | case FT_MAILDIR: | |||
maybe_create_maildir(complete_mfolder); | maybe_create_maildir(complete_mfolder); | |||
break; | break; | |||
case FT_MH: | case FT_MH: | |||
if (!directory_exists_remove_other(complete_mfolder)) { | if (!directory_exists_remove_other(complete_mfolder)) { | |||
create_dir(complete_mfolder); | create_dir(complete_mfolder); | |||
} | } | |||
break; | break; | |||
case FT_MBOX: | case FT_MBOX: | |||
/* Nothing to do */ | /* Nothing to do */ | |||
break; | break; | |||
case FT_RAW: | case FT_RAW: | |||
case FT_EXCERPT: | case FT_EXCERPT: | |||
case FT_IMAP: /* Do it later, we do not yet have an IMAP connection */ | ||||
break; | break; | |||
default: | default: | |||
assert(0); | assert(0); | |||
} | } | |||
if (!do_augment) { | if (!do_augment) { | |||
switch (ft) { | switch (ft) { | |||
case FT_MAILDIR: | case FT_MAILDIR: | |||
clear_maildir_subfolder(complete_mfolder, "new"); | clear_maildir_subfolder(complete_mfolder, "new"); | |||
clear_maildir_subfolder(complete_mfolder, "cur"); | clear_maildir_subfolder(complete_mfolder, "cur"); | |||
break; | break; | |||
case FT_MH: | case FT_MH: | |||
clear_mh_folder(complete_mfolder); | clear_mh_folder(complete_mfolder); | |||
break; | break; | |||
case FT_MBOX: | case FT_MBOX: | |||
clear_mbox_folder(complete_mfolder); | clear_mbox_folder(complete_mfolder); | |||
break; | break; | |||
case FT_RAW: | case FT_RAW: | |||
case FT_EXCERPT: | case FT_EXCERPT: | |||
break; | break; | |||
case FT_IMAP: | ||||
/* Do it later: we do not yet have an IMAP connection */ | ||||
please_clear = 1; | ||||
break; | ||||
default: | default: | |||
assert(0); | assert(0); | |||
} | } | |||
} | } | |||
result = do_search(db, argv, complete_mfolder, do_threads, ft, verbose); | result = do_search(db, argv, complete_mfolder, do_threads, ft, verbose, imap_p ipe, imap_server, imap_username, imap_password, please_clear); | |||
free(complete_mfolder); | free(complete_mfolder); | |||
close_db(db); | close_db(db); | |||
return result; | return result; | |||
} | } | |||
/*}}}*/ | /*}}}*/ | |||
End of changes. 19 change blocks. | ||||
5 lines changed or deleted | 143 lines changed or added |