summaryrefslogtreecommitdiff
path: root/src/mime/mime.cc
diff options
context:
space:
mode:
authorHenrik Rydberg <rydberg@euromail.se>2011-10-08 20:30:28 +0200
committerHenrik Rydberg <rydberg@euromail.se>2011-10-08 20:30:28 +0200
commit5df79c53745fde5d6c3340a2979b1429cd5892c1 (patch)
tree1a81af141708b826e9c61e8a04019994fcca8298 /src/mime/mime.cc
Initial import of htcd system 1.0
Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
Diffstat (limited to 'src/mime/mime.cc')
-rw-r--r--src/mime/mime.cc188
1 files changed, 188 insertions, 0 deletions
diff --git a/src/mime/mime.cc b/src/mime/mime.cc
new file mode 100644
index 0000000..a7a1884
--- /dev/null
+++ b/src/mime/mime.cc
@@ -0,0 +1,188 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <mime/mime.h>
21
22const charset par_left("([{"),par_right("}])");
23
24inline int is_field(const sref& s) {
25 sref p=s.left_first(':');
26 while(cset_spaces.test(p.back())) p=p.popb();
27 return p.nempty()&&p.find_of(cset_spaces)<0;
28}
29
30inline int getquoted(const sref& s,char c) {
31 int i,quote=0,par=0;
32 for(i=0;i<s.size();i++) {
33 if(s[i]=='\"') quote=!quote;
34 else if(par_left.test(s[i])) par++;
35 else if(par_right.test(s[i])) par--;
36 else if(s[i]==c&&!quote&&!par) break;
37 }
38 return i;
39}
40
41void Mime::Init(const sref& message)
42{
43 mstring line;
44 rrpile pile;
45 sref first;
46 head=body=message;
47 while(Splitln(first,body)) {
48 if(first.empty()) break;
49 if(!is_field(first)) Special(first);
50 else {
51 line=first;
52 while(cset_spaces.test(*body)) {
53 Splitln(first,body);
54 line.append(1,' ');
55 line+=first.right_first_not_of(cset_spaces);
56 }
57 sref opt=line;
58 int col=opt.find(':');
59 sref name=Trim(opt.left(col),cset_quotes);
60 opt=opt.adv(col).popf();
61 sref rawval=Trim(opt);
62 int semi=getquoted(opt,';');
63 sref val=Trim(opt.left(semi),cset_quotes);
64 if(getquoted(val,'=')<val.size()) val.clear();
65 else opt=opt.adv(semi).popf();
66 pile.clear();
67 while(opt.nempty()) {
68 sref optname=opt.left(getquoted(opt,'='));
69 opt=opt.adv(optname).popf();
70 semi=getquoted(opt,';');
71 sref optval=opt.left(semi);
72 opt=opt.adv(semi).popf();
73 optname=Trim(optname,cset_quotes);
74 optval=Trim(optval,cset_quotes);
75 if(optname.nempty()) pile.push_back(rrstring(optname,optval));
76 }
77 Handle(name,rawval,val,pile);
78 }
79 }
80 head=head.left(body-head);
81}
82
83
84///////////////////////////////////////////////////////////////////////////
85
86Mime::Mime()
87{
88 mime_version="1.0";
89}
90
91int Mime::Special(sref line)
92{
93 return 0;
94}
95
96int Mime::Handle(const sref& name,
97 const sref& rawval,
98 const sref& val,
99 const rrpile& opts) {
100 if(eqn(name,mime_version_tag)) mime_version=val;
101 else if(eqn(name,cont_type_tag)) {
102 (cont_type=val).tolower();
103 for(rrpile::const_iterator p=opts.begin();p!=opts.end();p++) {
104 if(eqn(p->first,charset_tag)) cont_type_charset=p->second;
105 else if(eqn(p->first,name_tag)) cont_type_name=p->second;
106 else if(eqn(p->first,boundary_tag)) cont_type_boundary=p->second;
107 }
108 }
109 else if(eqn(name,cont_id_tag)) cont_id=val;
110 else if(eqn(name,cont_desc_tag)) cont_desc=val;
111 else if(eqn(name,cont_disp_tag)) {
112 cont_disp=val;
113 for(rrpile::const_iterator p=opts.begin();p!=opts.end();p++) {
114 if(eqn(p->first,name_tag)) cont_disp_name=p->second;
115 else if(eqn(p->first,file_tag)) cont_disp_file=p->second;
116 }
117 }
118 else if(eqn(name,cont_trans_enc_tag)) cont_trans_enc=val;
119 else if(eqn(name,cont_length_tag)) cont_length=val;
120 else return 0;
121 return 1;
122}
123
124///////////////////////////////////////////////////////////////////////////
125
126void Mime::putHead(mstream& out) const
127{
128 if(putval(out,mime_version_tag,mime_version)) putend(out);
129 if(putval(out,cont_type_tag,cont_type)) {
130 putopt(out,charset_tag,cont_type_charset);
131 putopt(out,name_tag,cont_type_name);
132 putopt(out,boundary_tag,cont_type_boundary);
133 putend(out);
134 }
135 if(putval(out,cont_id_tag,cont_id)) putend(out);
136 if(putval(out,cont_desc_tag,cont_desc)) putend(out);
137 if(putval(out,cont_disp_tag,cont_disp)) {
138 putopt(out,name_tag,cont_disp_name);
139 putopt(out,file_tag,cont_disp_file);
140 putend(out);
141 }
142 if(putval(out,cont_trans_enc_tag,cont_trans_enc)) putend(out);
143 if(putval(out,cont_length_tag,cont_length)) putend(out);
144}
145
146
147///////////////////////////////////////////////////////////////////////////
148
149int Mime::Multipart(rpile& list) const
150{
151 if(cont_type_boundary.empty()) return 0;
152 mstring bound=sref("--")+cont_type_boundary;
153 sref rest=body.past_first(bound).past_nl();
154 while(rest.nempty()) {
155 int pos=rest.find(bound);
156 if(pos>=0) {
157 sref first=rest.left(pos);
158 if(first.back()=='\n') {
159 first=first.popb();
160 if(first.back()=='\r') first=first.popb();
161 }
162 list.push_back(first);
163 rest=rest.right(pos).adv(bound.size());
164 if(*rest=='-') rest.clear(); else rest=rest.past_nl();
165 }
166 else {
167 list.push_back(rest);
168 rest.clear();
169 }
170 }
171 return !list.empty();
172}
173
174void Mime::Pick(const sref& mime)
175{
176 rpile list;
177 if(Multipart(list)) {
178 if(eqn(cont_type,mime_multialt)) {
179 int pos=0;
180 for(int i=0;i<list.size();i++) {
181 Mime msg(list[i]);
182 if(eqn(msg.cont_type,mime)) { pos=i; break; }
183 }
184 Init(list[pos]);
185 }
186 }
187}
188