/[debian]/mimetic/branches/upstream/current/examples/exbin.cxx
ViewVC logotype

Contents of /mimetic/branches/upstream/current/examples/exbin.cxx

Parent Directory Parent Directory | Revision Log Revision Log


Revision 128 - (show annotations)
Sat Feb 25 16:49:20 2006 UTC (15 years, 5 months ago) by gregoa
File size: 8257 byte(s)
[svn-inject] Installing original source of mimetic
1 /***************************************************************************
2 copyright : (C) 2002-2005 by Stefano Barbato
3 email : stefano@codesink.org
4
5 $Id: exbin.cxx,v 1.4 2005/03/07 16:50:59 tat Exp $
6 ***************************************************************************/
7
8 /***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
16 /** \example exbin.cc
17 * extract a Part based on command line parameters
18 * more info on:
19 * exbin -h
20 */
21 #include <iostream>
22 #include <sstream>
23 #include <iterator>
24 #include <fstream>
25 #include <cassert>
26 #include <mimetic/mimetic.h>
27
28 using namespace std;
29 using namespace mimetic;
30
31 unsigned int g_decoded = 0, g_messages = 0, g_files = 0, g_parts = 0;
32
33 void usage()
34 {
35 cout << "exbin [params] [in_file...]" << endl;
36 cout << "\t-t type[/subtype] matches Content-Type" << endl;
37 cout << "\t-q totaly quiet; exit code = num of decoded entities" << endl;
38 exit(-1);
39 }
40
41
42 struct MatchParamRq
43 {
44 MatchParamRq()
45 : m_quiet(0), m_set(0)
46 {
47 }
48 bool operator()(const MimeEntity* pMe) const
49 {
50 const Header& h = pMe->header();
51 // if not set consider a part to be an attach if its
52 // MIME type is not text/*
53 if(!m_set)
54 return h.contentType().type() != "text" &&
55 h.contentType().type() != "message";
56 // check for content type match
57 if(m_type.length() && m_type != h.contentType().type())
58 return false;
59 if(m_subtype.length() && m_subtype != h.contentType().subtype())
60 return false;
61 return true;
62 }
63 void type(const string& s) { m_type = s; ++m_set; }
64 const istring& type() const { return m_type; }
65 void subtype(const string& s) { m_subtype = s; ++m_set; }
66 const istring& subtype() const { return m_subtype; }
67 void quiet(bool b) { m_quiet = b; }
68 bool quiet() const { return m_quiet; }
69 private:
70 istring m_type, m_subtype;
71 bool m_quiet, m_set;
72 } mpr;
73
74 void die(bool b, const string& msg)
75 {
76 if(b)
77 {
78 cerr << "Error: " << msg << endl << endl;
79 usage();
80 }
81 }
82
83 string get_filename(const MimeEntity& me)
84 {
85 if(me.hasField(ContentDisposition::label))
86 {
87 const ContentDisposition& cd = me.header().contentDisposition();
88 if(cd.param("filename").length())
89 return cd.param("filename");
90 } else if (me.hasField(ContentType::label)) {
91 const ContentType& ct = me.header().contentType();
92 return string("unnamed_" + ct.type() + "." + ct.subtype());
93 }
94 return "unknown_attachment";
95 }
96
97 static bool is_known_mechanism(const string& mechanism)
98 {
99 istring m = mechanism;
100
101 if(m == "base64" || m == "quoted-printable" || m == "binary" ||
102 m == "7bit" || m == "8bit")
103 return true;
104
105 return false;
106 }
107
108 void decode_bin(const MimeEntity& me)
109 {
110 const ContentTransferEncoding& cte = me.header().contentTransferEncoding();
111 const ContentDisposition& cd = me.header().contentDisposition();
112
113 if(is_known_mechanism(cte.mechanism()))
114 {
115 string filename = get_filename(me);
116 if(File::exists(filename))
117 {
118 int t;
119 for(t = 0; File::exists(utils::int2str(t)+"-"+filename);t++)
120 ;
121 filename = utils::int2str(t) + "-" + filename;
122 }
123 const ContentType& ct = me.header().contentType();
124 if(!mpr.quiet())
125 cout << "\tdecoding " << filename
126 << " (" << ct.type() << "/" << ct.subtype() << ")"
127 << endl;
128 ofstream of(filename.c_str());
129 if(!of.is_open())
130 {
131 cerr << "ERR: unable to write to " << filename << endl;
132 return;
133 }
134 ostreambuf_iterator<char> oi(of);
135 istring enc_algo = cte.mechanism();
136 if(enc_algo == "base64")
137 {
138 Base64::Decoder b64;
139 g_decoded++;
140 decode(me.body().begin(), me.body().end(), b64 ,oi);
141 } else if (enc_algo == "quoted-printable") {
142 QP::Decoder qp;
143 g_decoded++;
144 decode(me.body().begin(), me.body().end(), qp, oi);
145 } else if (enc_algo == "8bit" || enc_algo == "7bit" ||
146 enc_algo == "binary") {
147 copy(me.body().begin(), me.body().end(), oi);
148 } else {
149 cerr << "ERR: unknown encoding algorithm "
150 << enc_algo << endl;
151 }
152 }
153 }
154
155 void parsePart(const MimeEntity& me, string& fqn)
156 {
157 g_parts++;
158 if(mpr(&me))
159 {
160 if(!mpr.quiet() && fqn.length() > 0)
161 {
162 cout << fqn << endl;
163 fqn.clear();
164 }
165 decode_bin(me);
166 }
167 MimeEntityList::const_iterator mbit, meit;
168 mbit = me.body().parts().begin(), meit = me.body().parts().end();
169 for(; mbit != meit; ++mbit)
170 parsePart(**mbit, fqn);
171 }
172
173 inline int isnl(char c)
174 {
175 return c == '\n' || c == '\r';
176 }
177
178 template<typename Iterator>
179 void parseMboxFile(Iterator bit, Iterator eit, string& fqn)
180 {
181 char prev;
182 Iterator it = bit;
183 for(; bit != eit; )
184 {
185 for(;;)
186 {
187 it = utils::find_bm(it, eit, "From ");
188 //it = find_n(it, eit, "From ");
189 prev = *(it-1); // previous char (must be a newline)
190 if(it == eit || isnl(prev) )
191 break;
192 else
193 ++it; // From in the middle of a line
194 }
195 g_messages++;
196 MimeEntity me(bit, it);
197 parsePart(me, fqn);
198 if(it == eit)
199 return;
200 bit = it;
201 ++it; // skip the current From
202 }
203 }
204
205 template<typename Iterator>
206 void parse(Iterator bit, Iterator eit, string& fqn)
207 {
208 string sep = "From ";
209 Iterator it = utils::find_bm(bit, bit + sep.length(), sep);
210 if(it == bit)
211 {
212 parseMboxFile(bit, eit, fqn);
213 } else {
214 g_messages++;
215 MimeEntity me(bit, eit);
216 parsePart(me, fqn);
217 }
218 }
219
220
221 int main(int argc, char** argv)
222 {
223 std::ios_base::sync_with_stdio(false);
224
225 // handle command line parameters
226 int p = 1;
227 while(p < argc)
228 {
229 string param = argv[p];
230 if(param == "-h")
231 usage();
232 else if (param == "-q")
233 mpr.quiet(true);
234 else if (param == "-t") {
235 die( ++p == argc, param + " requires an argument");
236 ContentType ct(argv[p]);
237 die(mpr.type().length() != 0, "just one -t allowed");
238 mpr.type(ct.type());
239 mpr.subtype(ct.subtype());
240 } else {
241 // filename list starts here
242 // first filename: argv[p]
243 break;
244 }
245 ++p;
246 }
247
248 string fqn;
249 if(argc == p)
250 { // read from stdin
251 fqn = "stdin";
252 string buf;
253 enum { page_sz = 4096 };
254 char page[page_sz];
255 int count;
256 while((count = cin.rdbuf()->sgetn(page, page_sz)) > 0)
257 buf.append(page);
258 parse(buf.begin(), buf.end(), fqn);
259 g_files++;
260 } else {
261 for(int fc = p; fc < argc; ++fc)
262 {
263 fqn = argv[fc];
264 File in(fqn);
265 if(!in)
266 {
267 cerr << "ERR: unable to open file " << argv[fc]
268 << endl;
269 continue;
270 }
271 g_files++;
272 parse(in.begin(), in.end(), fqn);
273 }
274 }
275 if(!mpr.quiet())
276 cout << g_files << " file(s) analyzed, " <<
277 g_messages << " message(s) and " <<
278 g_parts << " entitie(s) parsed, " <<
279 g_decoded << " attachment(s) extracted." << endl;
280 return g_decoded;
281 }
282

  ViewVC Help
Powered by ViewVC 1.1.26