22// SPDX-FileCopyrightText: 2020–2025 grommunio GmbH
33// This file is part of Gromox.
44#include < cerrno>
5+ #include < climits>
56#include < cstdio>
67#include < cstring>
78#include < fcntl.h>
@@ -63,29 +64,35 @@ bool mjson_io::exists(const std::string &path) const
6364 return m_cache.find (path) != m_cache.cend ();
6465}
6566
66- mjson_io::c_iter mjson_io::find (const std::string &path)
67+ void mjson_io::place (const std::string &path, std::string &&content)
68+ {
69+ m_cache[path] = std::move (content);
70+ }
71+
72+ const std::string *mjson_io::get_full (const std::string &path) const
6773{
6874 auto iter = m_cache.find (path);
69- if (iter != m_cache.cend ())
70- return iter;
71- /*
72- * Not finding the element is not an error; asking for `BODY[2.1.3]`
73- * will iteratively look for /2.1.3.dgt, /2.1.dgt, /2.dgt.
74- */
75- return m_cache.cend ();
75+ return iter != m_cache.end () ? &iter->second : nullptr ;
7676}
7777
78- void mjson_io::place (const std::string &path, std::string &&content)
78+ ssize_t mjson_io::get_size (const std::string &path) const
7979{
80- m_cache[path] = std::move (content);
80+ auto str = get_full (path);
81+ if (str == nullptr )
82+ return -1 ;
83+ if (str->size () >= SSIZE_MAX)
84+ return SSIZE_MAX;
85+ return str->size ();
8186}
8287
83- std::string mjson_io::substr (mjson_io::c_iter it, size_t of, size_t len)
88+ std::optional<std::string> mjson_io::get_substr (const std::string &path,
89+ size_t of, size_t len) const
8490{
85- const auto &str = it->second ;
86- if (of <= str.size ())
87- return str.substr (of, len);
88- return {};
91+ std::optional<std::string> r;
92+ auto str = get_full (path);
93+ if (str == nullptr || of > str->size ())
94+ return r;
95+ return r.emplace (str->substr (of, len));
8996}
9097
9198bool MJSON_MIME::contains_none_type () const
@@ -364,10 +371,8 @@ static int mjson_fetch_mime_structure(mjson_io &io, const MJSON_MIME *pmime,
364371 temp_path = storage_path + " /" s + pmime->get_id ();
365372 else
366373 temp_path = storage_path + " /" s + msg_filename + " ." + pmime->get_id ();
367- auto fd = io.find (temp_path);
368- buf += io.valid (fd) ?
369- " " + std::to_string (fd->second .size ()) :
370- " NIL" ;
374+ ssize_t z = io.get_size (temp_path);
375+ buf += z >= 0 ? " " + std::to_string (z) : " NIL" ;
371376 } else {
372377 buf += " " + std::to_string (pmime->length );
373378 }
@@ -386,11 +391,11 @@ static int mjson_fetch_mime_structure(mjson_io &io, const MJSON_MIME *pmime,
386391 temp_path = storage_path + " /" s + msg_filename +
387392 " ." + pmime->get_id () + " .dgt" ;
388393
389- auto fd = io.find (temp_path);
390- if (io. invalid (fd) )
394+ auto eml_content = io.get_full (temp_path);
395+ if (eml_content == nullptr )
391396 goto RFC822_FAILURE;
392397 Json::Value digest;
393- if (!json_from_str (fd-> second , digest))
398+ if (!json_from_str (*eml_content , digest))
394399 goto RFC822_FAILURE;
395400 MJSON temp_mjson;
396401 if (!temp_mjson.load_from_json (digest))
@@ -559,15 +564,15 @@ static void mjson_enum_build(const MJSON_MIME *pmime, BUILD_PARAM *pbuild) { try
559564 dgt_path = msg_path + " .dgt" ;
560565 }
561566
562- auto iter = pbuild->io .find (temp_path);
563- if (pbuild->io .invalid (iter)) {
567+ auto eml_content = pbuild->io .get_substr (temp_path, pmime->get_content_offset (),
568+ pmime->get_content_length ());
569+ if (!eml_content.has_value ()) {
564570 pbuild->build_result = FALSE ;
565571 return ;
566572 }
567-
568- auto eml = mjson_io::substr (iter, pmime->get_content_offset (), pmime->get_content_length ());
573+ std::string eml;
569574 if (pmime->encoding_is_b ()) {
570- eml = base64_decode (eml );
575+ eml = base64_decode (* std::move (eml_content) );
571576 } else if (pmime->encoding_is_q ()) {
572577 std::string qpout;
573578 qpout.resize (eml.size ());
@@ -665,12 +670,12 @@ BOOL MJSON::rfc822_get(mjson_io &io, MJSON *pjson, const char *storage_path,
665670 char dgt_path[256 ];
666671 snprintf (dgt_path, std::size (dgt_path), " %s/%s/%s.dgt" , storage_path,
667672 pjson_base->get_mail_filename (), mjson_id);
668- auto fd = io.find (dgt_path);
669- if (io. invalid (fd) )
673+ auto eml_content = io.get_full (dgt_path);
674+ if (eml_content == nullptr )
670675 continue ;
671676 pjson->clear ();
672677 Json::Value digest;
673- if (!json_from_str (fd-> second , digest) ||
678+ if (!json_from_str (*eml_content , digest) ||
674679 !pjson->load_from_json (digest))
675680 return false ;
676681 pjson->path = temp_path;
0 commit comments