From 7366ab158e41f9304ec871ff3c2af1b701c4a942 Mon Sep 17 00:00:00 2001 From: Jean-Francois Dockes Date: Thu, 3 Oct 2013 09:38:35 +0200 Subject: [PATCH] Code for reaping xattrs and cmd metadata did not need to be implemented as internfile members and can be used in other contexts --- src/internfile/extrameta.cpp | 149 ++++++++++++++++++++++++++++++++++ src/internfile/extrameta.h | 52 ++++++++++++ src/internfile/internfile.cpp | 124 ++-------------------------- src/internfile/internfile.h | 4 - 4 files changed, 208 insertions(+), 121 deletions(-) create mode 100644 src/internfile/extrameta.cpp create mode 100644 src/internfile/extrameta.h diff --git a/src/internfile/extrameta.cpp b/src/internfile/extrameta.cpp new file mode 100644 index 00000000..3f2a5ac4 --- /dev/null +++ b/src/internfile/extrameta.cpp @@ -0,0 +1,149 @@ +/* Copyright (C) 2004 J.F.Dockes + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "autoconfig.h" + +#ifdef RCL_USE_XATTR + +#include + +#include "rclconfig.h" +#include "pxattr.h" +#include "debuglog.h" +#include "cstr.h" +#include "rcldoc.h" +#include "execmd.h" + +using std::string; +using std::map; + +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/xattr value [%s]\n", + fieldname.c_str(), value.c_str())); + if (fieldname == cstr_dj_keymd) { + doc.dmtime = value; + } else { + doc.meta[fieldname] = value; + } +} + +void reapXAttrs(const RclConfig* cfg, const string& path, + map& xfields) +{ + LOGDEB2(("reapXAttrs: [%s]\n", path.c_str())); + + // Retrieve xattrs names from files and mapping table from config + vector xnames; + if (!pxattr::list(path, &xnames)) { + LOGERR(("FileInterner::reapXattrs: pxattr::list: errno %d\n", errno)); + return; + } + const map& xtof = 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::const_iterator it = xnames.begin(); + it != xnames.end(); it++) { + string key = *it; + map::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 ? + xfields[key] = value; + LOGDEB2(("reapXAttrs: [%s] -> [%s]\n", key.c_str(), value.c_str())); + } +} + +void docFieldsFromXattrs(RclConfig *cfg, const map& xfields, + Rcl::Doc& doc) +{ + for (map::const_iterator it = xfields.begin(); + it != xfields.end(); it++) { + docfieldfrommeta(cfg, it->first, it->second, doc); + } +} + +void reapMetaCmds(RclConfig* cfg, const string& path, + map& cfields) +{ + const vector& reapers = cfg->getMDReapers(); + if (reapers.empty()) + return; + map smap = create_map('f', path); + for (vector::const_iterator rp = reapers.begin(); + rp != reapers.end(); rp++) { + vector cmd; + for (vector::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)) { + cfields[rp->fieldname] = output; + } + } +} + +// 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... +void docFieldsFromMetaCmds(RclConfig *cfg, const map& cfields, + Rcl::Doc& doc) +{ + for (map::const_iterator it = cfields.begin(); + it != cfields.end(); it++) { + if (!it->first.compare(0, 8, "rclmulti")) { + ConfSimple simple(it->second); + if (simple.ok()) { + vector names = simple.getNames(""); + for (vector::const_iterator nm = names.begin(); + nm != names.end(); nm++) { + string value; + if (simple.get(*nm, value)) { + docfieldfrommeta(cfg, *nm, value, doc); + } + } + } + } else { + docfieldfrommeta(cfg, it->first, it->second, doc); + } + } +} + +#endif // RCL_USE_XATTR diff --git a/src/internfile/extrameta.h b/src/internfile/extrameta.h new file mode 100644 index 00000000..93c70f11 --- /dev/null +++ b/src/internfile/extrameta.h @@ -0,0 +1,52 @@ +/* Copyright (C) 2004 J.F.Dockes + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#ifndef _REAPXATTRS_H_INCLUDED_ +#define _REAPXATTRS_H_INCLUDED_ + +#include "autoconfig.h" + +#ifdef RCL_USE_XATTR +/** Extended attributes processing helper functions */ + +#include +#include + +class RclConfig; +namespace Rcl {class Doc;}; + +/** Read external attributes, possibly ignore some or change the names + according to the fields configuration */ +extern void reapXAttrs(const RclConfig* config, const std::string& path, + std::map& xfields); + +/** Turn the pre-processed extended file attributes into doc fields */ +extern void docFieldsFromXattrs( + RclConfig *cfg, const std::map& xfields, + Rcl::Doc& doc); + +/** Get metadata by executing commands */ +extern void reapMetaCmds(RclConfig* config, const std::string& path, + std::map& xfields); + +/** Turn the pre-processed ext cmd metadata into doc fields */ +extern void docFieldsFromMetaCmds( + RclConfig *cfg, const std::map& xfields, + Rcl::Doc& doc); + +#endif /* RCL_USE_XATTR */ + +#endif /* _REAPXATTRS_H_INCLUDED_ */ diff --git a/src/internfile/internfile.cpp b/src/internfile/internfile.cpp index e51372d6..f6a46eff 100644 --- a/src/internfile/internfile.cpp +++ b/src/internfile/internfile.cpp @@ -46,11 +46,7 @@ using namespace std; #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 : "|" @@ -77,69 +73,6 @@ static string colon_restore(const string& in) 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 xnames; - if (!pxattr::list(path, &xnames)) { - LOGERR(("FileInterner::reapXattrs: pxattr::list: errno %d\n", errno)); - return; - } - const map& 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::const_iterator it = xnames.begin(); - it != xnames.end(); it++) { - string key = *it; - map::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& reapers = m_cfg->getMDReapers(); - if (reapers.empty()) - return; - map smap = create_map('f', fn); - for (vector::const_iterator rp = reapers.begin(); - rp != reapers.end(); rp++) { - vector cmd; - for (vector::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 // (ie message having a given attachment) bool FileInterner::getEnclosingUDI(const Rcl::Doc &doc, string& udi) @@ -300,9 +233,11 @@ void FileInterner::init(const string &f, const struct stat *stp, RclConfig *cnf, // 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 @@ bool FileInterner::dijontorcl(Rcl::Doc& doc) 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 @@ void FileInterner::collectIpathAndMT(Rcl::Doc& doc) const #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::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::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 names = simple.getNames(""); - for (vector::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; diff --git a/src/internfile/internfile.h b/src/internfile/internfile.h index 91759423..88c72b1c 100644 --- a/src/internfile/internfile.h +++ b/src/internfile/internfile.h @@ -290,10 +290,6 @@ class FileInterner { int addHandler(); void checkExternalMissing(const string& msg, const string& mt); void processNextDocError(Rcl::Doc &doc); -#ifdef RCL_USE_XATTR - void reapXAttrs(const string& fn); -#endif - void reapCmdMetadata(const string& fn); };