1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
%%{
machine content_type_parser;
alphtype unsigned char;
action Disposition_Start {
}
action Disposition_End {
}
action Disposition_Inline {
cd->type = RSPAMD_CT_INLINE;
}
action Disposition_Attachment {
cd->type = RSPAMD_CT_ATTACHMENT;
}
action Param_Name_Start {
qstart = NULL;
qend = NULL;
pname_start = p;
pname_end = NULL;
}
action Param_Name_End {
if (qstart) {
pname_start = qstart;
}
if (qend && qend >= qstart) {
pname_end = qend;
}
else if (p >= pname_start) {
pname_end = p;
}
qstart = NULL;
qend = NULL;
}
action Param_Value_Start {
qstart = NULL;
qend = NULL;
if (pname_end) {
pvalue_start = p;
pvalue_end = NULL;
}
}
action Param_Value_End {
if (pname_end) {
if (qstart) {
pvalue_start = qstart;
}
if (qend && qend >= qstart) {
pvalue_end = qend;
}
else if (p >= pvalue_start) {
pvalue_end = p;
}
qstart = NULL;
qend = NULL;
if (pvalue_end && pvalue_end > pvalue_start && pname_end > pname_start) {
rspamd_content_disposition_add_param (pool, cd, pname_start, pname_end, pvalue_start, pvalue_end);
}
}
pname_start = NULL;
pname_end = NULL;
pvalue_start = NULL;
pvalue_end = NULL;
qend = NULL;
qstart = NULL;
}
action Quoted_Str_Start {
qstart = p;
qend = NULL;
}
action Quoted_Str_End {
if (qstart) {
qend = p;
}
}
include smtp_base "smtp_base.rl";
include content_disposition "content_disposition.rl";
main := content_disposition;
}%%
#include "smtp_parsers.h"
#include "content_type.h"
%% write data;
gboolean
rspamd_content_disposition_parser (const char *data, size_t len, struct rspamd_content_disposition *cd, rspamd_mempool_t *pool)
{
const unsigned char *p = data, *pe = data + len, *eof, *qstart = NULL, *qend = NULL,
*pname_start = NULL, *pname_end = NULL, *pvalue_start = NULL, *pvalue_end = NULL;
int cs, *stack = NULL;
gsize top = 0;
struct _ragel_st_storage {
int *data;
gsize size;
} st_storage;
memset (&st_storage, 0, sizeof (st_storage));
memset (cd, 0, sizeof (*cd));
eof = pe;
%% write init;
%% write exec;
if (st_storage.data) {
free (st_storage.data);
}
return cd->type != RSPAMD_CT_UNKNOWN;
}
|