mu-message: various small tweaks
- Remove possible cache-dir - Retain Personal flag - Handle some corner cases
This commit is contained in:
@ -27,6 +27,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <utils/mu-utils.hh>
|
#include <utils/mu-utils.hh>
|
||||||
|
#include <utils/mu-utils-file.hh>
|
||||||
#include <utils/mu-error.hh>
|
#include <utils/mu-error.hh>
|
||||||
#include <utils/mu-option.hh>
|
#include <utils/mu-option.hh>
|
||||||
#include <utils/mu-lang-detector.hh>
|
#include <utils/mu-lang-detector.hh>
|
||||||
@ -50,6 +51,14 @@ struct Message::Private {
|
|||||||
Private(Message::Options options, Xapian::Document&& xdoc):
|
Private(Message::Options options, Xapian::Document&& xdoc):
|
||||||
opts{options}, doc{std::move(xdoc), doc_opts(opts)} {}
|
opts{options}, doc{std::move(xdoc), doc_opts(opts)} {}
|
||||||
|
|
||||||
|
~Private() { /* clean up the cache dir, if any */
|
||||||
|
if (cache_path.empty())
|
||||||
|
return;
|
||||||
|
if (auto&& res{remove_directory(cache_path)}; !res)
|
||||||
|
mu_warning("failed to remove cache dir '{}': {}",
|
||||||
|
cache_path, res.error().what());
|
||||||
|
}
|
||||||
|
|
||||||
Message::Options opts;
|
Message::Options opts;
|
||||||
Document doc;
|
Document doc;
|
||||||
mutable Option<MimeMessage> mime_msg;
|
mutable Option<MimeMessage> mime_msg;
|
||||||
@ -78,7 +87,7 @@ struct Message::Private {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Document::Options doc_opts(Message::Options mopts) {
|
Document::Options doc_opts(Message::Options mopts) {
|
||||||
return any_of(opts & Message::Options::NgramsEnabled) ?
|
return any_of(mopts & Message::Options::NgramsEnabled) ?
|
||||||
Document::Options::NgramsEnabled :
|
Document::Options::NgramsEnabled :
|
||||||
Document::Options::None;
|
Document::Options::None;
|
||||||
}
|
}
|
||||||
@ -326,7 +335,8 @@ extract_tags(const MimeMessage& mime_msg)
|
|||||||
for (auto&& tagval : split(*hdr, item.second)) {
|
for (auto&& tagval : split(*hdr, item.second)) {
|
||||||
tagval.erase(0, tagval.find_first_not_of(' '));
|
tagval.erase(0, tagval.find_first_not_of(' '));
|
||||||
tagval.erase(tagval.find_last_not_of(' ')+1);
|
tagval.erase(tagval.find_last_not_of(' ')+1);
|
||||||
tags.emplace_back(std::move(tagval));
|
if (!tagval.empty())
|
||||||
|
tags.emplace_back(std::move(tagval));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -493,6 +503,9 @@ handle_encrypted(const MimeMultipartEncrypted& part, Message::Private& info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (res->first.is_multipart()) {
|
if (res->first.is_multipart()) {
|
||||||
|
/* handle the multipart itself too, so e.g. a decrypted
|
||||||
|
* multipart/signed sets the Signed flag */
|
||||||
|
handle_object(part, res->first, info);
|
||||||
MimeMultipart{res->first}.for_each(
|
MimeMultipart{res->first}.for_each(
|
||||||
[&](auto&& parent, auto&& child_obj) {
|
[&](auto&& parent, auto&& child_obj) {
|
||||||
handle_object(parent, child_obj, info);
|
handle_object(parent, child_obj, info);
|
||||||
@ -538,8 +551,7 @@ handle_object(const MimeObject& parent,
|
|||||||
handle_encrypted(MimeMultipartEncrypted{obj}, info);
|
handle_encrypted(MimeMultipartEncrypted{obj}, info);
|
||||||
else if (obj.is_part() ||
|
else if (obj.is_part() ||
|
||||||
obj.is_message_part() ||
|
obj.is_message_part() ||
|
||||||
obj.is_multipart_signed() ||
|
obj.is_multipart_signed())
|
||||||
obj.is_multipart_encrypted())
|
|
||||||
info.parts.emplace_back(obj);
|
info.parts.emplace_back(obj);
|
||||||
|
|
||||||
if (obj.is_part())
|
if (obj.is_part())
|
||||||
@ -662,13 +674,14 @@ doc_add_list_post(Document& doc, const MimeMessage& mime_msg)
|
|||||||
* those cases, check the List-Post address and use that instead */
|
* those cases, check the List-Post address and use that instead */
|
||||||
|
|
||||||
GMatchInfo* minfo{};
|
GMatchInfo* minfo{};
|
||||||
GRegex* rx{};
|
|
||||||
const auto list_post{mime_msg.header("List-Post")};
|
const auto list_post{mime_msg.header("List-Post")};
|
||||||
if (!list_post)
|
if (!list_post)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
rx = g_regex_new("<?mailto:([a-z0-9!@#$%&'*+-/=?^_`{|}~]+)>?",
|
/* compile the regex only once */
|
||||||
G_REGEX_CASELESS, (GRegexMatchFlags)0, {});
|
static GRegex *rx = g_regex_new(
|
||||||
|
"<?mailto:([a-z0-9!@#$%&'*+-/=?^_`{|}~]+)>?",
|
||||||
|
G_REGEX_CASELESS, (GRegexMatchFlags)0, {});
|
||||||
g_return_if_fail(rx);
|
g_return_if_fail(rx);
|
||||||
|
|
||||||
Contacts contacts;
|
Contacts contacts;
|
||||||
@ -681,8 +694,6 @@ doc_add_list_post(Document& doc, const MimeMessage& mime_msg)
|
|||||||
if (minfo)
|
if (minfo)
|
||||||
g_match_info_free(minfo);
|
g_match_info_free(minfo);
|
||||||
|
|
||||||
g_regex_unref(rx);
|
|
||||||
|
|
||||||
doc.add_extra_contacts(":list-post", contacts);
|
doc.add_extra_contacts(":list-post", contacts);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -732,7 +743,10 @@ fill_document(Message::Private& priv)
|
|||||||
doc.add(field.id, mime_msg.contacts(Contact::Type::Cc));
|
doc.add(field.id, mime_msg.contacts(Contact::Type::Cc));
|
||||||
break;
|
break;
|
||||||
case Field::Id::Changed:
|
case Field::Id::Changed:
|
||||||
doc.add(field.id, priv.ctime);
|
/* when lazily re-filling a store-backed message, we
|
||||||
|
* never stat'ed the file; keep the stored value */
|
||||||
|
if (priv.ctime != 0)
|
||||||
|
doc.add(field.id, priv.ctime);
|
||||||
break;
|
break;
|
||||||
case Field::Id::Date:
|
case Field::Id::Date:
|
||||||
doc.add(field.id, mime_msg.date());
|
doc.add(field.id, mime_msg.date());
|
||||||
@ -745,7 +759,12 @@ fill_document(Message::Private& priv)
|
|||||||
doc.add(field.id, part.raw_filename());
|
doc.add(field.id, part.raw_filename());
|
||||||
break;
|
break;
|
||||||
case Field::Id::Flags:
|
case Field::Id::Flags:
|
||||||
doc.add(priv.flags);
|
/* the stored flags may include Flags::Personal, which
|
||||||
|
* is determined with the contacts-cache (mu-store.cc)
|
||||||
|
* and cannot be recomputed here; don't lose it when
|
||||||
|
* lazily re-filling a store-backed message */
|
||||||
|
doc.add(flags_keep_unmutable(doc.flags_value(), priv.flags,
|
||||||
|
Flags::Personal));
|
||||||
break;
|
break;
|
||||||
case Field::Id::From:
|
case Field::Id::From:
|
||||||
doc.add(field.id, mime_msg.contacts(Contact::Type::From));
|
doc.add(field.id, mime_msg.contacts(Contact::Type::From));
|
||||||
@ -806,7 +825,9 @@ fill_document(Message::Private& priv)
|
|||||||
Option<std::string>
|
Option<std::string>
|
||||||
Message::header(const std::string& header_field) const
|
Message::header(const std::string& header_field) const
|
||||||
{
|
{
|
||||||
load_mime_message();
|
if (!load_mime_message())
|
||||||
|
return Nothing;
|
||||||
|
|
||||||
return priv_->mime_msg->header(header_field);
|
return priv_->mime_msg->header(header_field);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -860,11 +881,11 @@ Message::cache_path(Option<size_t> index) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (index) {
|
if (index) {
|
||||||
GError *err{};
|
|
||||||
auto tpath = mu_format("{}/{}", priv_->cache_path, *index);
|
auto tpath = mu_format("{}/{}", priv_->cache_path, *index);
|
||||||
if (g_mkdir(tpath.c_str(), 0700) != 0)
|
if (g_mkdir(tpath.c_str(), 0700) != 0 && errno != EEXIST)
|
||||||
return Err(Error::Code::File, &err,
|
return Err(Error::Code::File,
|
||||||
"failed to create cache dir '{}'; err={}", tpath, errno);
|
"failed to create cache dir '{}': {}", tpath,
|
||||||
|
g_strerror(errno));
|
||||||
return Ok(std::move(tpath));
|
return Ok(std::move(tpath));
|
||||||
} else
|
} else
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user