Switch to side-by-side view

--- a/src/internfile/internfile.cpp
+++ b/src/internfile/internfile.cpp
@@ -46,11 +46,7 @@
 #include "cancelcheck.h"
 #include "copyfile.h"
 #include "fetcher.h"
-
-#ifdef RCL_USE_XATTR
-#include "pxattr.h"
-#endif // RCL_USE_XATTR
-
+#include "extrameta.h"
 
 // The internal path element separator. This can't be the same as the rcldb 
 // file to ipath separator : "|"
@@ -75,69 +71,6 @@
 	out += *it == cchar_colon_repl ? ':' : *it;
     }
     return out;
-}
-
-#ifdef RCL_USE_XATTR
-void FileInterner::reapXAttrs(const string& path)
-{
-    LOGDEB2(("FileInterner::reapXAttrs: [%s]\n", path.c_str()));
-    
-    // Retrieve xattrs names from files and mapping table from config
-    vector<string> xnames;
-    if (!pxattr::list(path, &xnames)) {
-	LOGERR(("FileInterner::reapXattrs: pxattr::list: errno %d\n", errno));
-	return;
-    }
-    const map<string, string>& xtof = m_cfg->getXattrToField();
-
-    // Record the xattrs: names found in the config are either skipped
-    // or mapped depending if the translation is empty. Other names
-    // are recorded as-is
-    for (vector<string>::const_iterator it = xnames.begin();
-	 it != xnames.end(); it++) {
-	string key = *it;
-	map<string, string>::const_iterator mit = xtof.find(*it);
-	if (mit != xtof.end()) {
-	    if (mit->second.empty()) {
-		continue;
-	    } else {
-		key = mit->second;
-	    }
-	}
-	string value;
-	if (!pxattr::get(path, *it, &value, pxattr::PXATTR_NOFOLLOW)) {
-	    LOGERR(("FileInterner::reapXattrs: pxattr::get failed"
-		    "for %s, errno %d\n", (*it).c_str(), errno));
-	    continue;
-	}
-	// Encode should we ?
-	m_XAttrsFields[key] = value;
-	LOGDEB2(("FileInterner::reapXAttrs: [%s] -> [%s]\n", 
-		 key.c_str(), value.c_str()));
-    }
-}
-#endif // RCL_USE_XATTR
-
-void FileInterner::reapCmdMetadata(const string& fn)
-{
-    const vector<MDReaper>& reapers = m_cfg->getMDReapers();
-    if (reapers.empty())
-	return;
-    map<char,string> smap = create_map<char, string>('f', fn);
-    for (vector<MDReaper>::const_iterator rp = reapers.begin();
-	 rp != reapers.end(); rp++) {
-	vector<string> cmd;
-	for (vector<string>::const_iterator it = rp->cmdv.begin();
-	     it != rp->cmdv.end(); it++) {
-	    string s;
-	    pcSubst(*it, s, smap);
-	    cmd.push_back(s);
-	}
-	string output;
-	if (ExecCmd::backtick(cmd, output)) {
-	    m_cmdFields[rp->fieldname] =  output;
-	}
-    }
 }
 
 // This is used when the user wants to retrieve a search result doc's parent
@@ -300,9 +233,11 @@
     // original file, not the m_fn which may be the uncompressed temp
     // file
     if (!m_noxattrs)
-	reapXAttrs(f);
+	reapXAttrs(m_cfg, f, m_XAttrsFields);
 #endif //RCL_USE_XATTR
-    reapCmdMetadata(f);
+
+    // Gather metadata from external commands as configured.
+    reapMetaCmds(m_cfg, f, m_cmdFields);
 
     df->set_docsize(docsize);
     if (!df->set_document_file(l_mime, m_fn)) {
@@ -619,19 +554,6 @@
     return true;
 }
 
-static void docfieldfrommeta(RclConfig* cfg, const string& name, 
-			     const string &value, Rcl::Doc& doc)
-{
-    string fieldname = cfg->fieldCanon(name);
-    LOGDEB0(("Internfile:: setting [%s] from cmd value [%s]\n",
-	     fieldname.c_str(), value.c_str()));
-    if (fieldname == cstr_dj_keymd) {
-	doc.dmtime = value;
-    } else {
-	doc.meta[fieldname] = value;
-    }
-}
-
 // Collect the ipath from the current path in the document tree.
 // While we're at it, we also set the mimetype and filename,
 // which are special properties: we want to get them from the topmost
@@ -654,43 +576,11 @@
 
 #ifdef RCL_USE_XATTR
     if (!m_noxattrs) {
-	// Set fields from extended file attributes.
-	// These can be later augmented by values from inside the file
-	for (map<string,string>::const_iterator it = m_XAttrsFields.begin(); 
-	     it != m_XAttrsFields.end(); it++) {
-	    LOGDEB1(("Internfile:: setting [%s] from xattrs value [%s]\n",
-		     m_cfg->fieldCanon(it->first).c_str(), it->second.c_str()));
-	    doc.meta[m_cfg->fieldCanon(it->first)] = it->second;
-	}
+	docFieldsFromXattrs(m_cfg, m_XAttrsFields, doc);
     }
 #endif //RCL_USE_XATTR
 
-    // Set fields from external commands
-    // These override those from xattrs and can be later augmented by
-    // values from inside the file.
-    //
-    // This is a bit atrocious because some entry names are special:
-    // "modificationdate" will set mtime instead of an ordinary field,
-    // and the output from anything beginning with "rclmulti" will be
-    // interpreted as multiple fields in configuration file format...
-    for (map<string,string>::const_iterator it = m_cmdFields.begin(); 
-	 it != m_cmdFields.end(); it++) {
-	if (!it->first.compare(0, 8, "rclmulti")) {
-	    ConfSimple simple(it->second);
-	    if (simple.ok()) {
-		vector<string> names = simple.getNames("");
-		for (vector<string>::const_iterator nm = names.begin(); 
-		     nm != names.end(); nm++) {
-		    string value;
-		    if (simple.get(*nm, value)) {
-			docfieldfrommeta(m_cfg, *nm, value, doc);
-		    }
-		}
-	    }
-	} else {
-	    docfieldfrommeta(m_cfg, it->first, it->second, doc);
-	}
-    }
+    docFieldsFromMetaCmds(m_cfg, m_cmdFields, doc);
 
     // If there is no ipath stack, the mimetype is the one from the file
     doc.mimetype = m_mimetype;