aboutsummaryrefslogtreecommitdiffstats
path: root/src/ragel/content_disposition_parser.rl
blob: c35d2b2320aa435ae48899a1a5d40ec9ff7f32cb (plain)
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
%%{
  machine content_type_parser;

  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_whitespace "smtp_whitespace.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 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;
}