aboutsummaryrefslogtreecommitdiff
path: root/vmime-master/src/vmime/platforms
diff options
context:
space:
mode:
authorWojtek Kosior <wk@koszkonutek-tmp.pl.eu.org>2021-04-30 00:33:56 +0200
committerWojtek Kosior <wk@koszkonutek-tmp.pl.eu.org>2021-04-30 00:33:56 +0200
commitaa4d426b4d3527d7e166df1a05058c9a4a0f6683 (patch)
tree4ff17ce8b89a2321b9d0ed4bcfc37c447bcb6820 /vmime-master/src/vmime/platforms
downloadsmtps-and-pop3s-console-program-master.tar.gz
smtps-and-pop3s-console-program-master.zip
initial/final commitHEADmaster
Diffstat (limited to 'vmime-master/src/vmime/platforms')
-rw-r--r--vmime-master/src/vmime/platforms/posix/posixChildProcess.cpp410
-rw-r--r--vmime-master/src/vmime/platforms/posix/posixChildProcess.hpp92
-rw-r--r--vmime-master/src/vmime/platforms/posix/posixCriticalSection.cpp67
-rw-r--r--vmime-master/src/vmime/platforms/posix/posixCriticalSection.hpp69
-rw-r--r--vmime-master/src/vmime/platforms/posix/posixFile.cpp715
-rw-r--r--vmime-master/src/vmime/platforms/posix/posixFile.hpp224
-rw-r--r--vmime-master/src/vmime/platforms/posix/posixHandler.cpp292
-rw-r--r--vmime-master/src/vmime/platforms/posix/posixHandler.hpp103
-rw-r--r--vmime-master/src/vmime/platforms/posix/posixSocket.cpp969
-rw-r--r--vmime-master/src/vmime/platforms/posix/posixSocket.hpp118
-rw-r--r--vmime-master/src/vmime/platforms/windows/windowsCodepages.hpp197
-rw-r--r--vmime-master/src/vmime/platforms/windows/windowsCriticalSection.cpp67
-rw-r--r--vmime-master/src/vmime/platforms/windows/windowsCriticalSection.hpp68
-rw-r--r--vmime-master/src/vmime/platforms/windows/windowsFile.cpp712
-rw-r--r--vmime-master/src/vmime/platforms/windows/windowsFile.hpp225
-rw-r--r--vmime-master/src/vmime/platforms/windows/windowsHandler.cpp315
-rw-r--r--vmime-master/src/vmime/platforms/windows/windowsHandler.hpp101
-rw-r--r--vmime-master/src/vmime/platforms/windows/windowsSocket.cpp547
-rw-r--r--vmime-master/src/vmime/platforms/windows/windowsSocket.hpp117
19 files changed, 5408 insertions, 0 deletions
diff --git a/vmime-master/src/vmime/platforms/posix/posixChildProcess.cpp b/vmime-master/src/vmime/platforms/posix/posixChildProcess.cpp
new file mode 100644
index 0000000..4a9fef3
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/posix/posixChildProcess.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_PLATFORM_IS_POSIX && VMIME_HAVE_FILESYSTEM_FEATURES
+
+
+#include "vmime/platforms/posix/posixChildProcess.hpp"
+#include "vmime/platforms/posix/posixFile.hpp"
+
+#include "vmime/exception.hpp"
+
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/wait.h>
+
+
+namespace vmime {
+namespace platforms {
+namespace posix {
+
+
+// posixChildProcessFactory
+
+shared_ptr <utility::childProcess> posixChildProcessFactory::create(const utility::file::path& path) const {
+
+ return make_shared <posixChildProcess>(path);
+}
+
+
+
+#ifndef VMIME_BUILDING_DOC
+
+
+// getPosixSignalMessage
+// Returns the name of a POSIX signal.
+
+static const string getPosixSignalMessage(const int num) {
+
+ switch (num) {
+ case SIGHUP: return "SIGHUP";
+ case SIGINT: return "SIGINT";
+ case SIGQUIT: return "SIGQUIT";
+ case SIGILL: return "SIGILL";
+ case SIGABRT: return "SIGABRT";
+ case SIGFPE: return "SIGFPE";
+ case SIGKILL: return "SIGKILL";
+ case SIGSEGV: return "SIGSEGV";
+ case SIGPIPE: return "SIGPIPE";
+ case SIGALRM: return "SIGALRM";
+ case SIGTERM: return "SIGTERM";
+ case SIGUSR1: return "SIGUSR1";
+ case SIGUSR2: return "SIGUSR2";
+ case SIGCHLD: return "SIGCHLD";
+ case SIGCONT: return "SIGCONT";
+ case SIGSTOP: return "SIGSTOP";
+ case SIGTSTP: return "SIGTSTP";
+ case SIGTTIN: return "SIGTTIN";
+ case SIGTTOU: return "SIGTTOU";
+ }
+
+ return "(unknown)";
+}
+
+
+// getPosixErrorMessage
+// Returns a message corresponding to an error code.
+
+static const string getPosixErrorMessage(const int num) {
+
+#ifdef strerror_r
+ char res[256];
+ res[0] = '\0';
+
+ strerror_r(num, res, sizeof(res));
+
+ return string(res);
+#else
+ return string(strerror(num));
+#endif
+
+}
+
+
+// Output stream adapter for POSIX pipe
+
+class outputStreamPosixPipeAdapter : public utility::outputStream {
+
+public:
+
+ outputStreamPosixPipeAdapter(const int desc)
+ : m_desc(desc) {
+
+ }
+
+ void flush() {
+
+ ::fsync(m_desc);
+ }
+
+protected:
+
+ void writeImpl(const byte_t* const data, const size_t count) {
+
+ if (::write(m_desc, data, count) == -1) {
+ const string errorMsg = getPosixErrorMessage(errno);
+ throw exceptions::system_error(errorMsg);
+ }
+ }
+
+private:
+
+ const int m_desc;
+};
+
+
+// Input stream adapter for POSIX pipe
+
+class inputStreamPosixPipeAdapter : public utility::inputStream {
+
+public:
+
+ inputStreamPosixPipeAdapter(const int desc)
+ : m_desc(desc) {
+ }
+
+ bool eof() const {
+
+ return m_eof;
+ }
+
+ void reset() {
+
+ // Do nothing: unsupported
+ }
+
+ size_t skip(const size_t count) {
+
+ // TODO: not tested
+ byte_t buffer[4096];
+
+ ssize_t bytesSkipped = 0;
+ ssize_t bytesRead = 0;
+
+ while ((bytesRead = ::read(m_desc, buffer,
+ std::min(sizeof(buffer), count - bytesSkipped))) != 0) {
+
+ if (bytesRead == -1) {
+ const string errorMsg = getPosixErrorMessage(errno);
+ throw exceptions::system_error(errorMsg);
+ }
+
+ bytesSkipped += bytesRead;
+ }
+
+ return static_cast <size_t>(bytesSkipped);
+ }
+
+ size_t read(byte_t* const data, const size_t count) {
+
+ ssize_t bytesRead = 0;
+
+ if ((bytesRead = ::read(m_desc, data, count)) == -1) {
+ const string errorMsg = getPosixErrorMessage(errno);
+ throw exceptions::system_error(errorMsg);
+ }
+
+ m_eof = (bytesRead == 0);
+
+ return static_cast <size_t>(bytesRead);
+ }
+
+private:
+
+ const int m_desc;
+
+ bool m_eof;
+};
+
+
+#endif // VMIME_BUILDING_DOC
+
+
+
+// posixChildProcess
+
+posixChildProcess::posixChildProcess(const utility::file::path& path)
+ : m_processPath(path),
+ m_started(false),
+ m_stdIn(null),
+ m_stdOut(null),
+ m_pid(0),
+ m_argArray(NULL) {
+
+ m_pipe[0] = 0;
+ m_pipe[1] = 0;
+
+ sigemptyset(&m_oldProcMask);
+}
+
+
+posixChildProcess::~posixChildProcess() {
+
+ if (m_started) {
+ sigprocmask(SIG_SETMASK, &m_oldProcMask, NULL);
+ }
+
+ if (m_pipe[0] != 0) {
+ close(m_pipe[0]);
+ }
+
+ if (m_pipe[1] != 0) {
+ close(m_pipe[1]);
+ }
+
+ delete [] m_argArray;
+}
+
+
+// The following code is highly inspired and adapted from the 'sendmail'
+// provider module in Evolution data server code.
+//
+// Original authors: Dan Winship <danw@ximian.com>
+// Copyright 2000 Ximian, Inc. (www.ximian.com)
+
+void posixChildProcess::start(const std::vector <string>& args, const int flags) {
+
+ if (m_started) {
+ return;
+ }
+
+ // Construct C-style argument array
+ const char** argv = new const char*[args.size() + 2];
+
+ m_argVector = args; // for c_str() pointer to remain valid
+ m_argArray = argv; // to free later
+
+ argv[0] = m_processPath.getLastComponent().getBuffer().c_str();
+ argv[args.size() + 1] = NULL;
+
+ for (unsigned int i = 0 ; i < m_argVector.size() ; ++i) {
+ argv[i + 1] = m_argVector[i].c_str();
+ }
+
+ // Create a pipe to communicate with the child process
+ int fd[2];
+
+ if (pipe(fd) == -1) {
+ throw exceptions::system_error(getPosixErrorMessage(errno));
+ }
+
+ m_pipe[0] = fd[0];
+ m_pipe[1] = fd[1];
+
+ // Block SIGCHLD so the calling application doesn't notice
+ // process exiting before we do
+ sigset_t mask;
+
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGCHLD);
+ sigprocmask(SIG_BLOCK, &mask, &m_oldProcMask);
+
+ // Spawn process
+ const pid_t pid = fork();
+
+ if (pid == -1) { // error
+
+ const string errorMsg = getPosixErrorMessage(errno);
+
+ sigprocmask(SIG_SETMASK, &m_oldProcMask, NULL);
+
+ close(fd[0]);
+ close(fd[1]);
+
+ throw exceptions::system_error(errorMsg);
+
+ } else if (pid == 0) { // child process
+
+ if (flags & FLAG_REDIRECT_STDIN) {
+ dup2(fd[0], STDIN_FILENO);
+ } else {
+ close(fd[0]);
+ }
+
+ if (flags & FLAG_REDIRECT_STDOUT) {
+ dup2(fd[1], STDOUT_FILENO);
+ } else {
+ close(fd[1]);
+ }
+
+ posixFileSystemFactory* pfsf = new posixFileSystemFactory();
+
+ const string path = pfsf->pathToString(m_processPath);
+
+ delete pfsf;
+
+ execv(path.c_str(), const_cast <char**>(argv));
+ _exit(255);
+ }
+
+ if (flags & FLAG_REDIRECT_STDIN) {
+
+ m_stdIn = make_shared <outputStreamPosixPipeAdapter>(m_pipe[1]);
+
+ } else {
+
+ close(m_pipe[1]);
+ m_pipe[1] = 0;
+ }
+
+ if (flags & FLAG_REDIRECT_STDOUT) {
+
+ m_stdOut = make_shared <inputStreamPosixPipeAdapter>(m_pipe[0]);
+
+ } else {
+
+ close(m_pipe[0]);
+ m_pipe[0] = 0;
+ }
+
+ m_pid = pid;
+ m_started = true;
+}
+
+
+shared_ptr <utility::outputStream> posixChildProcess::getStdIn() {
+
+ return m_stdIn;
+}
+
+
+shared_ptr <utility::inputStream> posixChildProcess::getStdOut() {
+
+ return m_stdOut;
+}
+
+
+void posixChildProcess::waitForFinish() {
+
+ // Close stdin pipe
+ if (m_pipe[1] != 0) {
+ close(m_pipe[1]);
+ m_pipe[1] = 0;
+ }
+
+ int wstat;
+
+ while (waitpid(m_pid, &wstat, 0) == -1 && errno == EINTR) {
+ ;
+ }
+
+ if (!WIFEXITED(wstat)) {
+
+ throw exceptions::system_error("Process exited with signal "
+ + getPosixSignalMessage(WTERMSIG(wstat)));
+
+ } else if (WEXITSTATUS(wstat) != 0) {
+
+ if (WEXITSTATUS(wstat) == 255) {
+
+ scoped_ptr <posixFileSystemFactory> pfsf(new posixFileSystemFactory());
+
+ throw exceptions::system_error("Could not execute '"
+ + pfsf->pathToString(m_processPath) + "'");
+
+ } else {
+
+ std::ostringstream oss;
+ oss.imbue(std::locale::classic());
+
+ oss << "Process exited with status " << WEXITSTATUS(wstat);
+
+ throw exceptions::system_error(oss.str());
+ }
+ }
+}
+
+
+} // posix
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_POSIX && VMIME_HAVE_FILESYSTEM_FEATURES
+
diff --git a/vmime-master/src/vmime/platforms/posix/posixChildProcess.hpp b/vmime-master/src/vmime/platforms/posix/posixChildProcess.hpp
new file mode 100644
index 0000000..b831e8b
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/posix/posixChildProcess.hpp
@@ -0,0 +1,92 @@
+//
+// 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_PLATFORMS_POSIX_POSIXCHILDPROCESS_HPP_INCLUDED
+#define VMIME_PLATFORMS_POSIX_POSIXCHILDPROCESS_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_PLATFORM_IS_POSIX && VMIME_HAVE_FILESYSTEM_FEATURES
+
+
+#include "vmime/utility/childProcess.hpp"
+
+#include <sys/types.h>
+#include <signal.h>
+
+
+namespace vmime {
+namespace platforms {
+namespace posix {
+
+
+class posixChildProcess : public utility::childProcess {
+
+public:
+
+ posixChildProcess(const utility::file::path& path);
+ ~posixChildProcess();
+
+ void start(const std::vector <string>& args, const int flags = 0);
+
+ shared_ptr <utility::outputStream> getStdIn();
+ shared_ptr <utility::inputStream> getStdOut();
+
+ void waitForFinish();
+
+private:
+
+ utility::file::path m_processPath;
+ bool m_started;
+
+ shared_ptr <utility::outputStream> m_stdIn;
+ shared_ptr <utility::inputStream> m_stdOut;
+
+ sigset_t m_oldProcMask;
+ pid_t m_pid;
+ int m_pipe[2];
+
+ std::vector <string> m_argVector;
+ const char** m_argArray;
+};
+
+
+class posixChildProcessFactory : public utility::childProcessFactory {
+
+public:
+
+ shared_ptr <utility::childProcess> create(const utility::file::path& path) const;
+};
+
+
+} // posix
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_POSIX && VMIME_HAVE_FILESYSTEM_FEATURES
+
+#endif // VMIME_PLATFORMS_POSIX_POSIXCHILDPROCESS_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/platforms/posix/posixCriticalSection.cpp b/vmime-master/src/vmime/platforms/posix/posixCriticalSection.cpp
new file mode 100644
index 0000000..2f25cfa
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/posix/posixCriticalSection.cpp
@@ -0,0 +1,67 @@
+//
+// 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_PLATFORM_IS_POSIX
+
+
+#include "vmime/platforms/posix/posixCriticalSection.hpp"
+
+
+namespace vmime {
+namespace platforms {
+namespace posix {
+
+
+posixCriticalSection::posixCriticalSection() {
+
+ pthread_mutex_init(&m_cs, NULL);
+}
+
+
+posixCriticalSection::~posixCriticalSection() {
+
+ pthread_mutex_destroy(&m_cs);
+}
+
+
+void posixCriticalSection::lock() {
+
+ pthread_mutex_lock(&m_cs);
+}
+
+
+void posixCriticalSection::unlock() {
+
+ pthread_mutex_unlock(&m_cs);
+}
+
+
+} // posix
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_POSIX
diff --git a/vmime-master/src/vmime/platforms/posix/posixCriticalSection.hpp b/vmime-master/src/vmime/platforms/posix/posixCriticalSection.hpp
new file mode 100644
index 0000000..9a4bed5
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/posix/posixCriticalSection.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_PLATFORMS_POSIX_CRITICALSECTION_HPP_INCLUDED
+#define VMIME_PLATFORMS_POSIX_CRITICALSECTION_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_PLATFORM_IS_POSIX
+
+
+#include "vmime/utility/sync/criticalSection.hpp"
+
+
+#include <unistd.h>
+#include <pthread.h>
+
+
+namespace vmime {
+namespace platforms {
+namespace posix {
+
+
+class posixCriticalSection : public utility::sync::criticalSection {
+
+public:
+
+ posixCriticalSection();
+ ~posixCriticalSection();
+
+ void lock();
+ void unlock();
+
+private:
+
+ pthread_mutex_t m_cs;
+};
+
+
+} // posix
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_POSIX
+
+#endif // VMIME_PLATFORMS_POSIX_CRITICALSECTION_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/platforms/posix/posixFile.cpp b/vmime-master/src/vmime/platforms/posix/posixFile.cpp
new file mode 100644
index 0000000..9773b3a
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/posix/posixFile.cpp
@@ -0,0 +1,715 @@
+//
+// 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_PLATFORM_IS_POSIX && VMIME_HAVE_FILESYSTEM_FEATURES
+
+
+#include "vmime/platforms/posix/posixFile.hpp"
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <dirent.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "vmime/exception.hpp"
+
+
+namespace vmime {
+namespace platforms {
+namespace posix {
+
+
+//
+// posixFileIterator
+//
+
+posixFileIterator::posixFileIterator(
+ const vmime::utility::file::path& path,
+ const vmime::string& nativePath
+)
+ : m_path(path),
+ m_nativePath(nativePath),
+ m_dir(NULL),
+ m_dirEntry(NULL) {
+
+ if ((m_dir = ::opendir(m_nativePath.c_str())) == NULL) {
+ posixFileSystemFactory::reportError(path, errno);
+ }
+
+ getNextElement();
+}
+
+
+posixFileIterator::~posixFileIterator() {
+
+ if (m_dir) {
+
+ if (::closedir(m_dir) == -1) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+ }
+}
+
+
+bool posixFileIterator::hasMoreElements() const {
+
+ return (m_dirEntry != NULL);
+}
+
+
+shared_ptr <vmime::utility::file> posixFileIterator::nextElement() {
+
+ shared_ptr <posixFile> file = make_shared <posixFile>(
+ m_path / vmime::utility::file::path::component(m_dirEntry->d_name)
+ );
+
+ getNextElement();
+
+ return file;
+}
+
+
+void posixFileIterator::getNextElement() {
+
+ errno = 0;
+
+ while ((m_dirEntry = ::readdir(m_dir)) != NULL) {
+
+ const char* name = m_dirEntry->d_name;
+ const size_t len = ::strlen(name);
+
+ if (!(len == 1 && name[0] == '.') &&
+ !(len == 2 && name[0] == '.' && name[1] == '.')) {
+
+ break;
+ }
+ }
+
+ if (errno) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+}
+
+
+
+//
+// posixFileWriterOutputStream
+//
+
+posixFileWriterOutputStream::posixFileWriterOutputStream(
+ const vmime::utility::file::path& path,
+ const int fd
+)
+ : m_path(path),
+ m_fd(fd) {
+
+}
+
+
+posixFileWriterOutputStream::~posixFileWriterOutputStream() {
+
+ ::close(m_fd);
+}
+
+
+void posixFileWriterOutputStream::writeImpl(
+ const byte_t* const data,
+ const size_t count
+) {
+
+ const byte_t* array = data;
+ size_t size = count;
+
+ while (1) {
+
+ ssize_t ret = ::write(m_fd, array, size);
+
+ if (ret == -1) {
+
+ if (errno == EINTR) {
+ continue;
+ }
+
+ posixFileSystemFactory::reportError(m_path, errno);
+ break;
+
+ } else if (size_t(ret) < size) {
+
+ array += ret;
+ size -= ret;
+ }
+
+ break;
+ }
+}
+
+
+void posixFileWriterOutputStream::flush() {
+
+ if (::fsync(m_fd) == -1) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+}
+
+
+
+//
+// posixFileReaderInputStream
+//
+
+posixFileReaderInputStream::posixFileReaderInputStream(
+ const vmime::utility::file::path& path,
+ const int fd
+)
+ : m_path(path),
+ m_fd(fd),
+ m_eof(false) {
+
+}
+
+
+posixFileReaderInputStream::~posixFileReaderInputStream() {
+
+ if (::close(m_fd) == -1) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+}
+
+
+bool posixFileReaderInputStream::eof() const {
+
+ return m_eof;
+}
+
+
+void posixFileReaderInputStream::reset() {
+
+ if (::lseek(m_fd, 0, SEEK_SET) == off_t(-1)) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+
+ m_eof = false;
+}
+
+
+size_t posixFileReaderInputStream::read(
+ byte_t* const data,
+ const size_t count
+) {
+
+ ssize_t c = 0;
+
+ if ((c = ::read(m_fd, data, count)) == -1) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+
+ if (c == 0 && count != 0) {
+ m_eof = true;
+ }
+
+ return static_cast <size_t>(c);
+}
+
+
+size_t posixFileReaderInputStream::skip(const size_t count) {
+
+ const off_t curPos = ::lseek(m_fd, 0, SEEK_CUR);
+
+ if (curPos == off_t(-1)) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+
+ const off_t newPos = ::lseek(m_fd, count, SEEK_CUR);
+
+ if (newPos == off_t(-1)) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+
+ return static_cast <size_t>(newPos - curPos);
+}
+
+
+size_t posixFileReaderInputStream::getPosition() const {
+
+ const off_t curPos = ::lseek(m_fd, 0, SEEK_CUR);
+
+ if (curPos == off_t(-1)) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+
+ return static_cast <size_t>(curPos);
+}
+
+
+void posixFileReaderInputStream::seek(const size_t pos) {
+
+ const off_t newPos = ::lseek(m_fd, pos, SEEK_SET);
+
+ if (newPos == off_t(-1)) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+}
+
+
+
+//
+// posixFileWriter
+//
+
+posixFileWriter::posixFileWriter(
+ const vmime::utility::file::path& path,
+ const vmime::string& nativePath
+)
+ : m_path(path),
+ m_nativePath(nativePath) {
+
+}
+
+
+shared_ptr <vmime::utility::outputStream> posixFileWriter::getOutputStream() {
+
+ int fd = 0;
+
+ if ((fd = ::open(m_nativePath.c_str(), O_WRONLY, 0660)) == -1) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+
+ return make_shared <posixFileWriterOutputStream>(m_path, fd);
+}
+
+
+
+//
+// posixFileReader
+//
+
+posixFileReader::posixFileReader(
+ const vmime::utility::file::path& path,
+ const vmime::string& nativePath
+)
+ : m_path(path),
+ m_nativePath(nativePath) {
+
+}
+
+
+shared_ptr <vmime::utility::inputStream> posixFileReader::getInputStream() {
+
+ int fd = 0;
+
+ if ((fd = ::open(m_nativePath.c_str(), O_RDONLY, 0640)) == -1) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+
+ return make_shared <posixFileReaderInputStream>(m_path, fd);
+}
+
+
+
+//
+// posixFile
+//
+
+posixFile::posixFile(const vmime::utility::file::path& path)
+ : m_path(path),
+ m_nativePath(posixFileSystemFactory::pathToStringImpl(path)) {
+
+}
+
+
+void posixFile::createFile() {
+
+ int fd = 0;
+
+ if ((fd = ::open(m_nativePath.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0660)) == -1) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+
+ if (::fsync(fd) == -1) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+
+ if (::close(fd) == -1) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+}
+
+
+void posixFile::createDirectory(const bool createAll) {
+
+ createDirectoryImpl(m_path, m_path, createAll);
+}
+
+
+bool posixFile::isFile() const {
+
+ struct stat buf;
+
+ if (::stat(m_nativePath.c_str(), &buf) == -1) {
+
+ if (errno == ENOENT) {
+ return false;
+ }
+
+ posixFileSystemFactory::reportError(m_path, errno);
+ return false;
+ }
+
+ return S_ISREG(buf.st_mode);
+}
+
+
+bool posixFile::isDirectory() const {
+
+ struct stat buf;
+
+ if (::stat(m_nativePath.c_str(), &buf) == -1) {
+
+ if (errno == ENOENT) {
+ return false;
+ }
+
+ posixFileSystemFactory::reportError(m_path, errno);
+ return false;
+ }
+
+ return S_ISDIR(buf.st_mode);
+}
+
+
+bool posixFile::canRead() const {
+
+ struct stat buf;
+
+ if (::stat(m_nativePath.c_str(), &buf) == -1) {
+
+ if (errno == ENOENT) {
+ return false;
+ }
+
+ posixFileSystemFactory::reportError(m_path, errno);
+ return false;
+ }
+
+ return S_ISREG(buf.st_mode)
+ && ::access(m_nativePath.c_str(), R_OK | F_OK) == 0;
+}
+
+
+bool posixFile::canWrite() const {
+
+ struct stat buf;
+
+ if (::stat(m_nativePath.c_str(), &buf) == -1) {
+
+ if (errno == ENOENT) {
+ return false;
+ }
+
+ posixFileSystemFactory::reportError(m_path, errno);
+ return false;
+ }
+
+ return S_ISREG(buf.st_mode)
+ && ::access(m_nativePath.c_str(), W_OK | F_OK) == 0;
+}
+
+
+posixFile::length_type posixFile::getLength() {
+
+ struct stat buf;
+
+ if (::stat(m_nativePath.c_str(), &buf) == -1) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+
+ return static_cast <length_type>(buf.st_size);
+}
+
+
+const posixFile::path& posixFile::getFullPath() const {
+
+ return m_path;
+}
+
+
+bool posixFile::exists() const {
+
+ struct stat buf;
+ return ::stat(m_nativePath.c_str(), &buf) == 0;
+}
+
+
+shared_ptr <vmime::utility::file> posixFile::getParent() const {
+
+ if (m_path.isEmpty()) {
+ return null;
+ } else {
+ return make_shared <posixFile>(m_path.getParent());
+ }
+}
+
+
+void posixFile::rename(const path& newName) {
+
+ const vmime::string newNativePath = posixFileSystemFactory::pathToStringImpl(newName);
+
+ posixFile dest(newName);
+
+ if (isDirectory()) {
+ dest.createDirectory();
+ } else {
+ dest.createFile();
+ }
+
+ if (::rename(m_nativePath.c_str(), newNativePath.c_str()) == -1) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+
+ m_path = newName;
+ m_nativePath = newNativePath;
+}
+
+
+void posixFile::remove() {
+
+ struct stat buf;
+
+ if (::stat(m_nativePath.c_str(), &buf) == -1) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+
+ if (S_ISDIR(buf.st_mode)) {
+
+ if (::rmdir(m_nativePath.c_str()) == -1) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+
+ } else if (S_ISREG(buf.st_mode)) {
+
+ if (::unlink(m_nativePath.c_str()) == -1) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+ }
+}
+
+
+shared_ptr <vmime::utility::fileWriter> posixFile::getFileWriter() {
+
+ return make_shared <posixFileWriter>(m_path, m_nativePath);
+}
+
+
+shared_ptr <vmime::utility::fileReader> posixFile::getFileReader() {
+
+ return make_shared <posixFileReader>(m_path, m_nativePath);
+}
+
+
+shared_ptr <vmime::utility::fileIterator> posixFile::getFiles() const {
+
+ if (!isDirectory()) {
+ throw vmime::exceptions::not_a_directory(m_path);
+ }
+
+ return make_shared <posixFileIterator>(m_path, m_nativePath);
+}
+
+
+void posixFile::createDirectoryImpl(
+ const vmime::utility::file::path& fullPath,
+ const vmime::utility::file::path& path,
+ const bool recursive
+) {
+
+ const vmime::string nativePath = posixFileSystemFactory::pathToStringImpl(path);
+ struct stat buf;
+
+ if (::stat(nativePath.c_str(), &buf) == 0 && S_ISDIR(buf.st_mode)) {
+ return;
+ }
+
+ if (!path.isEmpty() && recursive) {
+ createDirectoryImpl(fullPath, path.getParent(), true);
+ }
+
+ if (::mkdir(nativePath.c_str(), 0750) == -1) {
+ posixFileSystemFactory::reportError(fullPath, errno);
+ }
+}
+
+
+
+//
+// posixFileSystemFactory
+//
+
+shared_ptr <vmime::utility::file> posixFileSystemFactory::create(
+ const vmime::utility::file::path& path
+) const {
+
+ return make_shared <posixFile>(path);
+}
+
+
+const vmime::utility::file::path posixFileSystemFactory::stringToPath(
+ const vmime::string& str
+) const {
+
+ return stringToPathImpl(str);
+}
+
+
+const vmime::string posixFileSystemFactory::pathToString(
+ const vmime::utility::file::path& path
+) const {
+
+ return pathToStringImpl(path);
+}
+
+
+const vmime::utility::file::path posixFileSystemFactory::stringToPathImpl(
+ const vmime::string& str
+) {
+
+ vmime::size_t offset = 0;
+ vmime::size_t prev = 0;
+
+ vmime::utility::file::path path;
+
+ while ((offset = str.find_first_of("/", offset)) != vmime::string::npos) {
+
+ if (offset != prev) {
+
+ path.appendComponent(
+ vmime::utility::file::path::component(
+ vmime::string(str.begin() + prev, str.begin() + offset)
+ )
+ );
+ }
+
+ prev = offset + 1;
+ offset++;
+ }
+
+ if (prev < str.length()) {
+
+ path.appendComponent(
+ vmime::utility::file::path::component(
+ vmime::string(str.begin() + prev, str.end())
+ )
+ );
+ }
+
+ return path;
+}
+
+
+const vmime::string posixFileSystemFactory::pathToStringImpl(const vmime::utility::file::path& path) {
+
+ vmime::string native = "/";
+
+ for (size_t i = 0 ; i < path.getSize() ; ++i) {
+
+ if (i > 0) {
+ native += "/";
+ }
+
+ native += path[i].getBuffer();
+ }
+
+ return native;
+}
+
+
+bool posixFileSystemFactory::isValidPathComponent(
+ const vmime::utility::file::path::component& comp
+) const {
+
+ return comp.getBuffer().find_first_of("/*") == vmime::string::npos;
+}
+
+
+bool posixFileSystemFactory::isValidPath(const vmime::utility::file::path& path) const {
+
+ for (size_t i = 0 ; i < path.getSize() ; ++i) {
+
+ if (!isValidPathComponent(path[i])) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+void posixFileSystemFactory::reportError(const vmime::utility::path& path, const int err) {
+
+ vmime::string desc;
+
+ switch (err) {
+ case EEXIST: desc = "EEXIST: file already exists."; break;
+ case EISDIR: desc = "EISDIR: path refers to a directory."; break;
+ case EACCES: desc = "EACCES: permission denied"; break;
+ case ENAMETOOLONG: desc = "ENAMETOOLONG: path too long."; break;
+ case ENOENT: desc = "ENOENT: a directory in the path does not exist."; break;
+ case ENOTDIR: desc = "ENOTDIR: path is not a directory."; break;
+ case EROFS: desc = "EROFS: read-only filesystem."; break;
+ case ELOOP: desc = "ELOOP: too many symbolic links."; break;
+ case ENOSPC: desc = "ENOSPC: no space left on device."; break;
+ case ENOMEM: desc = "ENOMEM: insufficient kernel memory."; break;
+ case EMFILE: desc = "ENFILE: limit on number of files open by the process has been reached."; break;
+ case ENFILE: desc = "ENFILE: limit on number of files open on the system has been reached."; break;
+#ifndef AIX
+ case ENOTEMPTY: desc = "ENOTEMPTY: directory is not empty."; break;
+#endif
+
+ default:
+
+ std::ostringstream oss;
+ oss << ::strerror(err) << ".";
+
+ desc = oss.str();
+ break;
+ }
+
+ throw vmime::exceptions::filesystem_exception(desc, path);
+}
+
+
+} // posix
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_POSIX && VMIME_HAVE_FILESYSTEM_FEATURES
diff --git a/vmime-master/src/vmime/platforms/posix/posixFile.hpp b/vmime-master/src/vmime/platforms/posix/posixFile.hpp
new file mode 100644
index 0000000..d1fda9e
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/posix/posixFile.hpp
@@ -0,0 +1,224 @@
+//
+// 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_PLATFORMS_POSIX_FILE_HPP_INCLUDED
+#define VMIME_PLATFORMS_POSIX_FILE_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_PLATFORM_IS_POSIX && VMIME_HAVE_FILESYSTEM_FEATURES
+
+
+#include "vmime/utility/file.hpp"
+#include "vmime/utility/seekableInputStream.hpp"
+
+
+#include <dirent.h>
+
+
+namespace vmime {
+namespace platforms {
+namespace posix {
+
+
+class posixFileWriterOutputStream : public vmime::utility::outputStream {
+
+public:
+
+ posixFileWriterOutputStream(const vmime::utility::file::path& path, const int fd);
+ ~posixFileWriterOutputStream();
+
+ void flush();
+
+protected:
+
+ void writeImpl(const byte_t* const data, const size_t count);
+
+private:
+
+ const vmime::utility::file::path m_path;
+ const int m_fd;
+};
+
+
+
+class posixFileReaderInputStream : public vmime::utility::seekableInputStream {
+
+public:
+
+ posixFileReaderInputStream(const vmime::utility::file::path& path, const int fd);
+ ~posixFileReaderInputStream();
+
+ bool eof() const;
+
+ void reset();
+
+ size_t read(byte_t* const data, const size_t count);
+
+ size_t skip(const size_t count);
+
+ size_t getPosition() const;
+ void seek(const size_t pos);
+
+private:
+
+ const vmime::utility::file::path m_path;
+ const int m_fd;
+
+ bool m_eof;
+};
+
+
+
+class posixFileWriter : public vmime::utility::fileWriter {
+
+public:
+
+ posixFileWriter(const vmime::utility::file::path& path, const vmime::string& nativePath);
+
+ shared_ptr <vmime::utility::outputStream> getOutputStream();
+
+private:
+
+ vmime::utility::file::path m_path;
+ vmime::string m_nativePath;
+};
+
+
+
+class posixFileReader : public vmime::utility::fileReader {
+
+public:
+
+ posixFileReader(const vmime::utility::file::path& path, const vmime::string& nativePath);
+
+ shared_ptr <vmime::utility::inputStream> getInputStream();
+
+private:
+
+ vmime::utility::file::path m_path;
+ vmime::string m_nativePath;
+};
+
+
+
+class posixFileIterator : public vmime::utility::fileIterator {
+
+public:
+
+ posixFileIterator(const vmime::utility::file::path& path, const vmime::string& nativePath);
+ ~posixFileIterator();
+
+ bool hasMoreElements() const;
+ shared_ptr <vmime::utility::file> nextElement();
+
+private:
+
+ void getNextElement();
+
+ vmime::utility::file::path m_path;
+ vmime::string m_nativePath;
+
+ DIR* m_dir;
+ struct dirent* m_dirEntry;
+};
+
+
+
+class posixFile : public vmime::utility::file {
+
+public:
+
+ posixFile(const vmime::utility::file::path& path);
+
+ void createFile();
+ void createDirectory(const bool createAll = false);
+
+ bool isFile() const;
+ bool isDirectory() const;
+
+ bool canRead() const;
+ bool canWrite() const;
+
+ length_type getLength();
+
+ const path& getFullPath() const;
+
+ bool exists() const;
+
+ shared_ptr <vmime::utility::file> getParent() const;
+
+ void rename(const path& newName);
+
+ void remove();
+
+ shared_ptr <vmime::utility::fileWriter> getFileWriter();
+ shared_ptr <vmime::utility::fileReader> getFileReader();
+
+ shared_ptr <vmime::utility::fileIterator> getFiles() const;
+
+private:
+
+ static void createDirectoryImpl(
+ const vmime::utility::file::path& fullPath,
+ const vmime::utility::file::path& path,
+ const bool recursive = false
+ );
+
+private:
+
+ vmime::utility::file::path m_path;
+ vmime::string m_nativePath;
+};
+
+
+
+class posixFileSystemFactory : public vmime::utility::fileSystemFactory {
+
+public:
+
+ shared_ptr <vmime::utility::file> create(const vmime::utility::file::path& path) const;
+
+ const vmime::utility::file::path stringToPath(const vmime::string& str) const;
+ const vmime::string pathToString(const vmime::utility::file::path& path) const;
+
+ static const vmime::utility::file::path stringToPathImpl(const vmime::string& str);
+ static const vmime::string pathToStringImpl(const vmime::utility::file::path& path);
+
+ bool isValidPathComponent(const vmime::utility::file::path::component& comp) const;
+ bool isValidPath(const vmime::utility::file::path& path) const;
+
+ static void reportError(const vmime::utility::path& path, const int err);
+};
+
+
+} // posix
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_POSIX && VMIME_HAVE_FILESYSTEM_FEATURES
+
+#endif // VMIME_PLATFORMS_POSIX_FILE_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/platforms/posix/posixHandler.cpp b/vmime-master/src/vmime/platforms/posix/posixHandler.cpp
new file mode 100644
index 0000000..eecdbea
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/posix/posixHandler.cpp
@@ -0,0 +1,292 @@
+//
+// 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_PLATFORM_IS_POSIX
+
+
+#include "vmime/platforms/posix/posixHandler.hpp"
+
+#include "vmime/platforms/posix/posixCriticalSection.hpp"
+
+#include "vmime/utility/stringUtils.hpp"
+
+#include <time.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <locale.h>
+#include <langinfo.h>
+#include <errno.h>
+#include <limits.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+
+#if VMIME_HAVE_SYSCALL
+# include <sys/syscall.h>
+#endif
+
+#include <netdb.h>
+
+#include <string.h>
+#include <cassert>
+#include <cstdlib>
+
+
+/*
+#ifdef _POSIX_PRIORITY_SCHEDULING
+ #include <sched.h>
+#endif // _POSIX_PRIORITY_SCHEDULING
+*/
+
+
+namespace vmime {
+namespace platforms {
+namespace posix {
+
+
+posixHandler::posixHandler() {
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+ m_socketFactory = make_shared <posixSocketFactory>();
+#endif
+#if VMIME_HAVE_FILESYSTEM_FEATURES
+ m_fileSysFactory = make_shared <posixFileSystemFactory>();
+ m_childProcFactory = make_shared <posixChildProcessFactory>();
+#endif
+
+}
+
+
+posixHandler::~posixHandler() {
+
+}
+
+
+unsigned long posixHandler::getUnixTime() const {
+
+ return static_cast <unsigned long>(::time(NULL));
+}
+
+
+const vmime::datetime posixHandler::getCurrentLocalTime() const {
+
+ const time_t t(::time(NULL));
+
+ // Get the local time
+#if VMIME_HAVE_LOCALTIME_R
+ tm local;
+ ::localtime_r(&t, &local);
+#else
+ tm local = *::localtime(&t); // WARNING: this is not thread-safe!
+#endif
+
+ // Get the UTC time
+#if VMIME_HAVE_GMTIME_R
+ tm gmt;
+ ::gmtime_r(&t, &gmt);
+#else
+ tm gmt = *::gmtime(&t); // WARNING: this is not thread-safe!
+#endif
+
+ // "A negative value for tm_isdst causes mktime() to attempt
+ // to determine whether Daylight Saving Time is in effect
+ // for the specified time."
+ local.tm_isdst = -1;
+ gmt.tm_isdst = -1;
+
+ // Calculate the difference (in seconds)
+ const time_t diff = ::mktime(&local) - ::mktime(&gmt);
+
+ // Return the date
+ return vmime::datetime(
+ local.tm_year + 1900, local.tm_mon + 1, local.tm_mday,
+ local.tm_hour, local.tm_min, local.tm_sec, static_cast <int>(diff / 60)
+ );
+}
+
+
+const vmime::charset posixHandler::getLocalCharset() const {
+
+ // Note: nl_langinfo() might be affected by calls to setlocale()
+ // in a multithread environment. There is not MT-safe alternative
+ // to nl_langinfo().
+ auto codeset = ::nl_langinfo(CODESET);
+
+ if (codeset) {
+ return vmime::charset(codeset);
+ }
+
+ return vmime::charset();
+}
+
+
+static inline bool isAcceptableHostname(const vmime::string& str) {
+
+ // At least, try to find something better than "localhost"
+ if (utility::stringUtils::isStringEqualNoCase(str, "localhost", 9) ||
+ utility::stringUtils::isStringEqualNoCase(str, "localhost.localdomain", 21)) {
+
+ return false;
+ }
+
+ // Anything else will be OK, as long as it is a valid hostname
+ return utility::stringUtils::isValidHostname(str);
+}
+
+
+const vmime::string posixHandler::getHostName() const {
+ char hostname[256];
+
+ ::gethostname(hostname, sizeof(hostname));
+ hostname[sizeof(hostname)-1] = '\0';
+
+ // Try to get official canonical name of this host
+ struct addrinfo hints;
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family = AF_UNSPEC; // either IPV4 or IPV6
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_CANONNAME;
+
+ struct addrinfo* info;
+
+ if (getaddrinfo(hostname, "http", &hints, &info) == 0) {
+ // First, try to get a Fully-Qualified Domain Name (FQDN)
+ for (struct addrinfo* p = info ; p != NULL ; p = p->ai_next) {
+
+ if (p->ai_canonname) {
+
+ const string hn(p->ai_canonname);
+
+ if (utility::stringUtils::isValidFQDN(hn)) {
+ freeaddrinfo(info);
+ return hn;
+ }
+ }
+ }
+
+ // Then, try to find an acceptable host name
+ for (struct addrinfo* p = info ; p != NULL ; p = p->ai_next) {
+
+ if (p->ai_canonname) {
+
+ const string hn(p->ai_canonname);
+
+ if (isAcceptableHostname(hn)) {
+ freeaddrinfo(info);
+ return hn;
+ }
+ }
+ }
+
+ freeaddrinfo(info);
+ }
+
+ if (::strlen(hostname) == 0 || !isAcceptableHostname(hostname)) {
+ ::strcpy(hostname, "localhost.localdomain");
+ }
+
+ return hostname;
+}
+
+
+unsigned int posixHandler::getProcessId() const {
+
+ return ::getpid();
+}
+
+
+unsigned int posixHandler::getThreadId() const {
+
+#if VMIME_HAVE_GETTID
+ return static_cast <unsigned int>(::gettid());
+#elif VMIME_HAVE_SYSCALL && VMIME_HAVE_SYSCALL_GETTID
+ return static_cast <unsigned int>(::syscall(SYS_gettid));
+#elif VMIME_HAVE_GETTHRID // OpenBSD
+ return static_cast <unsigned int>(::getthrid());
+#else
+ #error We have no implementation of getThreadId() for this platform!
+#endif
+
+}
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+shared_ptr <vmime::net::socketFactory> posixHandler::getSocketFactory() {
+
+ return m_socketFactory;
+}
+
+#endif
+
+
+#if VMIME_HAVE_FILESYSTEM_FEATURES
+
+shared_ptr <vmime::utility::fileSystemFactory> posixHandler::getFileSystemFactory() {
+
+ return m_fileSysFactory;
+}
+
+
+shared_ptr <vmime::utility::childProcessFactory> posixHandler::getChildProcessFactory() {
+
+ return m_childProcFactory;
+}
+
+#endif
+
+
+void posixHandler::generateRandomBytes(unsigned char* buffer, const unsigned int count) {
+
+ int fd = open("/dev/urandom", O_RDONLY);
+
+ if (fd != -1) {
+
+ read(fd, buffer, count);
+ close(fd);
+
+ } else { // fallback
+
+ for (unsigned int i = 0 ; i < count ; ++i) {
+ buffer[i] = static_cast <unsigned char>(rand() % 255);
+ }
+ }
+}
+
+
+shared_ptr <utility::sync::criticalSection> posixHandler::createCriticalSection() {
+
+ return make_shared <posixCriticalSection>();
+}
+
+
+} // posix
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_POSIX
diff --git a/vmime-master/src/vmime/platforms/posix/posixHandler.hpp b/vmime-master/src/vmime/platforms/posix/posixHandler.hpp
new file mode 100644
index 0000000..30417f1
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/posix/posixHandler.hpp
@@ -0,0 +1,103 @@
+//
+// 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_PLATFORMS_POSIX_HANDLER_HPP_INCLUDED
+#define VMIME_PLATFORMS_POSIX_HANDLER_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_PLATFORM_IS_POSIX
+
+
+#include "vmime/platform.hpp"
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+ #include "vmime/platforms/posix/posixSocket.hpp"
+#endif
+
+#if VMIME_HAVE_FILESYSTEM_FEATURES
+ #include "vmime/platforms/posix/posixFile.hpp"
+ #include "vmime/platforms/posix/posixChildProcess.hpp"
+#endif
+
+
+namespace vmime {
+namespace platforms {
+namespace posix {
+
+
+class VMIME_EXPORT posixHandler : public vmime::platform::handler {
+
+public:
+
+ posixHandler();
+ ~posixHandler();
+
+ unsigned long getUnixTime() const;
+
+ const vmime::datetime getCurrentLocalTime() const;
+
+ const vmime::charset getLocalCharset() const;
+
+ const vmime::string getHostName() const;
+
+ unsigned int getProcessId() const;
+ unsigned int getThreadId() const;
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+ shared_ptr <vmime::net::socketFactory> getSocketFactory();
+#endif
+
+#if VMIME_HAVE_FILESYSTEM_FEATURES
+ shared_ptr <vmime::utility::fileSystemFactory> getFileSystemFactory();
+
+ shared_ptr <vmime::utility::childProcessFactory> getChildProcessFactory();
+#endif
+
+ void generateRandomBytes(unsigned char* buffer, const unsigned int count);
+
+ shared_ptr <utility::sync::criticalSection> createCriticalSection();
+
+private:
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+ shared_ptr <posixSocketFactory> m_socketFactory;
+#endif
+
+#if VMIME_HAVE_FILESYSTEM_FEATURES
+ shared_ptr <posixFileSystemFactory> m_fileSysFactory;
+ shared_ptr <posixChildProcessFactory> m_childProcFactory;
+#endif
+};
+
+
+} // posix
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_POSIX
+
+#endif // VMIME_PLATFORMS_POSIX_HANDLER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/platforms/posix/posixSocket.cpp b/vmime-master/src/vmime/platforms/posix/posixSocket.cpp
new file mode 100644
index 0000000..aec6a83
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/posix/posixSocket.cpp
@@ -0,0 +1,969 @@
+//
+// 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_PLATFORM_IS_POSIX && VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/platforms/posix/posixSocket.hpp"
+#include "vmime/platforms/posix/posixHandler.hpp"
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE // for getaddrinfo_a() in <netdb.h>
+#endif
+
+#include <unistd.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <poll.h>
+
+#include "vmime/utility/stringUtils.hpp"
+
+#include "vmime/exception.hpp"
+
+
+#if defined(EWOULDBLOCK)
+# define IS_EAGAIN(x) ((x) == EAGAIN || (x) == EWOULDBLOCK || (x) == EINTR || (x) == EINPROGRESS)
+#else
+# define IS_EAGAIN(x) ((x) == EAGAIN || (x) == EINTR || (x) == EINPROGRESS)
+#endif
+
+
+// Workaround for detection of strerror_r variants
+#if VMIME_HAVE_STRERROR_R
+
+namespace {
+
+char* vmime_strerror_r_result(int /* res */, char* buf) {
+
+ // XSI-compliant prototype:
+ // int strerror_r(int errnum, char *buf, size_t buflen);
+ return buf;
+}
+
+char* vmime_strerror_r_result(char* res, char* /* buf */) {
+
+ // GNU-specific prototype:
+ // char *strerror_r(int errnum, char *buf, size_t buflen);
+ return res;
+}
+
+}
+
+#endif // VMIME_HAVE_STRERROR_R
+
+
+
+namespace vmime {
+namespace platforms {
+namespace posix {
+
+
+//
+// posixSocket
+//
+
+posixSocket::posixSocket(shared_ptr <vmime::net::timeoutHandler> th)
+ : m_timeoutHandler(th),
+ m_desc(-1),
+ m_status(0) {
+
+}
+
+
+posixSocket::~posixSocket() {
+
+ if (m_desc != -1) {
+ ::close(m_desc);
+ }
+}
+
+
+void posixSocket::connect(const vmime::string& address, const vmime::port_t port) {
+
+ // Close current connection, if any
+ if (m_desc != -1) {
+ ::close(m_desc);
+ m_desc = -1;
+ }
+
+ if (m_tracer) {
+
+ std::ostringstream trace;
+ trace << "Connecting to " << address << ", port " << port;
+
+ m_tracer->traceSend(trace.str());
+ }
+
+#if VMIME_HAVE_GETADDRINFO // use thread-safe and IPv6-aware getaddrinfo() if available
+
+ // Resolve address, if needed
+ m_serverAddress = address;
+
+ struct ::addrinfo* addrInfo = NULL; // resolved addresses
+ resolve(&addrInfo, address, port);
+
+ // Connect to host
+ int sock = -1;
+ int connectErrno = 0;
+
+ if (m_timeoutHandler != NULL) {
+ m_timeoutHandler->resetTimeOut();
+ }
+
+ for (struct ::addrinfo* curAddrInfo = addrInfo ;
+ sock == -1 && curAddrInfo != NULL ;
+ curAddrInfo = curAddrInfo->ai_next, connectErrno = ETIMEDOUT) {
+
+ if (curAddrInfo->ai_family != AF_INET && curAddrInfo->ai_family != AF_INET6) {
+ continue;
+ }
+
+ sock = ::socket(curAddrInfo->ai_family, curAddrInfo->ai_socktype, curAddrInfo->ai_protocol);
+
+ if (sock < 0) {
+ connectErrno = errno;
+ continue; // try next
+ }
+
+#if VMIME_HAVE_SO_KEEPALIVE
+
+ // Enable TCP Keepalive
+ int keepAlive_optval = 1;
+ socklen_t keepAlive_optlen = sizeof(keepAlive_optval);
+
+ ::setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &keepAlive_optval, keepAlive_optlen);
+
+#endif // VMIME_HAVE_SO_KEEPALIVE
+
+#if VMIME_HAVE_SO_NOSIGPIPE
+
+ // Return EPIPE instead of generating SIGPIPE
+ int nosigpipe_optval = 1;
+ socklen_t nosigpipe_optlen = sizeof(nosigpipe_optval);
+
+ ::setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, &nosigpipe_optval, nosigpipe_optlen);
+
+#endif // VMIME_HAVE_SO_NOSIGPIPE
+
+
+ if (m_timeoutHandler) {
+
+ ::fcntl(sock, F_SETFL, ::fcntl(sock, F_GETFL) | O_NONBLOCK);
+
+ if (::connect(sock, curAddrInfo->ai_addr, curAddrInfo->ai_addrlen) < 0) {
+
+ switch (errno) {
+
+ case 0:
+ case EINPROGRESS:
+ case EINTR:
+#if defined(EAGAIN)
+ case EAGAIN:
+#endif // EAGAIN
+#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
+ case EWOULDBLOCK:
+#endif // EWOULDBLOCK
+
+ // Connection in progress
+ break;
+
+ default:
+
+ connectErrno = errno;
+ ::close(sock);
+ sock = -1;
+ continue; // try next
+ }
+
+ // Wait for socket to be connected.
+ bool connected = false;
+
+ const int pollTimeout = 1000; // poll() timeout (ms)
+ const int tryNextTimeout = 5000; // maximum time before trying next (ms)
+
+ timeval startTime = { 0, 0 };
+ gettimeofday(&startTime, /* timezone */ NULL);
+
+ do {
+
+ pollfd fds[1];
+ fds[0].fd = sock;
+ fds[0].events = POLLIN | POLLOUT;
+
+ const int ret = ::poll(fds, sizeof(fds) / sizeof(fds[0]), pollTimeout);
+
+ // Success
+ if (ret > 0) {
+
+ if (fds[0].revents & (POLLIN | POLLOUT)) {
+
+ int error = 0;
+ socklen_t len = sizeof(error);
+
+ if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
+
+ connectErrno = errno;
+
+ } else {
+
+ if (error != 0) {
+ connectErrno = error;
+ } else {
+ connected = true;
+ }
+ }
+ }
+
+ break;
+
+ // Error
+ } else if (ret < -1) {
+
+ if (errno != EAGAIN && errno != EINTR) {
+
+ // Cancel connection
+ connectErrno = errno;
+ break;
+ }
+ }
+
+ // Check for timeout
+ if (m_timeoutHandler->isTimeOut()) {
+
+ if (!m_timeoutHandler->handleTimeOut()) {
+
+ // Cancel connection
+ connectErrno = ETIMEDOUT;
+ break;
+
+ } else {
+
+ // Reset timeout and keep waiting for connection
+ m_timeoutHandler->resetTimeOut();
+ }
+
+ } else {
+
+ // Keep waiting for connection
+ }
+
+ timeval curTime = { 0, 0 };
+ gettimeofday(&curTime, /* timezone */ NULL);
+
+ if (curAddrInfo->ai_next != NULL &&
+ curTime.tv_usec - startTime.tv_usec >= tryNextTimeout * 1000) {
+
+ connectErrno = ETIMEDOUT;
+ break;
+ }
+
+ } while (true);
+
+ if (!connected) {
+
+ ::close(sock);
+ sock = -1;
+ continue; // try next
+ }
+
+ break;
+
+ } else {
+
+ // Connection successful
+ break;
+ }
+
+ } else {
+
+ if (::connect(sock, curAddrInfo->ai_addr, curAddrInfo->ai_addrlen) < 0) {
+
+ connectErrno = errno;
+ ::close(sock);
+ sock = -1;
+ continue; // try next
+ }
+ }
+ }
+
+ ::freeaddrinfo(addrInfo);
+
+ if (sock == -1) {
+
+ try {
+ throwSocketError(connectErrno);
+ } catch (exceptions::socket_exception& e) { // wrap
+ throw vmime::exceptions::connection_error("Error while connecting socket.", e);
+ }
+ }
+
+ m_desc = sock;
+
+#else // !VMIME_HAVE_GETADDRINFO
+
+ // Resolve address
+ ::sockaddr_in addr;
+
+ memset(&addr, 0, sizeof(addr));
+
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(static_cast <unsigned short>(port));
+ addr.sin_addr.s_addr = ::inet_addr(address.c_str());
+
+ if (addr.sin_addr.s_addr == static_cast <in_addr_t>(-1)) {
+
+ ::hostent* hostInfo = ::gethostbyname(address.c_str());
+
+ if (hostInfo == NULL) {
+ // Error: cannot resolve address
+ throw vmime::exceptions::connection_error("Cannot resolve address.");
+ }
+
+ ::memcpy(reinterpret_cast <char*>(&addr.sin_addr), hostInfo->h_addr, hostInfo->h_length);
+ }
+
+ m_serverAddress = address;
+
+ // Get a new socket
+ m_desc = ::socket(AF_INET, SOCK_STREAM, 0);
+
+ if (m_desc == -1) {
+
+ try {
+ throwSocketError(errno);
+ } catch (exceptions::socket_exception& e) { // wrap
+ throw vmime::exceptions::connection_error("Error while creating socket.", e);
+ }
+ }
+
+ // Start connection
+ if (::connect(m_desc, reinterpret_cast <sockaddr*>(&addr), sizeof(addr)) == -1) {
+
+ try {
+
+ throwSocketError(errno);
+
+ } catch (exceptions::socket_exception& e) { // wrap
+
+ ::close(m_desc);
+ m_desc = -1;
+
+ // Error
+ throw vmime::exceptions::connection_error("Error while connecting socket.", e);
+ }
+ }
+
+#endif // VMIME_HAVE_GETADDRINFO
+
+ ::fcntl(m_desc, F_SETFL, ::fcntl(m_desc, F_GETFL) | O_NONBLOCK);
+}
+
+
+void posixSocket::resolve(
+ struct ::addrinfo** addrInfo,
+ const vmime::string& address,
+ const vmime::port_t port
+) {
+
+ char portStr[16];
+ snprintf(portStr, sizeof(portStr), "%u", static_cast <unsigned int>(port));
+
+
+ struct ::addrinfo hints;
+ memset(&hints, 0, sizeof(hints));
+
+ hints.ai_flags = AI_CANONNAME | AI_NUMERICSERV;
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+
+#if VMIME_HAVE_GETADDRINFO_A
+
+ // If getaddrinfo_a() is available, use asynchronous resolving to allow
+ // the timeout handler to cancel the operation
+
+ struct ::gaicb gaiRequest;
+ memset(&gaiRequest, 0, sizeof(gaiRequest));
+
+ gaiRequest.ar_name = address.c_str();
+ gaiRequest.ar_service = portStr;
+ gaiRequest.ar_request = &hints;
+
+ struct ::gaicb* gaiRequests = &gaiRequest;
+ int gaiError;
+
+ if ((gaiError = getaddrinfo_a(GAI_NOWAIT, &gaiRequests, 1, NULL)) != 0) {
+
+ throw vmime::exceptions::connection_error(
+ "getaddrinfo_a() failed: " + std::string(gai_strerror(gaiError))
+ );
+ }
+
+ if (m_timeoutHandler) {
+ m_timeoutHandler->resetTimeOut();
+ }
+
+ while (true) {
+
+ struct timespec gaiTimeout;
+ gaiTimeout.tv_sec = 1; // query timeout handler every second
+ gaiTimeout.tv_nsec = 0;
+
+ gaiError = gai_suspend(&gaiRequests, 1, &gaiTimeout);
+
+ if (gaiError == 0 || gaiError == EAI_ALLDONE) {
+
+ const int ret = gai_error(&gaiRequest);
+
+ if (ret != 0) {
+
+ throw vmime::exceptions::connection_error(
+ "getaddrinfo_a() request failed: " + std::string(gai_strerror(ret))
+ );
+
+ } else {
+
+ *addrInfo = gaiRequest.ar_result;
+ break;
+ }
+
+ } else if (gaiError != EAI_AGAIN) {
+
+ if (gaiError == EAI_SYSTEM) {
+
+ const int ret = gai_error(&gaiRequest);
+
+ if (ret != EAI_INPROGRESS && errno != 0) {
+
+ try {
+ throwSocketError(errno);
+ } catch (exceptions::socket_exception& e) { // wrap
+ throw vmime::exceptions::connection_error("Error while connecting socket.", e);
+ }
+ }
+
+ } else {
+
+ throw vmime::exceptions::connection_error(
+ "gai_suspend() failed: " + std::string(gai_strerror(gaiError))
+ );
+ }
+ }
+
+ // Check for timeout
+ if (m_timeoutHandler && m_timeoutHandler->isTimeOut()) {
+
+ if (!m_timeoutHandler->handleTimeOut()) {
+
+ throw exceptions::operation_timed_out();
+
+ } else {
+
+ // Reset timeout and keep waiting for connection
+ m_timeoutHandler->resetTimeOut();
+ }
+ }
+ }
+
+#else // !VMIME_HAVE_GETADDRINFO_A
+
+ if (::getaddrinfo(address.c_str(), portStr, &hints, addrInfo) != 0) {
+
+ // Error: cannot resolve address
+ throw vmime::exceptions::connection_error("Cannot resolve address.");
+ }
+
+#endif // VMIME_HAVE_GETADDRINFO_A
+
+}
+
+
+bool posixSocket::isConnected() const {
+
+ if (m_desc == -1) {
+ return false;
+ }
+
+ char buff;
+
+ return ::recv(m_desc, &buff, 1, MSG_PEEK) != 0;
+}
+
+
+void posixSocket::disconnect() {
+
+ if (m_desc != -1) {
+
+ if (m_tracer) {
+ m_tracer->traceSend("Disconnecting");
+ }
+
+ ::shutdown(m_desc, SHUT_RDWR);
+ ::close(m_desc);
+
+ m_desc = -1;
+ }
+}
+
+
+static bool isNumericAddress(const char* address) {
+
+#if VMIME_HAVE_GETADDRINFO
+
+ struct addrinfo hint, *info = NULL;
+ memset(&hint, 0, sizeof(hint));
+
+ hint.ai_family = AF_UNSPEC;
+ hint.ai_flags = AI_NUMERICHOST;
+
+ if (getaddrinfo(address, 0, &hint, &info) == 0) {
+
+ freeaddrinfo(info);
+ return true;
+
+ } else {
+
+ return false;
+ }
+
+#else
+
+ return inet_addr(address) != INADDR_NONE;
+
+#endif
+
+}
+
+
+const string posixSocket::getPeerAddress() const {
+
+ // Get address of connected peer
+ sockaddr peer;
+ socklen_t peerLen = sizeof(peer);
+
+ if (getpeername(m_desc, &peer, &peerLen) != 0) {
+ throwSocketError(errno);
+ }
+
+ // Convert to numerical presentation format
+ char buf[INET6_ADDRSTRLEN];
+
+ if (!inet_ntop(peer.sa_family, &(reinterpret_cast <struct sockaddr_in *>(&peer))->sin_addr, buf, sizeof(buf))) {
+ throwSocketError(errno);
+ }
+
+ return string(buf);
+}
+
+
+const string posixSocket::getPeerName() const {
+
+ // Get address of connected peer
+ sockaddr peer;
+ socklen_t peerLen = sizeof(peer);
+
+ if (getpeername(m_desc, &peer, &peerLen) != 0) {
+ throwSocketError(errno);
+ }
+
+ // If server address as specified when connecting is a numeric
+ // address, try to get a host name for it
+ if (isNumericAddress(m_serverAddress.c_str())) {
+
+#if VMIME_HAVE_GETNAMEINFO
+
+ char host[NI_MAXHOST + 1];
+ char service[NI_MAXSERV + 1];
+
+ if (getnameinfo(reinterpret_cast <sockaddr *>(&peer), peerLen,
+ host, sizeof(host), service, sizeof(service),
+ /* flags */ NI_NAMEREQD) == 0) {
+
+ return string(host);
+ }
+
+#else
+
+ struct hostent *hp;
+
+ if ((hp = gethostbyaddr(reinterpret_cast <const void *>(&peer),
+ sizeof(peer), peer.sa_family)) != NULL) {
+
+ return string(hp->h_name);
+ }
+
+#endif
+
+ }
+
+ return m_serverAddress;
+}
+
+
+size_t posixSocket::getBlockSize() const {
+
+ return 16384; // 16 KB
+}
+
+
+bool posixSocket::waitForData(const bool read, const bool write, const int msecs) {
+
+ for (int i = 0 ; i <= msecs / 10 ; ++i) {
+
+ // Check whether data is available
+ pollfd fds[1];
+ fds[0].fd = m_desc;
+ fds[0].events = 0;
+
+ if (read) {
+ fds[0].events |= POLLIN;
+ }
+
+ if (write) {
+ fds[0].events |= POLLOUT;
+ }
+
+ const int ret = ::poll(fds, sizeof(fds) / sizeof(fds[0]), 10 /* ms */);
+
+ if (ret < 0) {
+
+ if (errno != EAGAIN && errno != EINTR) {
+ throwSocketError(errno);
+ }
+
+ } else if (ret > 0) {
+
+ if (fds[0].revents & (POLLIN | POLLOUT)) {
+ return true;
+ }
+ }
+
+ // No data available at this time
+ // Check if we are timed out
+ if (m_timeoutHandler &&
+ m_timeoutHandler->isTimeOut()) {
+
+ if (!m_timeoutHandler->handleTimeOut()) {
+
+ // Server did not react within timeout delay
+ throw exceptions::operation_timed_out();
+
+ } else {
+
+ // Reset timeout
+ m_timeoutHandler->resetTimeOut();
+ }
+ }
+ }
+
+ return false; // time out
+}
+
+
+bool posixSocket::waitForRead(const int msecs) {
+
+ return waitForData(/* read */ true, /* write */ false, msecs);
+}
+
+
+bool posixSocket::waitForWrite(const int msecs) {
+
+ return waitForData(/* read */ false, /* write */ true, msecs);
+}
+
+
+void posixSocket::receive(vmime::string& buffer) {
+
+ const size_t size = receiveRaw(m_buffer, sizeof(m_buffer));
+ buffer = utility::stringUtils::makeStringFromBytes(m_buffer, size);
+}
+
+
+size_t posixSocket::receiveRaw(byte_t* buffer, const size_t count) {
+
+ m_status &= ~STATUS_WOULDBLOCK;
+
+ // Check whether data is available
+ if (!waitForRead(50 /* msecs */)) {
+
+ m_status |= STATUS_WOULDBLOCK;
+
+ // Continue waiting for data
+ return 0;
+ }
+
+ // Read available data
+ ssize_t ret = ::recv(m_desc, buffer, count, 0);
+
+ if (ret < 0) {
+
+ if (!IS_EAGAIN(errno)) {
+ throwSocketError(errno);
+ }
+
+ // Check if we are timed out
+ if (m_timeoutHandler &&
+ m_timeoutHandler->isTimeOut()) {
+
+ if (!m_timeoutHandler->handleTimeOut()) {
+
+ // Server did not react within timeout delay
+ throwSocketError(errno);
+
+ } else {
+
+ // Reset timeout
+ m_timeoutHandler->resetTimeOut();
+ }
+ }
+
+ m_status |= STATUS_WOULDBLOCK;
+
+ // No data available at this time
+ return 0;
+
+ } else if (ret == 0) {
+
+ // Host shutdown
+ throwSocketError(ENOTCONN);
+
+ } else {
+
+ // Data received, reset timeout
+ if (m_timeoutHandler) {
+ m_timeoutHandler->resetTimeOut();
+ }
+ }
+
+ return ret;
+}
+
+
+void posixSocket::send(const vmime::string& buffer) {
+
+ sendRaw(reinterpret_cast <const byte_t*>(buffer.data()), buffer.length());
+}
+
+
+void posixSocket::send(const char* str) {
+
+ sendRaw(reinterpret_cast <const byte_t*>(str), ::strlen(str));
+}
+
+
+void posixSocket::sendRaw(const byte_t* buffer, const size_t count) {
+
+ m_status &= ~STATUS_WOULDBLOCK;
+
+ size_t size = count;
+
+ while (size > 0) {
+
+#if VMIME_HAVE_MSG_NOSIGNAL
+ const ssize_t ret = ::send(m_desc, buffer, size, MSG_NOSIGNAL);
+#else
+ const ssize_t ret = ::send(m_desc, buffer, size, 0);
+#endif
+
+ if (ret <= 0) {
+
+ if (ret < 0 && !IS_EAGAIN(errno)) {
+ throwSocketError(errno);
+ }
+
+ waitForWrite(50 /* msecs */);
+
+ } else {
+
+ buffer += ret;
+ size -= ret;
+ }
+ }
+
+ // Reset timeout
+ if (m_timeoutHandler) {
+ m_timeoutHandler->resetTimeOut();
+ }
+}
+
+
+size_t posixSocket::sendRawNonBlocking(const byte_t* buffer, const size_t count) {
+
+ m_status &= ~STATUS_WOULDBLOCK;
+
+#if VMIME_HAVE_MSG_NOSIGNAL
+ const ssize_t ret = ::send(m_desc, buffer, count, MSG_NOSIGNAL);
+#else
+ const ssize_t ret = ::send(m_desc, buffer, count, 0);
+#endif
+
+ if (ret <= 0) {
+
+ if (ret < 0 && !IS_EAGAIN(errno)) {
+ throwSocketError(errno);
+ }
+
+ // Check if we are timed out
+ if (m_timeoutHandler &&
+ m_timeoutHandler->isTimeOut()) {
+
+ if (!m_timeoutHandler->handleTimeOut()) {
+
+ // Could not send data within timeout delay
+ throw exceptions::operation_timed_out();
+
+ } else {
+
+ // Reset timeout
+ m_timeoutHandler->resetTimeOut();
+ }
+ }
+
+ m_status |= STATUS_WOULDBLOCK;
+
+ // No data can be written at this time
+ return 0;
+ }
+
+ // Reset timeout
+ if (m_timeoutHandler) {
+ m_timeoutHandler->resetTimeOut();
+ }
+
+ return ret;
+}
+
+
+void posixSocket::throwSocketError(const int err) {
+
+ const char* msg = NULL;
+
+ switch (err) {
+
+ case EACCES: msg = "EACCES: permission denied"; break;
+ case EAFNOSUPPORT: msg = "EAFNOSUPPORT: address family not supported"; break;
+ case EMFILE: msg = "EMFILE: process file table overflow"; break;
+ case ENFILE: msg = "ENFILE: system limit reached"; break;
+ case EPROTONOSUPPORT: msg = "EPROTONOSUPPORT: protocol not supported"; break;
+ case EAGAIN: msg = "EGAIN: blocking operation"; break;
+ case EBADF: msg = "EBADF: invalid descriptor"; break;
+ case ECONNRESET: msg = "ECONNRESET: connection reset by peer"; break;
+ case EFAULT: msg = "EFAULT: bad user space address"; break;
+ case EINTR: msg = "EINTR: signal occurred before transmission"; break;
+ case EINVAL: msg = "EINVAL: invalid argument"; break;
+ case EMSGSIZE: msg = "EMSGSIZE: message cannot be sent atomically"; break;
+ case ENOBUFS: msg = "ENOBUFS: output queue is full"; break;
+ case ENOMEM: msg = "ENOMEM: out of memory"; break;
+ case EPIPE: msg = "EPIPE: broken pipe"; break;
+ case ENOTCONN: msg = "ENOTCONN: not connected"; break;
+ case ECONNREFUSED: msg = "ECONNREFUSED: connection refused"; break;
+ }
+
+ if (msg) {
+
+ throw exceptions::socket_exception(msg);
+
+ } else {
+
+ // Use strerror() to get string describing error number
+
+#if VMIME_HAVE_STRERROR_R
+
+ char errbuf[512];
+
+ throw exceptions::socket_exception(
+ vmime_strerror_r_result(
+ strerror_r(err, errbuf, sizeof(errbuf)),
+ errbuf
+ )
+ );
+
+#else // !VMIME_HAVE_STRERROR_R
+
+ const std::string strmsg(strerror(err));
+ throw exceptions::socket_exception(strmsg);
+
+#endif // VMIME_HAVE_STRERROR_R
+
+ }
+}
+
+
+unsigned int posixSocket::getStatus() const {
+
+ return m_status;
+}
+
+
+shared_ptr <net::timeoutHandler> posixSocket::getTimeoutHandler() {
+
+ return m_timeoutHandler;
+}
+
+
+void posixSocket::setTracer(const shared_ptr <net::tracer>& tracer) {
+
+ m_tracer = tracer;
+}
+
+
+shared_ptr <net::tracer> posixSocket::getTracer() {
+
+ return m_tracer;
+}
+
+
+
+//
+// posixSocketFactory
+//
+
+shared_ptr <vmime::net::socket> posixSocketFactory::create() {
+
+ shared_ptr <vmime::net::timeoutHandler> th;
+ return make_shared <posixSocket>(th);
+}
+
+
+shared_ptr <vmime::net::socket> posixSocketFactory::create(const shared_ptr <vmime::net::timeoutHandler>& th) {
+
+ return make_shared <posixSocket>(th);
+}
+
+
+} // posix
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_POSIX && VMIME_HAVE_MESSAGING_FEATURES
diff --git a/vmime-master/src/vmime/platforms/posix/posixSocket.hpp b/vmime-master/src/vmime/platforms/posix/posixSocket.hpp
new file mode 100644
index 0000000..7d732b7
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/posix/posixSocket.hpp
@@ -0,0 +1,118 @@
+//
+// 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_PLATFORMS_POSIX_SOCKET_HPP_INCLUDED
+#define VMIME_PLATFORMS_POSIX_SOCKET_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_PLATFORM_IS_POSIX && VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/net/socket.hpp"
+
+
+struct addrinfo;
+
+
+namespace vmime {
+namespace platforms {
+namespace posix {
+
+
+class posixSocket : public vmime::net::socket {
+
+public:
+
+ posixSocket(shared_ptr <vmime::net::timeoutHandler> th);
+ ~posixSocket();
+
+ void connect(const vmime::string& address, const vmime::port_t port);
+ bool isConnected() const;
+ void disconnect();
+
+ bool waitForRead(const int msecs = 30000);
+ bool waitForWrite(const int msecs = 30000);
+
+ void receive(vmime::string& buffer);
+ size_t receiveRaw(byte_t* buffer, const size_t count);
+
+ void send(const vmime::string& buffer);
+ void send(const char* str);
+ void sendRaw(const byte_t* buffer, const size_t count);
+ size_t sendRawNonBlocking(const byte_t* buffer, const size_t count);
+
+ size_t getBlockSize() const;
+
+ unsigned int getStatus() const;
+
+ const string getPeerName() const;
+ const string getPeerAddress() const;
+
+ shared_ptr <net::timeoutHandler> getTimeoutHandler();
+
+ void setTracer(const shared_ptr <net::tracer>& tracer);
+ shared_ptr <net::tracer> getTracer();
+
+protected:
+
+ void resolve(struct ::addrinfo** addrInfo, const vmime::string& address, const vmime::port_t port);
+
+ bool waitForData(const bool read, const bool write, const int msecs);
+
+ static void throwSocketError(const int err);
+
+private:
+
+ shared_ptr <vmime::net::timeoutHandler> m_timeoutHandler;
+ shared_ptr <net::tracer> m_tracer;
+
+ byte_t m_buffer[65536];
+ int m_desc;
+
+ unsigned int m_status;
+
+ string m_serverAddress;
+};
+
+
+
+class posixSocketFactory : public vmime::net::socketFactory {
+
+public:
+
+ shared_ptr <vmime::net::socket> create();
+ shared_ptr <vmime::net::socket> create(const shared_ptr <vmime::net::timeoutHandler>& th);
+};
+
+
+} // posix
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_POSIX && VMIME_HAVE_MESSAGING_FEATURES
+
+#endif // VMIME_PLATFORMS_POSIX_SOCKET_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/platforms/windows/windowsCodepages.hpp b/vmime-master/src/vmime/platforms/windows/windowsCodepages.hpp
new file mode 100644
index 0000000..1457c59
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/windows/windowsCodepages.hpp
@@ -0,0 +1,197 @@
+//
+// 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_PLATFORMS_WINDOWS_CODEPAGES_HPP_INCLUDED
+#define VMIME_PLATFORMS_WINDOWS_CODEPAGES_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_PLATFORM_IS_WINDOWS
+
+
+#include <string.h>
+
+
+namespace vmime {
+namespace platforms {
+namespace windows {
+
+
+struct windowsCodepages {
+
+ static int getByName(const char* s8_Name) {
+
+ if (stricmp(s8_Name, "ASMO-708") == 0) return 708;
+ if (stricmp(s8_Name, "big5") == 0) return 950;
+ if (stricmp(s8_Name, "cp1025") == 0) return 21025;
+ if (stricmp(s8_Name, "cp866") == 0) return 866;
+ if (stricmp(s8_Name, "cp875") == 0) return 875;
+ if (stricmp(s8_Name, "DOS-720") == 0) return 720;
+ if (stricmp(s8_Name, "DOS-862") == 0) return 862;
+ if (stricmp(s8_Name, "EUC-CN") == 0) return 51936;
+ if (stricmp(s8_Name, "euc-jp") == 0) return 51932;
+ if (stricmp(s8_Name, "EUC-JP") == 0) return 20932;
+ if (stricmp(s8_Name, "euc-kr") == 0) return 51949;
+ if (stricmp(s8_Name, "GB18030") == 0) return 54936;
+ if (stricmp(s8_Name, "GBK") == 0) return 54936;
+ if (stricmp(s8_Name, "gb2312") == 0) return 936;
+ if (stricmp(s8_Name, "hz-gb-2312") == 0) return 52936;
+ if (stricmp(s8_Name, "IBM00858") == 0) return 858;
+ if (stricmp(s8_Name, "IBM00924") == 0) return 20924;
+ if (stricmp(s8_Name, "IBM01047") == 0) return 1047;
+ if (stricmp(s8_Name, "IBM01140") == 0) return 1140;
+ if (stricmp(s8_Name, "IBM01141") == 0) return 1141;
+ if (stricmp(s8_Name, "IBM01142") == 0) return 1142;
+ if (stricmp(s8_Name, "IBM01143") == 0) return 1143;
+ if (stricmp(s8_Name, "IBM01144") == 0) return 1144;
+ if (stricmp(s8_Name, "IBM01145") == 0) return 1145;
+ if (stricmp(s8_Name, "IBM01146") == 0) return 1146;
+ if (stricmp(s8_Name, "IBM01147") == 0) return 1147;
+ if (stricmp(s8_Name, "IBM01148") == 0) return 1148;
+ if (stricmp(s8_Name, "IBM01149") == 0) return 1149;
+ if (stricmp(s8_Name, "IBM037") == 0) return 37;
+ if (stricmp(s8_Name, "IBM1026") == 0) return 1026;
+ if (stricmp(s8_Name, "IBM273") == 0) return 20273;
+ if (stricmp(s8_Name, "IBM277") == 0) return 20277;
+ if (stricmp(s8_Name, "IBM278") == 0) return 20278;
+ if (stricmp(s8_Name, "IBM280") == 0) return 20280;
+ if (stricmp(s8_Name, "IBM284") == 0) return 20284;
+ if (stricmp(s8_Name, "IBM285") == 0) return 20285;
+ if (stricmp(s8_Name, "IBM290") == 0) return 20290;
+ if (stricmp(s8_Name, "IBM297") == 0) return 20297;
+ if (stricmp(s8_Name, "IBM420") == 0) return 20420;
+ if (stricmp(s8_Name, "IBM423") == 0) return 20423;
+ if (stricmp(s8_Name, "IBM424") == 0) return 20424;
+ if (stricmp(s8_Name, "IBM437") == 0) return 437;
+ if (stricmp(s8_Name, "IBM500") == 0) return 500;
+ if (stricmp(s8_Name, "ibm737") == 0) return 737;
+ if (stricmp(s8_Name, "ibm775") == 0) return 775;
+ if (stricmp(s8_Name, "ibm850") == 0) return 850;
+ if (stricmp(s8_Name, "ibm852") == 0) return 852;
+ if (stricmp(s8_Name, "IBM855") == 0) return 855;
+ if (stricmp(s8_Name, "ibm857") == 0) return 857;
+ if (stricmp(s8_Name, "IBM860") == 0) return 860;
+ if (stricmp(s8_Name, "ibm861") == 0) return 861;
+ if (stricmp(s8_Name, "IBM863") == 0) return 863;
+ if (stricmp(s8_Name, "IBM864") == 0) return 864;
+ if (stricmp(s8_Name, "IBM865") == 0) return 865;
+ if (stricmp(s8_Name, "ibm869") == 0) return 869;
+ if (stricmp(s8_Name, "IBM870") == 0) return 870;
+ if (stricmp(s8_Name, "IBM871") == 0) return 20871;
+ if (stricmp(s8_Name, "IBM880") == 0) return 20880;
+ if (stricmp(s8_Name, "IBM905") == 0) return 20905;
+ if (stricmp(s8_Name, "IBM-Thai") == 0) return 20838;
+ if (stricmp(s8_Name, "iso-2022-jp") == 0) return 50222;
+ if (stricmp(s8_Name, "iso-2022-kr") == 0) return 50225;
+ if (stricmp(s8_Name, "iso-8859-1") == 0) return 28591;
+ if (stricmp(s8_Name, "iso-8859-13") == 0) return 28603;
+ if (stricmp(s8_Name, "iso-8859-15") == 0) return 28605;
+ if (stricmp(s8_Name, "iso-8859-2") == 0) return 28592;
+ if (stricmp(s8_Name, "iso-8859-3") == 0) return 28593;
+ if (stricmp(s8_Name, "iso-8859-4") == 0) return 28594;
+ if (stricmp(s8_Name, "iso-8859-5") == 0) return 28595;
+ if (stricmp(s8_Name, "iso-8859-6") == 0) return 28596;
+ if (stricmp(s8_Name, "iso-8859-7") == 0) return 28597;
+ if (stricmp(s8_Name, "iso-8859-8") == 0) return 28598;
+ if (stricmp(s8_Name, "iso-8859-8-i") == 0) return 38598;
+ if (stricmp(s8_Name, "iso-8859-9") == 0) return 28599;
+ if (stricmp(s8_Name, "Johab") == 0) return 1361;
+ if (stricmp(s8_Name, "koi8-r") == 0) return 20866;
+ if (stricmp(s8_Name, "koi8-u") == 0) return 21866;
+ if (stricmp(s8_Name, "ks_c_5601-1987") == 0) return 949;
+ if (stricmp(s8_Name, "macintosh") == 0) return 10000;
+ if (stricmp(s8_Name, "unicodeFFFE") == 0) return 1201;
+ if (stricmp(s8_Name, "us-ascii") == 0) return 20127;
+ if (stricmp(s8_Name, "utf-16") == 0) return 1200;
+ if (stricmp(s8_Name, "utf-32") == 0) return 12000;
+ if (stricmp(s8_Name, "utf-32BE") == 0) return 12001;
+ if (stricmp(s8_Name, "utf-7") == 0) return 65000;
+ if (stricmp(s8_Name, "utf-8") == 0) return 65001;
+ if (stricmp(s8_Name, "windows-1250") == 0) return 1250;
+ if (stricmp(s8_Name, "windows-1251") == 0) return 1251;
+ if (stricmp(s8_Name, "Windows-1252") == 0) return 1252;
+ if (stricmp(s8_Name, "windows-1253") == 0) return 1253;
+ if (stricmp(s8_Name, "windows-1254") == 0) return 1254;
+ if (stricmp(s8_Name, "windows-1255") == 0) return 1255;
+ if (stricmp(s8_Name, "windows-1256") == 0) return 1256;
+ if (stricmp(s8_Name, "windows-1257") == 0) return 1257;
+ if (stricmp(s8_Name, "windows-1258") == 0) return 1258;
+ if (stricmp(s8_Name, "windows-874") == 0) return 874;
+ if (stricmp(s8_Name, "x-Chinese-CNS") == 0) return 20000;
+ if (stricmp(s8_Name, "x-Chinese-Eten") == 0) return 20002;
+ if (stricmp(s8_Name, "x-cp20001") == 0) return 20001;
+ if (stricmp(s8_Name, "x-cp20003") == 0) return 20003;
+ if (stricmp(s8_Name, "x-cp20004") == 0) return 20004;
+ if (stricmp(s8_Name, "x-cp20005") == 0) return 20005;
+ if (stricmp(s8_Name, "x-cp20261") == 0) return 20261;
+ if (stricmp(s8_Name, "x-cp20269") == 0) return 20269;
+ if (stricmp(s8_Name, "x-cp20936") == 0) return 20936;
+ if (stricmp(s8_Name, "x-cp20949") == 0) return 20949;
+ if (stricmp(s8_Name, "x-cp50227") == 0) return 50227;
+ if (stricmp(s8_Name, "x-EBCDIC-KoreanExtended") == 0) return 20833;
+ if (stricmp(s8_Name, "x-Europa") == 0) return 29001;
+ if (stricmp(s8_Name, "x-IA5") == 0) return 20105;
+ if (stricmp(s8_Name, "x-IA5-German") == 0) return 20106;
+ if (stricmp(s8_Name, "x-IA5-Norwegian") == 0) return 20108;
+ if (stricmp(s8_Name, "x-IA5-Swedish") == 0) return 20107;
+ if (stricmp(s8_Name, "x-iscii-as") == 0) return 57006;
+ if (stricmp(s8_Name, "x-iscii-be") == 0) return 57003;
+ if (stricmp(s8_Name, "x-iscii-de") == 0) return 57002;
+ if (stricmp(s8_Name, "x-iscii-gu") == 0) return 57010;
+ if (stricmp(s8_Name, "x-iscii-ka") == 0) return 57008;
+ if (stricmp(s8_Name, "x-iscii-ma") == 0) return 57009;
+ if (stricmp(s8_Name, "x-iscii-or") == 0) return 57007;
+ if (stricmp(s8_Name, "x-iscii-pa") == 0) return 57011;
+ if (stricmp(s8_Name, "x-iscii-ta") == 0) return 57004;
+ if (stricmp(s8_Name, "x-iscii-te") == 0) return 57005;
+ if (stricmp(s8_Name, "x-mac-arabic") == 0) return 10004;
+ if (stricmp(s8_Name, "x-mac-ce") == 0) return 10029;
+ if (stricmp(s8_Name, "x-mac-chinesesimp") == 0) return 10008;
+ if (stricmp(s8_Name, "x-mac-chinesetrad") == 0) return 10002;
+ if (stricmp(s8_Name, "x-mac-croatian") == 0) return 10082;
+ if (stricmp(s8_Name, "x-mac-cyrillic") == 0) return 10007;
+ if (stricmp(s8_Name, "x-mac-greek") == 0) return 10006;
+ if (stricmp(s8_Name, "x-mac-hebrew") == 0) return 10005;
+ if (stricmp(s8_Name, "x-mac-icelandic") == 0) return 10079;
+ if (stricmp(s8_Name, "x-mac-japanese") == 0) return 10001;
+ if (stricmp(s8_Name, "x-mac-korean") == 0) return 10003;
+ if (stricmp(s8_Name, "x-mac-romanian") == 0) return 10010;
+ if (stricmp(s8_Name, "x-mac-thai") == 0) return 10021;
+ if (stricmp(s8_Name, "x-mac-turkish") == 0) return 10081;
+ if (stricmp(s8_Name, "x-mac-ukrainian") == 0) return 10017;
+
+ throw exception(std::string("Unknown charset: ") + s8_Name);
+ }
+};
+
+
+} // windows
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_WINDOWS
+
+#endif // VMIME_PLATFORMS_WINDOWS_CODEPAGES_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/platforms/windows/windowsCriticalSection.cpp b/vmime-master/src/vmime/platforms/windows/windowsCriticalSection.cpp
new file mode 100644
index 0000000..c0a0bec
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/windows/windowsCriticalSection.cpp
@@ -0,0 +1,67 @@
+//
+// 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_PLATFORM_IS_WINDOWS
+
+
+#include "vmime/platforms/windows/windowsCriticalSection.hpp"
+
+
+namespace vmime {
+namespace platforms {
+namespace windows {
+
+
+windowsCriticalSection::windowsCriticalSection() {
+
+ InitializeCriticalSectionAndSpinCount(&m_cs, 0x400);
+}
+
+
+windowsCriticalSection::~windowsCriticalSection() {
+
+ DeleteCriticalSection(&m_cs);
+}
+
+
+void windowsCriticalSection::lock() {
+
+ EnterCriticalSection(&m_cs);
+}
+
+
+void windowsCriticalSection::unlock() {
+
+ LeaveCriticalSection(&m_cs);
+}
+
+
+} // windows
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_WINDOWS
diff --git a/vmime-master/src/vmime/platforms/windows/windowsCriticalSection.hpp b/vmime-master/src/vmime/platforms/windows/windowsCriticalSection.hpp
new file mode 100644
index 0000000..ffe8294
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/windows/windowsCriticalSection.hpp
@@ -0,0 +1,68 @@
+//
+// 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_PLATFORMS_WINDOWS_CRITICALSECTION_HPP_INCLUDED
+#define VMIME_PLATFORMS_WINDOWS_CRITICALSECTION_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_PLATFORM_IS_WINDOWS
+
+
+#include "vmime/utility/sync/criticalSection.hpp"
+
+
+#include <windows.h>
+
+
+namespace vmime {
+namespace platforms {
+namespace windows {
+
+
+class windowsCriticalSection : public utility::sync::criticalSection {
+
+public:
+
+ windowsCriticalSection();
+ ~windowsCriticalSection();
+
+ void lock();
+ void unlock();
+
+private:
+
+ CRITICAL_SECTION m_cs;
+};
+
+
+} // windows
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_WINDOWS
+
+#endif // VMIME_PLATFORMS_WINDOWS_CRITICALSECTION_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/platforms/windows/windowsFile.cpp b/vmime-master/src/vmime/platforms/windows/windowsFile.cpp
new file mode 100644
index 0000000..774731c
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/windows/windowsFile.cpp
@@ -0,0 +1,712 @@
+//
+// 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_PLATFORM_IS_WINDOWS && VMIME_HAVE_FILESYSTEM_FEATURES
+
+
+#include "vmime/platforms/windows/windowsFile.hpp"
+
+#include <windows.h>
+#include <string.h>
+
+#include "vmime/exception.hpp"
+#include "vmime/utility/stringUtils.hpp"
+
+
+namespace vmime {
+namespace platforms {
+namespace windows {
+
+
+shared_ptr <vmime::utility::file> windowsFileSystemFactory::create(
+ const vmime::utility::file::path& path
+) const {
+
+ return make_shared <windowsFile>(path);
+}
+
+
+const vmime::utility::file::path windowsFileSystemFactory::stringToPath(
+ const vmime::string& str
+) const {
+
+ return stringToPathImpl(str);
+}
+
+
+const vmime::string windowsFileSystemFactory::pathToString(
+ const vmime::utility::file::path& path
+) const {
+
+ return pathToStringImpl(path);
+}
+
+
+const vmime::utility::file::path windowsFileSystemFactory::stringToPathImpl(
+ const vmime::string& str
+) {
+
+ vmime::size_t offset = 0;
+ vmime::size_t prev = 0;
+
+ vmime::utility::file::path path;
+
+ while ((offset = str.find_first_of("\\", offset)) != vmime::string::npos) {
+
+ if (offset != prev) {
+
+ path.appendComponent(
+ vmime::utility::file::path::component(
+ vmime::string(str.begin() + prev, str.begin() + offset)
+ )
+ );
+ }
+
+ prev = offset + 1;
+ offset++;
+ }
+
+ if (prev < str.length()) {
+
+ path.appendComponent(
+ vmime::utility::file::path::component(
+ vmime::string(str.begin() + prev, str.end())
+ )
+ );
+ }
+
+ return path;
+}
+
+
+const vmime::string windowsFileSystemFactory::pathToStringImpl(
+ const vmime::utility::file::path& path
+) {
+
+ vmime::string native = "";
+
+ for (int i = 0 ; i < path.getSize() ; ++i) {
+
+ if (i > 0) {
+ native += "\\";
+ }
+
+ native += path[i].getBuffer();
+ }
+
+ return native;
+}
+
+
+bool windowsFileSystemFactory::isValidPathComponent(
+ const vmime::utility::file::path::component& comp
+) const {
+
+ return isValidPathComponent(comp, false);
+}
+
+
+bool windowsFileSystemFactory::isValidPathComponent(
+ const vmime::utility::file::path::component& comp,
+ bool firstComponent
+) const {
+
+ const string& buffer = comp.getBuffer();
+
+ // If first component, check if component is a drive
+ if (firstComponent && (buffer.length() == 2) && (buffer[1] == ':')) {
+
+ char drive = tolower(buffer[0]);
+
+ if ((drive >= 'a') && (drive <= 'z')) {
+ return true;
+ }
+ }
+
+ // Check for invalid characters
+ for (size_t i = 0 ; i < buffer.length() ; ++i) {
+
+ const unsigned char c = buffer[i];
+
+ switch (c) {
+
+ // Reserved characters
+ case '<': case '>': case ':':
+ case '"': case '/': case '\\':
+ case '|': case '$': case '*':
+
+ return false;
+
+ default:
+
+ if (c <= 31) {
+ return false;
+ }
+ }
+ }
+
+ string upperBuffer = vmime::utility::stringUtils::toUpper(buffer);
+
+ // Check for reserved names
+ if (upperBuffer.length() == 3) {
+
+ if (upperBuffer == "CON" || buffer == "PRN" || buffer == "AUX" || buffer == "NUL") {
+ return false;
+ }
+
+ } else if (upperBuffer.length() == 4) {
+
+ if ((upperBuffer.substr(0, 3) == "COM") && // COM0 to COM9
+ (upperBuffer[3] >= '0') && (upperBuffer[3] <= '9')) {
+
+ return false;
+
+ } else if ((upperBuffer.substr(0, 3) == "LPT") && // LPT0 to LPT9
+ (upperBuffer[3] >= '0') && (upperBuffer[3] <= '9')) {
+
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+bool windowsFileSystemFactory::isValidPath(const vmime::utility::file::path& path) const {
+
+ for (int i = 0 ; i < path.getSize() ; ++i) {
+
+ if (!isValidPathComponent(path[i], (i == 0))) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+void windowsFileSystemFactory::reportError(const vmime::utility::path& path, const int err) {
+
+ vmime::string desc;
+
+ LPVOID lpMsgBuf;
+
+ if (FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ err,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR) &lpMsgBuf,
+ 0,
+ NULL)) {
+
+ desc = (char*) lpMsgBuf;
+ LocalFree(lpMsgBuf);
+ }
+
+ throw vmime::exceptions::filesystem_exception(desc, path);
+}
+
+
+
+
+windowsFile::windowsFile(const vmime::utility::file::path& path)
+ : m_path(path),
+ m_nativePath(windowsFileSystemFactory::pathToStringImpl(path)) {
+
+}
+
+
+void windowsFile::createFile() {
+
+ HANDLE hFile = CreateFile(
+ m_nativePath.c_str(),
+ GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ );
+
+ if (hFile == INVALID_HANDLE_VALUE) {
+ windowsFileSystemFactory::reportError(m_path, GetLastError());
+ }
+
+ CloseHandle(hFile);
+}
+
+
+void windowsFile::createDirectory(const bool createAll) {
+
+ createDirectoryImpl(m_path, m_path, createAll);
+}
+
+
+bool windowsFile::isFile() const {
+
+ DWORD dwFileAttribute = GetFileAttributes(m_nativePath.c_str());
+
+ if (dwFileAttribute == INVALID_FILE_ATTRIBUTES) {
+ return false;
+ }
+
+ return (dwFileAttribute & FILE_ATTRIBUTE_DIRECTORY) == 0;
+}
+
+
+bool windowsFile::isDirectory() const {
+
+ DWORD dwFileAttribute = GetFileAttributes(m_nativePath.c_str());
+
+ if (dwFileAttribute == INVALID_FILE_ATTRIBUTES) {
+ return false;
+ }
+
+ return (dwFileAttribute & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY;
+}
+
+
+bool windowsFile::canRead() const {
+
+ HANDLE hFile = CreateFile(
+ m_nativePath.c_str(),
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ );
+
+ if (hFile == INVALID_HANDLE_VALUE) {
+ return false;
+ }
+
+ CloseHandle(hFile);
+
+ return true;
+}
+
+
+bool windowsFile::canWrite() const {
+
+ HANDLE hFile = CreateFile(
+ m_nativePath.c_str(),
+ GENERIC_WRITE,
+ FILE_SHARE_WRITE,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ );
+
+ if (hFile == INVALID_HANDLE_VALUE) {
+ return false;
+ }
+
+ CloseHandle(hFile);
+
+ return true;
+}
+
+
+windowsFile::length_type windowsFile::getLength() {
+
+ HANDLE hFile = CreateFile(
+ m_nativePath.c_str(),
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ );
+
+ if (hFile == INVALID_HANDLE_VALUE) {
+ windowsFileSystemFactory::reportError(m_path, GetLastError());
+ }
+
+ DWORD dwSize = GetFileSize(hFile, NULL);
+
+ CloseHandle(hFile);
+
+ return dwSize;
+}
+
+
+const vmime::utility::path& windowsFile::getFullPath() const {
+
+ return m_path;
+}
+
+
+bool windowsFile::exists() const {
+
+ WIN32_FIND_DATA findData;
+ HANDLE hFind = FindFirstFile(m_nativePath.c_str(), &findData);
+
+ if (hFind != INVALID_HANDLE_VALUE) {
+ FindClose(hFind);
+ return true;
+ }
+
+ return false;
+}
+
+
+shared_ptr <vmime::utility::file> windowsFile::getParent() const {
+
+ if (m_path.isEmpty()) {
+ return null;
+ } else {
+ return make_shared <windowsFile>(m_path.getParent());
+ }
+}
+
+
+void windowsFile::rename(const path& newName) {
+
+ const vmime::string newNativeName = windowsFileSystemFactory::pathToStringImpl(newName);
+
+ if (MoveFile(m_nativePath.c_str(), newNativeName.c_str())) {
+
+ m_path = newName;
+ m_nativePath = newNativeName;
+
+ } else {
+
+ windowsFileSystemFactory::reportError(m_path, GetLastError());
+ }
+}
+
+
+void windowsFile::remove() {
+
+ if (!DeleteFile(m_nativePath.c_str())) {
+ windowsFileSystemFactory::reportError(m_path, GetLastError());
+ }
+}
+
+
+shared_ptr <vmime::utility::fileWriter> windowsFile::getFileWriter() {
+
+ return make_shared <windowsFileWriter>(m_path, m_nativePath);
+}
+
+
+shared_ptr <vmime::utility::fileReader> windowsFile::getFileReader() {
+
+ return make_shared <windowsFileReader>(m_path, m_nativePath);
+}
+
+
+shared_ptr <vmime::utility::fileIterator> windowsFile::getFiles() const {
+
+ return make_shared <windowsFileIterator>(m_path, m_nativePath);
+}
+
+
+void windowsFile::createDirectoryImpl(
+ const vmime::utility::file::path& fullPath,
+ const vmime::utility::file::path& path,
+ const bool recursive
+) {
+
+ const vmime::string nativePath = windowsFileSystemFactory::pathToStringImpl(path);
+
+ windowsFile tmp(path);
+
+ if (tmp.isDirectory()) {
+ return;
+ }
+
+ if (!path.isEmpty() && recursive) {
+ createDirectoryImpl(fullPath, path.getParent(), true);
+ }
+
+ if (!CreateDirectory(nativePath.c_str(), NULL)) {
+ windowsFileSystemFactory::reportError(fullPath, GetLastError());
+ }
+}
+
+
+
+windowsFileIterator::windowsFileIterator(
+ const vmime::utility::file::path& path,
+ const vmime::string& nativePath
+)
+ : m_path(path),
+ m_nativePath(nativePath),
+ m_moreElements(false),
+ m_hFind(INVALID_HANDLE_VALUE) {
+
+ findFirst();
+}
+
+
+windowsFileIterator::~windowsFileIterator() {
+
+ if (m_hFind != INVALID_HANDLE_VALUE) {
+ FindClose(m_hFind);
+ }
+}
+
+
+bool windowsFileIterator::hasMoreElements() const {
+
+ return m_moreElements;
+}
+
+
+shared_ptr <vmime::utility::file> windowsFileIterator::nextElement() {
+
+ shared_ptr <vmime::utility::file> pFile = make_shared <windowsFile>(
+ m_path / vmime::utility::file::path::component(m_findData.cFileName)
+ );
+
+ findNext();
+
+ return pFile;
+}
+
+
+void windowsFileIterator::findFirst() {
+
+ m_hFind = FindFirstFile(m_nativePath.c_str(), &m_findData);
+
+ if (m_hFind == INVALID_HANDLE_VALUE) {
+ m_moreElements = false;
+ return;
+ }
+
+ m_moreElements = true;
+
+ if (isCurrentOrParentDir()) {
+ findNext();
+ }
+}
+
+
+void windowsFileIterator::findNext() {
+
+ do {
+
+ if (!FindNextFile(m_hFind, &m_findData)) {
+ m_moreElements = false;
+ return;
+ }
+
+ } while (isCurrentOrParentDir());
+}
+
+
+bool windowsFileIterator::isCurrentOrParentDir() const {
+
+ vmime::string s(m_findData.cFileName);
+
+ if ((s == ".") || (s == "..")) {
+ return true;
+ }
+
+ return false;
+}
+
+
+
+windowsFileReader::windowsFileReader(
+ const vmime::utility::file::path& path,
+ const vmime::string& nativePath
+)
+ : m_path(path),
+ m_nativePath(nativePath) {
+
+}
+
+
+shared_ptr <vmime::utility::inputStream> windowsFileReader::getInputStream() {
+
+ HANDLE hFile = CreateFile(
+ m_nativePath.c_str(),
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL
+ );
+
+ if (hFile == INVALID_HANDLE_VALUE) {
+ windowsFileSystemFactory::reportError(m_path, GetLastError());
+ }
+
+ return make_shared <windowsFileReaderInputStream>(m_path, hFile);
+}
+
+
+windowsFileReaderInputStream::windowsFileReaderInputStream(
+ const vmime::utility::file::path& path,
+ HANDLE hFile
+)
+ : m_path(path),
+ m_hFile(hFile) {
+
+}
+
+windowsFileReaderInputStream::~windowsFileReaderInputStream() {
+
+ CloseHandle(m_hFile);
+}
+
+
+bool windowsFileReaderInputStream::eof() const {
+
+ DWORD dwSize = GetFileSize(m_hFile, NULL);
+ DWORD dwPosition = SetFilePointer(m_hFile, 0, NULL, FILE_CURRENT);
+
+ return dwSize == dwPosition;
+}
+
+
+void windowsFileReaderInputStream::reset() {
+
+ SetFilePointer(m_hFile, 0, NULL, FILE_BEGIN);
+}
+
+
+size_t windowsFileReaderInputStream::read(byte_t* const data, const size_t count) {
+
+ DWORD dwBytesRead;
+
+ if (!ReadFile(m_hFile, (LPVOID) data, (DWORD) count, &dwBytesRead, NULL)) {
+ windowsFileSystemFactory::reportError(m_path, GetLastError());
+ }
+
+ return dwBytesRead;
+}
+
+
+size_t windowsFileReaderInputStream::skip(const size_t count) {
+
+ DWORD dwCurPos = SetFilePointer(m_hFile, 0, NULL, FILE_CURRENT);
+ DWORD dwNewPos = SetFilePointer(m_hFile, (LONG) count, NULL, FILE_CURRENT);
+
+ return dwNewPos - dwCurPos;
+}
+
+
+size_t windowsFileReaderInputStream::getPosition() const {
+
+ DWORD dwCurPos = SetFilePointer(m_hFile, 0, NULL, FILE_CURRENT);
+
+ if (dwCurPos == INVALID_SET_FILE_POINTER) {
+ windowsFileSystemFactory::reportError(m_path, GetLastError());
+ }
+
+ return static_cast <size_t>(dwCurPos);
+}
+
+void windowsFileReaderInputStream::seek(const size_t pos) {
+
+ DWORD dwNewPos = SetFilePointer(m_hFile, (LONG) pos, NULL, FILE_BEGIN);
+
+ if (dwNewPos == INVALID_SET_FILE_POINTER) {
+ windowsFileSystemFactory::reportError(m_path, GetLastError());
+ }
+}
+
+
+
+windowsFileWriter::windowsFileWriter(
+ const vmime::utility::file::path& path,
+ const vmime::string& nativePath
+)
+ : m_path(path),
+ m_nativePath(nativePath) {
+
+}
+
+shared_ptr <vmime::utility::outputStream> windowsFileWriter::getOutputStream() {
+
+ HANDLE hFile = CreateFile(
+ m_nativePath.c_str(),
+ GENERIC_WRITE,
+ FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ );
+
+ if (hFile == INVALID_HANDLE_VALUE) {
+ windowsFileSystemFactory::reportError(m_path, GetLastError());
+ }
+
+ return make_shared <windowsFileWriterOutputStream>(m_path, hFile);
+}
+
+
+windowsFileWriterOutputStream::windowsFileWriterOutputStream(
+ const vmime::utility::file::path& path,
+ HANDLE hFile
+)
+ : m_path(path),
+ m_hFile(hFile) {
+
+}
+
+
+windowsFileWriterOutputStream::~windowsFileWriterOutputStream() {
+
+ CloseHandle(m_hFile);
+}
+
+
+void windowsFileWriterOutputStream::writeImpl(const byte_t* const data, const size_t count) {
+
+ DWORD dwBytesWritten;
+
+ if (!WriteFile(m_hFile, data, (DWORD) count, &dwBytesWritten, NULL)) {
+ windowsFileSystemFactory::reportError(m_path, GetLastError());
+ }
+}
+
+
+void windowsFileWriterOutputStream::flush() {
+
+ // TODO
+}
+
+
+} // windows
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_WINDOWS && VMIME_HAVE_FILESYSTEM_FEATURES
+
diff --git a/vmime-master/src/vmime/platforms/windows/windowsFile.hpp b/vmime-master/src/vmime/platforms/windows/windowsFile.hpp
new file mode 100644
index 0000000..dc4b5ed
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/windows/windowsFile.hpp
@@ -0,0 +1,225 @@
+//
+// 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_PLATFORMS_WINDOWS_FILE_HPP_INCLUDED
+#define VMIME_PLATFORMS_WINDOWS_FILE_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_PLATFORM_IS_WINDOWS && VMIME_HAVE_FILESYSTEM_FEATURES
+
+
+#include "vmime/utility/file.hpp"
+#include "vmime/utility/seekableInputStream.hpp"
+
+#include <windows.h>
+
+
+namespace vmime {
+namespace platforms {
+namespace windows {
+
+
+class windowsFileSystemFactory : public vmime::utility::fileSystemFactory {
+
+public:
+
+ shared_ptr <vmime::utility::file> create(const vmime::utility::file::path& path) const;
+
+ const vmime::utility::file::path stringToPath(const vmime::string& str) const;
+ const vmime::string pathToString(const vmime::utility::file::path& path) const;
+
+ static const vmime::utility::file::path stringToPathImpl(const vmime::string& str);
+ static const vmime::string pathToStringImpl(const vmime::utility::file::path& path);
+
+ bool isValidPathComponent(const vmime::utility::file::path::component& comp) const;
+ bool isValidPathComponent(const vmime::utility::file::path::component& comp,
+ bool firstComponent) const;
+ bool isValidPath(const vmime::utility::file::path& path) const;
+
+ static void reportError(const vmime::utility::path& path, const int err);
+};
+
+
+class windowsFile : public vmime::utility::file {
+
+public:
+
+ windowsFile(const vmime::utility::file::path& path);
+
+ void createFile();
+ void createDirectory(const bool createAll = false);
+
+ bool isFile() const;
+ bool isDirectory() const;
+
+ bool canRead() const;
+ bool canWrite() const;
+
+ length_type getLength();
+
+ const path& getFullPath() const;
+
+ bool exists() const;
+
+ shared_ptr <file> getParent() const;
+
+ void rename(const path& newName);
+ void remove();
+
+ shared_ptr <vmime::utility::fileWriter> getFileWriter();
+
+ shared_ptr <vmime::utility::fileReader> getFileReader();
+
+ shared_ptr <vmime::utility::fileIterator> getFiles() const;
+
+private:
+
+ static void createDirectoryImpl(
+ const vmime::utility::file::path& fullPath,
+ const vmime::utility::file::path& path,
+ const bool recursive = false
+ );
+
+private:
+
+ vmime::utility::file::path m_path;
+ vmime::string m_nativePath;
+};
+
+
+class windowsFileIterator : public vmime::utility::fileIterator {
+
+public:
+
+ windowsFileIterator(const vmime::utility::file::path& path, const vmime::string& nativePath);
+ ~windowsFileIterator();
+
+ bool hasMoreElements() const;
+ shared_ptr <vmime::utility::file> nextElement();
+
+private:
+
+ void findFirst();
+ void findNext();
+ bool isCurrentOrParentDir() const;
+
+private:
+
+ vmime::utility::file::path m_path;
+ vmime::string m_nativePath;
+ WIN32_FIND_DATA m_findData;
+ bool m_moreElements;
+ HANDLE m_hFind;
+};
+
+
+class windowsFileReader : public vmime::utility::fileReader {
+
+public:
+
+ windowsFileReader(const vmime::utility::file::path& path, const vmime::string& nativePath);
+
+public:
+
+ shared_ptr <vmime::utility::inputStream> getInputStream();
+
+private:
+
+ vmime::utility::file::path m_path;
+ vmime::string m_nativePath;
+};
+
+
+class windowsFileReaderInputStream : public vmime::utility::inputStream {
+
+public:
+
+ windowsFileReaderInputStream(const vmime::utility::file::path& path, HANDLE hFile);
+ ~windowsFileReaderInputStream();
+
+public:
+
+ bool eof() const;
+ void reset();
+ size_t read(byte_t* const data, const size_t count);
+ size_t skip(const size_t count);
+ size_t getPosition() const;
+ void seek(const size_t pos);
+
+private:
+
+ const vmime::utility::file::path m_path;
+ HANDLE m_hFile;
+};
+
+
+class windowsFileWriter : public vmime::utility::fileWriter {
+
+public:
+
+ windowsFileWriter(const vmime::utility::file::path& path, const vmime::string& nativePath);
+
+public:
+
+ shared_ptr <vmime::utility::outputStream> getOutputStream();
+
+private:
+
+ vmime::utility::file::path m_path;
+ vmime::string m_nativePath;
+};
+
+
+class windowsFileWriterOutputStream : public vmime::utility::outputStream {
+
+public:
+
+ windowsFileWriterOutputStream(const vmime::utility::file::path& path, HANDLE hFile);
+ ~windowsFileWriterOutputStream();
+
+public:
+
+ void flush();
+
+protected:
+
+ void writeImpl(const byte_t* const data, const size_t count);
+
+private:
+
+ const vmime::utility::file::path m_path;
+ HANDLE m_hFile;
+};
+
+
+} // windows
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_WINDOWS && VMIME_HAVE_FILESYSTEM_FEATURES
+
+#endif // VMIME_PLATFORMS_WINDOWS_FILE_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/platforms/windows/windowsHandler.cpp b/vmime-master/src/vmime/platforms/windows/windowsHandler.cpp
new file mode 100644
index 0000000..551f672
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/windows/windowsHandler.cpp
@@ -0,0 +1,315 @@
+//
+// 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_PLATFORM_IS_WINDOWS
+
+
+#include "vmime/platforms/windows/windowsHandler.hpp"
+
+#include "vmime/platforms/windows/windowsCriticalSection.hpp"
+
+#include "vmime/utility/stringUtils.hpp"
+
+#include <time.h>
+#include <locale.h>
+#include <process.h>
+#include <winsock2.h> // for WSAStartup()
+#include <windows.h> // for winnls.h
+#include <ws2tcpip.h>
+#include <wincrypt.h>
+
+#if VMIME_HAVE_MLANG
+# include <mlang.h>
+#endif
+
+
+namespace vmime {
+namespace platforms {
+namespace windows {
+
+
+windowsHandler::windowsHandler() {
+
+ WSAData wsaData;
+ WSAStartup(MAKEWORD(1, 1), &wsaData);
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+ m_socketFactory = make_shared <windowsSocketFactory>();
+#endif
+#if VMIME_HAVE_FILESYSTEM_FEATURES
+ m_fileSysFactory = make_shared <windowsFileSystemFactory>();
+#endif
+
+}
+
+
+windowsHandler::~windowsHandler() {
+
+ WSACleanup();
+}
+
+
+unsigned long windowsHandler::getUnixTime() const {
+
+ return static_cast <unsigned long>(::time(NULL));
+}
+
+
+const vmime::datetime windowsHandler::getCurrentLocalTime() const {
+
+ const time_t t(::time(NULL));
+
+ // Get the local time
+#if VMIME_HAVE_LOCALTIME_S
+ tm local;
+ ::localtime_s(&local, &t);
+#elif VMIME_HAVE_LOCALTIME_R
+ tm local;
+ ::localtime_r(&t, &local);
+#else
+ tm local = *::localtime(&t); // WARNING: this is not thread-safe!
+#endif
+
+ // Get the UTC time
+#if VMIME_HAVE_GMTIME_S
+ tm gmt;
+ ::gmtime_s(&gmt, &t);
+#elif VMIME_HAVE_GMTIME_R
+ tm gmt;
+ ::gmtime_r(&t, &gmt);
+#else
+ tm gmt = *::gmtime(&t); // WARNING: this is not thread-safe!
+#endif
+
+ // "A negative value for tm_isdst causes mktime() to attempt
+ // to determine whether Daylight Saving Time is in effect
+ // for the specified time."
+ local.tm_isdst = -1;
+ gmt.tm_isdst = -1;
+
+ // Calculate the difference (in seconds)
+ const int diff = (const int)(::mktime(&local) - ::mktime(&gmt));
+
+ // Return the date
+ return vmime::datetime(
+ local.tm_year + 1900, local.tm_mon + 1, local.tm_mday,
+ local.tm_hour, local.tm_min, local.tm_sec, diff / 60 // minutes needed
+ );
+}
+
+
+const vmime::charset windowsHandler::getLocalCharset() const {
+
+#if VMIME_HAVE_MLANG
+
+ char szCharset[256];
+
+ CoInitialize(NULL);
+ {
+ IMultiLanguage* pMultiLanguage;
+
+ CoCreateInstance(
+ CLSID_CMultiLanguage,
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ IID_IMultiLanguage,
+ (void**) &pMultiLanguage
+ );
+
+ UINT codePage = GetACP();
+ MIMECPINFO cpInfo;
+ pMultiLanguage->GetCodePageInfo(codePage, &cpInfo);
+
+ int nLengthW = lstrlenW(cpInfo.wszBodyCharset) + 1;
+
+ WideCharToMultiByte(
+ codePage, 0, cpInfo.wszBodyCharset, nLengthW,
+ szCharset, sizeof(szCharset), NULL, NULL
+ );
+
+ pMultiLanguage->Release();
+ }
+ CoUninitialize();
+
+ return vmime::charset(szCharset);
+
+#else // VMIME_HAVE_MLANG
+
+ vmime::string ch = vmime::charsets::ISO8859_1; // default
+
+ switch (GetACP()) {
+
+ case 437: ch = vmime::charsets::CP_437; break;
+ case 737: ch = vmime::charsets::CP_737; break;
+ case 775: ch = vmime::charsets::CP_775; break;
+ case 850: ch = vmime::charsets::CP_850; break;
+ case 852: ch = vmime::charsets::CP_852; break;
+ case 853: ch = vmime::charsets::CP_853; break;
+ case 855: ch = vmime::charsets::CP_855; break;
+ case 857: ch = vmime::charsets::CP_857; break;
+ case 858: ch = vmime::charsets::CP_858; break;
+ case 860: ch = vmime::charsets::CP_860; break;
+ case 861: ch = vmime::charsets::CP_861; break;
+ case 862: ch = vmime::charsets::CP_862; break;
+ case 863: ch = vmime::charsets::CP_863; break;
+ case 864: ch = vmime::charsets::CP_864; break;
+ case 865: ch = vmime::charsets::CP_865; break;
+ case 866: ch = vmime::charsets::CP_866; break;
+ case 869: ch = vmime::charsets::CP_869; break;
+ case 874: ch = vmime::charsets::CP_874; break;
+
+ case 1125: ch = vmime::charsets::CP_1125; break;
+ case 1250: ch = vmime::charsets::CP_1250; break;
+ case 1251: ch = vmime::charsets::CP_1251; break;
+ case 1252: ch = vmime::charsets::CP_1252; break;
+ case 1253: ch = vmime::charsets::CP_1253; break;
+ case 1254: ch = vmime::charsets::CP_1254; break;
+ case 1255: ch = vmime::charsets::CP_1255; break;
+ case 1256: ch = vmime::charsets::CP_1256; break;
+ case 1257: ch = vmime::charsets::CP_1257; break;
+
+ case 28591: ch = vmime::charsets::ISO8859_1; break;
+ case 28592: ch = vmime::charsets::ISO8859_2; break;
+ case 28593: ch = vmime::charsets::ISO8859_3; break;
+ case 28594: ch = vmime::charsets::ISO8859_4; break;
+ case 28595: ch = vmime::charsets::ISO8859_5; break;
+ case 28596: ch = vmime::charsets::ISO8859_6; break;
+ case 28597: ch = vmime::charsets::ISO8859_7; break;
+ case 28598: ch = vmime::charsets::ISO8859_8; break;
+ case 28599: ch = vmime::charsets::ISO8859_9; break;
+ case 28605: ch = vmime::charsets::ISO8859_15; break;
+
+ case 65000: ch = vmime::charsets::UTF_7; break;
+ case 65001: ch = vmime::charsets::UTF_8; break;
+ }
+
+ return vmime::charset(ch);
+
+#endif
+
+}
+
+
+const vmime::string windowsHandler::getHostName() const {
+
+ char hostname[1024];
+ DWORD hostnameLen;
+
+ // First, try to get a Fully-Qualified Domain Name (FQDN)
+ for (int cnf = ComputerNameDnsHostname ; cnf <= ComputerNameDnsFullyQualified ; ++cnf) {
+
+ hostnameLen = sizeof(hostname);
+
+ if (GetComputerNameEx((COMPUTER_NAME_FORMAT) cnf, hostname, &hostnameLen)) {
+
+ const vmime::string hostnameStr(hostname);
+
+ if (utility::stringUtils::isValidFQDN(hostnameStr)) {
+ return hostnameStr;
+ }
+ }
+ }
+
+ // Anything else will be OK, as long as it is a valid hostname
+ for (int cnf = 0 ; cnf < ComputerNameMax ; ++cnf) {
+
+ hostnameLen = sizeof(hostname);
+
+ if (GetComputerNameEx((COMPUTER_NAME_FORMAT) cnf, hostname, &hostnameLen)) {
+
+ const vmime::string hostnameStr(hostname);
+
+ if (utility::stringUtils::isValidHostname(hostnameStr)) {
+ return hostnameStr;
+ }
+ }
+ }
+
+ return "localhost.localdomain";
+}
+
+
+unsigned int windowsHandler::getProcessId() const {
+
+ return static_cast <unsigned int>(::GetCurrentProcessId());
+}
+
+
+unsigned int windowsHandler::getThreadId() const {
+
+ return static_cast <unsigned int>(::GetCurrentThreadId());
+}
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+shared_ptr <vmime::net::socketFactory> windowsHandler::getSocketFactory() {
+
+ return m_socketFactory;
+}
+
+#endif
+
+
+#if VMIME_HAVE_FILESYSTEM_FEATURES
+
+shared_ptr <vmime::utility::fileSystemFactory> windowsHandler::getFileSystemFactory() {
+
+ return m_fileSysFactory;
+}
+
+
+shared_ptr <vmime::utility::childProcessFactory> windowsHandler::getChildProcessFactory() {
+
+ // TODO: Not implemented
+ return null;
+}
+
+#endif
+
+
+void windowsHandler::generateRandomBytes(unsigned char* buffer, const unsigned int count) {
+
+ HCRYPTPROV cryptProvider = 0;
+ CryptAcquireContext(&cryptProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
+ CryptGenRandom(cryptProvider, static_cast <unsigned long>(count), static_cast <unsigned char*>(buffer));
+ CryptReleaseContext(cryptProvider, 0);
+}
+
+
+shared_ptr <utility::sync::criticalSection> windowsHandler::createCriticalSection() {
+
+ return make_shared <windowsCriticalSection>();
+}
+
+
+} // posix
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_WINDOWS
+
diff --git a/vmime-master/src/vmime/platforms/windows/windowsHandler.hpp b/vmime-master/src/vmime/platforms/windows/windowsHandler.hpp
new file mode 100644
index 0000000..9dda256
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/windows/windowsHandler.hpp
@@ -0,0 +1,101 @@
+//
+// 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_PLATFORMS_WINDOWS_HANDLER_HPP_INCLUDED
+#define VMIME_PLATFORMS_WINDOWS_HANDLER_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_PLATFORM_IS_WINDOWS
+
+
+#include "vmime/platform.hpp"
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+ #include "vmime/platforms/windows/windowsSocket.hpp"
+#endif
+
+#if VMIME_HAVE_FILESYSTEM_FEATURES
+ #include "vmime/platforms/windows/windowsFile.hpp"
+#endif
+
+
+namespace vmime {
+namespace platforms {
+namespace windows {
+
+
+class VMIME_EXPORT windowsHandler : public vmime::platform::handler {
+
+public:
+
+ windowsHandler();
+ ~windowsHandler();
+
+ unsigned long getUnixTime() const;
+
+ const vmime::datetime getCurrentLocalTime() const;
+
+ const vmime::charset getLocalCharset() const;
+
+ const vmime::string getHostName() const;
+
+ unsigned int getProcessId() const;
+ unsigned int getThreadId() const;
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+ shared_ptr <vmime::net::socketFactory> getSocketFactory();
+#endif
+
+#if VMIME_HAVE_FILESYSTEM_FEATURES
+ shared_ptr <vmime::utility::fileSystemFactory> getFileSystemFactory();
+
+ shared_ptr <vmime::utility::childProcessFactory> getChildProcessFactory();
+#endif
+
+ void generateRandomBytes(unsigned char* buffer, const unsigned int count);
+
+ shared_ptr <utility::sync::criticalSection> createCriticalSection();
+
+private:
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+ shared_ptr <windowsSocketFactory> m_socketFactory;
+#endif
+
+#if VMIME_HAVE_FILESYSTEM_FEATURES
+ shared_ptr <windowsFileSystemFactory> m_fileSysFactory;
+#endif
+};
+
+
+} // windows
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_WINDOWS
+
+#endif // VMIME_PLATFORMS_WINDOWS_HANDLER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/platforms/windows/windowsSocket.cpp b/vmime-master/src/vmime/platforms/windows/windowsSocket.cpp
new file mode 100644
index 0000000..3a93c53
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/windows/windowsSocket.cpp
@@ -0,0 +1,547 @@
+//
+// 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_PLATFORM_IS_WINDOWS && VMIME_HAVE_MESSAGING_FEATURES
+
+
+#pragma warning(disable: 4267)
+
+#include "vmime/platforms/windows/windowsSocket.hpp"
+
+#include "vmime/utility/stringUtils.hpp"
+#include "vmime/exception.hpp"
+
+#include <ws2tcpip.h>
+
+
+namespace vmime {
+namespace platforms {
+namespace windows {
+
+
+//
+// windowsSocket
+//
+
+windowsSocket::windowsSocket(shared_ptr <vmime::net::timeoutHandler> th)
+ : m_timeoutHandler(th),
+ m_desc(INVALID_SOCKET),
+ m_status(0) {
+
+ WSAData wsaData;
+ WSAStartup(MAKEWORD(1, 1), &wsaData);
+}
+
+
+windowsSocket::~windowsSocket() {
+
+ if (m_desc != INVALID_SOCKET) {
+ ::closesocket(m_desc);
+ }
+
+ WSACleanup();
+}
+
+
+void windowsSocket::connect(const vmime::string& address, const vmime::port_t port) {
+
+ // Close current connection, if any
+ if (m_desc != INVALID_SOCKET) {
+ ::closesocket(m_desc);
+ m_desc = INVALID_SOCKET;
+ }
+
+ // Resolve address
+ ::sockaddr_in addr;
+
+ memset(&addr, 0, sizeof(addr));
+
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(static_cast <unsigned short>(port));
+ addr.sin_addr.s_addr = ::inet_addr(address.c_str());
+
+ if (m_tracer) {
+
+ std::ostringstream trace;
+ trace << "Connecting to " << address << ", port " << port;
+
+ m_tracer->traceSend(trace.str());
+ }
+
+ if (addr.sin_addr.s_addr == static_cast <int>(-1)) {
+
+ ::hostent* hostInfo = ::gethostbyname(address.c_str());
+
+ if (!hostInfo) {
+ // Error: cannot resolve address
+ throw vmime::exceptions::connection_error("Cannot resolve address.");
+ }
+
+ memcpy(reinterpret_cast <char*>(&addr.sin_addr), hostInfo->h_addr, hostInfo->h_length);
+ }
+
+ m_serverAddress = address;
+
+ // Get a new socket
+ m_desc = ::socket(AF_INET, SOCK_STREAM, 0);
+
+ if (m_desc == INVALID_SOCKET) {
+
+ try {
+
+ int err = WSAGetLastError();
+ throwSocketError(err);
+
+ } catch (exceptions::socket_exception& e) {
+
+ throw vmime::exceptions::connection_error("Error while creating socket.", e);
+ }
+ }
+
+ // Start connection
+ if (::connect(m_desc, reinterpret_cast <sockaddr*>(&addr), sizeof(addr)) == -1) {
+
+ try {
+
+ int err = WSAGetLastError();
+ throwSocketError(err);
+
+ } catch (exceptions::socket_exception& e) {
+
+ ::closesocket(m_desc);
+ m_desc = INVALID_SOCKET;
+
+ // Error
+ throw vmime::exceptions::connection_error("Error while connecting socket.", e);
+ }
+ }
+
+ // Set socket to non-blocking
+ unsigned long non_blocking = 1;
+ ::ioctlsocket(m_desc, FIONBIO, &non_blocking);
+}
+
+
+bool windowsSocket::isConnected() const {
+
+ if (m_desc == INVALID_SOCKET) {
+ return false;
+ }
+
+ char buff;
+
+ return ::recv(m_desc, &buff, 1, MSG_PEEK) != 0;
+}
+
+
+void windowsSocket::disconnect() {
+
+ if (m_desc != INVALID_SOCKET) {
+
+ if (m_tracer) {
+ m_tracer->traceSend("Disconnecting");
+ }
+
+ ::shutdown(m_desc, SD_BOTH);
+ ::closesocket(m_desc);
+
+ m_desc = INVALID_SOCKET;
+ }
+}
+
+
+static bool isNumericAddress(const char* address) {
+
+ struct addrinfo hint, *info = NULL;
+ memset(&hint, 0, sizeof(hint));
+
+ hint.ai_family = AF_UNSPEC;
+ hint.ai_flags = AI_NUMERICHOST;
+
+ if (getaddrinfo(address, 0, &hint, &info) == 0) {
+
+ freeaddrinfo(info);
+ return true;
+
+ } else {
+
+ return false;
+ }
+}
+
+
+const string windowsSocket::getPeerAddress() const {
+
+ // Get address of connected peer
+ sockaddr peer;
+ socklen_t peerLen = sizeof(peer);
+
+ getpeername(m_desc, reinterpret_cast <sockaddr*>(&peer), &peerLen);
+
+ // Convert to numerical presentation format
+ char host[NI_MAXHOST + 1];
+ char service[NI_MAXSERV + 1];
+
+ if (getnameinfo(reinterpret_cast <sockaddr *>(&peer), peerLen,
+ host, sizeof(host), service, sizeof(service),
+ /* flags */ NI_NUMERICHOST) == 0) {
+
+ return string(host);
+ }
+
+ return ""; // should not happen
+}
+
+
+const string windowsSocket::getPeerName() const {
+
+ // Get address of connected peer
+ sockaddr peer;
+ socklen_t peerLen = sizeof(peer);
+
+ getpeername(m_desc, reinterpret_cast <sockaddr*>(&peer), &peerLen);
+
+ // If server address as specified when connecting is a numeric
+ // address, try to get a host name for it
+ if (isNumericAddress(m_serverAddress.c_str())) {
+
+ char host[NI_MAXHOST + 1];
+ char service[NI_MAXSERV + 1];
+
+ if (getnameinfo(reinterpret_cast <sockaddr *>(&peer), peerLen,
+ host, sizeof(host), service, sizeof(service),
+ /* flags */ NI_NAMEREQD) == 0) {
+
+ return string(host);
+ }
+ }
+
+ return m_serverAddress;
+}
+
+
+size_t windowsSocket::getBlockSize() const {
+
+ return 16384; // 16 KB
+}
+
+
+void windowsSocket::receive(vmime::string& buffer) {
+
+ const size_t size = receiveRaw(m_buffer, sizeof(m_buffer));
+ buffer = utility::stringUtils::makeStringFromBytes(m_buffer, size);
+}
+
+
+size_t windowsSocket::receiveRaw(byte_t* buffer, const size_t count) {
+
+ m_status &= ~STATUS_WOULDBLOCK;
+
+ // Check whether data is available
+ if (!waitForRead(50 /* msecs */)) {
+
+ // No data available at this time
+ // Check if we are timed out
+ if (m_timeoutHandler &&
+ m_timeoutHandler->isTimeOut()) {
+
+ if (!m_timeoutHandler->handleTimeOut()) {
+
+ // Server did not react within timeout delay
+ throwSocketError(WSAETIMEDOUT);
+
+ } else {
+
+ // Reset timeout
+ m_timeoutHandler->resetTimeOut();
+ }
+ }
+
+ // Continue waiting for data
+ return 0;
+ }
+
+ // Read available data
+ int ret = ::recv(m_desc, reinterpret_cast <char*>(buffer), count, 0);
+
+ if (ret == SOCKET_ERROR) {
+
+ int err = WSAGetLastError();
+
+ if (err != WSAEWOULDBLOCK) {
+ throwSocketError(err);
+ }
+
+ m_status |= STATUS_WOULDBLOCK;
+
+ // Error or no data
+ return 0;
+
+ } else if (ret == 0) {
+
+ // Host shutdown
+ throwSocketError(WSAENOTCONN);
+
+ } else {
+
+ // Data received, reset timeout
+ if (m_timeoutHandler) {
+ m_timeoutHandler->resetTimeOut();
+ }
+
+ return ret;
+ }
+}
+
+
+void windowsSocket::send(const vmime::string& buffer) {
+
+ sendRaw(reinterpret_cast <const byte_t*>(buffer.data()), buffer.length());
+}
+
+
+void windowsSocket::send(const char* str) {
+
+ sendRaw(reinterpret_cast <const byte_t*>(str), strlen(str));
+}
+
+
+void windowsSocket::sendRaw(const byte_t* buffer, const size_t count) {
+
+ m_status &= ~STATUS_WOULDBLOCK;
+
+ size_t size = count;
+
+ while (size > 0) {
+
+ const int ret = ::send(m_desc, reinterpret_cast <const char*>(buffer), size, 0);
+
+ if (ret == SOCKET_ERROR) {
+
+ int err = WSAGetLastError();
+
+ if (err != WSAEWOULDBLOCK) {
+ throwSocketError(err);
+ }
+
+ waitForWrite(50 /* msecs */);
+
+ } else {
+
+ buffer += ret;
+ size -= ret;
+ }
+ }
+
+ // Reset timeout
+ if (m_timeoutHandler) {
+ m_timeoutHandler->resetTimeOut();
+ }
+}
+
+
+size_t windowsSocket::sendRawNonBlocking(const byte_t* buffer, const size_t count) {
+
+ m_status &= ~STATUS_WOULDBLOCK;
+
+ const int ret = ::send(m_desc, reinterpret_cast <const char*>(buffer), count, 0);
+
+ if (ret == SOCKET_ERROR) {
+
+ int err = WSAGetLastError();
+
+ if (err == WSAEWOULDBLOCK) {
+
+ // Check if we are timed out
+ if (m_timeoutHandler &&
+ m_timeoutHandler->isTimeOut()) {
+
+ if (!m_timeoutHandler->handleTimeOut()) {
+
+ // Could not send data within timeout delay
+ throwSocketError(err);
+
+ } else {
+
+ // Reset timeout
+ m_timeoutHandler->resetTimeOut();
+ }
+ }
+
+ m_status |= STATUS_WOULDBLOCK;
+
+ // No data can be written at this time
+ return 0;
+
+ } else {
+
+ throwSocketError(err);
+ }
+ }
+
+ // Reset timeout
+ if (m_timeoutHandler) {
+ m_timeoutHandler->resetTimeOut();
+ }
+
+ return ret;
+}
+
+
+unsigned int windowsSocket::getStatus() const {
+
+ return m_status;
+}
+
+
+void windowsSocket::throwSocketError(const int err) {
+
+ std::ostringstream oss;
+ string msg;
+
+ LPTSTR str;
+
+ if (::FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, err, 0, (LPTSTR) &str, 0, NULL) == 0) {
+
+ // Failed getting message
+ oss << "Unknown socket error (code " << err << ")";
+
+ } else {
+
+ oss << str;
+ ::LocalFree(str);
+ }
+
+ msg = oss.str();
+
+ throw exceptions::socket_exception(msg);
+}
+
+
+bool windowsSocket::waitForData(const bool read, const bool write, const int msecs) {
+
+ for (int i = 0 ; i <= msecs / 10 ; ++i) {
+
+ // Check whether data is available
+ fd_set fds;
+ FD_ZERO(&fds);
+ FD_SET(m_desc, &fds);
+
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 10000; // 10 ms
+
+ int ret = ::select(m_desc + 1, read ? &fds : NULL, write ? &fds : NULL, NULL, &tv);
+
+ if (ret == SOCKET_ERROR) {
+
+ int err = WSAGetLastError();
+ throwSocketError(err);
+
+ } else if (ret > 0) {
+
+ return true;
+ }
+
+ // No data available at this time
+ // Check if we are timed out
+ if (m_timeoutHandler &&
+ m_timeoutHandler->isTimeOut()) {
+
+ if (!m_timeoutHandler->handleTimeOut()) {
+
+ // Server did not react within timeout delay
+ throw exceptions::operation_timed_out();
+
+ } else {
+
+ // Reset timeout
+ m_timeoutHandler->resetTimeOut();
+ }
+ }
+ }
+
+ return false; // time out
+}
+
+
+bool windowsSocket::waitForRead(const int msecs) {
+
+ return waitForData(/* read */ true, /* write */ false, msecs);
+}
+
+
+bool windowsSocket::waitForWrite(const int msecs) {
+
+ return waitForData(/* read */ false, /* write */ true, msecs);
+}
+
+
+shared_ptr <net::timeoutHandler> windowsSocket::getTimeoutHandler() {
+
+ return m_timeoutHandler;
+}
+
+
+void windowsSocket::setTracer(const shared_ptr <net::tracer>& tracer) {
+
+ m_tracer = tracer;
+}
+
+
+shared_ptr <net::tracer> windowsSocket::getTracer() {
+
+ return m_tracer;
+}
+
+
+
+//
+// posixSocketFactory
+//
+
+shared_ptr <vmime::net::socket> windowsSocketFactory::create() {
+
+ shared_ptr <vmime::net::timeoutHandler> th;
+ return make_shared <windowsSocket>(th);
+}
+
+
+shared_ptr <vmime::net::socket> windowsSocketFactory::create(const shared_ptr <vmime::net::timeoutHandler>& th) {
+
+ return make_shared <windowsSocket>(th);
+}
+
+
+} // posix
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_WINDOWS && VMIME_HAVE_MESSAGING_FEATURES
+
diff --git a/vmime-master/src/vmime/platforms/windows/windowsSocket.hpp b/vmime-master/src/vmime/platforms/windows/windowsSocket.hpp
new file mode 100644
index 0000000..ddb82da
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/windows/windowsSocket.hpp
@@ -0,0 +1,117 @@
+//
+// 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_PLATFORMS_WINDOWS_SOCKET_HPP_INCLUDED
+#define VMIME_PLATFORMS_WINDOWS_SOCKET_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_PLATFORM_IS_WINDOWS && VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include <winsock2.h>
+#include "vmime/net/socket.hpp"
+
+
+namespace vmime {
+namespace platforms {
+namespace windows {
+
+
+class windowsSocket : public vmime::net::socket {
+
+public:
+
+ windowsSocket();
+ windowsSocket(shared_ptr <vmime::net::timeoutHandler> th);
+ ~windowsSocket();
+
+public:
+
+ void connect(const vmime::string& address, const vmime::port_t port);
+ bool isConnected() const;
+ void disconnect();
+
+ bool waitForRead(const int msecs = 30000);
+ bool waitForWrite(const int msecs = 30000);
+
+ void receive(vmime::string& buffer);
+ size_t receiveRaw(byte_t* buffer, const size_t count);
+
+ void send(const vmime::string& buffer);
+ void send(const char* str);
+ void sendRaw(const byte_t* buffer, const size_t count);
+ size_t sendRawNonBlocking(const byte_t* buffer, const size_t count);
+
+ size_t getBlockSize() const;
+
+ unsigned int getStatus() const;
+
+ const string getPeerName() const;
+ const string getPeerAddress() const;
+
+ shared_ptr <net::timeoutHandler> getTimeoutHandler();
+ shared_ptr <net::tracer> m_tracer;
+
+ void setTracer(const shared_ptr <net::tracer>& tracer);
+ shared_ptr <net::tracer> getTracer();
+
+protected:
+
+ void throwSocketError(const int err);
+
+ bool waitForData(const bool read, const bool write, const int msecs);
+
+private:
+
+ shared_ptr <vmime::net::timeoutHandler> m_timeoutHandler;
+
+ byte_t m_buffer[65536];
+ SOCKET m_desc;
+
+ unsigned int m_status;
+
+ string m_serverAddress;
+};
+
+
+
+class windowsSocketFactory : public vmime::net::socketFactory {
+
+public:
+
+ shared_ptr <vmime::net::socket> create();
+ shared_ptr <vmime::net::socket> create(const shared_ptr <vmime::net::timeoutHandler>& th);
+};
+
+
+} // windows
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_WINDOWS && VMIME_HAVE_MESSAGING_FEATURES
+
+#endif // VMIME_PLATFORMS_WINDOWS_SOCKET_HPP_INCLUDED