29 |
#define obstack_chunk_free free |
#define obstack_chunk_free free |
30 |
#include <obstack.h> |
#include <obstack.h> |
31 |
|
|
|
typedef int (*read_fn_t)(void *data, char *buf, size_t size); |
|
|
|
|
32 |
static int transfer_command(void *, void *, char *); |
static int transfer_command(void *, void *, char *); |
33 |
static void process_command(void *, void *, char *, int); |
static void process_command(void *, void *, char *, int); |
34 |
static void transfer_header(void *, void *, read_fn_t, void *); |
static void transfer_header(void *, void *, struct list *list); |
35 |
static void process_header_line(char *); |
static void process_header_line(char *); |
36 |
static void transfer_body(void *, void *, read_fn_t, void *); |
static void transfer_body(void *, void *); |
|
static void static_body_transfer(void *, void *, read_fn_t, void *); |
|
|
static void dynamic_body_transfer(void *, void *, read_fn_t, void *); |
|
|
static void clear_body_transfer(void *, void *); |
|
37 |
static void add_remailer_commands(void *); |
static void add_remailer_commands(void *); |
38 |
static void transform_body(void *sd_server); |
static void transform_body(void *sd_server); |
39 |
static void process_data(void *sd_client, void *sd_server); |
static void process_data(void *sd_client, void *sd_server); |
40 |
|
|
41 |
static void collect_body(void *sd_client, char **retptr); |
|
42 |
static void collect_headers(void *sd_client, struct list **listp); |
/* Auxiliary list handling functions */ |
43 |
|
/* These belong to the future list.c */ |
44 |
|
typedef int (*list_iterator_t)(struct list *list, void *data); |
45 |
|
|
46 |
int |
void |
47 |
socket_reader(void *sd_client, char *buf, size_t size) |
list_iterate(struct list *p, list_iterator_t itr, void *data) |
48 |
{ |
{ |
49 |
return recvline(SERVER, sd_client, buf, size); |
while (p) { |
50 |
|
struct list *q = p->next; |
51 |
|
itr(p, data); |
52 |
|
p = q; |
53 |
|
}; |
54 |
} |
} |
55 |
|
|
|
enum buf_state { |
|
|
state_init, |
|
|
state_end, |
|
|
state_finish |
|
|
}; |
|
|
|
|
|
struct mem_buf { |
|
|
char *buffer; |
|
|
size_t pos; |
|
|
size_t size; |
|
|
enum buf_state state; |
|
|
}; |
|
|
|
|
56 |
void |
void |
57 |
init_mem_buf(struct mem_buf *mb, char *buf) |
list_append(struct list **a, struct list *b) |
58 |
{ |
{ |
59 |
memset(mb, 0, sizeof(*mb)); |
if (!*a) |
60 |
mb->buffer = buf; |
*a = b; |
61 |
mb->size = strlen(buf); |
else { |
62 |
mb->pos = 0; |
struct list *p; |
63 |
mb->state = state_init; |
|
64 |
|
for (p = *a; p->next; p = p->next) |
65 |
|
; |
66 |
|
p->next = b; |
67 |
|
} |
68 |
} |
} |
69 |
|
|
70 |
int |
|
71 |
memory_reader(void *closure, char *buf, size_t size) |
/* Collect and send headers */ |
72 |
|
|
73 |
|
/* Headers spanning multiple lines are wrapped into a single line, preserving |
74 |
|
the newlines. When sending to the server they are split again at newlines |
75 |
|
snd sent in multiline lines. */ |
76 |
|
|
77 |
|
static void |
78 |
|
get_boundary(char *line) |
79 |
{ |
{ |
80 |
struct mem_buf *mb = closure; |
char boundary_buf[LINEBUFFER+1], *p; |
|
int i = 0; |
|
|
int crlf; |
|
|
|
|
|
switch (mb->state) { |
|
|
case state_init: |
|
|
crlf = 0; |
|
|
size--; /* make space for terminating zero */ |
|
|
for (i = 0; i < size; i++) { |
|
|
if (mb->pos == mb->size) { |
|
|
mb->state = state_end; |
|
|
break; |
|
|
} |
|
|
*buf++ = mb->buffer[mb->pos++]; |
|
|
if (i > 2 && buf[-2] == '\r' && buf[-1] == '\n') { |
|
|
crlf = 1; |
|
|
break; |
|
|
} |
|
|
} |
|
81 |
|
|
82 |
if (!crlf) { |
if (strncmp(line, "Content-Type:", 13)) |
83 |
strcpy(buf, CRLF); |
return; |
84 |
i += 2; |
|
85 |
buf += 2; |
safe_strcpy(boundary_buf, line); |
86 |
} |
change_to_lower(boundary_buf); |
87 |
*buf = 0; |
p = strstr(boundary_buf, "boundary="); |
88 |
break; |
if (!p) |
89 |
|
return; |
90 |
case state_end: |
p += 9; |
91 |
if (size < 4) |
if (*p == '"') { |
92 |
i = 0; |
char *q = strchr(++p, '"'); |
93 |
else { |
if (*q) |
94 |
strcpy(buf, "." CRLF); |
*q = 0; |
95 |
i = 3; |
} |
96 |
|
message.boundary = xmalloc(strlen(p) + 3); |
97 |
|
sprintf(message.boundary, "--%s", p); |
98 |
|
topt |= T_BOUNDARY; |
99 |
|
} |
100 |
|
|
101 |
|
static void |
102 |
|
collect_headers(void *sd_client, struct list **listp) |
103 |
|
{ |
104 |
|
struct list *tail; |
105 |
|
char buf[LINEBUFFER+1]; |
106 |
|
|
107 |
|
*listp = tail = NULL; |
108 |
|
while (recvline(SERVER, sd_client, buf, LINEBUFFER)) { |
109 |
|
if (strncmp(buf, CRLF, 2) == 0) |
110 |
|
break; |
111 |
|
remcrlf(buf); |
112 |
|
if (isspace(buf[0])) { |
113 |
|
if (!tail) |
114 |
|
/* Something wrong, assume we've got no |
115 |
|
headers */ |
116 |
|
break; |
117 |
|
tail->line = xrealloc(tail->line, |
118 |
|
strlen(tail->line) + |
119 |
|
strlen(buf) + 2); |
120 |
|
strcat(tail->line, "\n"); |
121 |
|
strcat(tail->line, buf); |
122 |
|
} else { |
123 |
|
if (!(topt & (T_BOUNDARY|T_ENTIRE_BODY)) && tail) |
124 |
|
get_boundary(tail->line); |
125 |
|
tail = new_element(tail, listp, buf); |
126 |
} |
} |
|
break; |
|
|
|
|
|
case state_finish: |
|
|
i = 0; |
|
127 |
} |
} |
|
return i; |
|
128 |
} |
} |
129 |
|
static void |
130 |
|
write_header_line (void *sd_server, char *line) |
131 |
|
{ |
132 |
|
char *p; |
133 |
|
|
134 |
struct list_buf { |
p = strtok(line, "\n"); |
135 |
struct list *list; |
do { |
136 |
enum buf_state state; |
swrite(CLIENT, sd_server, p); |
137 |
}; |
swrite(CLIENT, sd_server, CRLF); |
138 |
|
} while (p = strtok(NULL, "\n")); |
139 |
|
} |
140 |
|
|
141 |
void |
void |
142 |
init_list_buf(struct list_buf *lb, struct list *list) |
send_header (void *sd_server, struct list **plist) |
143 |
{ |
{ |
144 |
lb->list = list; |
struct list *p; |
145 |
lb->state = state_init; |
p = *plist; |
146 |
} |
while (p) { |
147 |
|
struct list *q = p->next; |
148 |
|
write_header_line(sd_server, p->line); |
149 |
|
free(p->line); |
150 |
|
free(p); |
151 |
|
p = q; |
152 |
|
} |
153 |
|
*plist = NULL; |
154 |
|
} |
155 |
|
|
156 |
|
|
157 |
|
/* Collect and sent the message body */ |
158 |
|
|
159 |
|
/* When read each CRLF is replaced by a single newline. |
160 |
|
When sent, the reverse procedure is performed. |
161 |
|
|
162 |
|
The handling of MIME encoded messages depends on the |
163 |
|
setting of T_ENTIRE_BODY bit in topt. If the bit is set, the |
164 |
|
entire body is read into memory. Otherwise, only the first |
165 |
|
part is read and processed, all the rest is passed to the |
166 |
|
server verbatim. */ |
167 |
|
|
168 |
|
#define ST_INIT 0 |
169 |
|
#define ST_HDR 1 |
170 |
|
#define ST_BODY 2 |
171 |
|
#define ST_DONE 3 |
172 |
|
|
173 |
int |
static void |
174 |
list_reader(void *closure, char *buf, size_t size) |
collect_body(void *sd_client, char **retptr) |
175 |
{ |
{ |
176 |
struct list_buf *lb = closure; |
int nread; |
177 |
|
char buf[LINEBUFFER+1]; |
178 |
|
struct obstack stk; |
179 |
|
int state = 0; |
180 |
|
struct list *tail = NULL; |
181 |
|
int len; |
182 |
|
|
183 |
switch (lb->state) { |
if (topt & T_BOUNDARY) |
184 |
case state_init: |
len = strlen(message.boundary); |
185 |
if (!lb->list) { |
|
186 |
lb->state = state_finish; |
obstack_init (&stk); |
187 |
strncpy(buf, CRLF, size); |
while (state != ST_DONE |
188 |
|
&& (nread = recvline(SERVER, sd_client, buf, LINEBUFFER))) { |
189 |
|
if (strncmp(buf, "."CRLF, 3) == 0) /* EOM */ |
190 |
|
break; |
191 |
|
|
192 |
|
remcrlf(buf); |
193 |
|
|
194 |
|
if (topt & T_BOUNDARY) { |
195 |
|
switch (state) { |
196 |
|
case ST_INIT: |
197 |
|
if (strcmp(buf, message.boundary) == 0) |
198 |
|
state = ST_HDR; |
199 |
|
break; |
200 |
|
|
201 |
|
case ST_HDR: |
202 |
|
if (buf[0] == 0) |
203 |
|
state = ST_BODY; |
204 |
|
else |
205 |
|
tail = new_element(tail, |
206 |
|
&message.mime_hdr, |
207 |
|
buf); |
208 |
|
break; |
209 |
|
|
210 |
|
case ST_BODY: |
211 |
|
if (strncmp(buf, message.boundary, len) == 0) |
212 |
|
state = ST_DONE; |
213 |
|
else { |
214 |
|
obstack_grow(&stk, buf, strlen(buf)); |
215 |
|
obstack_1grow(&stk, '\n'); |
216 |
|
} |
217 |
|
} |
218 |
} else { |
} else { |
219 |
strncpy(buf, lb->list->line, size); |
obstack_grow(&stk, buf, strlen(buf)); |
220 |
lb->list = lb->list->next; |
obstack_1grow(&stk, '\n'); |
221 |
} |
} |
|
return strlen(buf); |
|
|
|
|
|
default: |
|
|
return 0; |
|
222 |
} |
} |
223 |
|
obstack_1grow(&stk, 0); |
224 |
|
*retptr = strdup(obstack_finish(&stk)); |
225 |
|
obstack_free(&stk, NULL); |
226 |
} |
} |
227 |
|
|
228 |
|
void |
229 |
|
send_body(void *sd_server) |
230 |
|
{ |
231 |
|
char *p; |
232 |
|
|
233 |
|
if (topt & T_BOUNDARY) { |
234 |
|
swrite(CLIENT, sd_server, message.boundary); |
235 |
|
swrite(CLIENT, sd_server, CRLF); |
236 |
|
send_header(sd_server, &message.mime_hdr); |
237 |
|
swrite(CLIENT, sd_server, CRLF); |
238 |
|
} |
239 |
|
|
240 |
|
for (p = message.body; *p; ) { |
241 |
|
char *q = strchr(p, '\n'); |
242 |
|
if (q) |
243 |
|
*q++ = 0; |
244 |
|
else |
245 |
|
q = p + strlen(p); |
246 |
|
|
247 |
|
swrite(CLIENT, sd_server, p); |
248 |
|
swrite(CLIENT, sd_server, CRLF); |
249 |
|
p = q; |
250 |
|
} |
251 |
|
|
252 |
|
if (topt & T_BOUNDARY) { |
253 |
|
swrite(CLIENT, sd_server, message.boundary); |
254 |
|
swrite(CLIENT, sd_server, CRLF); |
255 |
|
} |
256 |
|
} |
257 |
|
|
258 |
|
|
259 |
/****************** |
/****************** |
260 |
The Tunnel core |
The Tunnel core |
261 |
*******************/ |
*******************/ |
591 |
return 1; /* OK */ |
return 1; /* OK */ |
592 |
} |
} |
593 |
|
|
|
static void |
|
|
collect_headers(void *sd_client, struct list **listp) |
|
|
{ |
|
|
struct list *tail; |
|
|
char buf[LINEBUFFER+1]; |
|
|
|
|
|
*listp = tail = NULL; |
|
|
while (recvline(SERVER, sd_client, buf, LINEBUFFER)) |
|
|
{ |
|
|
if (strncmp(buf, CRLF, 2) == 0) |
|
|
break; |
|
|
|
|
|
tail = new_element(tail, listp, buf); |
|
|
} |
|
|
} |
|
|
|
|
|
static void |
|
|
collect_body(void *sd_client, char **retptr) |
|
|
{ |
|
|
int nread; |
|
|
char body_line[LINEBUFFER+1]; |
|
|
struct obstack stk; |
|
|
|
|
|
obstack_init (&stk); |
|
|
while ((nread = recvline(SERVER, sd_client, body_line, LINEBUFFER))) { |
|
|
if (strncmp(body_line, "."CRLF, 3) == 0) /* EOM */ |
|
|
break; |
|
|
obstack_grow(&stk, body_line, strlen (body_line)); |
|
|
} |
|
|
obstack_1grow(&stk, 0); |
|
|
*retptr = strdup(obstack_finish(&stk)); |
|
|
obstack_free(&stk, NULL); |
|
|
} |
|
|
|
|
594 |
void |
void |
595 |
process_data(void *sd_client, void *sd_server) |
process_data(void *sd_client, void *sd_server) |
596 |
{ |
{ |
597 |
struct list *message_hdr; |
struct list *message_hdr; |
598 |
struct mem_buf mb; |
char buf[LINEBUFFER+1]; |
|
struct list_buf lb; |
|
599 |
|
|
600 |
alarm(1800); |
alarm(1800); |
601 |
|
|
602 |
collect_headers(sd_client, &message_hdr); |
collect_headers(sd_client, &message_hdr); |
603 |
collect_body(sd_client, &message.body); |
collect_body(sd_client, &message.body); |
604 |
|
|
605 |
init_list_buf(&lb, message_hdr); |
transfer_header(sd_client, sd_server, message_hdr); |
606 |
transfer_header(sd_client, sd_server, list_reader, &lb); |
transform_body(sd_server); |
607 |
|
transfer_body(sd_client, sd_server); |
608 |
|
|
609 |
init_mem_buf(&mb, message.body); |
recvline(CLIENT, sd_server, buf, LINEBUFFER); |
610 |
transfer_body(sd_client, sd_server, memory_reader, &mb); |
swrite(SERVER, sd_client, buf); |
611 |
|
|
612 |
/* FIXME: |
/* FIXME: xfree(message_body); */ |
|
destroy_list(&message_hdr); |
|
|
xfree(message_body); */ |
|
613 |
|
|
614 |
alarm(0); |
alarm(0); |
615 |
} |
} |
618 |
MESSAGE HEADER |
MESSAGE HEADER |
619 |
******************/ |
******************/ |
620 |
|
|
621 |
static void |
struct header_data { |
622 |
transfer_header(void *sd_client, void *sd_server, |
void *sd_client; |
623 |
read_fn_t readfn, void *closure) |
void *sd_server; |
624 |
{ |
struct list *header; |
625 |
struct list *header_buf = NULL; |
}; |
|
struct list *header_tail = NULL; |
|
|
struct list *p1; |
|
|
struct list *p2; |
|
|
char header_line[LINEBUFFER+1]; |
|
626 |
|
|
627 |
while (readfn(closure, header_line, LINEBUFFER)) { |
struct closure { |
628 |
if (strncmp(header_line, CRLF, 2) == 0) |
RC_REGEX *regex; |
629 |
break; |
char *modify; |
630 |
|
struct list *head, *tail; |
631 |
|
}; |
632 |
|
|
633 |
process_header_line(header_line); |
int |
634 |
header_tail = new_element(header_tail, |
action_remove2(struct list *p, void *data) |
635 |
&header_buf, header_line); |
{ |
636 |
|
struct closure *clos = data; |
637 |
|
int rc, stat; |
638 |
|
char **rv = NULL; |
639 |
|
|
640 |
|
stat = anubis_regex_match(clos->regex, p->line, &rc, &rv); |
641 |
|
free_pptr(rv); |
642 |
|
if (stat) { |
643 |
|
free(p->line); |
644 |
|
free(p); |
645 |
|
} else { |
646 |
|
p->next = NULL; |
647 |
|
if (clos->head == NULL) |
648 |
|
clos->head = p; |
649 |
|
if (clos->tail) |
650 |
|
clos->tail->next = p; |
651 |
|
clos->tail = p; |
652 |
} |
} |
653 |
|
return 0; |
654 |
|
} |
655 |
|
|
656 |
#ifdef WITH_GUILE |
int |
657 |
guile_process_list(&header_buf, &message.body); |
action_remove(struct list *p, void *data) |
658 |
for (header_tail = header_buf; header_tail && header_tail->next; |
{ |
659 |
header_tail = header_tail->next) |
struct header_data *hp = data; |
660 |
; |
struct closure clos; |
|
#endif /* WITH_GUILE */ |
|
|
|
|
|
if (message.remlist) { |
|
|
struct list *h1; |
|
|
struct list *h2; |
|
|
struct list *previous; |
|
|
char hline[LINEBUFFER+1]; |
|
|
|
|
|
p1 = message.remlist; |
|
|
do { |
|
|
p2 = p1->next; |
|
|
h1 = header_buf; |
|
|
previous = NULL; |
|
|
|
|
|
do { |
|
|
h2 = h1->next; |
|
|
strncpy(hline, h1->line, LINEBUFFER); |
|
|
remcrlf(hline); |
|
|
if (regex_match(p1->line, hline)) { |
|
|
if (previous) |
|
|
previous->next = h2; |
|
|
else |
|
|
header_buf = h2; |
|
|
free(h1->line); |
|
|
free(h1); |
|
|
if (h2) |
|
|
h1 = h2; |
|
|
} |
|
|
else { |
|
|
if (h2) { |
|
|
previous = h1; |
|
|
h1 = h2; |
|
|
} |
|
|
} |
|
|
} while (h2 != NULL); |
|
661 |
|
|
662 |
free(p1->line); |
clos.regex = anubis_regex_compile(p->line, 0); |
663 |
free(p1); |
clos.head = clos.tail = NULL; |
664 |
if (p2) |
list_iterate(hp->header, action_remove2, &clos); |
665 |
p1 = p2; |
hp->header = clos.head; |
666 |
} while (p2 != NULL); |
anubis_regex_free(clos.regex); |
667 |
message.remlist = NULL; |
free(p->line); |
668 |
} |
free(p); |
669 |
|
return 0; |
670 |
if (message.addlist) { |
} |
|
p1 = message.addlist; |
|
|
do { |
|
|
p2 = p1->next; |
|
|
strncpy(header_line, p1->line, LINEBUFFER-2); |
|
|
strcat(header_line, CRLF); |
|
|
header_tail = new_element(header_tail, &header_buf, header_line); |
|
|
free(p1->line); |
|
|
free(p1); |
|
|
if (p2) |
|
|
p1 = p2; |
|
|
} while (p2 != NULL); |
|
|
message.addlist = NULL; |
|
|
} |
|
|
|
|
|
if (message.modlist) { |
|
|
struct list *h1; |
|
|
struct list *h2; |
|
|
char hline[LINEBUFFER+1]; |
|
|
|
|
|
p1 = message.modlist; |
|
|
do { |
|
|
p2 = p1->next; |
|
|
h1 = header_buf; |
|
671 |
|
|
672 |
do { |
int |
673 |
h2 = h1->next; |
action_mod2(struct list *p, void *data) |
674 |
strncpy(hline, h1->line, LINEBUFFER); |
{ |
675 |
remcrlf(hline); |
struct closure *clos = data; |
676 |
if (regex_match(p1->line, hline)) { |
int rc, stat; |
677 |
char *outbuf = substitute(p1->modify, |
char **rv = NULL; |
678 |
submatch); |
|
679 |
free(h1->line); |
stat = anubis_regex_match(clos->regex, p->line, &rc, &rv); |
680 |
if (outbuf) |
if (stat) { |
681 |
h1->line = outbuf; |
free(p->line); |
682 |
else |
p->line = substitute(clos->modify, rv); |
683 |
h1->line = strdup(p1->modify); |
if (!p->line) |
684 |
} |
p->line = strdup(clos->modify); |
685 |
if (h2) |
free_pptr(rv); |
|
h1 = h2; |
|
|
} while (h2 != NULL); |
|
|
|
|
|
free(p1->line); |
|
|
free(p1->modify); |
|
|
free(p1); |
|
|
if (p2) |
|
|
p1 = p2; |
|
|
} while (p2 != NULL); |
|
|
message.modlist = NULL; |
|
686 |
} |
} |
687 |
|
return 0; |
688 |
|
} |
689 |
|
|
690 |
#ifdef WITH_GUILE |
int |
691 |
guile_postprocess_list(&header_buf, &message.body); |
action_mod(struct list *p, void *data) |
692 |
#endif /* WITH_GUILE */ |
{ |
693 |
|
struct header_data *hp = data; |
694 |
|
struct closure clos; |
695 |
|
|
696 |
p1 = header_buf; |
clos.regex = anubis_regex_compile(p->line, 0); |
697 |
do { |
clos.head = clos.tail = NULL; |
698 |
p2 = p1->next; |
clos.modify = p->modify; |
699 |
|
list_iterate(hp->header, action_mod2, &clos); |
700 |
|
anubis_regex_free(clos.regex); |
701 |
|
free(p->line); |
702 |
|
free(p); |
703 |
|
return 0; |
704 |
|
} |
705 |
|
|
706 |
/* |
int |
707 |
If there are any attachments, find the BOUNDARY. |
action_free(struct list *p, void *data) |
708 |
*/ |
{ |
709 |
|
free(p->line); |
710 |
|
free(p); |
711 |
|
return 0; |
712 |
|
} |
713 |
|
|
714 |
if (strncmp(p1->line, "Content-Type:", 13) == 0) { |
static void |
715 |
if (mopt & M_BODYCLEARAPPEND) { |
transfer_header(void *sd_client, void *sd_server, struct list *header_buf) |
716 |
message.remlist_tail = new_element(message.remlist_tail, |
{ |
717 |
&message.remlist, "^Content-Type:"); |
struct list *p; |
718 |
message.remlist_tail = new_element(message.remlist_tail, |
struct header_data hd; |
719 |
&message.remlist, "^Content-Transfer-Encoding:"); |
|
720 |
} |
hd.sd_server = sd_server; |
721 |
else { |
hd.sd_client = sd_client; |
722 |
char *ptr1 = 0; |
hd.header = header_buf; |
|
char *ptr2 = 0; |
|
|
char boundary_buf[LINEBUFFER+1]; |
|
|
struct list *plist = p1; |
|
|
|
|
|
safe_strcpy(boundary_buf, plist->line); |
|
|
change_to_lower(boundary_buf); |
|
|
|
|
|
ptr1 = strstr(boundary_buf, "boundary="); |
|
|
if (ptr1 == 0) { |
|
|
plist = plist->next; |
|
|
safe_strcpy(boundary_buf, plist->line); |
|
|
change_to_lower(boundary_buf); |
|
|
ptr1 = strstr(boundary_buf, "boundary="); |
|
|
} |
|
723 |
|
|
724 |
if (ptr1) { |
for (p = hd.header; p; p = p->next) |
725 |
topt |= T_BOUNDARY; |
process_header_line(p->line); |
726 |
safe_strcpy(boundary_buf, plist->line); |
|
727 |
|
#ifdef WITH_GUILE |
728 |
ptr2 = strchr(boundary_buf, '='); |
guile_process_list(&header_buf, &message.body); |
729 |
if (!ptr2) |
#endif /* WITH_GUILE */ |
730 |
ptr2 = boundary_buf; |
|
731 |
else |
list_iterate(message.remlist, action_remove, &hd); |
732 |
ptr2 = parse_line_option(ptr2); |
message.remlist = NULL; |
|
message.boundary = (char *)xmalloc(strlen(ptr2) + 3); |
|
|
if (*ptr2 == '"') { |
|
|
ptr2++; |
|
|
sprintf(message.boundary, "--%s", ptr2); |
|
|
ptr2 = strstr(message.boundary, "\""); |
|
|
*ptr2 = '\0'; |
|
|
} |
|
|
else |
|
|
sprintf(message.boundary, "--%s", ptr2); |
|
|
} |
|
|
} |
|
|
} |
|
733 |
|
|
734 |
swrite(CLIENT, sd_server, p1->line); |
list_append(&hd.header, message.addlist); |
735 |
free(p1->line); |
message.addlist = NULL; |
736 |
free(p1); |
|
737 |
if (p2) |
list_iterate(message.modlist, action_mod, &hd); |
738 |
p1 = p2; |
message.modlist = NULL; |
739 |
} while (p2 != NULL); |
|
740 |
header_buf = NULL; |
#ifdef WITH_GUILE |
741 |
|
guile_postprocess_list(&hd.header, &message.body); |
742 |
|
#endif /* WITH_GUILE */ |
743 |
|
|
744 |
|
send_header(sd_server, &hd.header); |
745 |
swrite(CLIENT, sd_server, CRLF); |
swrite(CLIENT, sd_server, CRLF); |
746 |
return; |
|
747 |
|
list_iterate(hd.header, action_free, NULL); |
748 |
} |
} |
749 |
|
|
750 |
static void |
static void |
760 |
p = strstr(header_line, BEGIN_TRIGGER); |
p = strstr(header_line, BEGIN_TRIGGER); |
761 |
if (p) { |
if (p) { |
762 |
safe_strcpy(backup, p); |
safe_strcpy(backup, p); |
|
*p++ = '\r'; |
|
|
*p++ = '\n'; |
|
763 |
*p = '\0'; |
*p = '\0'; |
764 |
p = backup; |
p = backup; |
765 |
p += sizeof(BEGIN_TRIGGER) - 1; |
p += sizeof(BEGIN_TRIGGER) - 1; |
766 |
} |
} else |
|
else |
|
767 |
p = header_line; |
p = header_line; |
768 |
|
|
769 |
rcfile_process_cond("RULE", HEADER, p); |
rcfile_process_cond("RULE", HEADER, p); |
774 |
MESSAGE BODY |
MESSAGE BODY |
775 |
****************/ |
****************/ |
776 |
|
|
777 |
#define M_OPT_STATIC (M_GPG_ENCRYPT | M_GPG_SIGN | M_RM \ |
|
|
| M_SIGNATURE | M_BODYAPPEND | M_EXTBODYPROC) |
|
778 |
|
|
779 |
static void |
static void |
780 |
transfer_body(void *sd_client, void *sd_server, |
raw_transfer(void *sd_client, void *sd_server) |
|
read_fn_t readfn, void *closure) |
|
781 |
{ |
{ |
782 |
if (mopt & M_BODYCLEARAPPEND) |
int nread; |
783 |
clear_body_transfer(sd_client, sd_server); |
char buf[LINEBUFFER+1]; |
784 |
else { |
|
785 |
if (mopt & M_OPT_STATIC) |
while ((nread = recvline(SERVER, sd_client, buf, LINEBUFFER)) > 0) { |
786 |
static_body_transfer(sd_client, sd_server, |
if (strncmp(buf, "."CRLF, 3) == 0) /* EOM */ |
787 |
readfn, closure); |
break; |
788 |
else |
swrite(CLIENT, sd_server, buf); |
|
dynamic_body_transfer(sd_client, sd_server, |
|
|
readfn, closure); |
|
789 |
} |
} |
|
return; |
|
790 |
} |
} |
791 |
|
|
792 |
static void |
void |
793 |
static_body_transfer(void *sd_client, void *sd_server, |
transfer_body(void *sd_client, void *sd_server) |
|
read_fn_t readfn, void *data) |
|
794 |
{ |
{ |
|
int nb = 0; |
|
|
int nread; |
|
|
int capacity = DATABUFFER; |
|
|
char body_line[LINEBUFFER+1]; |
|
|
|
|
|
message.body = (char *)xmalloc(DATABUFFER); |
|
|
|
|
|
/* |
|
|
If there are some attachments... |
|
|
*/ |
|
|
|
|
795 |
if (topt & T_BOUNDARY) { |
if (topt & T_BOUNDARY) { |
796 |
nb = strlen(message.boundary); |
send_body(sd_server); |
|
while (readfn(data, body_line, LINEBUFFER)) { |
|
|
swrite(CLIENT, sd_server, body_line); |
|
|
if (strncmp(body_line, message.boundary, nb) == 0) { |
|
|
while (recvline(SERVER, sd_client, body_line, LINEBUFFER)) |
|
|
{ |
|
|
swrite(CLIENT, sd_server, body_line); |
|
|
if (strncmp(body_line, CRLF, 2) == 0) |
|
|
break; |
|
|
} |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
/* |
|
|
Now we have reached the message body... |
|
|
*/ |
|
|
|
|
|
while ((nread = readfn(data, body_line, LINEBUFFER))) |
|
|
{ |
|
|
if (strncmp(body_line, message.boundary, nb) == 0) |
|
|
break; |
|
|
|
|
|
capacity -= nread; |
|
|
if (capacity >= nread) |
|
|
strcat(message.body, body_line); |
|
|
else { |
|
|
message.body = (char *)xrealloc((char *)message.body, |
|
|
strlen(message.body) + DATABUFFER + 1); |
|
|
strcat(message.body, body_line); |
|
|
capacity = DATABUFFER - nread; |
|
|
} |
|
|
} |
|
|
|
|
|
remcrlf(message.body); |
|
|
transform_body(sd_server); |
|
|
swrite(CLIENT, sd_server, message.body); |
|
797 |
#ifdef HAVE_GPG |
#ifdef HAVE_GPG |
798 |
if ((mopt & M_GPG_ENCRYPT) || (mopt & M_GPG_SIGN)) |
if ((mopt & M_GPG_ENCRYPT) || (mopt & M_GPG_SIGN)) |
799 |
swrite(CLIENT, sd_server, CRLF); |
swrite(CLIENT, sd_server, CRLF); |
800 |
#endif /* HAVE_GPG */ |
#endif /* HAVE_GPG */ |
801 |
swrite(CLIENT, sd_server, body_line); |
|
802 |
|
/* Transfer everything else */ |
803 |
/* |
raw_transfer(sd_client, sd_server); |
804 |
Transfer everything else... |
} else |
805 |
*/ |
send_body(sd_server); |
806 |
|
swrite(CLIENT, sd_server, "."CRLF); |
|
dynamic_body_transfer(sd_client, sd_server, readfn, data); |
|
|
} |
|
|
|
|
|
/* |
|
|
else... No attachments. |
|
|
*/ |
|
|
|
|
|
else { |
|
|
while ((nread = readfn(data, body_line, LINEBUFFER))) { |
|
|
if (strncmp(body_line, "."CRLF, 3) == 0) /* EOM */ |
|
|
break; |
|
|
|
|
|
capacity -= nread; |
|
|
if (capacity < nread) { |
|
|
message.body = (char *)xrealloc((char *)message.body, |
|
|
strlen(message.body) + DATABUFFER + 1); |
|
|
capacity = DATABUFFER - nread; |
|
|
} |
|
|
strcat(message.body, body_line); |
|
|
} |
|
|
remcrlf(message.body); |
|
|
transform_body(sd_server); |
|
|
swrite(CLIENT, sd_server, message.body); |
|
|
swrite(CLIENT, sd_server, CRLF"."CRLF); |
|
|
|
|
|
recvline(CLIENT, sd_server, body_line, LINEBUFFER); |
|
|
swrite(SERVER, sd_client, body_line); |
|
|
} |
|
|
return; |
|
|
} |
|
|
|
|
|
static void |
|
|
dynamic_body_transfer(void *sd_client, void *sd_server, |
|
|
read_fn_t readfn, void *data) |
|
|
{ |
|
|
char body_line[LINEBUFFER+1]; |
|
|
|
|
|
while (readfn(data, body_line, LINEBUFFER)) |
|
|
{ |
|
|
swrite(CLIENT, sd_server, body_line); |
|
|
if (strncmp(body_line, "."CRLF, 3) == 0) /* EOM */ |
|
|
break; |
|
|
} |
|
|
|
|
|
recvline(CLIENT, sd_server, body_line, LINEBUFFER); |
|
|
swrite(SERVER, sd_client, body_line); |
|
|
|
|
|
return; |
|
807 |
} |
} |
808 |
|
|
|
static void |
|
|
clear_body_transfer(void *sd_client, void *sd_server) |
|
|
{ |
|
|
char body_line[LINEBUFFER+1]; |
|
|
message.body = (char *)xmalloc(1); |
|
|
|
|
|
while (recvline(SERVER, sd_client, body_line, LINEBUFFER)) |
|
|
{ |
|
|
if (strncmp(body_line, "."CRLF, 3) == 0) /* EOM */ |
|
|
break; |
|
|
} |
|
|
|
|
|
transform_body(sd_server); |
|
|
swrite(CLIENT, sd_server, message.body); |
|
|
swrite(CLIENT, sd_server, body_line); |
|
|
recvline(CLIENT, sd_server, body_line, LINEBUFFER); |
|
|
swrite(SERVER, sd_client, body_line); |
|
|
|
|
|
return; |
|
|
} |
|
809 |
|
|
810 |
static void |
static void |
811 |
add_remailer_commands(void *sd_server) |
add_remailer_commands(void *sd_server) |
858 |
|
|
859 |
#ifdef HAVE_GPG |
#ifdef HAVE_GPG |
860 |
if (!(topt & T_ERROR) && ((mopt & M_GPG_ENCRYPT) |
if (!(topt & T_ERROR) && ((mopt & M_GPG_ENCRYPT) |
861 |
|| (mopt & M_GPG_SIGN) || (mopt & M_RMGPG))) |
|| (mopt & M_GPG_SIGN) || (mopt & M_RMGPG))) |
862 |
check_gpg(); |
check_gpg(); |
863 |
#endif /* HAVE_GPG */ |
#endif /* HAVE_GPG */ |
864 |
|
|