aboutsummaryrefslogtreecommitdiff
path: root/vmime-master/src/vmime/net/maildir
diff options
context:
space:
mode:
Diffstat (limited to 'vmime-master/src/vmime/net/maildir')
-rw-r--r--vmime-master/src/vmime/net/maildir/format/courierMaildirFormat.cpp569
-rw-r--r--vmime-master/src/vmime/net/maildir/format/courierMaildirFormat.hpp127
-rw-r--r--vmime-master/src/vmime/net/maildir/format/kmailMaildirFormat.cpp337
-rw-r--r--vmime-master/src/vmime/net/maildir/format/kmailMaildirFormat.hpp115
-rw-r--r--vmime-master/src/vmime/net/maildir/maildir.hpp34
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirFolder.cpp1365
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirFolder.hpp211
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirFolderStatus.cpp88
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirFolderStatus.hpp75
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirFormat.cpp104
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirFormat.hpp192
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirMessage.cpp410
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirMessage.hpp137
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirMessagePart.cpp178
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirMessagePart.hpp106
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirMessageStructure.cpp104
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirMessageStructure.hpp82
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirServiceInfos.cpp76
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirServiceInfos.hpp69
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirStore.cpp294
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirStore.hpp123
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirUtils.cpp288
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirUtils.hpp160
23 files changed, 5244 insertions, 0 deletions
diff --git a/vmime-master/src/vmime/net/maildir/format/courierMaildirFormat.cpp b/vmime-master/src/vmime/net/maildir/format/courierMaildirFormat.cpp
new file mode 100644
index 0000000..e611949
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/format/courierMaildirFormat.cpp
@@ -0,0 +1,569 @@
+//
+// 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/format/courierMaildirFormat.hpp"
+
+#include "vmime/net/maildir/maildirStore.hpp"
+#include "vmime/net/maildir/maildirUtils.hpp"
+
+#include "vmime/platform.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+namespace format {
+
+
+courierMaildirFormat::courierMaildirFormat(const shared_ptr <context>& ctx)
+ : maildirFormat(ctx) {
+
+}
+
+
+const string courierMaildirFormat::getName() const {
+
+ return "courier";
+}
+
+
+void courierMaildirFormat::createFolder(const folder::path& path) {
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ if (!fsf->isValidPath(folderPathToFileSystemPath(path, ROOT_DIRECTORY))) {
+ throw exceptions::invalid_folder_name();
+ }
+
+ shared_ptr <utility::file> rootDir = fsf->create(
+ folderPathToFileSystemPath(path, ROOT_DIRECTORY)
+ );
+
+ shared_ptr <utility::file> newDir = fsf->create(
+ folderPathToFileSystemPath(path, NEW_DIRECTORY)
+ );
+ shared_ptr <utility::file> tmpDir = fsf->create(
+ folderPathToFileSystemPath(path, TMP_DIRECTORY)
+ );
+ shared_ptr <utility::file> curDir = fsf->create(
+ folderPathToFileSystemPath(path, CUR_DIRECTORY)
+ );
+
+ rootDir->createDirectory(true);
+
+ newDir->createDirectory(false);
+ tmpDir->createDirectory(false);
+ curDir->createDirectory(false);
+
+ shared_ptr <utility::file> maildirFile = fsf->create(
+ folderPathToFileSystemPath(path, ROOT_DIRECTORY)
+ / utility::file::path::component("maildirfolder")
+ );
+
+ maildirFile->createFile();
+}
+
+
+void courierMaildirFormat::destroyFolder(const folder::path& path) {
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ // Recursively delete directories of subfolders
+ const std::vector <folder::path> folders = listFolders(path, true);
+
+ for (std::vector <folder::path>::size_type i = 0, n = folders.size() ; i < n ; ++i) {
+
+ maildirUtils::recursiveFSDelete(
+ fsf->create(folderPathToFileSystemPath(folders[i], ROOT_DIRECTORY))
+ );
+ }
+
+ // Recursively delete the directory of this folder
+ maildirUtils::recursiveFSDelete(
+ fsf->create(folderPathToFileSystemPath(path, ROOT_DIRECTORY))
+ );
+}
+
+
+void courierMaildirFormat::renameFolder(
+ const folder::path& oldPath,
+ const folder::path& newPath
+) {
+
+ const std::vector <folder::path> folders = listFolders(oldPath, true);
+
+ for (std::vector <folder::path>::size_type i = 0, n = folders.size() ; i < n ; ++i) {
+
+ const folder::path folderOldPath = folders[i];
+
+ folder::path folderNewPath = folderOldPath;
+ folderNewPath.renameParent(oldPath, newPath);
+
+ renameFolderImpl(folderOldPath, folderNewPath);
+ }
+
+ renameFolderImpl(oldPath, newPath);
+}
+
+
+void courierMaildirFormat::renameFolderImpl(
+ const folder::path& oldPath,
+ const folder::path& newPath
+) {
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ const utility::file::path oldFSPath =
+ folderPathToFileSystemPath(oldPath, ROOT_DIRECTORY);
+
+ const utility::file::path newFSPath =
+ folderPathToFileSystemPath(newPath, ROOT_DIRECTORY);
+
+ shared_ptr <utility::file> rootDir = fsf->create(oldFSPath);
+ rootDir->rename(newFSPath);
+}
+
+
+bool courierMaildirFormat::folderExists(const folder::path& path) const {
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ shared_ptr <utility::file> rootDir = fsf->create(
+ folderPathToFileSystemPath(path, ROOT_DIRECTORY)
+ );
+
+ shared_ptr <utility::file> newDir = fsf->create(
+ folderPathToFileSystemPath(path, NEW_DIRECTORY)
+ );
+ shared_ptr <utility::file> tmpDir = fsf->create(
+ folderPathToFileSystemPath(path, TMP_DIRECTORY)
+ );
+ shared_ptr <utility::file> curDir = fsf->create(
+ folderPathToFileSystemPath(path, CUR_DIRECTORY)
+ );
+
+ shared_ptr <utility::file> maildirFile = fsf->create(
+ folderPathToFileSystemPath(path, ROOT_DIRECTORY)
+ / utility::file::path::component("maildirfolder")
+ );
+
+ bool exists = rootDir->exists() && rootDir->isDirectory() &&
+ newDir->exists() && newDir->isDirectory() &&
+ tmpDir->exists() && tmpDir->isDirectory() &&
+ curDir->exists() && curDir->isDirectory();
+
+ // If this is not the root folder, then a file named "maildirfolder"
+ // must also be present in the directory
+ if (!path.isRoot()) {
+ exists = exists && maildirFile->exists() && maildirFile->isFile();
+ }
+
+ return exists;
+}
+
+
+bool courierMaildirFormat::folderHasSubfolders(const folder::path& path) const {
+
+ std::vector <string> dirs;
+ return listDirectories(path, dirs, true);
+}
+
+
+const utility::file::path courierMaildirFormat::folderPathToFileSystemPath(
+ const folder::path& path,
+ const DirectoryType type
+) const {
+
+ // Virtual folder "/MyFolder/SubFolder" corresponds to physical
+ // directory "[store root]/.MyFolder.SubFolder"
+ utility::file::path fsPath = getContext()->getStore()->getFileSystemPath();
+
+ if (!path.isRoot()) {
+
+ string folderComp;
+
+ for (size_t i = 0, n = path.getSize() ; i < n ; ++i) {
+ folderComp += "." + toModifiedUTF7(path[i]);
+ }
+
+ fsPath /= utility::file::path::component(folderComp);
+ }
+
+ // Last component
+ switch (type) {
+
+ case ROOT_DIRECTORY:
+
+ // Nothing to add
+ break;
+
+ case NEW_DIRECTORY:
+
+ fsPath /= NEW_DIR;
+ break;
+
+ case CUR_DIRECTORY:
+
+ fsPath /= CUR_DIR;
+ break;
+
+ case TMP_DIRECTORY:
+
+ fsPath /= TMP_DIR;
+ break;
+
+ case CONTAINER_DIRECTORY:
+
+ // Not used
+ break;
+ }
+
+ return fsPath;
+}
+
+
+const std::vector <folder::path> courierMaildirFormat::listFolders(
+ const folder::path& root,
+ const bool recursive
+) const {
+
+ // First, list directories
+ std::vector <string> dirs;
+ listDirectories(root, dirs, false);
+
+ // Then, map directories to folders
+ std::vector <folder::path> folders;
+
+ for (std::vector <string>::size_type i = 0, n = dirs.size() ; i < n ; ++i) {
+
+ const string dir = dirs[i].substr(1) + ".";
+ folder::path path;
+
+ for (size_t pos = dir.find("."), prev = 0 ;
+ pos != string::npos ; prev = pos + 1, pos = dir.find(".", pos + 1)) {
+
+ const string comp = dir.substr(prev, pos - prev);
+ path /= fromModifiedUTF7(comp);
+ }
+
+ if (recursive || path.getSize() == root.getSize() + 1) {
+ folders.push_back(path);
+ }
+ }
+
+ return folders;
+}
+
+
+bool courierMaildirFormat::listDirectories(
+ const folder::path& root,
+ std::vector <string>& dirs,
+ const bool onlyTestForExistence
+) const {
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ shared_ptr <utility::file> rootDir = fsf->create(
+ getContext()->getStore()->getFileSystemPath()
+ );
+
+ if (rootDir->exists()) {
+
+ // To speed up things, and if we are not searching in root folder,
+ // search for directories with a common prefix
+ string base;
+
+ if (!root.isRoot()) {
+ for (size_t i = 0, n = root.getSize() ; i < n ; ++i) {
+ base += "." + toModifiedUTF7(root[i]);
+ }
+ }
+
+ // Enumerate directories
+ shared_ptr <utility::fileIterator> it = rootDir->getFiles();
+
+ while (it->hasMoreElements()) {
+
+ shared_ptr <utility::file> file = it->nextElement();
+
+ if (isSubfolderDirectory(*file)) {
+
+ const string dir = file->getFullPath().getLastComponent().getBuffer();
+
+ if (base.empty() || (dir.length() > base.length() && dir.substr(0, base.length()) == base)) {
+
+ dirs.push_back(dir);
+
+ if (onlyTestForExistence) {
+ return true;
+ }
+ }
+ }
+ }
+
+ } else {
+
+ // No sub-folder
+ }
+
+ std::sort(dirs.begin(), dirs.end());
+
+ return !dirs.empty();
+}
+
+
+// static
+bool courierMaildirFormat::isSubfolderDirectory(const utility::file& file) {
+
+ // A directory which names starts with '.' may be a subfolder
+ if (file.isDirectory() &&
+ file.getFullPath().getLastComponent().getBuffer().length() >= 1 &&
+ file.getFullPath().getLastComponent().getBuffer()[0] == '.') {
+
+ return true;
+ }
+
+ return false;
+}
+
+
+// static
+const string courierMaildirFormat::toModifiedUTF7(const folder::path::component& text) {
+
+ // From http://www.courier-mta.org/?maildir.html:
+ //
+ // Folder names can contain any Unicode character, except for control
+ // characters. US-ASCII characters, U+0x0020 - U+0x007F, except for the
+ // period, forward-slash, and ampersand characters (U+0x002E, U+0x002F,
+ // and U+0x0026) represent themselves. The ampersand is represented by
+ // the two character sequence "&-". The period, forward slash, and non
+ // US-ASCII Unicode characters are represented using the UTF-7 character
+ // set, and encoded with a modified form of base64-encoding.
+ //
+ // The "&" character starts the modified base64-encoded sequence; the
+ // sequence is terminated by the "-" character. The sequence of 16-bit
+ // Unicode characters is written in big-endian order, and encoded using
+ // the base64-encoding method described in section 5.2 of RFC 1521, with
+ // the following modifications:
+ //
+ // * The "=" padding character is omitted. When decoding, an incomplete
+ // 16-bit character is discarded.
+ //
+ // * The comma character, "," is used in place of the "/" character in
+ // the base64 alphabet.
+ //
+ // For example, the word "Resume" with both "e"s being the e-acute
+ // character, U+0x00e9, is encoded as "R&AOk-sum&AOk-" (so a folder of
+ // that name would be a maildir subdirectory called ".R&AOk-sum&AOk-").
+ //
+
+ // Transcode path component to UTF-7 charset.
+ // WARNING: This may throw "exceptions::charset_conv_error"
+ const string cvt = text.getConvertedText(charset(charsets::UTF_7));
+
+ // Transcode to modified UTF-7 (RFC-2060).
+ string out;
+ out.reserve((cvt.length() * 3) / 2);
+
+ bool inB64sequence = false;
+
+ for (string::const_iterator it = cvt.begin() ; it != cvt.end() ; ++it) {
+
+ const unsigned char c = *it;
+
+ switch (c) {
+
+ // Beginning of Base64 sequence: replace '+' with '&'
+ case '+': {
+
+ if (!inB64sequence) {
+ inB64sequence = true;
+ out += '&';
+ } else {
+ out += '+';
+ }
+
+ break;
+ }
+ // End of Base64 sequence
+ case '-': {
+
+ inB64sequence = false;
+ out += '-';
+ break;
+ }
+ // ',' is used instead of '/' in modified Base64,
+ // and simply UTF7-encoded out of a Base64 sequence
+ case '/': {
+
+ if (inB64sequence) {
+ out += ',';
+ } else {
+ out += "&Lw-";
+ }
+
+ break;
+ }
+ // Encode period (should not happen in a Base64 sequence)
+ case '.': {
+
+ out += "&Lg-";
+ break;
+ }
+ // '&' (0x26) is represented by the two-octet sequence "&-"
+ case '&': {
+
+ if (!inB64sequence) {
+ out += "&-";
+ } else {
+ out += '&';
+ }
+
+ break;
+ }
+ default: {
+
+ out += c;
+ break;
+ }
+ }
+ }
+
+ return out;
+}
+
+
+// static
+const folder::path::component courierMaildirFormat::fromModifiedUTF7(const string& text) {
+
+ // Transcode from modified UTF-7
+ string out;
+ out.reserve(text.length());
+
+ bool inB64sequence = false;
+ unsigned char prev = 0;
+
+ for (string::const_iterator it = text.begin() ; it != text.end() ; ++it) {
+
+ const unsigned char c = *it;
+
+ switch (c) {
+
+ // Start of Base64 sequence
+ case '&': {
+
+ if (!inB64sequence) {
+ inB64sequence = true;
+ out += '+';
+ } else {
+ out += '&';
+ }
+
+ break;
+ }
+ // End of Base64 sequence (or "&-" --> "&")
+ case '-': {
+
+ if (inB64sequence && prev == '&') {
+ out += '&';
+ } else {
+ out += '-';
+ }
+
+ inB64sequence = false;
+ break;
+ }
+ // ',' is used instead of '/' in modified Base64
+ case ',': {
+
+ out += (inB64sequence ? '/' : ',');
+ break;
+ }
+ default: {
+
+ out += c;
+ break;
+ }
+
+ }
+
+ prev = c;
+ }
+
+ // Store it as UTF-8 by default
+ string cvt;
+ charset::convert(out, cvt, charset(charsets::UTF_7), charset(charsets::UTF_8));
+
+ return folder::path::component(cvt, charset(charsets::UTF_8));
+}
+
+
+bool courierMaildirFormat::supports() const {
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ shared_ptr <utility::file> rootDir = fsf->create(
+ getContext()->getStore()->getFileSystemPath()
+ );
+
+ if (rootDir->exists()) {
+
+ // Try to find a file named "maildirfolder", which indicates
+ // the Maildir is in Courier format
+ shared_ptr <utility::fileIterator> it = rootDir->getFiles();
+
+ while (it->hasMoreElements()) {
+
+ shared_ptr <utility::file> file = it->nextElement();
+
+ if (isSubfolderDirectory(*file)) {
+
+ shared_ptr <utility::file> folderFile = fsf->create(
+ file->getFullPath() / utility::file::path::component("maildirfolder")
+ );
+
+ if (folderFile->exists() && folderFile->isFile()) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+
+} // format
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
diff --git a/vmime-master/src/vmime/net/maildir/format/courierMaildirFormat.hpp b/vmime-master/src/vmime/net/maildir/format/courierMaildirFormat.hpp
new file mode 100644
index 0000000..7db1a83
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/format/courierMaildirFormat.hpp
@@ -0,0 +1,127 @@
+//
+// 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.
+//
+
+#ifndef VMIME_NET_MAILDIR_FORMAT_COURIERMAILDIRFORMAT_HPP_INCLUDED
+#define VMIME_NET_MAILDIR_FORMAT_COURIERMAILDIRFORMAT_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#include "vmime/net/maildir/maildirFormat.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+namespace format {
+
+
+/** Reads Courier/QMail Maildir format.
+ */
+class VMIME_EXPORT courierMaildirFormat : public maildirFormat {
+
+public:
+
+ courierMaildirFormat(const shared_ptr <context>& ctx);
+
+
+ /* Folder types:
+ *
+ * - ROOT_DIRECTORY: ~/Mail/.MyFolder
+ * - NEW_DIRECTORY: ~/Mail/.MyFolder/new
+ * - CUR_DIRECTORY: ~/Mail/.MyFolder/cur
+ * - TMP_DIRECTORY: ~/Mail/.MyFolder/tmp
+ * - CONTAINER_DIRECTORY: not used
+ */
+
+ const string getName() const;
+
+ void createFolder(const folder::path& path);
+ void destroyFolder(const folder::path& path);
+ void renameFolder(const folder::path& oldPath, const folder::path& newPath);
+
+ bool folderExists(const folder::path& path) const;
+ bool folderHasSubfolders(const folder::path& path) const;
+
+ const utility::file::path folderPathToFileSystemPath(
+ const folder::path& path,
+ const DirectoryType type
+ ) const;
+
+ const std::vector <folder::path> listFolders(
+ const folder::path& root,
+ const bool recursive
+ ) const;
+
+protected:
+
+ bool supports() const;
+
+
+ static const string toModifiedUTF7(const folder::path::component& text);
+ static const folder::path::component fromModifiedUTF7(const string& text);
+
+ void renameFolderImpl(const folder::path& oldPath, const folder::path& newPath);
+
+ /** Test whether the specified file system directory corresponds to
+ * a maildir subfolder. The name of the directory should start
+ * with a '.' to be listed as a subfolder.
+ *
+ * @param file reference to a file system directory
+ * @return true if the specified directory is a maildir subfolder,
+ * false otherwise
+ */
+ static bool isSubfolderDirectory(const utility::file& file);
+
+ /** List directories corresponding to folders which are (direct or
+ * indirect) children of specified folder.
+ *
+ * @param root root folder
+ * @param dirs list in which found directories will be added
+ * @param onlyTestForExistence if true, the function returns as soon
+ * as the first directory is found
+ * @return true if at least one directory has been found,
+ * false otherwise
+ */
+ bool listDirectories(
+ const folder::path& root,
+ std::vector <string>& dirs,
+ const bool onlyTestForExistence
+ ) const;
+};
+
+
+} // format
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+#endif // VMIME_NET_MAILDIR_FORMAT_COURIERMAILDIRFORMAT_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/net/maildir/format/kmailMaildirFormat.cpp b/vmime-master/src/vmime/net/maildir/format/kmailMaildirFormat.cpp
new file mode 100644
index 0000000..4eb89e8
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/format/kmailMaildirFormat.cpp
@@ -0,0 +1,337 @@
+//
+// 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/format/kmailMaildirFormat.hpp"
+
+#include "vmime/net/maildir/maildirStore.hpp"
+#include "vmime/net/maildir/maildirUtils.hpp"
+
+#include "vmime/platform.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+namespace format {
+
+
+kmailMaildirFormat::kmailMaildirFormat(const shared_ptr <context>& ctx)
+ : maildirFormat(ctx) {
+
+}
+
+
+const string kmailMaildirFormat::getName() const {
+
+ return "kmail";
+}
+
+
+void kmailMaildirFormat::createFolder(const folder::path& path) {
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ if (!fsf->isValidPath(folderPathToFileSystemPath(path, ROOT_DIRECTORY))) {
+ throw exceptions::invalid_folder_name();
+ }
+
+ shared_ptr <utility::file> rootDir = fsf->create(
+ folderPathToFileSystemPath(path, ROOT_DIRECTORY)
+ );
+
+ shared_ptr <utility::file> newDir = fsf->create(
+ folderPathToFileSystemPath(path, NEW_DIRECTORY)
+ );
+ shared_ptr <utility::file> tmpDir = fsf->create(
+ folderPathToFileSystemPath(path, TMP_DIRECTORY)
+ );
+ shared_ptr <utility::file> curDir = fsf->create(
+ folderPathToFileSystemPath(path, CUR_DIRECTORY)
+ );
+
+ rootDir->createDirectory(true);
+
+ newDir->createDirectory(false);
+ tmpDir->createDirectory(false);
+ curDir->createDirectory(false);
+}
+
+
+void kmailMaildirFormat::destroyFolder(const folder::path& path) {
+
+ // Delete 'folder' and '.folder.directory' directories
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ maildirUtils::recursiveFSDelete(
+ fsf->create(folderPathToFileSystemPath(path, ROOT_DIRECTORY)) // root
+ );
+
+ maildirUtils::recursiveFSDelete(
+ fsf->create(folderPathToFileSystemPath(path, CONTAINER_DIRECTORY)) // container
+ );
+}
+
+
+bool kmailMaildirFormat::folderExists(const folder::path& path) const {
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ shared_ptr <utility::file> rootDir = fsf->create(
+ folderPathToFileSystemPath(path, ROOT_DIRECTORY)
+ );
+
+ shared_ptr <utility::file> newDir = fsf->create(
+ folderPathToFileSystemPath(path, NEW_DIRECTORY)
+ );
+ shared_ptr <utility::file> tmpDir = fsf->create(
+ folderPathToFileSystemPath(path, TMP_DIRECTORY)
+ );
+ shared_ptr <utility::file> curDir = fsf->create(
+ folderPathToFileSystemPath(path, CUR_DIRECTORY)
+ );
+
+ return rootDir->exists() && rootDir->isDirectory() &&
+ newDir->exists() && newDir->isDirectory() &&
+ tmpDir->exists() && tmpDir->isDirectory() &&
+ curDir->exists() && curDir->isDirectory();
+}
+
+
+const utility::file::path kmailMaildirFormat::folderPathToFileSystemPath(
+ const folder::path& path,
+ const DirectoryType type
+) const {
+
+ // Root path
+ utility::file::path fsPath = getContext()->getStore()->getFileSystemPath();
+
+ const size_t pathSize = path.getSize();
+ const size_t count = (type == CONTAINER_DIRECTORY
+ ? pathSize : (pathSize >= 1 ? pathSize - 1 : 0));
+
+ // Parent folders
+ for (size_t i = 0 ; i < count ; ++i) {
+
+ utility::file::path::component comp(path[i]);
+
+ // TODO: may not work with all encodings...
+ comp.setBuffer("." + comp.getBuffer() + ".directory");
+
+ fsPath /= comp;
+ }
+
+ // Last component
+ if (path.getSize() != 0 && type != CONTAINER_DIRECTORY) {
+
+ fsPath /= path.getLastComponent();
+
+ switch (type) {
+
+ case ROOT_DIRECTORY:
+
+ // Nothing to add
+ break;
+
+ case NEW_DIRECTORY:
+
+ fsPath /= NEW_DIR;
+ break;
+
+ case CUR_DIRECTORY:
+
+ fsPath /= CUR_DIR;
+ break;
+
+ case TMP_DIRECTORY:
+
+ fsPath /= TMP_DIR;
+ break;
+
+ case CONTAINER_DIRECTORY:
+
+ // Can't happen...
+ break;
+ }
+ }
+
+ return fsPath;
+}
+
+
+const std::vector <folder::path> kmailMaildirFormat::listFolders(
+ const folder::path& root,
+ const bool recursive
+) const {
+
+ std::vector <folder::path> list;
+ listFoldersImpl(list, root, recursive);
+
+ return list;
+}
+
+
+void kmailMaildirFormat::listFoldersImpl(
+ std::vector <folder::path>& list,
+ const folder::path& root,
+ const bool recursive
+) const {
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ shared_ptr <utility::file> rootDir = fsf->create(
+ folderPathToFileSystemPath(root, root.isEmpty() ? ROOT_DIRECTORY : CONTAINER_DIRECTORY)
+ );
+
+ if (rootDir->exists()) {
+
+ shared_ptr <utility::fileIterator> it = rootDir->getFiles();
+
+ while (it->hasMoreElements()) {
+
+ shared_ptr <utility::file> file = it->nextElement();
+
+ if (isSubfolderDirectory(*file)) {
+
+ const utility::path subPath = root / file->getFullPath().getLastComponent();
+
+ list.push_back(subPath);
+
+ if (recursive) {
+ listFoldersImpl(list, subPath, true);
+ }
+ }
+ }
+
+ } else {
+
+ // No sub-folder
+ }
+}
+
+
+// static
+bool kmailMaildirFormat::isSubfolderDirectory(const utility::file& file) {
+
+ // A directory which name does not start with '.' is listed as a sub-folder
+ if (file.isDirectory() &&
+ file.getFullPath().getLastComponent().getBuffer().length() >= 1 &&
+ file.getFullPath().getLastComponent().getBuffer()[0] != '.') {
+
+ return true;
+ }
+
+ return false;
+}
+
+
+void kmailMaildirFormat::renameFolder(const folder::path& oldPath, const folder::path& newPath) {
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ shared_ptr <utility::file> rootDir = fsf->create(
+ folderPathToFileSystemPath(oldPath, ROOT_DIRECTORY)
+ );
+ shared_ptr <utility::file> contDir = fsf->create(
+ folderPathToFileSystemPath(oldPath, CONTAINER_DIRECTORY)
+ );
+
+ try {
+
+ const utility::file::path newRootPath =
+ folderPathToFileSystemPath(newPath, ROOT_DIRECTORY);
+ const utility::file::path newContPath =
+ folderPathToFileSystemPath(newPath, CONTAINER_DIRECTORY);
+
+ rootDir->rename(newRootPath);
+
+ // Container directory may not exist, so ignore error when trying to rename it
+ try {
+ contDir->rename(newContPath);
+ } catch (exceptions::filesystem_exception& e) {
+ // Ignore
+ }
+
+ } catch (exceptions::filesystem_exception& e) {
+
+ // Revert to old location
+ const utility::file::path rootPath =
+ folderPathToFileSystemPath(oldPath, ROOT_DIRECTORY);
+ const utility::file::path contPath =
+ folderPathToFileSystemPath(oldPath, CONTAINER_DIRECTORY);
+
+ try {
+ rootDir->rename(rootPath);
+ contDir->rename(contPath);
+ } catch (exceptions::filesystem_exception& e) {
+ // Ignore (not recoverable)
+ }
+
+ throw;
+ }
+}
+
+
+bool kmailMaildirFormat::folderHasSubfolders(const folder::path& path) const {
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ shared_ptr <utility::file> rootDir = fsf->create(
+ folderPathToFileSystemPath(path, CONTAINER_DIRECTORY)
+ );
+
+ shared_ptr <utility::fileIterator> it = rootDir->getFiles();
+
+ while (it->hasMoreElements()) {
+
+ shared_ptr <utility::file> file = it->nextElement();
+
+ if (isSubfolderDirectory(*file)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+bool kmailMaildirFormat::supports() const {
+
+ // This is the default
+ return true;
+}
+
+
+} // format
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
diff --git a/vmime-master/src/vmime/net/maildir/format/kmailMaildirFormat.hpp b/vmime-master/src/vmime/net/maildir/format/kmailMaildirFormat.hpp
new file mode 100644
index 0000000..26b557a
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/format/kmailMaildirFormat.hpp
@@ -0,0 +1,115 @@
+//
+// 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.
+//
+
+#ifndef VMIME_NET_MAILDIR_FORMAT_KMAILMAILDIRFORMAT_HPP_INCLUDED
+#define VMIME_NET_MAILDIR_FORMAT_KMAILMAILDIRFORMAT_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#include "vmime/net/maildir/maildirFormat.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+namespace format {
+
+
+/** Reads KMail Maildir format.
+ */
+class VMIME_EXPORT kmailMaildirFormat : public maildirFormat {
+
+public:
+
+ kmailMaildirFormat(const shared_ptr <context>& ctx);
+
+
+ /* Folder types:
+ *
+ * - ROOT_DIRECTORY: ~/Mail/MyFolder
+ * - NEW_DIRECTORY: ~/Mail/MyFolder/new
+ * - CUR_DIRECTORY: ~/Mail/MyFolder/cur
+ * - TMP_DIRECTORY: ~/Mail/MyFolder/tmp
+ * - CONTAINER_DIRECTORY: ~/Mail/.MyFolder.directory
+ */
+
+ const string getName() const;
+
+ void createFolder(const folder::path& path);
+ void destroyFolder(const folder::path& path);
+ void renameFolder(const folder::path& oldPath, const folder::path& newPath);
+
+ bool folderExists(const folder::path& path) const;
+ bool folderHasSubfolders(const folder::path& path) const;
+
+ const utility::file::path folderPathToFileSystemPath(
+ const folder::path& path,
+ const DirectoryType type
+ ) const;
+
+ const std::vector <folder::path> listFolders(
+ const folder::path& root,
+ const bool recursive
+ ) const;
+
+protected:
+
+ bool supports() const;
+
+
+ /** Recursive implementation of listFolders().
+ */
+ void listFoldersImpl(
+ std::vector <folder::path>& list,
+ const folder::path& root,
+ const bool recursive
+ ) const;
+
+ /** Test whether the specified file system directory corresponds to
+ * a maildir subfolder. The name of the directory should not start
+ * with '.' to be listed as a subfolder.
+ *
+ * @param file reference to a file system directory
+ * @return true if the specified directory is a maildir subfolder,
+ * false otherwise
+ */
+ static bool isSubfolderDirectory(const utility::file& file);
+};
+
+
+} // format
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#endif // VMIME_NET_MAILDIR_FORMAT_KMAILMAILDIRFORMAT_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/net/maildir/maildir.hpp b/vmime-master/src/vmime/net/maildir/maildir.hpp
new file mode 100644
index 0000000..8835bf4
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildir.hpp
@@ -0,0 +1,34 @@
+//
+// 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.
+//
+
+#ifndef VMIME_NET_MAILDIR_MAILDIR_HPP_INCLUDED
+#define VMIME_NET_MAILDIR_MAILDIR_HPP_INCLUDED
+
+
+#include "vmime/net/maildir/maildirFolder.hpp"
+#include "vmime/net/maildir/maildirFolderStatus.hpp"
+#include "vmime/net/maildir/maildirMessage.hpp"
+#include "vmime/net/maildir/maildirStore.hpp"
+
+
+#endif // VMIME_NET_MAILDIR_MAILDIR_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/maildir/maildirFolder.cpp b/vmime-master/src/vmime/net/maildir/maildirFolder.cpp
new file mode 100644
index 0000000..8c02025
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirFolder.cpp
@@ -0,0 +1,1365 @@
+//
+// 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/maildirFolder.hpp"
+
+#include "vmime/net/maildir/maildirStore.hpp"
+#include "vmime/net/maildir/maildirMessage.hpp"
+#include "vmime/net/maildir/maildirUtils.hpp"
+#include "vmime/net/maildir/maildirFormat.hpp"
+#include "vmime/net/maildir/maildirFolderStatus.hpp"
+
+#include "vmime/message.hpp"
+
+#include "vmime/exception.hpp"
+#include "vmime/platform.hpp"
+
+#include "vmime/utility/outputStreamAdapter.hpp"
+#include "vmime/utility/inputStreamStringAdapter.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+maildirFolder::maildirFolder(
+ const folder::path& path,
+ const shared_ptr <maildirStore>& store
+)
+ : m_store(store),
+ m_path(path),
+ m_name(path.isEmpty() ? folder::path::component("") : path.getLastComponent()),
+ m_mode(-1),
+ m_open(false),
+ m_unreadMessageCount(0),
+ m_messageCount(0) {
+
+ store->registerFolder(this);
+}
+
+
+maildirFolder::~maildirFolder() {
+
+ try {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ if (store) {
+
+ if (m_open) {
+ close(false);
+ }
+
+ store->unregisterFolder(this);
+
+ } else if (m_open) {
+
+ close(false);
+ }
+
+ } catch (...) {
+
+ // Don't throw in destructor
+ }
+}
+
+
+void maildirFolder::onStoreDisconnected() {
+
+ m_store.reset();
+}
+
+
+int maildirFolder::getMode() const {
+
+ if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ }
+
+ return m_mode;
+}
+
+
+const folderAttributes maildirFolder::getAttributes() {
+
+ folderAttributes attribs;
+
+ if (m_path.isEmpty()) {
+ attribs.setType(folderAttributes::TYPE_CONTAINS_FOLDERS);
+ } else {
+ attribs.setType(folderAttributes::TYPE_CONTAINS_FOLDERS | folderAttributes::TYPE_CONTAINS_MESSAGES);
+ }
+
+ if (m_store.lock()->getFormat()->folderHasSubfolders(m_path)) {
+ attribs.setFlags(folderAttributes::FLAG_HAS_CHILDREN); // contains at least one sub-folder
+ }
+
+ return attribs;
+}
+
+
+const folder::path::component maildirFolder::getName() const {
+
+ return m_name;
+}
+
+
+const folder::path maildirFolder::getFullPath() const {
+
+ return m_path;
+}
+
+
+void maildirFolder::open(const int mode, bool /* failIfModeIsNotAvailable */) {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ } else if (isOpen()) {
+ throw exceptions::illegal_state("Folder is already open");
+ } else if (!exists()) {
+ throw exceptions::illegal_state("Folder does not exist");
+ }
+
+ scanFolder();
+
+ m_open = true;
+ m_mode = mode;
+}
+
+
+void maildirFolder::close(const bool expunge) {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ }
+
+ if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ }
+
+ if (expunge) {
+ this->expunge();
+ }
+
+ m_open = false;
+ m_mode = -1;
+
+ onClose();
+}
+
+
+void maildirFolder::onClose() {
+
+ for (std::vector <maildirMessage*>::iterator it = m_messages.begin() ;
+ it != m_messages.end() ; ++it) {
+
+ (*it)->onFolderClosed();
+ }
+
+ m_messages.clear();
+}
+
+
+void maildirFolder::registerMessage(maildirMessage* msg) {
+
+ m_messages.push_back(msg);
+}
+
+
+void maildirFolder::unregisterMessage(maildirMessage* msg) {
+
+ std::vector <maildirMessage*>::iterator it =
+ std::find(m_messages.begin(), m_messages.end(), msg);
+
+ if (it != m_messages.end()) {
+ m_messages.erase(it);
+ }
+}
+
+
+void maildirFolder::create(const folderAttributes& /* attribs */) {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ } else if (isOpen()) {
+ throw exceptions::illegal_state("Folder is open");
+ } else if (exists()) {
+ throw exceptions::illegal_state("Folder already exists");
+ } else if (!store->isValidFolderName(m_name)) {
+ throw exceptions::invalid_folder_name();
+ }
+
+ // Create directory on file system
+ try {
+ store->getFormat()->createFolder(m_path);
+ } catch (exceptions::filesystem_exception& e) {
+ throw exceptions::command_error("CREATE", "", "File system exception", e);
+ }
+
+ // Notify folder created
+ shared_ptr <events::folderEvent> event =
+ make_shared <events::folderEvent>(
+ dynamicCast <folder>(shared_from_this()),
+ events::folderEvent::TYPE_CREATED,
+ m_path, m_path
+ );
+
+ notifyFolder(event);
+}
+
+
+void maildirFolder::destroy() {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ } else if (isOpen()) {
+ throw exceptions::illegal_state("Folder is open");
+ }
+
+ // Delete folder
+ try {
+ store->getFormat()->destroyFolder(m_path);
+ } catch (std::exception&) {
+ // Ignore exception: anyway, we can't recover from this...
+ }
+
+ // Notify folder deleted
+ shared_ptr <events::folderEvent> event =
+ make_shared <events::folderEvent>(
+ dynamicCast <folder>(shared_from_this()),
+ events::folderEvent::TYPE_DELETED,
+ m_path, m_path
+ );
+
+ notifyFolder(event);
+}
+
+
+bool maildirFolder::exists() {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ return store->getFormat()->folderExists(m_path);
+}
+
+
+bool maildirFolder::isOpen() const {
+
+ return m_open;
+}
+
+
+void maildirFolder::scanFolder() {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ try {
+
+ m_messageCount = 0;
+ m_unreadMessageCount = 0;
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ utility::file::path newDirPath =
+ store->getFormat()->folderPathToFileSystemPath(m_path, maildirFormat::NEW_DIRECTORY);
+ shared_ptr <utility::file> newDir = fsf->create(newDirPath);
+
+ utility::file::path curDirPath =
+ store->getFormat()->folderPathToFileSystemPath(m_path, maildirFormat::CUR_DIRECTORY);
+ shared_ptr <utility::file> curDir = fsf->create(curDirPath);
+
+ // New received messages (new/)
+ shared_ptr <utility::fileIterator> nit = newDir->getFiles();
+ std::vector <utility::file::path::component> newMessageFilenames;
+
+ while (nit->hasMoreElements()) {
+
+ shared_ptr <utility::file> file = nit->nextElement();
+
+ if (maildirUtils::isMessageFile(*file)) {
+ newMessageFilenames.push_back(file->getFullPath().getLastComponent());
+ }
+ }
+
+ // Current messages (cur/)
+ shared_ptr <utility::fileIterator> cit = curDir->getFiles();
+ std::vector <utility::file::path::component> curMessageFilenames;
+
+ while (cit->hasMoreElements()) {
+
+ shared_ptr <utility::file> file = cit->nextElement();
+
+ if (maildirUtils::isMessageFile(*file)) {
+ curMessageFilenames.push_back(file->getFullPath().getLastComponent());
+ }
+ }
+
+ // Update/delete existing messages (found in previous scan)
+ for (size_t i = 0 ; i < m_messageInfos.size() ; ++i) {
+
+ messageInfos& msgInfos = m_messageInfos[i];
+
+ // NOTE: the flags may have changed (eg. moving from 'new' to 'cur'
+ // may imply the 'S' flag) and so the filename. That's why we use
+ // "maildirUtils::messageIdComparator" to compare only the 'unique'
+ // portion of the filename...
+
+ if (msgInfos.type == messageInfos::TYPE_CUR) {
+
+ const std::vector <utility::file::path::component>::iterator pos =
+ std::find_if(
+ curMessageFilenames.begin(),
+ curMessageFilenames.end(),
+ maildirUtils::messageIdComparator(msgInfos.path)
+ );
+
+ // If we cannot find this message in the 'cur' directory,
+ // it means it has been deleted (and expunged).
+ if (pos == curMessageFilenames.end()) {
+
+ msgInfos.type = messageInfos::TYPE_DELETED;
+
+ // Otherwise, update its information.
+ } else {
+
+ msgInfos.path = *pos;
+ curMessageFilenames.erase(pos);
+ }
+ }
+ }
+
+ m_messageInfos.reserve(m_messageInfos.size()
+ + newMessageFilenames.size() + curMessageFilenames.size());
+
+ // Add new messages from 'new': we are responsible to move the files
+ // from the 'new' directory to the 'cur' directory, and append them
+ // to our message list.
+ for (std::vector <utility::file::path::component>::const_iterator
+ it = newMessageFilenames.begin() ; it != newMessageFilenames.end() ; ++it) {
+
+ const utility::file::path::component newFilename =
+ maildirUtils::buildFilename(maildirUtils::extractId(*it), 0);
+
+ // Move messages from 'new' to 'cur'
+ shared_ptr <utility::file> file = fsf->create(newDirPath / *it);
+ file->rename(curDirPath / newFilename);
+
+ // Append to message list
+ messageInfos msgInfos;
+ msgInfos.path = newFilename;
+
+ if (maildirUtils::extractFlags(msgInfos.path) & message::FLAG_DELETED) {
+ msgInfos.type = messageInfos::TYPE_DELETED;
+ } else {
+ msgInfos.type = messageInfos::TYPE_CUR;
+ }
+
+ m_messageInfos.push_back(msgInfos);
+ }
+
+ // Add new messages from 'cur': the files have already been moved
+ // from 'new' to 'cur'. Just append them to our message list.
+ for (std::vector <utility::file::path::component>::const_iterator
+ it = curMessageFilenames.begin() ; it != curMessageFilenames.end() ; ++it) {
+
+ // Append to message list
+ messageInfos msgInfos;
+ msgInfos.path = *it;
+
+ if (maildirUtils::extractFlags(msgInfos.path) & message::FLAG_DELETED) {
+ msgInfos.type = messageInfos::TYPE_DELETED;
+ } else {
+ msgInfos.type = messageInfos::TYPE_CUR;
+ }
+
+ m_messageInfos.push_back(msgInfos);
+ }
+
+ // Update message count
+ size_t unreadMessageCount = 0;
+
+ for (std::vector <messageInfos>::const_iterator
+ it = m_messageInfos.begin() ; it != m_messageInfos.end() ; ++it) {
+
+ if ((maildirUtils::extractFlags((*it).path) & message::FLAG_SEEN) == 0) {
+ ++unreadMessageCount;
+ }
+ }
+
+ m_unreadMessageCount = unreadMessageCount;
+ m_messageCount = static_cast <size_t>(m_messageInfos.size());
+
+ } catch (exceptions::filesystem_exception&) {
+
+ // Should not happen...
+ }
+}
+
+
+shared_ptr <message> maildirFolder::getMessage(const size_t num) {
+
+ if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ }
+
+ if (num < 1 || num > m_messageCount) {
+ throw exceptions::message_not_found();
+ }
+
+ return make_shared <maildirMessage>(dynamicCast <maildirFolder>(shared_from_this()), num);
+}
+
+
+std::vector <shared_ptr <message> > maildirFolder::getMessages(const messageSet& msgs) {
+
+ if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ }
+
+ if (msgs.isNumberSet()) {
+
+ const std::vector <size_t> numbers = maildirUtils::messageSetToNumberList(msgs, m_messageCount);
+
+ std::vector <shared_ptr <message> > messages;
+ shared_ptr <maildirFolder> thisFolder = dynamicCast <maildirFolder>(shared_from_this());
+
+ for (std::vector <size_t>::const_iterator it = numbers.begin() ; it != numbers.end() ; ++it) {
+
+ if (*it < 1|| *it > m_messageCount) {
+ throw exceptions::message_not_found();
+ }
+
+ messages.push_back(make_shared <maildirMessage>(thisFolder, *it));
+ }
+
+ return messages;
+
+ } else {
+
+ throw exceptions::operation_not_supported();
+ }
+}
+
+
+size_t maildirFolder::getMessageCount() {
+
+ return m_messageCount;
+}
+
+
+shared_ptr <folder> maildirFolder::getFolder(const folder::path::component& name) {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ }
+
+ return shared_ptr <maildirFolder>(new maildirFolder(m_path / name, store));
+}
+
+
+std::vector <shared_ptr <folder> > maildirFolder::getFolders(const bool recursive) {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ if (!isOpen() && !store) {
+ throw exceptions::illegal_state("Store disconnected");
+ }
+
+ std::vector <shared_ptr <folder> > list;
+
+ listFolders(list, recursive);
+
+ return list;
+}
+
+
+void maildirFolder::listFolders(std::vector <shared_ptr <folder> >& list, const bool recursive) {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ try {
+
+ std::vector <folder::path> pathList =
+ store->getFormat()->listFolders(m_path, recursive);
+
+ list.reserve(pathList.size());
+
+ for (std::vector <folder::path>::size_type i = 0, n = pathList.size() ; i < n ; ++i) {
+
+ shared_ptr <maildirFolder> subFolder(
+ new maildirFolder(pathList[i], store)
+ );
+
+ list.push_back(subFolder);
+ }
+
+ } catch (exceptions::filesystem_exception& e) {
+
+ throw exceptions::command_error("LIST", "", "", e);
+ }
+}
+
+
+void maildirFolder::rename(const folder::path& newPath) {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ } else if (m_path.isEmpty() || newPath.isEmpty()) {
+ throw exceptions::illegal_operation("Cannot rename root folder");
+ } else if (!store->isValidFolderName(newPath.getLastComponent())) {
+ throw exceptions::invalid_folder_name();
+ }
+
+ // Rename the directory on the file system
+ try {
+ store->getFormat()->renameFolder(m_path, newPath);
+ } catch (vmime::exception& e) {
+ throw exceptions::command_error("RENAME", "", "", e);
+ }
+
+ // Notify folder renamed
+ folder::path oldPath(m_path);
+
+ m_path = newPath;
+ m_name = newPath.getLastComponent();
+
+ shared_ptr <events::folderEvent> event =
+ make_shared <events::folderEvent>(
+ dynamicCast <folder>(shared_from_this()),
+ events::folderEvent::TYPE_RENAMED,
+ oldPath, newPath
+ );
+
+ notifyFolder(event);
+
+ // Notify folders with the same path
+ for (std::list <maildirFolder*>::iterator it = store->m_folders.begin() ;
+ it != store->m_folders.end() ; ++it) {
+
+ if ((*it) != this && (*it)->getFullPath() == oldPath) {
+
+ (*it)->m_path = newPath;
+ (*it)->m_name = newPath.getLastComponent();
+
+ shared_ptr <events::folderEvent> event =
+ make_shared <events::folderEvent>(
+ dynamicCast <folder>((*it)->shared_from_this()),
+ events::folderEvent::TYPE_RENAMED,
+ oldPath, newPath
+ );
+
+ (*it)->notifyFolder(event);
+
+ } else if ((*it) != this && oldPath.isParentOf((*it)->getFullPath())) {
+
+ folder::path oldPath((*it)->m_path);
+
+ (*it)->m_path.renameParent(oldPath, newPath);
+
+ shared_ptr <events::folderEvent> event =
+ make_shared <events::folderEvent>(
+ dynamicCast <folder>((*it)->shared_from_this()),
+ events::folderEvent::TYPE_RENAMED,
+ oldPath, (*it)->m_path
+ );
+
+ (*it)->notifyFolder(event);
+ }
+ }
+}
+
+
+void maildirFolder::deleteMessages(const messageSet& msgs) {
+
+ // Mark messages as deleted
+ setMessageFlags(msgs, message::FLAG_DELETED, message::FLAG_MODE_ADD);
+}
+
+
+void maildirFolder::setMessageFlags(
+ const messageSet& msgs,
+ const int flags,
+ const int mode
+) {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ } else if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ } else if (m_mode == MODE_READ_ONLY) {
+ throw exceptions::illegal_state("Folder is read-only");
+ }
+
+ if (msgs.isNumberSet()) {
+
+ const std::vector <size_t> nums = maildirUtils::messageSetToNumberList(msgs, m_messageCount);
+
+ // Change message flags
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ utility::file::path curDirPath = store->getFormat()->
+ folderPathToFileSystemPath(m_path, maildirFormat::CUR_DIRECTORY);
+
+ for (std::vector <size_t>::const_iterator it =
+ nums.begin() ; it != nums.end() ; ++it) {
+
+ const size_t num = *it - 1;
+
+ try {
+
+ const utility::file::path::component path = m_messageInfos[num].path;
+ shared_ptr <utility::file> file = fsf->create(curDirPath / path);
+
+ int newFlags = maildirUtils::extractFlags(path);
+
+ switch (mode) {
+ case message::FLAG_MODE_ADD: newFlags |= flags; break;
+ case message::FLAG_MODE_REMOVE: newFlags &= ~flags; break;
+ default:
+ case message::FLAG_MODE_SET: newFlags = flags; break;
+ }
+
+ const utility::file::path::component newPath =
+ maildirUtils::buildFilename(maildirUtils::extractId(path), newFlags);
+
+ file->rename(curDirPath / newPath);
+
+ if (flags & message::FLAG_DELETED) {
+ m_messageInfos[num].type = messageInfos::TYPE_DELETED;
+ } else {
+ m_messageInfos[num].type = messageInfos::TYPE_CUR;
+ }
+
+ m_messageInfos[num].path = newPath;
+
+ } catch (exceptions::filesystem_exception& e) {
+
+ // Ignore (not important)
+ }
+ }
+
+ // Update local flags
+ switch (mode) {
+
+ case message::FLAG_MODE_ADD: {
+
+ for (std::vector <maildirMessage*>::iterator it =
+ m_messages.begin() ; it != m_messages.end() ; ++it) {
+
+ if (std::binary_search(nums.begin(), nums.end(), (*it)->getNumber()) &&
+ (*it)->m_flags != maildirMessage::FLAG_UNDEFINED) {
+
+ (*it)->m_flags |= flags;
+ }
+ }
+
+ break;
+ }
+ case message::FLAG_MODE_REMOVE: {
+
+ for (std::vector <maildirMessage*>::iterator it =
+ m_messages.begin() ; it != m_messages.end() ; ++it) {
+
+ if (std::binary_search(nums.begin(), nums.end(), (*it)->getNumber()) &&
+ (*it)->m_flags != maildirMessage::FLAG_UNDEFINED) {
+
+ (*it)->m_flags &= ~flags;
+ }
+ }
+
+ break;
+ }
+ default:
+ case message::FLAG_MODE_SET: {
+
+ for (std::vector <maildirMessage*>::iterator it =
+ m_messages.begin() ; it != m_messages.end() ; ++it) {
+
+ if (std::binary_search(nums.begin(), nums.end(), (*it)->getNumber()) &&
+ (*it)->m_flags != maildirMessage::FLAG_UNDEFINED) {
+
+ (*it)->m_flags = flags;
+ }
+ }
+
+ break;
+ }
+
+ }
+
+ // Notify message flags changed
+ shared_ptr <events::messageChangedEvent> event =
+ make_shared <events::messageChangedEvent>(
+ dynamicCast <folder>(shared_from_this()),
+ events::messageChangedEvent::TYPE_FLAGS,
+ nums
+ );
+
+ notifyMessageChanged(event);
+
+ // TODO: notify other folders with the same path
+
+ } else {
+
+ throw exceptions::operation_not_supported();
+ }
+}
+
+
+messageSet maildirFolder::addMessage(
+ const shared_ptr <vmime::message>& msg,
+ const int flags,
+ vmime::datetime* date,
+ utility::progressListener* progress
+) {
+
+ std::ostringstream oss;
+ utility::outputStreamAdapter ossAdapter(oss);
+
+ msg->generate(ossAdapter);
+
+ const string& str = oss.str();
+ utility::inputStreamStringAdapter strAdapter(str);
+
+ return addMessage(strAdapter, str.length(), flags, date, progress);
+}
+
+
+messageSet maildirFolder::addMessage(
+ utility::inputStream& is,
+ const size_t size,
+ const int flags,
+ vmime::datetime* /* date */,
+ utility::progressListener* progress
+) {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ } else if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ } else if (m_mode == MODE_READ_ONLY) {
+ throw exceptions::illegal_state("Folder is read-only");
+ }
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ utility::file::path tmpDirPath = store->getFormat()->
+ folderPathToFileSystemPath(m_path,maildirFormat::TMP_DIRECTORY);
+ utility::file::path dstDirPath = store->getFormat()->
+ folderPathToFileSystemPath(
+ m_path,
+ flags == message::FLAG_RECENT ?
+ maildirFormat::NEW_DIRECTORY :
+ maildirFormat::CUR_DIRECTORY
+ );
+
+ const utility::file::path::component filename =
+ maildirUtils::buildFilename(maildirUtils::generateId(), ((flags == -1) ? 0 : flags));
+
+ try {
+ shared_ptr <utility::file> tmpDir = fsf->create(tmpDirPath);
+ tmpDir->createDirectory(true);
+ } catch (exceptions::filesystem_exception&) {
+ // Don't throw now, it will fail later...
+ }
+
+ try {
+ shared_ptr <utility::file> curDir = fsf->create(dstDirPath);
+ curDir->createDirectory(true);
+ } catch (exceptions::filesystem_exception&) {
+ // Don't throw now, it will fail later...
+ }
+
+ // Actually add the message
+ copyMessageImpl(tmpDirPath, dstDirPath, filename, is, size, progress);
+
+ // Append the message to the cache list
+ messageInfos msgInfos;
+ msgInfos.path = filename;
+ msgInfos.type = messageInfos::TYPE_CUR;
+
+ m_messageInfos.push_back(msgInfos);
+ m_messageCount++;
+
+ if ((flags == -1) || !(flags & message::FLAG_SEEN)) {
+ m_unreadMessageCount++;
+ }
+
+ // Notification
+ std::vector <size_t> nums;
+ nums.push_back(m_messageCount);
+
+ shared_ptr <events::messageCountEvent> event =
+ make_shared <events::messageCountEvent>(
+ dynamicCast <folder>(shared_from_this()),
+ events::messageCountEvent::TYPE_ADDED,
+ nums
+ );
+
+ notifyMessageCount(event);
+
+ // Notify folders with the same path
+ for (std::list <maildirFolder*>::iterator it = store->m_folders.begin() ;
+ it != store->m_folders.end() ; ++it) {
+
+ if ((*it) != this && (*it)->getFullPath() == m_path) {
+
+ (*it)->m_messageCount = m_messageCount;
+ (*it)->m_unreadMessageCount = m_unreadMessageCount;
+
+ (*it)->m_messageInfos.resize(m_messageInfos.size());
+ std::copy(m_messageInfos.begin(), m_messageInfos.end(), (*it)->m_messageInfos.begin());
+
+ shared_ptr <events::messageCountEvent> event =
+ make_shared <events::messageCountEvent>(
+ dynamicCast <folder>((*it)->shared_from_this()),
+ events::messageCountEvent::TYPE_ADDED,
+ nums
+ );
+
+ (*it)->notifyMessageCount(event);
+ }
+ }
+
+ return messageSet::empty();
+}
+
+
+void maildirFolder::copyMessageImpl(
+ const utility::file::path& tmpDirPath,
+ const utility::file::path& dstDirPath,
+ const utility::file::path::component& filename,
+ utility::inputStream& is, const size_t size,
+ utility::progressListener* progress
+) {
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ shared_ptr <utility::file> file = fsf->create(tmpDirPath / filename);
+
+ if (progress) {
+ progress->start(size);
+ }
+
+ // First, write the message into 'tmp'...
+ try {
+
+ file->createFile();
+
+ shared_ptr <utility::fileWriter> fw = file->getFileWriter();
+ shared_ptr <utility::outputStream> os = fw->getOutputStream();
+
+ byte_t buffer[65536];
+ size_t total = 0;
+
+ while (!is.eof()) {
+
+ const size_t read = is.read(buffer, sizeof(buffer));
+
+ if (read != 0) {
+ os->write(buffer, read);
+ total += read;
+ }
+
+ if (progress) {
+ progress->progress(total, size);
+ }
+ }
+
+ os->flush();
+
+ } catch (exception& e) {
+
+ if (progress) {
+ progress->stop(size);
+ }
+
+ // Delete temporary file
+ try {
+ shared_ptr <utility::file> file = fsf->create(tmpDirPath / filename);
+ file->remove();
+ } catch (exceptions::filesystem_exception&) {
+ // Ignore
+ }
+
+ throw exceptions::command_error("ADD", "", "", e);
+ }
+
+ // ...then, move it to 'cur'
+ try {
+
+ file->rename(dstDirPath / filename);
+
+ } catch (exception& e) {
+
+ if (progress) {
+ progress->stop(size);
+ }
+
+ // Delete temporary file
+ try {
+
+ file->remove();
+ shared_ptr <utility::file> file = fsf->create(dstDirPath / filename);
+ file->remove();
+
+ } catch (exceptions::filesystem_exception&) {
+
+ // Ignore
+ }
+
+ throw exceptions::command_error("ADD", "", "", e);
+ }
+
+ if (progress) {
+ progress->stop(size);
+ }
+}
+
+
+messageSet maildirFolder::copyMessages(const folder::path& dest, const messageSet& msgs) {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ } else if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ }
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ utility::file::path curDirPath =
+ store->getFormat()->folderPathToFileSystemPath(m_path, maildirFormat::CUR_DIRECTORY);
+
+ utility::file::path destCurDirPath = store->getFormat()->
+ folderPathToFileSystemPath(dest, maildirFormat::CUR_DIRECTORY);
+ utility::file::path destTmpDirPath = store->getFormat()->
+ folderPathToFileSystemPath(dest, maildirFormat::TMP_DIRECTORY);
+
+ // Create destination directories
+ try {
+
+ shared_ptr <utility::file> destTmpDir = fsf->create(destTmpDirPath);
+ destTmpDir->createDirectory(true);
+
+ } catch (exceptions::filesystem_exception&) {
+
+ // Don't throw now, it will fail later...
+ }
+
+ try {
+
+ shared_ptr <utility::file> destCurDir = fsf->create(destCurDirPath);
+ destCurDir->createDirectory(true);
+
+ } catch (exceptions::filesystem_exception&) {
+
+ // Don't throw now, it will fail later...
+ }
+
+ // Copy messages
+ const std::vector <size_t> nums = maildirUtils::messageSetToNumberList(msgs, m_messageCount);
+
+ try {
+
+ for (std::vector <size_t>::const_iterator it =
+ nums.begin() ; it != nums.end() ; ++it) {
+
+ const size_t num = *it;
+ const messageInfos& msg = m_messageInfos[num - 1];
+ const int flags = maildirUtils::extractFlags(msg.path);
+
+ const utility::file::path::component filename =
+ maildirUtils::buildFilename(maildirUtils::generateId(), flags);
+
+ shared_ptr <utility::file> file = fsf->create(curDirPath / msg.path);
+ shared_ptr <utility::fileReader> fr = file->getFileReader();
+ shared_ptr <utility::inputStream> is = fr->getInputStream();
+
+ copyMessageImpl(destTmpDirPath, destCurDirPath,
+ filename, *is, file->getLength(), NULL);
+ }
+
+ } catch (exception& e) {
+
+ notifyMessagesCopied(dest);
+ throw exceptions::command_error("COPY", "", "", e);
+ }
+
+ notifyMessagesCopied(dest);
+
+ return messageSet::empty();
+}
+
+
+void maildirFolder::notifyMessagesCopied(const folder::path& dest) {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ for (std::list <maildirFolder*>::iterator it = store->m_folders.begin() ;
+ it != store->m_folders.end() ; ++it) {
+
+ if ((*it) != this && (*it)->getFullPath() == dest) {
+
+ // We only need to update the first folder we found as calling
+ // status() will notify all the folders with the same path.
+ size_t count, unseen;
+ (*it)->status(count, unseen);
+
+ return;
+ }
+ }
+}
+
+
+void maildirFolder::status(size_t& count, size_t& unseen) {
+
+ count = 0;
+ unseen = 0;
+
+ shared_ptr <folderStatus> status = getStatus();
+
+ count = status->getMessageCount();
+ unseen = status->getUnseenCount();
+
+ m_messageCount = count;
+}
+
+
+shared_ptr <folderStatus> maildirFolder::getStatus() {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ const size_t oldCount = m_messageCount;
+
+ scanFolder();
+
+ shared_ptr <maildirFolderStatus> status = make_shared <maildirFolderStatus>();
+
+ status->setMessageCount(m_messageCount);
+ status->setUnseenCount(m_unreadMessageCount);
+
+ // Notify message count changed (new messages)
+ if (m_messageCount > oldCount) {
+
+ std::vector <size_t> nums;
+ nums.reserve(m_messageCount - oldCount);
+
+ for (size_t i = oldCount + 1, j = 0 ; i <= m_messageCount ; ++i, ++j) {
+ nums[j] = i;
+ }
+
+ shared_ptr <events::messageCountEvent> event =
+ make_shared <events::messageCountEvent>(
+ dynamicCast <folder>(shared_from_this()),
+ events::messageCountEvent::TYPE_ADDED,
+ nums
+ );
+
+ notifyMessageCount(event);
+
+ // Notify folders with the same path
+ for (std::list <maildirFolder*>::iterator it = store->m_folders.begin() ;
+ it != store->m_folders.end() ; ++it) {
+
+ if ((*it) != this && (*it)->getFullPath() == m_path) {
+
+ (*it)->m_messageCount = m_messageCount;
+ (*it)->m_unreadMessageCount = m_unreadMessageCount;
+
+ (*it)->m_messageInfos.resize(m_messageInfos.size());
+ std::copy(m_messageInfos.begin(), m_messageInfos.end(), (*it)->m_messageInfos.begin());
+
+ shared_ptr <events::messageCountEvent> event =
+ make_shared <events::messageCountEvent>(
+ dynamicCast <folder>((*it)->shared_from_this()),
+ events::messageCountEvent::TYPE_ADDED,
+ nums
+ );
+
+ (*it)->notifyMessageCount(event);
+ }
+ }
+ }
+
+ return status;
+}
+
+
+void maildirFolder::expunge() {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ } else if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ } else if (m_mode == MODE_READ_ONLY) {
+ throw exceptions::illegal_state("Folder is read-only");
+ }
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ utility::file::path curDirPath = store->getFormat()->
+ folderPathToFileSystemPath(m_path, maildirFormat::CUR_DIRECTORY);
+
+ std::vector <size_t> nums;
+ size_t unreadCount = 0;
+
+ for (size_t num = 1 ; num <= m_messageCount ; ++num) {
+
+ messageInfos& infos = m_messageInfos[num - 1];
+
+ if (infos.type == messageInfos::TYPE_DELETED) {
+
+ nums.push_back(num);
+
+ for (std::vector <maildirMessage*>::iterator it =
+ m_messages.begin() ; it != m_messages.end() ; ++it) {
+
+ if ((*it)->m_num == num) {
+ (*it)->m_expunged = true;
+ } else if ((*it)->m_num > num) {
+ (*it)->m_num--;
+ }
+ }
+
+ if (maildirUtils::extractFlags(infos.path) & message::FLAG_SEEN) {
+ ++unreadCount;
+ }
+
+ // Delete file from file system
+ try {
+ shared_ptr <utility::file> file = fsf->create(curDirPath / infos.path);
+ file->remove();
+ } catch (exceptions::filesystem_exception& e) {
+ // Ignore (not important)
+ }
+ }
+ }
+
+ if (!nums.empty()) {
+
+ for (std::vector <size_t>::size_type i = nums.size() ; i != 0 ; --i) {
+ m_messageInfos.erase(m_messageInfos.begin() + (i - 1));
+ }
+ }
+
+ m_messageCount -= static_cast <size_t>(nums.size());
+ m_unreadMessageCount -= unreadCount;
+
+ // Notify message expunged
+ shared_ptr <events::messageCountEvent> event =
+ make_shared <events::messageCountEvent>(
+ dynamicCast <folder>(shared_from_this()),
+ events::messageCountEvent::TYPE_REMOVED,
+ nums
+ );
+
+ notifyMessageCount(event);
+
+ // Notify folders with the same path
+ for (std::list <maildirFolder*>::iterator it = store->m_folders.begin() ;
+ it != store->m_folders.end() ; ++it) {
+
+ if ((*it) != this && (*it)->getFullPath() == m_path) {
+
+ (*it)->m_messageCount = m_messageCount;
+ (*it)->m_unreadMessageCount = m_unreadMessageCount;
+
+ (*it)->m_messageInfos.resize(m_messageInfos.size());
+ std::copy(m_messageInfos.begin(), m_messageInfos.end(), (*it)->m_messageInfos.begin());
+
+ shared_ptr <events::messageCountEvent> event =
+ make_shared <events::messageCountEvent>(
+ dynamicCast <folder>((*it)->shared_from_this()),
+ events::messageCountEvent::TYPE_REMOVED,
+ nums
+ );
+
+ (*it)->notifyMessageCount(event);
+ }
+ }
+}
+
+
+shared_ptr <folder> maildirFolder::getParent() {
+
+ if (m_path.isEmpty()) {
+ return null;
+ } else {
+ return shared_ptr <maildirFolder>(new maildirFolder(m_path.getParent(), m_store.lock()));
+ }
+}
+
+
+shared_ptr <const store> maildirFolder::getStore() const {
+
+ return m_store.lock();
+}
+
+
+shared_ptr <store> maildirFolder::getStore() {
+
+ return m_store.lock();
+}
+
+
+void maildirFolder::fetchMessages(
+ std::vector <shared_ptr <message> >& msg,
+ const fetchAttributes& options,
+ utility::progressListener* progress
+) {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ } else if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ }
+
+ if (msg.empty()) {
+ return;
+ }
+
+ const size_t total = msg.size();
+ size_t current = 0;
+
+ if (progress) {
+ progress->start(total);
+ }
+
+ shared_ptr <maildirFolder> thisFolder = dynamicCast <maildirFolder>(shared_from_this());
+
+ for (std::vector <shared_ptr <message> >::iterator it = msg.begin() ;
+ it != msg.end() ; ++it) {
+
+ dynamicCast <maildirMessage>(*it)->fetch(thisFolder, options);
+
+ if (progress) {
+ progress->progress(++current, total);
+ }
+ }
+
+ if (progress) {
+ progress->stop(total);
+ }
+}
+
+
+void maildirFolder::fetchMessage(
+ const shared_ptr <message>& msg,
+ const fetchAttributes& options
+) {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ } else if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ }
+
+ dynamicCast <maildirMessage>(msg)->fetch(
+ dynamicCast <maildirFolder>(shared_from_this()),
+ options
+ );
+}
+
+
+std::vector <shared_ptr <message> > maildirFolder::getAndFetchMessages(
+ const messageSet& msgs,
+ const fetchAttributes& attribs
+) {
+
+ if (msgs.isEmpty()) {
+ return std::vector <shared_ptr <message> >();
+ }
+
+ std::vector <shared_ptr <message> > messages = getMessages(msgs);
+ fetchMessages(messages, attribs);
+
+ return messages;
+}
+
+
+int maildirFolder::getFetchCapabilities() const {
+
+ return fetchAttributes::ENVELOPE |
+ fetchAttributes::STRUCTURE |
+ fetchAttributes::CONTENT_INFO |
+ fetchAttributes::FLAGS |
+ fetchAttributes::SIZE |
+ fetchAttributes::FULL_HEADER |
+ fetchAttributes::UID |
+ fetchAttributes::IMPORTANCE;
+}
+
+
+const utility::file::path maildirFolder::getMessageFSPath(const size_t number) const {
+
+ utility::file::path curDirPath = m_store.lock()->getFormat()->
+ folderPathToFileSystemPath(m_path, maildirFormat::CUR_DIRECTORY);
+
+ return curDirPath / m_messageInfos[number - 1].path;
+}
+
+
+std::vector <size_t> maildirFolder::getMessageNumbersStartingOnUID(const message::uid& /* uid */) {
+
+ throw exceptions::operation_not_supported();
+}
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
diff --git a/vmime-master/src/vmime/net/maildir/maildirFolder.hpp b/vmime-master/src/vmime/net/maildir/maildirFolder.hpp
new file mode 100644
index 0000000..24f2bf8
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirFolder.hpp
@@ -0,0 +1,211 @@
+//
+// 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.
+//
+
+#ifndef VMIME_NET_MAILDIR_MAILDIRFOLDER_HPP_INCLUDED
+#define VMIME_NET_MAILDIR_MAILDIRFOLDER_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#include <vector>
+#include <map>
+
+#include "vmime/types.hpp"
+
+#include "vmime/net/folder.hpp"
+
+#include "vmime/utility/file.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+class maildirStore;
+class maildirMessage;
+
+
+/** maildir folder implementation.
+ */
+class VMIME_EXPORT maildirFolder : public folder {
+
+private:
+
+ friend class maildirStore;
+ friend class maildirMessage;
+
+ maildirFolder(const maildirFolder&) : folder() { }
+ maildirFolder(const folder::path& path, const shared_ptr <maildirStore>& store);
+
+public:
+
+ ~maildirFolder();
+
+
+ int getMode() const;
+
+ const folderAttributes getAttributes();
+
+ const folder::path::component getName() const;
+ const folder::path getFullPath() const;
+
+ void open(const int mode, bool failIfModeIsNotAvailable = false);
+ void close(const bool expunge);
+ void create(const folderAttributes& attribs);
+
+ bool exists();
+
+ void destroy();
+
+ bool isOpen() const;
+
+ shared_ptr <message> getMessage(const size_t num);
+ std::vector <shared_ptr <message> > getMessages(const messageSet& msgs);
+
+ size_t getMessageCount();
+
+ shared_ptr <folder> getFolder(const folder::path::component& name);
+ std::vector <shared_ptr <folder> > getFolders(const bool recursive = false);
+
+ void rename(const folder::path& newPath);
+
+ void deleteMessages(const messageSet& msgs);
+
+ void setMessageFlags(
+ const messageSet& msgs,
+ const int flags,
+ const int mode = message::FLAG_MODE_SET
+ );
+
+ messageSet addMessage(
+ const shared_ptr <vmime::message>& msg,
+ const int flags = -1,
+ vmime::datetime* date = NULL,
+ utility::progressListener* progress = NULL
+ );
+
+ messageSet addMessage(
+ utility::inputStream& is,
+ const size_t size,
+ const int flags = -1,
+ vmime::datetime* date = NULL,
+ utility::progressListener* progress = NULL
+ );
+
+ messageSet copyMessages(const folder::path& dest, const messageSet& msgs);
+
+ void status(size_t& count, size_t& unseen);
+ shared_ptr <folderStatus> getStatus();
+
+ void expunge();
+
+ shared_ptr <folder> getParent();
+
+ shared_ptr <const store> getStore() const;
+ shared_ptr <store> getStore();
+
+
+ void fetchMessages(
+ std::vector <shared_ptr <message> >& msg,
+ const fetchAttributes& options,
+ utility::progressListener* progress = NULL
+ );
+
+ void fetchMessage(const shared_ptr <message>& msg, const fetchAttributes& options);
+
+ std::vector <shared_ptr <message> > getAndFetchMessages(
+ const messageSet& msgs,
+ const fetchAttributes& attribs
+ );
+
+ int getFetchCapabilities() const;
+
+ std::vector <size_t> getMessageNumbersStartingOnUID(const message::uid& uid);
+
+private:
+
+ void scanFolder();
+
+ void listFolders(std::vector <shared_ptr <folder> >& list, const bool recursive);
+
+ void registerMessage(maildirMessage* msg);
+ void unregisterMessage(maildirMessage* msg);
+
+ const utility::file::path getMessageFSPath(const size_t number) const;
+
+ void onStoreDisconnected();
+
+ void onClose();
+
+ void deleteMessagesImpl(const std::vector <size_t>& nums);
+ void setMessageFlagsImpl(const std::vector <size_t>& nums, const int flags, const int mode);
+
+ void copyMessagesImpl(const folder::path& dest, const std::vector <size_t>& nums);
+ void copyMessageImpl(const utility::file::path& tmpDirPath, const utility::file::path& curDirPath, const utility::file::path::component& filename, utility::inputStream& is, const size_t size, utility::progressListener* progress);
+
+ void notifyMessagesCopied(const folder::path& dest);
+
+
+ weak_ptr <maildirStore> m_store;
+
+ folder::path m_path;
+ folder::path::component m_name;
+
+ int m_mode;
+ bool m_open;
+
+ size_t m_unreadMessageCount;
+ size_t m_messageCount;
+
+ // Store information about scanned messages
+ struct messageInfos {
+
+ enum Type {
+ TYPE_CUR,
+ TYPE_DELETED
+ };
+
+ utility::file::path::component path; // filename
+ Type type; // current location
+ };
+
+ std::vector <messageInfos> m_messageInfos;
+
+ // Instanciated message objects
+ std::vector <maildirMessage*> m_messages;
+};
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+#endif // VMIME_NET_MAILDIR_MAILDIRFOLDER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/maildir/maildirFolderStatus.cpp b/vmime-master/src/vmime/net/maildir/maildirFolderStatus.cpp
new file mode 100644
index 0000000..7438d8c
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirFolderStatus.cpp
@@ -0,0 +1,88 @@
+//
+// 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/maildirFolderStatus.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+maildirFolderStatus::maildirFolderStatus()
+ : m_count(0),
+ m_unseen(0) {
+
+}
+
+
+maildirFolderStatus::maildirFolderStatus(const maildirFolderStatus& other)
+ : folderStatus(),
+ m_count(other.m_count),
+ m_unseen(other.m_unseen) {
+
+}
+
+
+size_t maildirFolderStatus::getMessageCount() const {
+
+ return m_count;
+}
+
+
+size_t maildirFolderStatus::getUnseenCount() const {
+
+ return m_unseen;
+}
+
+
+void maildirFolderStatus::setMessageCount(const size_t count) {
+
+ m_count = count;
+}
+
+
+void maildirFolderStatus::setUnseenCount(const size_t unseen) {
+
+ m_unseen = unseen;
+}
+
+
+shared_ptr <folderStatus> maildirFolderStatus::clone() const {
+
+ return make_shared <maildirFolderStatus>(*this);
+}
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
diff --git a/vmime-master/src/vmime/net/maildir/maildirFolderStatus.hpp b/vmime-master/src/vmime/net/maildir/maildirFolderStatus.hpp
new file mode 100644
index 0000000..3b69375
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirFolderStatus.hpp
@@ -0,0 +1,75 @@
+//
+// 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.
+//
+
+#ifndef VMIME_NET_MAILDIR_MAILDIRFOLDERSTATUS_HPP_INCLUDED
+#define VMIME_NET_MAILDIR_MAILDIRFOLDERSTATUS_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#include "vmime/net/folderStatus.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+/** Holds the status of a Maildir folder.
+ */
+class VMIME_EXPORT maildirFolderStatus : public folderStatus {
+
+public:
+
+ maildirFolderStatus();
+ maildirFolderStatus(const maildirFolderStatus& other);
+
+ // Inherited from folderStatus
+ size_t getMessageCount() const;
+ size_t getUnseenCount() const;
+
+ shared_ptr <folderStatus> clone() const;
+
+
+ void setMessageCount(const size_t count);
+ void setUnseenCount(const size_t unseen);
+
+private:
+
+ size_t m_count;
+ size_t m_unseen;
+};
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+#endif // VMIME_NET_MAILDIR_MAILDIRFOLDERSTATUS_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/maildir/maildirFormat.cpp b/vmime-master/src/vmime/net/maildir/maildirFormat.cpp
new file mode 100644
index 0000000..914c078
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirFormat.cpp
@@ -0,0 +1,104 @@
+//
+// 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/maildirFormat.hpp"
+#include "vmime/net/maildir/maildirStore.hpp"
+
+#include "vmime/net/maildir/format/kmailMaildirFormat.hpp"
+#include "vmime/net/maildir/format/courierMaildirFormat.hpp"
+
+#include "vmime/utility/file.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+const utility::file::path::component maildirFormat::TMP_DIR("tmp", vmime::charset(vmime::charsets::US_ASCII));
+const utility::file::path::component maildirFormat::CUR_DIR("cur", vmime::charset(vmime::charsets::US_ASCII));
+const utility::file::path::component maildirFormat::NEW_DIR("new", vmime::charset(vmime::charsets::US_ASCII));
+
+
+//
+// maildirFormat::context
+//
+
+maildirFormat::context::context(const shared_ptr <maildirStore>& store)
+ : m_store(store) {
+
+}
+
+
+shared_ptr <maildirStore> maildirFormat::context::getStore() {
+
+ return m_store.lock();
+}
+
+
+//
+// maildirFormat
+//
+
+maildirFormat::maildirFormat(const shared_ptr <context>& ctx)
+ : m_context(ctx) {
+
+}
+
+
+shared_ptr <maildirFormat::context> maildirFormat::getContext() const {
+
+ return m_context;
+}
+
+
+// static
+shared_ptr <maildirFormat> maildirFormat::detect(const shared_ptr <maildirStore>& store) {
+
+ shared_ptr <context> ctx = make_shared <context>(store);
+
+ // Try Courier format
+ shared_ptr <maildirFormat> fmt = make_shared <format::courierMaildirFormat>(ctx);
+
+ if (fmt->supports()) {
+ return fmt;
+ }
+
+ // Default is KMail format
+ return make_shared <format::kmailMaildirFormat>(ctx);
+}
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
diff --git a/vmime-master/src/vmime/net/maildir/maildirFormat.hpp b/vmime-master/src/vmime/net/maildir/maildirFormat.hpp
new file mode 100644
index 0000000..9b9e063
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirFormat.hpp
@@ -0,0 +1,192 @@
+//
+// 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.
+//
+
+#ifndef VMIME_NET_MAILDIR_FORMAT_MAILDIRFORMAT_HPP_INCLUDED
+#define VMIME_NET_MAILDIR_FORMAT_MAILDIRFORMAT_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#include "vmime/net/folder.hpp"
+
+#include "vmime/utility/file.hpp"
+#include "vmime/utility/path.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+class maildirStore;
+
+
+/** Interface for an object capable of reading a specific Maildir format.
+ */
+class VMIME_EXPORT maildirFormat : public object {
+
+public:
+
+ class context : public object {
+
+ public:
+
+ context(const shared_ptr <maildirStore>& store);
+
+ shared_ptr <maildirStore> getStore();
+
+ private:
+
+ weak_ptr <maildirStore> m_store;
+ };
+
+
+ /** Physical directory types. */
+ enum DirectoryType {
+ ROOT_DIRECTORY, /**< Root directory. */
+ NEW_DIRECTORY, /**< Directory containing unread messages. */
+ CUR_DIRECTORY, /**< Directory containing messages that have been seen. */
+ TMP_DIRECTORY, /**< Temporary directory used for reliable delivery. */
+ CONTAINER_DIRECTORY /**< Container for subfolders. */
+ };
+
+ /** Return the name of this Maildir format.
+ *
+ * @return format name
+ */
+ virtual const string getName() const = 0;
+
+ /** Create the specified folder.
+ *
+ * @param path virtual path of the folder
+ * @throw exceptions::filesystem_exception, invalid_folder_name
+ */
+ virtual void createFolder(const folder::path& path) = 0;
+
+ /** Destroy the specified folder.
+ *
+ * @param path virtual path of the folder
+ * @throw exceptions::filesystem_exception
+ */
+ virtual void destroyFolder(const folder::path& path) = 0;
+
+ /** Rename the specified folder.
+ *
+ * @param oldPath old virtual path of the folder
+ * @param newPath new virtual path of the folder
+ * @throw exceptions::filesystem_exception
+ */
+ virtual void renameFolder(const folder::path& oldPath, const folder::path& newPath) = 0;
+
+ /** Test whether the specified folder exists.
+ *
+ * @param path virtual path of the folder
+ * @return true if the folder exists, false otherwise
+ */
+ virtual bool folderExists(const folder::path& path) const = 0;
+
+ /** Test whether the specified folder has subfolders.
+ *
+ * @param path virtual path of the folder
+ * @return true if the folder has at least one subfolder,
+ * false otherwise
+ */
+ virtual bool folderHasSubfolders(const folder::path& path) const = 0;
+
+ /** Returns the directory which represents the specified
+ * folder on the file system.
+ *
+ * @param path virtual path of the folder
+ * @param type type of directory to return
+ * @return corresponding directory on the file system
+ */
+ virtual const utility::file::path folderPathToFileSystemPath(
+ const folder::path& path,
+ const DirectoryType type
+ ) const = 0;
+
+ /** List subfolders in the specified folder.
+ *
+ * @param root root folder in which to start the search
+ * @param recursive if set to true, all the descendant are
+ * returned; if set to false, only direct children are returned.
+ * @return list of subfolders
+ */
+ virtual const std::vector <folder::path> listFolders(
+ const folder::path& root,
+ const bool recursive
+ ) const = 0;
+
+
+ /** Try to detect the format of the specified Maildir store.
+ * If the format cannot be detected, a compatible implementation
+ * will be returned.
+ *
+ * @param store of which to detect format
+ * @return a Maildir format implementation for the specified store
+ */
+ static shared_ptr <maildirFormat> detect(const shared_ptr <maildirStore>& store);
+
+protected:
+
+ static const utility::file::path::component TMP_DIR; /**< Ensure reliable delivery (not to be listed). */
+ static const utility::file::path::component CUR_DIR; /**< No longer new messages. */
+ static const utility::file::path::component NEW_DIR; /**< Unread messages. */
+
+
+ maildirFormat(const shared_ptr <context>& ctx);
+
+
+ /** Returns the current context.
+ *
+ * @return current context
+ */
+ shared_ptr <context> getContext() const;
+
+ /** Quick checks whether this implementation can read the Maildir
+ * format in the specified directory.
+ *
+ * @return true if the implementation supports the specified
+ * Maildir, or false otherwise
+ */
+ virtual bool supports() const = 0;
+
+private:
+
+ shared_ptr <context> m_context;
+};
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+#endif // VMIME_NET_MAILDIR_FORMAT_MAILDIRFORMAT_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/net/maildir/maildirMessage.cpp b/vmime-master/src/vmime/net/maildir/maildirMessage.cpp
new file mode 100644
index 0000000..ae99c59
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirMessage.cpp
@@ -0,0 +1,410 @@
+//
+// 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/maildirMessage.hpp"
+#include "vmime/net/maildir/maildirMessagePart.hpp"
+#include "vmime/net/maildir/maildirMessageStructure.hpp"
+#include "vmime/net/maildir/maildirFolder.hpp"
+#include "vmime/net/maildir/maildirUtils.hpp"
+#include "vmime/net/maildir/maildirStore.hpp"
+
+#include "vmime/message.hpp"
+
+#include "vmime/exception.hpp"
+#include "vmime/platform.hpp"
+
+#include "vmime/utility/outputStreamAdapter.hpp"
+#include "vmime/utility/stringUtils.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+maildirMessage::maildirMessage(const shared_ptr <maildirFolder>& folder, const size_t num)
+ : m_folder(folder),
+ m_num(num),
+ m_size(-1),
+ m_flags(FLAG_UNDEFINED),
+ m_expunged(false),
+ m_structure(null) {
+
+ folder->registerMessage(this);
+}
+
+
+maildirMessage::~maildirMessage() {
+
+ try {
+
+ shared_ptr <maildirFolder> folder = m_folder.lock();
+
+ if (folder) {
+ folder->unregisterMessage(this);
+ }
+
+ } catch (...) {
+
+ // Don't throw in destructor
+ }
+}
+
+
+void maildirMessage::onFolderClosed() {
+
+ m_folder.reset();
+}
+
+
+size_t maildirMessage::getNumber() const {
+
+ return m_num;
+}
+
+
+const message::uid maildirMessage::getUID() const {
+
+ return m_uid;
+}
+
+
+size_t maildirMessage::getSize() const {
+
+ if (m_size == static_cast <size_t>(-1)) {
+ throw exceptions::unfetched_object();
+ }
+
+ return m_size;
+}
+
+
+bool maildirMessage::isExpunged() const {
+
+ return m_expunged;
+}
+
+
+shared_ptr <const messageStructure> maildirMessage::getStructure() const {
+
+ if (!m_structure) {
+ throw exceptions::unfetched_object();
+ }
+
+ return m_structure;
+}
+
+
+shared_ptr <messageStructure> maildirMessage::getStructure() {
+
+ if (!m_structure) {
+ throw exceptions::unfetched_object();
+ }
+
+ return m_structure;
+}
+
+
+shared_ptr <const header> maildirMessage::getHeader() const {
+
+ if (!m_header) {
+ throw exceptions::unfetched_object();
+ }
+
+ return m_header;
+}
+
+
+int maildirMessage::getFlags() const {
+
+ if (m_flags == FLAG_UNDEFINED) {
+ throw exceptions::unfetched_object();
+ }
+
+ return m_flags;
+}
+
+
+void maildirMessage::setFlags(const int flags, const int mode) {
+
+ shared_ptr <maildirFolder> folder = m_folder.lock();
+
+ if (!folder) {
+ throw exceptions::folder_not_found();
+ }
+
+ folder->setMessageFlags(messageSet::byNumber(m_num), flags, mode);
+}
+
+
+void maildirMessage::extract(
+ utility::outputStream& os,
+ utility::progressListener* progress,
+ const size_t start,
+ const size_t length,
+ const bool peek
+) const {
+
+ extractImpl(os, progress, 0, m_size, start, length, peek);
+}
+
+
+void maildirMessage::extractPart(
+ const shared_ptr <const messagePart>& p,
+ utility::outputStream& os,
+ utility::progressListener* progress,
+ const size_t start,
+ const size_t length,
+ const bool peek
+) const {
+
+ shared_ptr <const maildirMessagePart> mp = dynamicCast <const maildirMessagePart>(p);
+
+ extractImpl(
+ os, progress, mp->getBodyParsedOffset(), mp->getBodyParsedLength(),
+ start, length, peek
+ );
+}
+
+
+void maildirMessage::extractImpl(
+ utility::outputStream& os,
+ utility::progressListener* progress,
+ const size_t start,
+ const size_t length,
+ const size_t partialStart,
+ const size_t partialLength,
+ const bool /* peek */
+) const {
+
+ shared_ptr <const maildirFolder> folder = m_folder.lock();
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ const utility::file::path path = folder->getMessageFSPath(m_num);
+ shared_ptr <utility::file> file = fsf->create(path);
+
+ shared_ptr <utility::fileReader> reader = file->getFileReader();
+ shared_ptr <utility::inputStream> is = reader->getInputStream();
+
+ is->skip(start + partialStart);
+
+ byte_t buffer[8192];
+ size_t remaining =
+ (partialLength == static_cast <size_t>(-1)
+ ? length
+ : std::min(partialLength, length)
+ );
+
+ const size_t total = remaining;
+ size_t current = 0;
+
+ if (progress) {
+ progress->start(total);
+ }
+
+ while (!is->eof() && remaining > 0) {
+
+ const size_t read = is->read(buffer, std::min(remaining, sizeof(buffer)));
+
+ remaining -= read;
+ current += read;
+
+ os.write(buffer, read);
+
+ if (progress) {
+ progress->progress(current, total);
+ }
+ }
+
+ if (progress) {
+ progress->stop(total);
+ }
+
+ // TODO: mark as read unless 'peek' is set
+}
+
+
+void maildirMessage::fetchPartHeader(const shared_ptr <messagePart>& p) {
+
+ shared_ptr <maildirFolder> folder = m_folder.lock();
+
+ shared_ptr <maildirMessagePart> mp = dynamicCast <maildirMessagePart>(p);
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ const utility::file::path path = folder->getMessageFSPath(m_num);
+ shared_ptr <utility::file> file = fsf->create(path);
+
+ shared_ptr <utility::fileReader> reader = file->getFileReader();
+ shared_ptr <utility::inputStream> is = reader->getInputStream();
+
+ is->skip(mp->getHeaderParsedOffset());
+
+ byte_t buffer[1024];
+ size_t remaining = mp->getHeaderParsedLength();
+
+ string contents;
+ contents.reserve(remaining);
+
+ while (!is->eof() && remaining > 0) {
+
+ const size_t read = is->read(buffer, std::min(remaining, sizeof(buffer)));
+
+ remaining -= read;
+
+ vmime::utility::stringUtils::appendBytesToString(contents, buffer, read);
+ }
+
+ mp->getOrCreateHeader().parse(contents);
+}
+
+
+void maildirMessage::fetch(const shared_ptr <maildirFolder>& msgFolder, const fetchAttributes& options) {
+
+ shared_ptr <maildirFolder> folder = m_folder.lock();
+
+ if (folder != msgFolder) {
+ throw exceptions::folder_not_found();
+ }
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ const utility::file::path path = folder->getMessageFSPath(m_num);
+ shared_ptr <utility::file> file = fsf->create(path);
+
+ if (options.has(fetchAttributes::FLAGS)) {
+ m_flags = maildirUtils::extractFlags(path.getLastComponent());
+ }
+
+ if (options.has(fetchAttributes::SIZE)) {
+ m_size = file->getLength();
+ }
+
+ if (options.has(fetchAttributes::UID)) {
+ m_uid = maildirUtils::extractId(path.getLastComponent()).getBuffer();
+ }
+
+ if (options.has(fetchAttributes::ENVELOPE | fetchAttributes::CONTENT_INFO |
+ fetchAttributes::FULL_HEADER | fetchAttributes::STRUCTURE |
+ fetchAttributes::IMPORTANCE)) {
+
+ string contents;
+
+ shared_ptr <utility::fileReader> reader = file->getFileReader();
+ shared_ptr <utility::inputStream> is = reader->getInputStream();
+
+ // Need whole message contents for structure
+ if (options.has(fetchAttributes::STRUCTURE)) {
+
+ byte_t buffer[16384];
+
+ contents.reserve(file->getLength());
+
+ while (!is->eof()) {
+ const size_t read = is->read(buffer, sizeof(buffer));
+ vmime::utility::stringUtils::appendBytesToString(contents, buffer, read);
+ }
+
+ // Need only header
+ } else {
+
+ byte_t buffer[1024];
+
+ contents.reserve(4096);
+
+ while (!is->eof()) {
+
+ const size_t read = is->read(buffer, sizeof(buffer));
+ vmime::utility::stringUtils::appendBytesToString(contents, buffer, read);
+
+ const size_t sep1 = contents.rfind("\r\n\r\n");
+ const size_t sep2 = contents.rfind("\n\n");
+
+ if (sep1 != string::npos) {
+ contents.erase(contents.begin() + sep1 + 4, contents.end());
+ break;
+ } else if (sep2 != string::npos) {
+ contents.erase(contents.begin() + sep2 + 2, contents.end());
+ break;
+ }
+ }
+ }
+
+ vmime::message msg;
+ msg.parse(contents);
+
+ // Extract structure
+ if (options.has(fetchAttributes::STRUCTURE)) {
+ m_structure = make_shared <maildirMessageStructure>(shared_ptr <maildirMessagePart>(), msg);
+ }
+
+ // Extract some header fields or whole header
+ if (options.has(fetchAttributes::ENVELOPE |
+ fetchAttributes::CONTENT_INFO |
+ fetchAttributes::FULL_HEADER |
+ fetchAttributes::IMPORTANCE)) {
+
+ getOrCreateHeader()->copyFrom(*(msg.getHeader()));
+ }
+ }
+}
+
+
+shared_ptr <header> maildirMessage::getOrCreateHeader() {
+
+ if (m_header) {
+ return m_header;
+ } else {
+ return (m_header = make_shared <header>());
+ }
+}
+
+
+shared_ptr <vmime::message> maildirMessage::getParsedMessage() {
+
+ std::ostringstream oss;
+ utility::outputStreamAdapter os(oss);
+
+ extract(os);
+
+ shared_ptr <vmime::message> msg = make_shared <vmime::message>();
+ msg->parse(oss.str());
+
+ return msg;
+}
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
diff --git a/vmime-master/src/vmime/net/maildir/maildirMessage.hpp b/vmime-master/src/vmime/net/maildir/maildirMessage.hpp
new file mode 100644
index 0000000..8cd0aac
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirMessage.hpp
@@ -0,0 +1,137 @@
+//
+// 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.
+//
+
+#ifndef VMIME_NET_MAILDIR_MAILDIRMESSAGE_HPP_INCLUDED
+#define VMIME_NET_MAILDIR_MAILDIRMESSAGE_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#include "vmime/net/message.hpp"
+#include "vmime/net/folder.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+class maildirFolder;
+
+
+/** maildir message implementation.
+ */
+class VMIME_EXPORT maildirMessage : public message {
+
+ friend class maildirFolder;
+
+ maildirMessage(const maildirMessage&) : message() { }
+
+public:
+
+ maildirMessage(const shared_ptr <maildirFolder>& folder, const size_t num);
+
+ ~maildirMessage();
+
+
+ size_t getNumber() const;
+
+ const uid getUID() const;
+
+ size_t getSize() const;
+
+ bool isExpunged() const;
+
+ shared_ptr <const messageStructure> getStructure() const;
+ shared_ptr <messageStructure> getStructure();
+
+ shared_ptr <const header> getHeader() const;
+
+ int getFlags() const;
+ void setFlags(const int flags, const int mode = FLAG_MODE_SET);
+
+ void extract(
+ utility::outputStream& os,
+ utility::progressListener* progress = NULL,
+ const size_t start = 0,
+ const size_t length = -1,
+ const bool peek = false
+ ) const;
+
+ void extractPart(
+ const shared_ptr <const messagePart>& p,
+ utility::outputStream& os,
+ utility::progressListener* progress = NULL,
+ const size_t start = 0,
+ const size_t length = -1,
+ const bool peek = false
+ ) const;
+
+ void fetchPartHeader(const shared_ptr <messagePart>& p);
+
+ shared_ptr <vmime::message> getParsedMessage();
+
+private:
+
+ void fetch(const shared_ptr <maildirFolder>& folder, const fetchAttributes& options);
+
+ void onFolderClosed();
+
+ shared_ptr <header> getOrCreateHeader();
+
+ void extractImpl(
+ utility::outputStream& os,
+ utility::progressListener* progress,
+ const size_t start,
+ const size_t length,
+ const size_t partialStart,
+ const size_t partialLength,
+ const bool peek
+ ) const;
+
+
+ weak_ptr <maildirFolder> m_folder;
+
+ size_t m_num;
+ size_t m_size;
+ int m_flags;
+ bool m_expunged;
+ uid m_uid;
+
+ shared_ptr <header> m_header;
+ shared_ptr <messageStructure> m_structure;
+};
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+#endif // VMIME_NET_MAILDIR_MAILDIRMESSAGE_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/maildir/maildirMessagePart.cpp b/vmime-master/src/vmime/net/maildir/maildirMessagePart.cpp
new file mode 100644
index 0000000..7448d7e
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirMessagePart.cpp
@@ -0,0 +1,178 @@
+//
+// 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/maildirMessagePart.hpp"
+#include "vmime/net/maildir/maildirMessageStructure.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+maildirMessagePart::maildirMessagePart(
+ const shared_ptr <maildirMessagePart>& parent,
+ const size_t number,
+ const bodyPart& part
+)
+ : m_parent(parent),
+ m_header(null),
+ m_number(number) {
+
+ m_headerParsedOffset = part.getHeader()->getParsedOffset();
+ m_headerParsedLength = part.getHeader()->getParsedLength();
+
+ m_bodyParsedOffset = part.getBody()->getParsedOffset();
+ m_bodyParsedLength = part.getBody()->getParsedLength();
+
+ m_size = part.getBody()->getContents()->getLength();
+
+ m_mediaType = part.getBody()->getContentType();
+
+ auto cdispField = part.getHeader()->ContentDisposition();
+ if (cdispField) {
+ m_dispType = dynamic_cast <const contentDisposition&>(*cdispField->getValue());
+ }
+}
+
+
+maildirMessagePart::~maildirMessagePart() {
+
+}
+
+
+void maildirMessagePart::initStructure(const bodyPart& part) {
+
+ if (part.getBody()->getPartList().size() == 0) {
+
+ m_structure = null;
+
+ } else {
+
+ m_structure = make_shared <maildirMessageStructure>(
+ dynamicCast <maildirMessagePart>(shared_from_this()), part.getBody()->getPartList()
+ );
+ }
+}
+
+
+shared_ptr <const messageStructure> maildirMessagePart::getStructure() const {
+
+ if (m_structure) {
+ return m_structure;
+ } else {
+ return maildirMessageStructure::emptyStructure();
+ }
+}
+
+
+shared_ptr <messageStructure> maildirMessagePart::getStructure() {
+
+ if (m_structure) {
+ return m_structure;
+ } else {
+ return maildirMessageStructure::emptyStructure();
+ }
+}
+
+
+const mediaType& maildirMessagePart::getType() const {
+
+ return m_mediaType;
+}
+
+
+const contentDisposition &maildirMessagePart::getDisposition() const {
+
+ return m_dispType;
+}
+
+
+size_t maildirMessagePart::getSize() const {
+
+ return m_size;
+}
+
+
+size_t maildirMessagePart::getNumber() const {
+
+ return m_number;
+}
+
+
+shared_ptr <const header> maildirMessagePart::getHeader() const {
+
+ if (!m_header) {
+ throw exceptions::unfetched_object();
+ } else {
+ return m_header;
+ }
+}
+
+
+header& maildirMessagePart::getOrCreateHeader() {
+
+ if (m_header) {
+ return *m_header;
+ } else {
+ return *(m_header = make_shared <header>());
+ }
+}
+
+
+size_t maildirMessagePart::getHeaderParsedOffset() const {
+
+ return m_headerParsedOffset;
+}
+
+
+size_t maildirMessagePart::getHeaderParsedLength() const {
+
+ return m_headerParsedLength;
+}
+
+
+size_t maildirMessagePart::getBodyParsedOffset() const {
+
+ return m_bodyParsedOffset;
+}
+
+
+size_t maildirMessagePart::getBodyParsedLength() const {
+
+ return m_bodyParsedLength;
+}
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
diff --git a/vmime-master/src/vmime/net/maildir/maildirMessagePart.hpp b/vmime-master/src/vmime/net/maildir/maildirMessagePart.hpp
new file mode 100644
index 0000000..5ecc739
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirMessagePart.hpp
@@ -0,0 +1,106 @@
+//
+// 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.
+//
+
+#ifndef VMIME_NET_MAILDIR_MAILDIRMESSAGEPART_HPP_INCLUDED
+#define VMIME_NET_MAILDIR_MAILDIRMESSAGEPART_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#include "vmime/net/message.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+class maildirMessageStructure;
+
+
+class maildirMessagePart : public messagePart
+{
+public:
+
+ maildirMessagePart(
+ const shared_ptr <maildirMessagePart>& parent,
+ const size_t number,
+ const bodyPart& part
+ );
+
+ ~maildirMessagePart();
+
+
+ shared_ptr <const messageStructure> getStructure() const;
+ shared_ptr <messageStructure> getStructure();
+
+ weak_ptr <const maildirMessagePart> getParent() const { return (m_parent); }
+
+ const mediaType& getType() const;
+ const contentDisposition &getDisposition() const;
+ size_t getSize() const;
+ size_t getNumber() const;
+
+ shared_ptr <const header> getHeader() const;
+
+ header& getOrCreateHeader();
+
+ size_t getHeaderParsedOffset() const;
+ size_t getHeaderParsedLength() const;
+
+ size_t getBodyParsedOffset() const;
+ size_t getBodyParsedLength() const;
+
+ void initStructure(const bodyPart& part);
+
+private:
+
+ shared_ptr <maildirMessageStructure> m_structure;
+ weak_ptr <maildirMessagePart> m_parent;
+ shared_ptr <header> m_header;
+
+ size_t m_number;
+ size_t m_size;
+ mediaType m_mediaType;
+ contentDisposition m_dispType;
+
+ size_t m_headerParsedOffset;
+ size_t m_headerParsedLength;
+
+ size_t m_bodyParsedOffset;
+ size_t m_bodyParsedLength;
+};
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+#endif // VMIME_NET_MAILDIR_MAILDIRMESSAGEPART_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/maildir/maildirMessageStructure.cpp b/vmime-master/src/vmime/net/maildir/maildirMessageStructure.cpp
new file mode 100644
index 0000000..1e2f2cc
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirMessageStructure.cpp
@@ -0,0 +1,104 @@
+//
+// 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/maildirMessageStructure.hpp"
+#include "vmime/net/maildir/maildirMessagePart.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+shared_ptr <maildirMessageStructure> maildirMessageStructure::m_emptyStructure = make_shared <maildirMessageStructure>();
+
+
+maildirMessageStructure::maildirMessageStructure()
+{
+}
+
+
+maildirMessageStructure::maildirMessageStructure(
+ const shared_ptr <maildirMessagePart>& parent,
+ const bodyPart& part
+) {
+
+ shared_ptr <maildirMessagePart> mpart = make_shared <maildirMessagePart>(parent, 0, part);
+ mpart->initStructure(part);
+
+ m_parts.push_back(mpart);
+}
+
+
+maildirMessageStructure::maildirMessageStructure(
+ const shared_ptr <maildirMessagePart>& parent,
+ const std::vector <shared_ptr <const vmime::bodyPart> >& list
+) {
+
+ for (size_t i = 0 ; i < list.size() ; ++i) {
+
+ shared_ptr <maildirMessagePart> mpart = make_shared <maildirMessagePart>(parent, i, *list[i]);
+ mpart->initStructure(*list[i]);
+
+ m_parts.push_back(mpart);
+ }
+}
+
+
+shared_ptr <const messagePart> maildirMessageStructure::getPartAt(const size_t x) const {
+
+ return m_parts[x];
+}
+
+
+shared_ptr <messagePart> maildirMessageStructure::getPartAt(const size_t x) {
+
+ return m_parts[x];
+}
+
+
+size_t maildirMessageStructure::getPartCount() const {
+
+ return m_parts.size();
+}
+
+
+// static
+shared_ptr <maildirMessageStructure> maildirMessageStructure::emptyStructure() {
+
+ return m_emptyStructure;
+}
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
diff --git a/vmime-master/src/vmime/net/maildir/maildirMessageStructure.hpp b/vmime-master/src/vmime/net/maildir/maildirMessageStructure.hpp
new file mode 100644
index 0000000..1a20ea4
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirMessageStructure.hpp
@@ -0,0 +1,82 @@
+//
+// 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.
+//
+
+#ifndef VMIME_NET_MAILDIR_MAILDIRMESSAGESTRUCTURE_HPP_INCLUDED
+#define VMIME_NET_MAILDIR_MAILDIRMESSAGESTRUCTURE_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#include "vmime/net/message.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+class maildirMessagePart;
+
+
+class maildirMessageStructure : public messageStructure {
+
+public:
+
+ maildirMessageStructure();
+ maildirMessageStructure(
+ const shared_ptr <maildirMessagePart>& parent,
+ const bodyPart& part
+ );
+ maildirMessageStructure(
+ const shared_ptr <maildirMessagePart>& parent,
+ const std::vector <shared_ptr <const vmime::bodyPart> >& list
+ );
+
+
+ shared_ptr <const messagePart> getPartAt(const size_t x) const;
+ shared_ptr <messagePart> getPartAt(const size_t x);
+
+ size_t getPartCount() const;
+
+ static shared_ptr <maildirMessageStructure> emptyStructure();
+
+private:
+
+ static shared_ptr <maildirMessageStructure> m_emptyStructure;
+
+ std::vector <shared_ptr <maildirMessagePart> > m_parts;
+};
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+#endif // VMIME_NET_MAILDIR_MAILDIRMESSAGESTRUCTURE_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/maildir/maildirServiceInfos.cpp b/vmime-master/src/vmime/net/maildir/maildirServiceInfos.cpp
new file mode 100644
index 0000000..f9d92d3
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirServiceInfos.cpp
@@ -0,0 +1,76 @@
+//
+// 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/maildirServiceInfos.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+maildirServiceInfos::maildirServiceInfos() {
+
+}
+
+
+const string maildirServiceInfos::getPropertyPrefix() const {
+
+ return "store.maildir.";
+}
+
+
+const maildirServiceInfos::props& maildirServiceInfos::getProperties() const {
+
+ static props maildirProps = {
+ property(serviceInfos::property::SERVER_ROOTPATH, serviceInfos::property::FLAG_REQUIRED)
+ };
+
+ return maildirProps;
+}
+
+
+const std::vector <serviceInfos::property> maildirServiceInfos::getAvailableProperties() const {
+
+ std::vector <property> list;
+ const props& p = getProperties();
+
+ list.push_back(p.PROPERTY_SERVER_ROOTPATH);
+
+ return list;
+}
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
diff --git a/vmime-master/src/vmime/net/maildir/maildirServiceInfos.hpp b/vmime-master/src/vmime/net/maildir/maildirServiceInfos.hpp
new file mode 100644
index 0000000..827a7d7
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirServiceInfos.hpp
@@ -0,0 +1,69 @@
+//
+// 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.
+//
+
+#ifndef VMIME_NET_MAILDIR_MAILDIRSERVICEINFOS_HPP_INCLUDED
+#define VMIME_NET_MAILDIR_MAILDIRSERVICEINFOS_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#include "vmime/net/serviceInfos.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+/** Information about maildir service.
+ */
+class VMIME_EXPORT maildirServiceInfos : public serviceInfos {
+
+public:
+
+ maildirServiceInfos();
+
+ struct props {
+ serviceInfos::property PROPERTY_SERVER_ROOTPATH;
+ };
+
+ const props& getProperties() const;
+
+ const string getPropertyPrefix() const;
+ const std::vector <serviceInfos::property> getAvailableProperties() const;
+};
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+#endif // VMIME_NET_MAILDIR_MAILDIRSERVICEINFOS_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/net/maildir/maildirStore.cpp b/vmime-master/src/vmime/net/maildir/maildirStore.cpp
new file mode 100644
index 0000000..a994f45
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirStore.cpp
@@ -0,0 +1,294 @@
+//
+// 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/maildirStore.hpp"
+
+#include "vmime/net/maildir/maildirFolder.hpp"
+#include "vmime/net/maildir/maildirFormat.hpp"
+
+#include "vmime/exception.hpp"
+#include "vmime/platform.hpp"
+
+#include "vmime/net/defaultConnectionInfos.hpp"
+
+
+// Helpers for service properties
+#define GET_PROPERTY(type, prop) \
+ (getInfos().getPropertyValue <type>(getSession(), \
+ dynamic_cast <const maildirServiceInfos&>(getInfos()).getProperties().prop))
+#define HAS_PROPERTY(prop) \
+ (getInfos().hasProperty(getSession(), \
+ dynamic_cast <const maildirServiceInfos&>(getInfos()).getProperties().prop))
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+maildirStore::maildirStore(
+ const shared_ptr <session>& sess,
+ const shared_ptr <security::authenticator>& auth
+)
+ : store(sess, getInfosInstance(), auth),
+ m_connected(false) {
+
+}
+
+
+maildirStore::~maildirStore() {
+
+ try {
+
+ if (isConnected()) {
+ disconnect();
+ }
+
+ } catch (...) {
+
+ // Don't throw in destructor
+ }
+}
+
+
+const string maildirStore::getProtocolName() const {
+
+ return "maildir";
+}
+
+
+shared_ptr <folder> maildirStore::getRootFolder() {
+
+ if (!isConnected()) {
+ throw exceptions::illegal_state("Not connected");
+ }
+
+ return shared_ptr <maildirFolder>(
+ new maildirFolder(
+ folder::path(),
+ dynamicCast <maildirStore>(shared_from_this())
+ )
+ );
+}
+
+
+shared_ptr <folder> maildirStore::getDefaultFolder() {
+
+ if (!isConnected()) {
+ throw exceptions::illegal_state("Not connected");
+ }
+
+ return shared_ptr <maildirFolder>(
+ new maildirFolder(
+ folder::path::component("inbox"),
+ dynamicCast <maildirStore>(shared_from_this())
+ )
+ );
+}
+
+
+shared_ptr <folder> maildirStore::getFolder(const folder::path& path) {
+
+ if (!isConnected()) {
+ throw exceptions::illegal_state("Not connected");
+ }
+
+ return shared_ptr <maildirFolder>(
+ new maildirFolder(
+ path,
+ dynamicCast <maildirStore>(shared_from_this())
+ )
+ );
+}
+
+
+bool maildirStore::isValidFolderName(const folder::path::component& name) const {
+
+ if (!platform::getHandler()->getFileSystemFactory()->isValidPathComponent(name)) {
+ return false;
+ }
+
+ const string& buf = name.getBuffer();
+
+ // Name cannot start/end with spaces
+ if (utility::stringUtils::trim(buf) != buf) {
+ return false;
+ }
+
+ // Name cannot start with '.'
+ const size_t length = buf.length();
+ size_t pos = 0;
+
+ while ((pos < length) && (buf[pos] == '.')) {
+ ++pos;
+ }
+
+ return (pos == 0);
+}
+
+
+void maildirStore::connect() {
+
+ if (isConnected()) {
+ throw exceptions::already_connected();
+ }
+
+ // Get root directory
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ m_fsPath = fsf->stringToPath(GET_PROPERTY(string, PROPERTY_SERVER_ROOTPATH));
+
+ shared_ptr <utility::file> rootDir = fsf->create(m_fsPath);
+
+ // Try to create the root directory if it does not exist
+ if (!(rootDir->exists() && rootDir->isDirectory())) {
+
+ try {
+ rootDir->createDirectory();
+ } catch (exceptions::filesystem_exception& e) {
+ throw exceptions::connection_error("Cannot create root directory.", e);
+ }
+ }
+
+ m_format = maildirFormat::detect(dynamicCast <maildirStore>(shared_from_this()));
+
+ m_connected = true;
+}
+
+
+bool maildirStore::isConnected() const {
+
+ return m_connected;
+}
+
+
+bool maildirStore::isSecuredConnection() const {
+
+ return false;
+}
+
+
+shared_ptr <connectionInfos> maildirStore::getConnectionInfos() const {
+
+ return make_shared <defaultConnectionInfos>("localhost", static_cast <port_t>(0));
+}
+
+
+void maildirStore::disconnect() {
+
+ for (std::list <maildirFolder*>::iterator it = m_folders.begin() ;
+ it != m_folders.end() ; ++it) {
+
+ (*it)->onStoreDisconnected();
+ }
+
+ m_folders.clear();
+
+ m_connected = false;
+}
+
+
+void maildirStore::noop() {
+
+ // Nothing to do.
+}
+
+
+shared_ptr <maildirFormat> maildirStore::getFormat() {
+
+ return m_format;
+}
+
+
+shared_ptr <const maildirFormat> maildirStore::getFormat() const {
+
+ return m_format;
+}
+
+
+void maildirStore::registerFolder(maildirFolder* folder) {
+
+ m_folders.push_back(folder);
+}
+
+
+void maildirStore::unregisterFolder(maildirFolder* folder) {
+
+ std::list <maildirFolder*>::iterator it = std::find(m_folders.begin(), m_folders.end(), folder);
+
+ if (it != m_folders.end()) {
+ m_folders.erase(it);
+ }
+}
+
+
+const utility::path& maildirStore::getFileSystemPath() const {
+
+ return m_fsPath;
+}
+
+
+int maildirStore::getCapabilities() const {
+
+ return CAPABILITY_CREATE_FOLDER |
+ CAPABILITY_RENAME_FOLDER |
+ CAPABILITY_ADD_MESSAGE |
+ CAPABILITY_COPY_MESSAGE |
+ CAPABILITY_DELETE_MESSAGE |
+ CAPABILITY_PARTIAL_FETCH |
+ CAPABILITY_MESSAGE_FLAGS |
+ CAPABILITY_EXTRACT_PART;
+}
+
+
+
+// Service infos
+
+maildirServiceInfos maildirStore::sm_infos;
+
+
+const serviceInfos& maildirStore::getInfosInstance() {
+
+ return sm_infos;
+}
+
+
+const serviceInfos& maildirStore::getInfos() const {
+
+ return sm_infos;
+}
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
diff --git a/vmime-master/src/vmime/net/maildir/maildirStore.hpp b/vmime-master/src/vmime/net/maildir/maildirStore.hpp
new file mode 100644
index 0000000..13255c0
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirStore.hpp
@@ -0,0 +1,123 @@
+//
+// 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.
+//
+
+#ifndef VMIME_NET_MAILDIR_MAILDIRSTORE_HPP_INCLUDED
+#define VMIME_NET_MAILDIR_MAILDIRSTORE_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#include "vmime/net/store.hpp"
+#include "vmime/net/socket.hpp"
+#include "vmime/net/folder.hpp"
+
+#include "vmime/net/maildir/maildirFormat.hpp"
+#include "vmime/net/maildir/maildirServiceInfos.hpp"
+
+#include "vmime/utility/file.hpp"
+
+#include <ostream>
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+class maildirFolder;
+
+
+/** maildir store service.
+ */
+class VMIME_EXPORT maildirStore : public store {
+
+ friend class maildirFolder;
+
+public:
+
+ maildirStore(
+ const shared_ptr <session>& sess,
+ const shared_ptr <security::authenticator>& auth
+ );
+
+ ~maildirStore();
+
+ const string getProtocolName() const;
+
+ shared_ptr <folder> getDefaultFolder();
+ shared_ptr <folder> getRootFolder();
+ shared_ptr <folder> getFolder(const folder::path& path);
+
+ bool isValidFolderName(const folder::path::component& name) const;
+
+ static const serviceInfos& getInfosInstance();
+ const serviceInfos& getInfos() const;
+
+ void connect();
+ bool isConnected() const;
+ void disconnect();
+
+ void noop();
+
+ const utility::path& getFileSystemPath() const;
+
+ int getCapabilities() const;
+
+ bool isSecuredConnection() const;
+ shared_ptr <connectionInfos> getConnectionInfos() const;
+
+ shared_ptr <maildirFormat> getFormat();
+ shared_ptr <const maildirFormat> getFormat() const;
+
+private:
+
+ void registerFolder(maildirFolder* folder);
+ void unregisterFolder(maildirFolder* folder);
+
+
+ std::list <maildirFolder*> m_folders;
+
+ shared_ptr <maildirFormat> m_format;
+
+ bool m_connected;
+
+ utility::path m_fsPath;
+
+
+ // Service infos
+ static maildirServiceInfos sm_infos;
+};
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+#endif // VMIME_NET_MAILDIR_MAILDIRSTORE_HPP_INCLUDED
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
+
diff --git a/vmime-master/src/vmime/net/maildir/maildirUtils.hpp b/vmime-master/src/vmime/net/maildir/maildirUtils.hpp
new file mode 100644
index 0000000..94ab998
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirUtils.hpp
@@ -0,0 +1,160 @@
+//
+// 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.
+//
+
+#ifndef VMIME_NET_MAILDIR_MAILDIRUTILS_HPP_INCLUDED
+#define VMIME_NET_MAILDIR_MAILDIRUTILS_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#include "vmime/utility/file.hpp"
+#include "vmime/utility/path.hpp"
+
+#include "vmime/net/messageSet.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+class maildirStore;
+
+
+/** Miscellaneous helpers functions for maildir messaging system.
+ */
+class VMIME_EXPORT maildirUtils {
+
+public:
+
+ /** Comparator for message filenames, based only on the
+ * unique identifier part of the filename.
+ */
+ class messageIdComparator {
+
+ public:
+
+ messageIdComparator(const utility::file::path::component& comp);
+
+ bool operator()(const utility::file::path::component& other) const;
+
+ private:
+
+ const utility::file::path::component m_comp;
+ };
+
+ /** Test whether the specified file-system object is a message.
+ *
+ * @param file reference to a file-system object
+ * @return true if the specified object is a message file,
+ * false otherwise
+ */
+ static bool isMessageFile(const utility::file& file);
+
+ /** Extract the unique identifier part of the message filename.
+ * Eg: for the filename "1071577232.28549.m03s:2,RS", it will
+ * return "1071577232.28549.m03s".
+ *
+ * @param filename filename part
+ * @return part of the filename that corresponds to the unique
+ * identifier of the message
+ */
+ static const utility::file::path::component extractId(const utility::file::path::component& filename);
+
+ /** Extract message flags from the specified message filename.
+ * Eg: for the filename "1071577232.28549.m03s:2,RS", it will
+ * return (message::FLAG_SEEN | message::FLAG_REPLIED).
+ *
+ * @param comp filename part
+ * @return message flags extracted from the specified filename
+ */
+ static int extractFlags(const utility::file::path::component& comp);
+
+ /** Return a string representing the specified message flags.
+ * Eg: for (message::FLAG_SEEN | message::FLAG_REPLIED), it will
+ * return "RS".
+ *
+ * @param flags set of flags
+ * @return message flags in a string representation
+ */
+ static const utility::file::path::component buildFlags(const int flags);
+
+ /** Build a filename with the specified id and flags.
+ *
+ * @param id id part of the filename
+ * @param flags flags part of the filename
+ * @return message filename
+ */
+ static const utility::file::path::component buildFilename(
+ const utility::file::path::component& id,
+ const utility::file::path::component& flags
+ );
+
+ /** Build a filename with the specified id and flags.
+ *
+ * @param id id part of the filename
+ * @param flags set of flags
+ * @return message filename
+ */
+ static const utility::file::path::component buildFilename(
+ const utility::file::path::component& id,
+ const int flags
+ );
+
+ /** Generate a new unique message identifier.
+ *
+ * @return unique message id
+ */
+ static const utility::file::path::component generateId();
+
+ /** Recursively delete a directory on the file system.
+ *
+ * @param dir directory to delete
+ */
+ static void recursiveFSDelete(const shared_ptr <utility::file>& dir);
+
+ /** Returns a list of message numbers given a message set.
+ *
+ * @param msgs message set
+ * @param msgCount number of messages in folder
+ * @return list of message numbers
+ */
+ static const std::vector <size_t> messageSetToNumberList(
+ const messageSet& msgs,
+ const size_t msgCount
+ );
+};
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+#endif // VMIME_NET_MAILDIR_MAILDIRUTILS_HPP_INCLUDED