diff --git a/src/common/rclconfig.cpp b/src/common/rclconfig.cpp index b27115ef..1c82e94d 100644 --- a/src/common/rclconfig.cpp +++ b/src/common/rclconfig.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include "cstr.h" #include "pathut.h" @@ -70,6 +71,12 @@ bool o_uptodate_test_use_mtime = false; string RclConfig::o_localecharset; string RclConfig::o_origcwd; +// We build this once. Used to ensure that the suffix used for a temp +// file of a given MIME type is the FIRST one from the mimemap config +// file. Previously it was the first in alphabetic (map) order, with +// sometimes strange results. +static unordered_map mime_suffixes; + // Compute the difference of 1st to 2nd sets and return as plus/minus // sets. Some args are std::set and some others stringToString() // strings for convenience @@ -316,6 +323,27 @@ RclConfig::RclConfig(const string *argcnf) m_reason = string("No or bad mimemap file in: ") + cnferrloc; return; } + + // Maybe create the MIME to suffix association reverse map. Do it + // in file order so that we can control what suffix is used when + // there are several. This only uses the distributed file, not any + // local customization (too complicated). + if (mime_suffixes.empty()) { + ConfSimple mm( + path_cat(path_cat(m_datadir, "examples"), "mimemap").c_str()); + vector order = mm.getlines(); + for (const auto& entry: order) { + if (entry.m_kind == ConfLine::CFL_VAR) { + LOGDEB1("CONFIG: " << entry.m_data << " -> " << entry.m_value << + endl); + // Remember: insert() only does anything for new keys, + // so we only have the first value in the map + mime_suffixes.insert( + pair(entry.m_value, entry.m_data)); + } + } + } + mimeconf = new ConfStack("mimeconf", m_cdirs, true); if (mimeconf == 0 || !mimeconf->ok()) { m_reason = string("No/bad mimeconf in: ") + cnferrloc; @@ -753,14 +781,20 @@ string RclConfig::getMimeTypeFromSuffix(const string& suff) const string RclConfig::getSuffixFromMimeType(const string &mt) const { - string suffix; - vectorsfs = mimemap->getNames(cstr_null); - string mt1; - for (vector::const_iterator it = sfs.begin(); - it != sfs.end(); it++) { - if (mimemap->get(*it, mt1, cstr_null)) - if (!stringicmp(mt, mt1)) - return *it; + // First try from standard data, ensuring that we can control the value + // from the order in the configuration file. + auto rclsuff = mime_suffixes.find(mt); + if (rclsuff != mime_suffixes.end()) { + return rclsuff->second; + } + // Try again from local data. The map is in the wrong direction, + // have to walk it. + vector sfs = mimemap->getNames(cstr_null); + for (const auto& suff : sfs) { + string mt1; + if (mimemap->get(suff, mt1, cstr_null) && !stringicmp(mt, mt1)) { + return suff; + } } return cstr_null; } diff --git a/src/sampleconf/mimemap b/src/sampleconf/mimemap index 69b61ef5..e3408765 100644 --- a/src/sampleconf/mimemap +++ b/src/sampleconf/mimemap @@ -4,6 +4,11 @@ # All entries must be in lower case characters. File name extensions are # lower-cased for comparison during indexing, meaning that an upper or # mixed case entry will never be matched. +# +# When creating a temporary file for a MIME type (e.g. temp file for +# display), the FIRST entry for the MIME type will be used to determine the +# file suffix. This may be important if the app used does not grok all the +# possible suffixes. .txt = text/plain .text = text/plain @@ -101,18 +106,18 @@ # OpenOffice / opendocument. We handle opendocument as old openoffice files # for now -.sxc = application/vnd.sun.xml.calc .ods = application/vnd.sun.xml.calc +.sxc = application/vnd.sun.xml.calc .stc = application/vnd.sun.xml.calc.template -.sxd = application/vnd.sun.xml.draw .odg = application/vnd.sun.xml.draw +.sxd = application/vnd.sun.xml.draw .std = application/vnd.sun.xml.draw.template -.sxi = application/vnd.sun.xml.impress .odp = application/vnd.sun.xml.impress +.sxi = application/vnd.sun.xml.impress .sti = application/vnd.sun.xml.impress.template .sxm = application/vnd.sun.xml.math -.sxw = application/vnd.sun.xml.writer .odt = application/vnd.sun.xml.writer +.sxw = application/vnd.sun.xml.writer .sxg = application/vnd.sun.xml.writer.global .stw = application/vnd.sun.xml.writer.template diff --git a/src/utils/conftree.cpp b/src/utils/conftree.cpp index 09b71b8a..3e3f6f19 100644 --- a/src/utils/conftree.cpp +++ b/src/utils/conftree.cpp @@ -415,6 +415,7 @@ int ConfSimple::i_set(const std::string& nm, const std::string& value, // During the initial construction, just append: CONFDEB("ConfSimple::i_set: init true: append\n"); m_order.push_back(ConfLine(ConfLine::CFL_VAR, nm)); + m_order.back().m_value = value; return 1; } diff --git a/src/utils/conftree.h b/src/utils/conftree.h index 905d7823..98c68ef7 100644 --- a/src/utils/conftree.h +++ b/src/utils/conftree.h @@ -71,6 +71,7 @@ public: enum Kind {CFL_COMMENT, CFL_SK, CFL_VAR, CFL_VARCOMMENT}; Kind m_kind; std::string m_data; + std::string m_value; std::string m_aux; ConfLine(Kind k, const std::string& d, std::string a = std::string()) : m_kind(k), m_data(d), m_aux(a) {