--- /dev/null
+#include <h/mh.h>
+#include <h/utils.h>
+#include <h/addrsbr.h>
+
+static char *threadid(char *, char *);
+
+char *
+getthreadid(const char *path)
+{
+ char *msgid = NULL;
+ char *referens = NULL;
+ char *ret;
+ struct field f = {{0}};
+ enum state state = FLD2;
+ FILE *file = fopen(path, "r");
+
+ while (state == FLD2 && !msgid && !referens) {
+ switch (state = m_getfld2(state, &f, file)) {
+ case FLD2:
+ if (strncasecmp("message-id", f.name, f.namelen)==0) {
+ msgid = f.value;
+ f.value = NULL;
+ } else if (strncasecmp("references", f.name, f.namelen)==0) {
+ referens = f.value;
+ f.value = NULL;
+ }
+ break;
+ default:
+ fclose(file);
+ break;
+ }
+ }
+
+ ret = threadid(msgid, referens);
+
+ mh_free0(&msgid);
+ mh_free0(&referens);
+
+ return ret;
+}
+
+static char *
+threadid(char *msgid, char *referens)
+{
+ char *threadfrom;
+ char *start, *end;
+ char *cp;
+
+ threadfrom = referens ? referens : msgid;
+
+ start = strchr(threadfrom, '<');
+ end = strchr(start, '>');
+ if (!(*start) || !(*end)) {
+ return NULL;
+ }
+ *end = '\0';
+ cp = mh_xstrdup(start + 1);
+ *end = '>';
+
+ return cp;
+}
{ "format format", 0 },
#define WIDTHSW 23
{ "width columns", 0 },
-#define VERSIONSW 24
+#define THREADSW 24
+ { "thread", 0 },
+#define VERSIONSW 25
{ "Version", 0 },
-#define HELPSW 25
+#define HELPSW 26
{ "help", 0 },
{ NULL, 0 }
};
*/
static int pcompile(char **, char *);
static int pmatches(FILE *, int);
+static struct nexus * createonethread(char *);
+static struct nexus * createpickthread(char *);
static int listsw = -1;
case AFTRSW:
case BEFRSW:
case SRCHSW:
+ case THREADSW:
vec[vecp++] = --cp;
pattern:
if (!(cp = *argp++)) /* allow -xyz arguments */
}
}
- head->free(&head);
+ if (head) {
+ head->free(&head);
+ }
mp->lowsel = lo;
mp->hghsel = hi;
{ "before date", 0 },
#define PRDATF 14
{ "datefield field", 5 },
+#define PRTHREAD 15
+ { "thread msg", 0 },
{ NULL, 0 }
};
prvarg();
return NULL;
+ case PRTHREAD:
+ if (!(cp = nxtarg())) { /* allow -xyz arguments */
+ padvise(NULL, "missing argument to %s", argp[-2]);
+ }
+ return createpickthread(cp);
case PRCC:
case PRDATE:
case PRFROM:
static void
BINfree(struct nexus **n)
{
- struct nexus *bin = *n;
- struct bin_data *bd = bin->data;
+ struct bin_data *bd;
+
+ if (!(*n)) {
+ return;
+ }
+
+ bd = (*n)->data;
if (bd->left && bd->left->free) {
bd->left->free(&bd->left);
int ret;
char *buf;
- /* check for the write field */
- if (g->header && *g->header && mh_strcasecmp(g->header, f->name)) {
+ if (!g->header && *f->name) {
return FALSE;
}
- if (!g->header && *f->name) {
+ /* check for the right field */
+ if (g->header && *g->header && mh_strcasecmp(g->header, f->name)==0) {
return FALSE;
}
static void
GREPfree(struct nexus **n)
{
- struct grep_data *gd = (*n)->data;
+ struct grep_data *gd;
+ if (!(*n)) {
+ return;
+ }
+ gd = (*n)->data;
mh_free0(&gd->header);
regfree(gd->preg);
mh_free0(n);
static void
DATEfree(struct nexus **n)
{
- struct date_data *dd = (*n)->data;
+ struct date_data *dd;
+ if (!(*n)) {
+ return;
+ }
+ dd = (*n)->data;
mh_free0(&dd->datef);
mh_free0(n);
print_debug_level(level);
fprintf(stderr, "TEMPORAL(%s) %s: %s\n",dd->after ? "after" : "before", dd->datef, dasctime(&dd->tws));
}
+
+static struct nexus *
+createpickthread(char *msgs)
+{
+ char *folder = NULL;
+ struct msgs_array msgarray = {0};
+ struct msgs_array files = {0};
+ struct nexus *ret = NULL;
+ struct nexus *c;
+ struct nexus *or;
+ struct bin_data *bd;
+ char *buf;
+ char **cp = brkstring(msgs, " \t", NULL);
+ int i;
+
+ for (; cp && *cp; cp++) {
+ switch (**cp) {
+ case '@':
+ case '+':
+ if (folder) {
+ advise("","");
+ break;
+ }
+ folder = mh_xstrdup(*cp);
+ break;
+ default:
+ app_msgarg(&msgarray, mh_xstrdup(*cp));
+ }
+ }
+
+ parse_msgs(&msgarray, folder, &files);
+
+ for (i = 0; i < files.size; i++) {
+ buf = getthreadid(files.msgs[i]);
+ if (!buf) {
+ continue;
+ }
+
+ c = createonethread(buf);
+
+ if (!ret) {
+ ret = c;
+ continue;
+ }
+
+
+ or = newnexus(TYPE_OR);
+ bd = or->data;
+ bd->right = ret;
+ bd->left = c;
+ ret = or;
+ }
+
+ mh_free0(&(files.msgs));
+ mh_free0(&(msgarray.msgs));
+
+ return ret;
+}
+
+static struct nexus *
+createonethread(char *c)
+{
+ struct nexus *ret = newnexus(TYPE_OR);
+ struct nexus *left = newnexus(TYPE_GREP);
+ struct nexus *right = newnexus(TYPE_GREP);
+ struct bin_data *bd = ret->data;
+ struct grep_data *gd = left->data;
+ char buf[BUFSIZ];
+
+ bd->left = left;
+ bd->right = right;
+ gd->header = "message-id";
+
+ snprintf(buf, sizeof(buf), "^[ \t]*<%s>", c);
+ if(!gcompile(gd, buf)) {
+ padvise(NULL, "pattern error %s", c);
+ goto error;
+ }
+
+ gd = right->data;
+ gd->header = "references";
+
+ snprintf(buf, sizeof(buf), "^[ \t]*<%s>", c);
+ if(!gcompile(gd, buf)) {
+ padvise(NULL, "pattern error in %s", c);
+ goto error;
+ }
+
+ return ret;
+
+error:
+ GREPfree(&left);
+ GREPfree(&right);
+ BINfree(&ret);
+ return NULL;
+
+}