7 #define LEN(a) (sizeof(a) / sizeof((a)[0]))
11 char *id
; /* message-id header value */
12 int id_len
; /* message-id length */
13 char *rply
; /* reply-to header value */
14 int rply_len
; /* reply-to length */
15 int date
; /* message receiving date */
16 int depth
; /* depth of message in the thread */
17 int oidx
; /* the original index of the message */
24 static int id_cmp(char *i1
, int l1
, char *i2
, int l2
)
28 return strncmp(i1
, i2
, l1
);
31 static int msgcmp_id(void *v1
, void *v2
)
33 struct msg
*t1
= *(struct msg
**) v1
;
34 struct msg
*t2
= *(struct msg
**) v2
;
35 return id_cmp(t1
->id
, t1
->id_len
, t2
->id
, t2
->id_len
);
38 static int msgcmp_date(void *v1
, void *v2
)
40 struct msg
*t1
= *(struct msg
**) v1
;
41 struct msg
*t2
= *(struct msg
**) v2
;
42 return t1
->date
== t2
->date
? t1
->oidx
- t2
->oidx
: t1
->date
- t2
->date
;
45 static char *months
[] = {
46 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
47 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
50 static char *readtok(char *s
, char *d
)
52 while (*s
== ' ' || *s
== ':')
54 while (!strchr(" \t\r\n:", *s
))
60 static int fromdate(char *s
)
63 int year
, mon
, day
, hour
, min
, sec
;
65 /* parsing "From ali Tue Apr 16 20:18:40 2013" */
66 s
= readtok(s
, tok
); /* From */
67 s
= readtok(s
, tok
); /* username */
68 s
= readtok(s
, tok
); /* day of week */
69 s
= readtok(s
, tok
); /* month name */
71 for (i
= 0; i
< LEN(months
); i
++)
72 if (!strcmp(months
[i
], tok
))
74 s
= readtok(s
, tok
); /* day of month */
76 s
= readtok(s
, tok
); /* hour */
78 s
= readtok(s
, tok
); /* minute */
80 s
= readtok(s
, tok
); /* seconds */
82 s
= readtok(s
, tok
); /* year */
84 return ((year
- 1970) * 400 + mon
* 31 + day
) * 24 * 3600 +
85 hour
* 3600 + min
* 60 + sec
;
88 static struct msg
*msg_byid(struct msg
**msgs
, int n
, char *id
, int len
)
94 int d
= id_cmp(id
, len
, msgs
[m
]->id
, msgs
[m
]->id_len
);
105 static void msgs_tree(struct msg
**all
, struct msg
**sorted_id
, int n
)
108 for (i
= 0; i
< n
; i
++) {
109 struct msg
*msg
= all
[i
];
113 dad
= msg_byid(sorted_id
, n
, msg
->rply
, msg
->rply_len
);
117 msg
->depth
= dad
->depth
+ 1;
118 if (!msg
->parent
->head
)
119 msg
->parent
->head
= msg
;
121 msg
->parent
->tail
->next
= msg
;
122 msg
->parent
->tail
= msg
;
126 static void hdr_init(struct msg
*msg
)
128 char *id_hdr
= mail_hdr(msg
->mail
, "Message-ID:");
129 char *rply_hdr
= mail_hdr(msg
->mail
, "In-Reply-To:");
131 int len
= hdr_len(id_hdr
);
132 char *beg
= memchr(id_hdr
, '<', len
);
133 char *end
= beg
? memchr(id_hdr
, '>', len
) : NULL
;
138 msg
->id_len
= end
- beg
;
142 int len
= hdr_len(rply_hdr
);
143 char *beg
= memchr(rply_hdr
, '<', len
);
144 char *end
= beg
? memchr(rply_hdr
, '>', len
) : NULL
;
149 msg
->rply_len
= end
- beg
;
152 msg
->date
= fromdate(msg
->mail
->head
);
155 static struct msg
**put_msg(struct msg
**sorted
, struct msg
*msg
)
157 struct msg
*cur
= msg
->head
;
160 sorted
= put_msg(sorted
, cur
);
166 static void msgs_sort(struct msg
**sorted
, struct msg
**msgs
, int n
)
169 for (i
= 0; i
< n
; i
++)
170 if (!msgs
[i
]->parent
)
171 sorted
= put_msg(sorted
, msgs
[i
]);
174 int sort_mails(struct mail
**mails
, int *levels
, int n
)
176 struct msg
*msgs
= malloc(n
* sizeof(*msgs
));
177 struct msg
**sorted_date
= malloc(n
* sizeof(*sorted_date
));
178 struct msg
**sorted_id
= malloc(n
* sizeof(*sorted_id
));
179 struct msg
**sorted
= malloc(n
* sizeof(*sorted
));
181 if (!msgs
|| !sorted_date
|| !sorted_id
) {
188 memset(msgs
, 0, n
* sizeof(*msgs
));
189 for (i
= 0; i
< n
; i
++) {
190 struct msg
*msg
= &msgs
[i
];
192 msg
->mail
= mails
[i
];
194 sorted_date
[i
] = msg
;
197 qsort(sorted_date
, n
, sizeof(*sorted_date
), (void *) msgcmp_date
);
198 qsort(sorted_id
, n
, sizeof(*sorted_id
), (void *) msgcmp_id
);
199 msgs_tree(sorted_date
, sorted_id
, n
);
200 msgs_sort(sorted
, sorted_date
, n
);
201 for (i
= 0; i
< n
; i
++)
202 mails
[i
] = sorted
[i
]->mail
;
203 for (i
= 0; i
< n
; i
++)
204 levels
[i
] = sorted
[i
]->depth
;