1 /***************************************************************************
2 copyright : (C) 2002-2005 by Stefano Barbato
3 email : stefano@codesink.org
5 $Id: search.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 search.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 << "search [params] [in_file...]" << endl;
36 cout << "\t-I filename use index (disables '-r')" << endl;
37 cout << "\t-r looks for matches in nested entities"<<endl;
38 cout << "\t-t type[/subtype] matches Content-Type" << endl;
39 cout << "\t-p param[=value] matches Content-Type param" << endl;
40 cout << "\t-f name[=value] matches an header field" << endl;
41 cout << "\t-l doesn't write anything but filename" << endl;
42 cout << "\t-q totaly quiet; exit code = num of matches" << endl;
49 typedef pair<istring,istring> Param;
50 typedef pair<istring,istring> Field;
52 : recursive(0), quiet(0)
55 bool operator()(const MimeEntity* pMe) const
57 // check for content type match
58 const Header& h = pMe->header();
59 if(type.length() && type != h.contentType().type())
61 if(subtype.length() && subtype != h.contentType().subtype())
65 // check for params matches
68 ContentType::ParamList::const_iterator ctpbit,ctpeit;
69 ctpbit = h.contentType().paramList().begin();
70 ctpeit = h.contentType().paramList().end();
72 for(; !matched && ctpbit != ctpeit; ++ctpbit)
74 list<Param>::const_iterator pbit, peit;
75 pbit = paramList.begin(), peit = paramList.end();
76 for(; pbit != peit; ++pbit)
78 if(ctpbit->name() != pbit->first)
81 istring value = ctpbit->value();
82 if(value.find(pbit->second) != string::npos)
90 // check for field matches
94 Header::const_iterator hbit, heit;
97 for(; !matched && hbit != heit; ++hbit)
99 list<Field>::const_iterator fbit, feit;
100 fbit = fieldList.begin(), feit = fieldList.end();
101 for(; fbit != feit; ++fbit)
103 if(hbit->name() != fbit->first)
106 istring value = hbit->value();
107 if(value.find(fbit->second) != string::npos)
118 istring type, subtype;
119 list<Param> paramList;
120 list<Field> fieldList;
121 bool recursive, quiet;
124 void die(bool b, const string& msg)
128 cerr << "Error: " << msg << endl << endl;
133 void printPart(const MimeEntity& me, const MatchParamRq& mpr, string& fqn)
140 if(fqn.length() == 0)
147 return; // just top level entity
148 MimeEntityList::const_iterator mbit, meit;
149 mbit = me.body().parts().begin(), meit = me.body().parts().end();
150 for(; mbit != meit; ++mbit)
151 printPart(**mbit, mpr, fqn);
154 // search the whole index for matches
155 void searchIndex(const MimeEntity& me, const MatchParamRq& mpr)
157 cout << "PARTS COUNT: " << me.body().parts().size() << endl;
158 MimeEntityList::const_iterator mbit, meit;
159 mbit = me.body().parts().begin(), meit = me.body().parts().end();
160 for(; mbit != meit; ++mbit)
162 MimeEntity* pMe = *mbit;
164 cout << pMe->header().field("x-filename").value() << endl;
167 int main(int argc, char** argv)
169 std::ios_base::sync_with_stdio(false);
171 int ignoreMask = imChildParts | imBody;
178 string param = argv[p];
181 else if (param == "-r") {
183 ignoreMask = ignoreMask & ~imChildParts;
184 } else if (param == "-q") {
186 } else if (param == "-t") {
187 die( ++p == argc, param + " requires an argument");
188 ContentType ct(argv[p]);
189 die(mpr.type.length() != 0, "just one -t allowed");
190 mpr.type = ct.type();
191 mpr.subtype = ct.subtype();
192 } else if (param == "-I") {
193 die( ++p == argc, param + " requires an argument");
196 } else if (param == "-p") {
197 die( ++p == argc, param + " requires an argument");
198 string switch_param = argv[p];
199 StringTokenizer stok(&switch_param, "=");
200 pair<string,string> item;
201 stok.next(item.first) && stok.next(item.second);
202 mpr.paramList.push_back(item);
203 } else if (param == "-f") {
204 die( ++p == argc, param + " requires an argument");
205 string switch_param = argv[p];
206 StringTokenizer stok(&switch_param, "=");
207 pair<string,string> item;
208 stok.next(item.first) && stok.next(item.second);
209 mpr.fieldList.push_back(item);
210 } else if( param.length() == 2 && param[0] == '-') {
213 // filename list starts here
214 // first filename: argv[p]
223 die(!in, "Error opening index file");
225 MimeEntity idxEntity;
226 idxEntity.load(in.begin(), in.end());
227 searchIndex(idxEntity, mpr);
228 } else if(argc == p) {
230 istreambuf_iterator<char> bit(cin), eit;
232 me.load(bit, eit, ignoreMask);
234 printPart(me, mpr, fqn);
236 for(int fc = p; fc < argc; ++fc)
242 cerr << "ERR: unable to open file " << argv[fc]
247 me.load(in.begin(), in.end(), ignoreMask);
248 printPart(me,mpr, fqn);