aboutsummaryrefslogtreecommitdiffstats
path: root/src/vmime/net/maildir/maildirUtils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/vmime/net/maildir/maildirUtils.cpp')
-rw-r--r--src/vmime/net/maildir/maildirUtils.cpp273
1 files changed, 273 insertions, 0 deletions
diff --git a/src/vmime/net/maildir/maildirUtils.cpp b/src/vmime/net/maildir/maildirUtils.cpp
new file mode 100644
index 00000000..77aac715
--- /dev/null
+++ b/src/vmime/net/maildir/maildirUtils.cpp
@@ -0,0 +1,273 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2013 Vincent Richard <[email protected]>
+//
+// 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 3 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.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// Linking this library statically or dynamically with other modules is making
+// a combined work based on this library. Thus, the terms and conditions of
+// the GNU General Public License cover the whole combination.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#include "vmime/net/maildir/maildirUtils.hpp"
+#include "vmime/net/maildir/maildirStore.hpp"
+
+#include "vmime/utility/random.hpp"
+#include "vmime/platform.hpp"
+
+#include "vmime/exception.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+bool maildirUtils::isMessageFile(const utility::file& file)
+{
+ // Ignore files which name begins with '.'
+ if (file.isFile() &&
+ file.getFullPath().getLastComponent().getBuffer().length() >= 1 &&
+ file.getFullPath().getLastComponent().getBuffer()[0] != '.')
+ {
+ return (true);
+ }
+
+ return (false);
+}
+
+
+// NOTE ABOUT ID/FLAGS SEPARATOR
+// -----------------------------
+// In the maildir specification, the character ':' is used to separate
+// the unique identifier and the message flags.
+//
+// On Windows (and particularly FAT file systems), ':' is not allowed
+// in a filename, so we use a dash ('-') instead. This is the solution
+// used by Mutt/Win32, so we also use it here.
+//
+// To be compatible between implementations, we check for both
+// characters when reading file names.
+
+
+const utility::file::path::component maildirUtils::extractId
+ (const utility::file::path::component& filename)
+{
+ size_t sep = filename.getBuffer().rfind(':'); // try colon
+
+ if (sep == string::npos)
+ {
+ sep = filename.getBuffer().rfind('-'); // try dash (Windows)
+ if (sep == string::npos) return (filename);
+ }
+
+ return (utility::path::component
+ (string(filename.getBuffer().begin(), filename.getBuffer().begin() + sep)));
+}
+
+
+int maildirUtils::extractFlags(const utility::file::path::component& comp)
+{
+ size_t sep = comp.getBuffer().rfind(':'); // try colon
+
+ if (sep == string::npos)
+ {
+ sep = comp.getBuffer().rfind('-'); // try dash (Windows)
+ if (sep == string::npos) return 0;
+ }
+
+ const string flagsString(comp.getBuffer().begin() + sep + 1, comp.getBuffer().end());
+ const size_t count = flagsString.length();
+
+ int flags = 0;
+
+ for (size_t i = 0 ; i < count ; ++i)
+ {
+ switch (flagsString[i])
+ {
+ case 'R': case 'r': flags |= message::FLAG_REPLIED; break;
+ case 'S': case 's': flags |= message::FLAG_SEEN; break;
+ case 'T': case 't': flags |= message::FLAG_DELETED; break;
+ case 'F': case 'f': flags |= message::FLAG_MARKED; break;
+ case 'P': case 'p': flags |= message::FLAG_PASSED; break;
+ case 'D': case 'd': flags |= message::FLAG_DRAFT; break;
+ }
+ }
+
+ return (flags);
+}
+
+
+const utility::file::path::component maildirUtils::buildFlags(const int flags)
+{
+ string str;
+ str.reserve(8);
+
+ str += "2,";
+
+ if (flags & message::FLAG_MARKED) str += "F";
+ if (flags & message::FLAG_PASSED) str += "P";
+ if (flags & message::FLAG_REPLIED) str += "R";
+ if (flags & message::FLAG_SEEN) str += "S";
+ if (flags & message::FLAG_DELETED) str += "T";
+ if (flags & message::FLAG_DRAFT) str += "D";
+
+ return (utility::file::path::component(str));
+}
+
+
+const utility::file::path::component maildirUtils::buildFilename
+ (const utility::file::path::component& id, const int flags)
+{
+ if (flags == message::FLAG_RECENT)
+ return id;
+ else
+ return (buildFilename(id, buildFlags(flags)));
+}
+
+
+const utility::file::path::component maildirUtils::buildFilename
+ (const utility::file::path::component& id,
+ const utility::file::path::component& flags)
+{
+#if VMIME_PLATFORM_IS_WINDOWS
+ static const char DELIMITER[] = "-";
+#else
+ static const char DELIMITER[] = ":";
+#endif
+
+ return utility::path::component(id.getBuffer() + DELIMITER + flags.getBuffer());
+}
+
+
+const utility::file::path::component maildirUtils::generateId()
+{
+ std::ostringstream oss;
+ oss.imbue(std::locale::classic());
+
+ oss << utility::random::getTime();
+ oss << ".";
+ oss << utility::random::getProcess();
+ oss << ".";
+ oss << utility::random::getString(6);
+ oss << ".";
+ oss << platform::getHandler()->getHostName();
+
+ return (utility::file::path::component(oss.str()));
+}
+
+
+void maildirUtils::recursiveFSDelete(shared_ptr <utility::file> dir)
+{
+ shared_ptr <utility::fileIterator> files = dir->getFiles();
+
+ // First, delete files and subdirectories in this directory
+ while (files->hasMoreElements())
+ {
+ shared_ptr <utility::file> file = files->nextElement();
+
+ if (file->isDirectory())
+ {
+ maildirUtils::recursiveFSDelete(file);
+ }
+ else
+ {
+ try
+ {
+ file->remove();
+ }
+ catch (exceptions::filesystem_exception&)
+ {
+ // Ignore
+ }
+ }
+ }
+
+ // Then, delete this (empty) directory
+ try
+ {
+ dir->remove();
+ }
+ catch (exceptions::filesystem_exception&)
+ {
+ // Ignore
+ }
+}
+
+
+
+class maildirMessageSetEnumerator : public messageSetEnumerator
+{
+public:
+
+ void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range)
+ {
+ for (int i = range.getFirst(), last = range.getLast() ; i <= last ; ++i)
+ list.push_back(i);
+ }
+
+ void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& /* range */)
+ {
+ // Not supported
+ }
+
+public:
+
+ std::vector <int> list;
+};
+
+
+// static
+const std::vector <int> maildirUtils::messageSetToNumberList(const messageSet& msgs)
+{
+ maildirMessageSetEnumerator en;
+ msgs.enumerate(en);
+
+ return en.list;
+}
+
+
+
+//
+// messageIdComparator
+//
+
+maildirUtils::messageIdComparator::messageIdComparator
+ (const utility::file::path::component& comp)
+ : m_comp(maildirUtils::extractId(comp))
+{
+}
+
+
+bool maildirUtils::messageIdComparator::operator()
+ (const utility::file::path::component& other) const
+{
+ return (m_comp == maildirUtils::extractId(other));
+}
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+