1 /***************************************************************************
2 copyright : (C) 2002-2005 by Stefano Barbato
3 email : stefano@codesink.org
5 $Id: catpart.cxx,v 1.2 2005/02/23 10:26:14 tat Exp $
6 ***************************************************************************/
8 /***************************************************************************
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. *
15 ***************************************************************************/
16 /** \example catpart.cc
17 * extract a Part based on command line parameters
26 #include <mimetic/mimetic.h>
29 using namespace mimetic;
31 unsigned int g_matches = 0;
35 cout << "catpart [params] [in_file...]" << endl;
36 cout << "\t-r look for matches in nested entities"<<endl;
37 cout << "\t-t type[/subtype] matches Content-Type" << endl;
38 cout << "\t-p param[=value] matches Content-Type param" << endl;
39 cout << "\t-f name[=value] matches an header field" << endl;
40 cout << "\t-l don't write anything but filename" << endl;
41 cout << "\t-q totaly quiet; exit code = num of matches" << endl;
42 cout << "\t-H ignore header fields" << endl;
43 cout << "\t-B ignore entities' body" << endl;
44 cout << "\t-C ignore child entities" << endl;
51 typedef pair<istring,istring> Param;
52 typedef pair<istring,istring> Field;
54 : recursive(0), justFilename(0), quiet(0)
57 bool operator()(const MimeEntity* pMe) const
59 // check for content type match
60 const Header& h = pMe->header();
61 if(type.length() && type != h.contentType().type())
63 if(subtype.length() && subtype != h.contentType().subtype())
67 // check for params matches
70 ContentType::ParamList::const_iterator ctpbit,ctpeit;
71 ctpbit = h.contentType().paramList().begin();
72 ctpeit = h.contentType().paramList().end();
74 for(; !matched && ctpbit != ctpeit; ++ctpbit)
76 list<Param>::const_iterator pbit, peit;
77 pbit = paramList.begin(), peit = paramList.end();
78 for(; pbit != peit; ++pbit)
80 if(ctpbit->name() != pbit->first)
83 istring value = ctpbit->value();
84 if(value.find(pbit->second) != string::npos)
92 // check for field matches
96 Header::const_iterator hbit, heit;
99 for(; !matched && hbit != heit; ++hbit)
101 list<Field>::const_iterator fbit, feit;
102 fbit = fieldList.begin(), feit = fieldList.end();
103 for(; fbit != feit; ++fbit)
105 if(hbit->name() != fbit->first)
108 istring value = hbit->value();
109 if(value.find(fbit->second) != string::npos)
120 istring type, subtype;
121 list<Param> paramList;
122 list<Field> fieldList;
123 bool recursive, justFilename, quiet;
126 void die(bool b, const string& msg)
130 cerr << "Error: " << msg << endl << endl;
135 void printPart(const MimeEntity& me, const MatchParamRq& mpr, string& fqn)
144 if(fqn.length() == 0)
156 return; // just top level entity
157 MimeEntityList::const_iterator mbit, meit;
158 mbit = me.body().parts().begin(), meit = me.body().parts().end();
159 for(; mbit != meit; ++mbit)
160 printPart(**mbit, mpr, fqn);
163 int main(int argc, char** argv)
165 std::ios_base::sync_with_stdio(false);
172 string param = argv[p];
175 else if (param == "-r")
177 else if (param == "-q")
179 else if (param == "-l")
180 mpr.justFilename = 1;
181 else if (param == "-H")
182 ignoreMask += imHeader;
183 else if (param == "-B")
184 ignoreMask += imBody;
185 else if (param == "-C")
186 ignoreMask += imChildParts;
187 else if (param == "-t") {
188 die( ++p == argc, param + " requires an argument");
189 ContentType ct(argv[p]);
190 die(mpr.type.length() != 0, "just one -t allowed");
191 mpr.type = ct.type();
192 mpr.subtype = ct.subtype();
193 } else if (param == "-p") {
194 die( ++p == argc, param + " requires an argument");
195 string switch_param = argv[p];
196 StringTokenizer stok(&switch_param, "=");
197 pair<string,string> item;
198 stok.next(item.first) && stok.next(item.second);
199 mpr.paramList.push_back(item);
200 } else if (param == "-f") {
201 die( ++p == argc, param + " requires an argument");
202 string switch_param = argv[p];
203 StringTokenizer stok(&switch_param, "=");
204 pair<string,string> item;
205 stok.next(item.first) && stok.next(item.second);
206 mpr.fieldList.push_back(item);
207 } else if( param.length() == 2 && param[0] == '-') {
210 // filename list starts here
211 // first filename: argv[p]
220 istreambuf_iterator<char> bit(cin), eit;
222 me.load(bit, eit, ignoreMask);
224 printPart(me, mpr, fqn);
226 for(int fc = p; fc < argc; ++fc)
232 cerr << "ERR: unable to open file " << argv[fc]
237 me.load(in.begin(), in.end(), ignoreMask);
238 printPart(me, mpr, fqn);