aboutsummaryrefslogtreecommitdiff
path: root/vmime-master/src/vmime/net/maildir/maildirUtils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'vmime-master/src/vmime/net/maildir/maildirUtils.cpp')
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirUtils.cpp288
1 files changed, 288 insertions, 0 deletions
diff --git a/vmime-master/src/vmime/net/maildir/maildirUtils.cpp b/vmime-master/src/vmime/net/maildir/maildirUtils.cpp
new file mode 100644
index 0000000..9942e56
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirUtils.cpp
@@ -0,0 +1,288 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
+//
+// 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(const 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:
+
+ maildirMessageSetEnumerator(const size_t msgCount)
+ : m_msgCount(msgCount) {
+
+ }
+
+ void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) {
+
+ size_t last = range.getLast();
+ if (last == size_t(-1)) last = m_msgCount;
+
+ for (size_t i = range.getFirst() ; i <= last ; ++i) {
+ list.push_back(i);
+ }
+ }
+
+ void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& /* range */) {
+
+ // Not supported
+ }
+
+public:
+
+ std::vector <size_t> list;
+
+private:
+
+ size_t m_msgCount;
+};
+
+
+// static
+const std::vector <size_t> maildirUtils::messageSetToNumberList(
+ const messageSet& msgs,
+ const size_t msgCount
+) {
+
+ maildirMessageSetEnumerator en(msgCount);
+ 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
+