--- a/src/rcldb/searchdata.cpp
+++ b/src/rcldb/searchdata.cpp
@@ -17,6 +17,7 @@
// Handle translation from rcl's SearchData structures to Xapian Queries
#include <stdio.h>
+#include <fnmatch.h>
#include <string>
#include <vector>
@@ -133,6 +134,35 @@
}
return Xapian::Query(Xapian::Query::OP_OR, v.begin(), v.end());
+}
+
+// Expand categories and mime type wild card exps
+bool SearchData::expandFileTypes(RclConfig *cfg, vector<string>& tps)
+{
+ if (!cfg) {
+ LOGFATAL(("Db::expandFileTypes: null configuration!!\n"));
+ return false;
+ }
+ vector<string> exptps;
+ list<string> alltypes = cfg->getAllMimeTypes();
+
+ for (vector<string>::iterator it = tps.begin(); it != tps.end(); it++) {
+ if (cfg->isMimeCategory(*it)) {
+ list<string>tps;
+ cfg->getMimeCatTypes(*it, tps);
+ exptps.insert(exptps.end(), tps.begin(), tps.end());
+ } else {
+ for (list<string>::const_iterator ait = alltypes.begin();
+ ait != alltypes.end(); ait++) {
+ if (fnmatch(it->c_str(), ait->c_str(), FNM_CASEFOLD)
+ != FNM_NOMATCH) {
+ exptps.push_back(*ait);
+ }
+ }
+ }
+ }
+ tps = exptps;
+ return true;
}
bool SearchData::toNativeQuery(Rcl::Db &db, void *d)
@@ -220,30 +250,32 @@
// Add the file type filtering clause if any
if (!m_filetypes.empty()) {
- vector<string> exptps;
- exptps.reserve(m_filetypes.size());
- // Expand categories
- RclConfig *cfg = db.getConf();
+ expandFileTypes(db.getConf(), m_filetypes);
+
+ Xapian::Query tq;
for (vector<string>::iterator it = m_filetypes.begin();
it != m_filetypes.end(); it++) {
- if (cfg && cfg->isMimeCategory(*it)) {
- list<string>tps;
- cfg->getMimeCatTypes(*it, tps);
- exptps.insert(exptps.end(), tps.begin(), tps.end());
- } else {
- exptps.push_back(*it);
- }
- }
-
- Xapian::Query tq;
- for (vector<string>::iterator it = exptps.begin();
- it != exptps.end(); it++) {
string term = "T" + *it;
LOGDEB0(("Adding file type term: [%s]\n", term.c_str()));
tq = tq.empty() ? Xapian::Query(term) :
Xapian::Query(Xapian::Query::OP_OR, tq, Xapian::Query(term));
}
xq = xq.empty() ? tq : Xapian::Query(Xapian::Query::OP_FILTER, xq, tq);
+ }
+
+ // Add the neg file type filtering clause if any
+ if (!m_nfiletypes.empty()) {
+ expandFileTypes(db.getConf(), m_nfiletypes);
+
+ Xapian::Query tq;
+ for (vector<string>::iterator it = m_nfiletypes.begin();
+ it != m_nfiletypes.end(); it++) {
+ string term = "T" + *it;
+ LOGDEB0(("Adding negative file type term: [%s]\n", term.c_str()));
+ tq = tq.empty() ? Xapian::Query(term) :
+ Xapian::Query(Xapian::Query::OP_OR, tq, Xapian::Query(term));
+ }
+ xq = xq.empty() ? tq : Xapian::Query(Xapian::Query::OP_AND_NOT, xq, tq);
}
// Add the directory filtering clause