diff options
| author | Vincent Richard <[email protected]> | 2013-12-29 10:02:12 +0100 |
|---|---|---|
| committer | Vincent Richard <[email protected]> | 2013-12-29 10:02:12 +0100 |
| commit | 152c6bed75598a6ca5efb7914701157270155833 (patch) | |
| tree | 8faced1d75a45c819630323da256248415992ed0 /src/platforms | |
| parent | Merge branch 'master' of https://github.com/kisli/vmime (diff) | |
| download | vmime-152c6bed75598a6ca5efb7914701157270155833.tar.gz vmime-152c6bed75598a6ca5efb7914701157270155833.zip | |
Merged source and header files in directory structure. Got rid of SConstruct build.
Diffstat (limited to 'src/platforms')
| -rw-r--r-- | src/platforms/posix/posixChildProcess.cpp | 404 | ||||
| -rw-r--r-- | src/platforms/posix/posixCriticalSection.cpp | 67 | ||||
| -rw-r--r-- | src/platforms/posix/posixFile.cpp | 628 | ||||
| -rw-r--r-- | src/platforms/posix/posixHandler.cpp | 322 | ||||
| -rw-r--r-- | src/platforms/posix/posixSocket.cpp | 680 | ||||
| -rw-r--r-- | src/platforms/windows/windowsCriticalSection.cpp | 67 | ||||
| -rw-r--r-- | src/platforms/windows/windowsFile.cpp | 553 | ||||
| -rw-r--r-- | src/platforms/windows/windowsHandler.cpp | 329 | ||||
| -rw-r--r-- | src/platforms/windows/windowsSocket.cpp | 484 |
9 files changed, 0 insertions, 3534 deletions
diff --git a/src/platforms/posix/posixChildProcess.cpp b/src/platforms/posix/posixChildProcess.cpp deleted file mode 100644 index 54d4cd75..00000000 --- a/src/platforms/posix/posixChildProcess.cpp +++ /dev/null @@ -1,404 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules is making -// a combined work based on this library. Thus, the terms and conditions of -// the GNU General Public License cover the whole combination. -// - -#include "vmime/config.hpp" - - -#if VMIME_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 <[email protected]> -// 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) - { - std::auto_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/src/platforms/posix/posixCriticalSection.cpp b/src/platforms/posix/posixCriticalSection.cpp deleted file mode 100644 index fb2c469c..00000000 --- a/src/platforms/posix/posixCriticalSection.cpp +++ /dev/null @@ -1,67 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules is making -// a combined work based on this library. Thus, the terms and conditions of -// the GNU General Public License cover the whole combination. -// - -#include "vmime/config.hpp" - - -#if VMIME_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/src/platforms/posix/posixFile.cpp b/src/platforms/posix/posixFile.cpp deleted file mode 100644 index 9387414d..00000000 --- a/src/platforms/posix/posixFile.cpp +++ /dev/null @@ -1,628 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules is making -// a combined work based on this library. Thus, the terms and conditions of -// the GNU General Public License cover the whole combination. -// - -#include "vmime/config.hpp" - - -#if VMIME_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 != NULL) - { - 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::string(str.begin() + prev, str.begin() + offset)); - - prev = offset + 1; - offset++; - } - - if (prev < str.length()) - path.appendComponent(vmime::string(str.begin() + prev, str.end())); - - return (path); -} - - -const vmime::string posixFileSystemFactory::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 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 (int 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/src/platforms/posix/posixHandler.cpp b/src/platforms/posix/posixHandler.cpp deleted file mode 100644 index 7ab0341a..00000000 --- a/src/platforms/posix/posixHandler.cpp +++ /dev/null @@ -1,322 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules is making -// a combined work based on this library. Thus, the terms and conditions of -// the GNU General Public License cover the whole combination. -// - -#include "vmime/config.hpp" - - -#if VMIME_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 <sys/types.h> -#include <sys/stat.h> - -#if VMIME_HAVE_SYSCALL -# include <sys/syscall.h> -#endif - -#include <netdb.h> - -#include <string.h> -#include <cassert> -#include <cstdlib> - -#if VMIME_HAVE_PTHREAD -# include <pthread.h> -#endif // VMIME_HAVE_PTHREAD - -/* -#ifdef _POSIX_PRIORITY_SCHEDULING - #include <sched.h> -#endif // _POSIX_PRIORITY_SCHEDULING -*/ - - -#if VMIME_HAVE_PTHREAD - -namespace -{ - // This construction ensures mutex will be initialized in compile-time - // and will be available any time in the runtime. - pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; - - // Helper lock, to be exception safe all the time. - class PLockHelper - { - public: - - PLockHelper() - { - if (pthread_mutex_lock(&g_mutex) != 0) - assert(!"unable to lock mutex - thread safety's void"); - } - - ~PLockHelper() - { - if (pthread_mutex_unlock(&g_mutex) != 0) - assert(!"unable to unlock mutex - application's dead..."); - } - - private: - - // Object cannot be copied - PLockHelper(const PLockHelper&); - const PLockHelper& operator=(const PLockHelper&); - }; - -} // unnamed namespace - -#endif // VMIME_HAVE_PTHREAD - - -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 long 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, diff / 60); // minutes needed -} - - -const vmime::charset posixHandler::getLocalCharset() const -{ - const PLockHelper lock; - - const char* prevLocale = ::setlocale(LC_ALL, ""); - vmime::charset ch(::nl_langinfo(CODESET)); - ::setlocale(LC_ALL, prevLocale); - - return (ch); -} - - -static inline bool isFQDN(const vmime::string& str) -{ - if (utility::stringUtils::isStringEqualNoCase(str, "localhost", 9)) - return false; - - const vmime::size_t p = str.find_first_of("."); - return p != vmime::string::npos && p > 0 && p != str.length() - 1; -} - - -const vmime::string posixHandler::getHostName() const -{ - char hostname[256]; - - // Try with 'gethostname' - ::gethostname(hostname, sizeof(hostname)); - hostname[sizeof(hostname) - 1] = '\0'; - - // If this is a Fully-Qualified Domain Name (FQDN), return immediately - if (isFQDN(hostname)) - return hostname; - - if (::strlen(hostname) == 0) - ::strcpy(hostname, "localhost"); - - // Try to get canonical name for the hostname - 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) - { - for (struct addrinfo* p = info ; p != NULL ; p = p->ai_next) - { - if (isFQDN(p->ai_canonname)) - { - const string ret(p->ai_canonname); - freeaddrinfo(info); - return ret; - } - } - - freeaddrinfo(info); - } - - 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)); -#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::wait() const -{ -/* -#ifdef _POSIX_PRIORITY_SCHEDULING - ::sched_yield(); -#else - ::sleep(1); -#endif // _POSIX_PRIORITY_SCHEDULING -*/ - - struct timespec ts; - ts.tv_sec = 0; - ts.tv_nsec = 500000; // 500 microseconds - - nanosleep(&ts, NULL); -} - - -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/src/platforms/posix/posixSocket.cpp b/src/platforms/posix/posixSocket.cpp deleted file mode 100644 index ab434116..00000000 --- a/src/platforms/posix/posixSocket.cpp +++ /dev/null @@ -1,680 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules is making -// a combined work based on this library. Thus, the terms and conditions of -// the GNU General Public License cover the whole combination. -// - -#include "vmime/config.hpp" - - -#if VMIME_PLATFORM_IS_POSIX && VMIME_HAVE_MESSAGING_FEATURES - - -#include "vmime/platforms/posix/posixSocket.hpp" -#include "vmime/platforms/posix/posixHandler.hpp" - -#include <unistd.h> -#include <sys/socket.h> -#include <arpa/inet.h> -#include <sys/types.h> -#include <netinet/in.h> -#include <netdb.h> -#include <fcntl.h> -#include <errno.h> -#include <string.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 - - -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 VMIME_HAVE_GETADDRINFO // use thread-safe and IPv6-aware getaddrinfo() if available - - // Resolve address, if needed - struct ::addrinfo hints; - memset(&hints, 0, sizeof(hints)); - - hints.ai_flags = AI_CANONNAME; - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - - std::ostringstream portStr; - portStr.imbue(std::locale::classic()); - - portStr << port; - - struct ::addrinfo* res0; - - if (::getaddrinfo(address.c_str(), portStr.str().c_str(), &hints, &res0) != 0) - { - // Error: cannot resolve address - throw vmime::exceptions::connection_error("Cannot resolve address."); - } - - m_serverAddress = address; - - // Connect to host - int sock = -1; - struct ::addrinfo* res = res0; - - for ( ; sock == -1 && res != NULL ; res = res->ai_next) - { - sock = ::socket(res->ai_family, res->ai_socktype, res->ai_protocol); - - if (sock < 0) - continue; // try next - - if (m_timeoutHandler != NULL) - { - ::fcntl(sock, F_SETFL, ::fcntl(sock, F_GETFL) | O_NONBLOCK); - - if (::connect(sock, res->ai_addr, res->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: - - ::close(sock); - sock = -1; - continue; // try next - } - - // Wait for socket to be connected. - // We will check for time out every second. - fd_set fds; - FD_ZERO(&fds); - FD_SET(sock, &fds); - - fd_set fdsError; - FD_ZERO(&fdsError); - FD_SET(sock, &fdsError); - - struct timeval tm; - tm.tv_sec = 1; - tm.tv_usec = 0; - - m_timeoutHandler->resetTimeOut(); - - bool connected = false; - - do - { - const int ret = select(sock + 1, NULL, &fds, &fdsError, &tm); - - // Success - if (ret > 0) - { - connected = true; - break; - } - // Error - else if (ret < -1) - { - if (errno != EINTR) - { - // Cancel connection - break; - } - } - // 1-second timeout - else if (ret == 0) - { - if (m_timeoutHandler->isTimeOut()) - { - if (!m_timeoutHandler->handleTimeOut()) - { - // Cancel connection - break; - } - else - { - // Reset timeout and keep waiting for connection - m_timeoutHandler->resetTimeOut(); - } - } - else - { - // Keep waiting for connection - } - } - - ::sched_yield(); - - } while (true); - - if (!connected) - { - ::close(sock); - sock = -1; - continue; // try next - } - - break; - } - } - else - { - if (::connect(sock, res->ai_addr, res->ai_addrlen) < 0) - { - ::close(sock); - sock = -1; - continue; // try next - } - } - } - - ::freeaddrinfo(res0); - - if (sock == -1) - { - try - { - throwSocketError(errno); - } - catch (exceptions::socket_exception& e) - { - 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) - { - 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) - { - ::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); -} - - -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) - { - ::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); - - getpeername(m_desc, reinterpret_cast <sockaddr*>(&peer), &peerLen); - - // Convert to numerical presentation format - char numericAddress[1024]; - - if (inet_ntop(peer.sa_family, &peer, numericAddress, sizeof(numericAddress)) != NULL) - return string(numericAddress); - - return ""; // should not happen -} - - -const string posixSocket::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())) - { - -#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 -} - - -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 - fd_set fds; - FD_ZERO(&fds); - FD_SET(m_desc, &fds); - - struct timeval tv; - tv.tv_sec = 1; - tv.tv_usec = 0; - - ssize_t ret = ::select(m_desc + 1, &fds, NULL, NULL, &tv); - - if (ret < 0) - { - if (!IS_EAGAIN(errno)) - throwSocketError(errno); - - // 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(errno); - } - else - { - // Reset timeout - m_timeoutHandler->resetTimeOut(); - } - } - - m_status |= STATUS_WOULDBLOCK; - - // Continue waiting for data - return 0; - } - - // Read available data - 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) - { - const ssize_t ret = ::send(m_desc, buffer, size, 0); - - if (ret <= 0) - { - if (ret < 0 && !IS_EAGAIN(errno)) - throwSocketError(errno); - - platform::getHandler()->wait(); - } - 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; - - const ssize_t ret = ::send(m_desc, buffer, count, 0); - - 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 - throwSocketError(errno); - } - 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) -{ - string msg; - - 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 occured 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: - case ENOTCONN: msg = "ENOTCONN: not connected"; break; - case ECONNREFUSED: msg = "ECONNREFUSED: connection refused"; break; - default: - - std::ostringstream oss; - oss << ::strerror(err); - - msg = oss.str(); - break; - } - - throw exceptions::socket_exception(msg); -} - - -unsigned int posixSocket::getStatus() const -{ - return m_status; -} - - - -// -// 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(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/src/platforms/windows/windowsCriticalSection.cpp b/src/platforms/windows/windowsCriticalSection.cpp deleted file mode 100644 index d6ef0c45..00000000 --- a/src/platforms/windows/windowsCriticalSection.cpp +++ /dev/null @@ -1,67 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules is making -// a combined work based on this library. Thus, the terms and conditions of -// the GNU General Public License cover the whole combination. -// - -#include "vmime/config.hpp" - - -#if VMIME_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/src/platforms/windows/windowsFile.cpp b/src/platforms/windows/windowsFile.cpp deleted file mode 100644 index 6aa0fea8..00000000 --- a/src/platforms/windows/windowsFile.cpp +++ /dev/null @@ -1,553 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules is making -// a combined work based on this library. Thus, the terms and conditions of -// the GNU General Public License cover the whole combination. -// - -#include "vmime/config.hpp" - - -#if VMIME_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::string(str.begin() + prev, str.begin() + offset)); - - prev = offset + 1; - offset++; - } - - if (prev < str.length()) - path.appendComponent(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(fullPath); - 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/src/platforms/windows/windowsHandler.cpp b/src/platforms/windows/windowsHandler.cpp deleted file mode 100644 index 9c96b271..00000000 --- a/src/platforms/windows/windowsHandler.cpp +++ /dev/null @@ -1,329 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules is making -// a combined work based on this library. Thus, the terms and conditions of -// the GNU General Public License cover the whole combination. -// - -#include "vmime/config.hpp" - - -#if VMIME_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 -} - - -static inline bool isFQDN(const vmime::string& str) -{ - if (utility::stringUtils::isStringEqualNoCase(str, "localhost", 9)) - return false; - - const vmime::size_t p = str.find_first_of("."); - return p != vmime::string::npos && p > 0 && p != str.length() - 1; -} - - -const vmime::string windowsHandler::getHostName() const -{ - char hostname[256]; - - // Try with 'gethostname' - ::gethostname(hostname, sizeof(hostname)); - hostname[sizeof(hostname) - 1] = '\0'; - - // If this is a Fully-Qualified Domain Name (FQDN), return immediately - if (isFQDN(hostname)) - return hostname; - - if (::strlen(hostname) == 0) - { -#if VMIME_HAVE_STRCPY_S - ::strcpy_s(hostname, "localhost"); -#else - ::strcpy(hostname, "localhost"); -#endif // VMIME_HAVE_STRCPY_S - } - - // Try to get canonical name for the hostname - 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) - { - for (struct addrinfo* p = info ; p != NULL ; p = p->ai_next) - { - if (p->ai_canonname && isFQDN(p->ai_canonname)) - { - const string ret(p->ai_canonname); - freeaddrinfo(info); - return ret; - } - } - - freeaddrinfo(info); - } - - return hostname; -} - - -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::wait() const -{ - ::Sleep(100); -} - - -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/src/platforms/windows/windowsSocket.cpp b/src/platforms/windows/windowsSocket.cpp deleted file mode 100644 index 40e69363..00000000 --- a/src/platforms/windows/windowsSocket.cpp +++ /dev/null @@ -1,484 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules is making -// a combined work based on this library. Thus, the terms and conditions of -// the GNU General Public License cover the whole combination. -// - -#include "vmime/config.hpp" - - -#if VMIME_PLATFORM_IS_WINDOWS && VMIME_HAVE_MESSAGING_FEATURES - - -#pragma warning(disable: 4267) - -#include "vmime/platforms/windows/windowsSocket.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 (addr.sin_addr.s_addr == static_cast <int>(-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 == 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) - { - ::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 = vmime::string(m_buffer, size); -} - - -size_t windowsSocket::receiveRaw(char* buffer, const size_t count) -{ - m_status &= ~STATUS_WOULDBLOCK; - - // Check whether data is available - bool timedout; - waitForData(READ, timedout); - - if (timedout) - { - // 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, 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 char* buffer, const size_t count) -{ - m_status &= ~STATUS_WOULDBLOCK; - - size_t size = count; - - while (size > 0) - { - const int ret = ::send(m_desc, buffer, size, 0); - - if (ret == SOCKET_ERROR) - { - int err = WSAGetLastError(); - - if (err != WSAEWOULDBLOCK) - throwSocketError(err); - - bool timedout; - waitForData(WRITE, timedout); - } - else - { - buffer += ret; - size -= ret; - } - } - - // Reset timeout - if (m_timeoutHandler) - m_timeoutHandler->resetTimeOut(); -} - - -size_t windowsSocket::sendRawNonBlocking(const char* buffer, const size_t count) -{ - m_status &= ~STATUS_WOULDBLOCK; - - const int ret = ::send(m_desc, 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); -} - - -void windowsSocket::waitForData(const WaitOpType t, bool& timedOut) -{ - // Check whether data is available - fd_set fds; - FD_ZERO(&fds); - FD_SET(m_desc, &fds); - - struct timeval tv; - tv.tv_sec = 1; - tv.tv_usec = 0; - - int ret; - - if (t & READ) - ret = ::select(m_desc + 1, &fds, NULL, NULL, &tv); - else if (t & WRITE) - ret = ::select(m_desc + 1, NULL, &fds, NULL, &tv); - else - ret = ::select(m_desc + 1, &fds, &fds, NULL, &tv); - - timedOut = (ret == 0); - - if (ret == SOCKET_ERROR) - { - int err = WSAGetLastError(); - throwSocketError(err); - } -} - - - -// -// posixSocketFactory -// - -shared_ptr <vmime::net::socket> windowsSocketFactory::create() -{ - shared_ptr <vmime::net::timeoutHandler> th = NULL; - return make_shared <windowsSocket>(th); -} - -shared_ptr <vmime::net::socket> windowsSocketFactory::create(shared_ptr <vmime::net::timeoutHandler> th) -{ - return make_shared <windowsSocket>(th); -} - -} // posix -} // platforms -} // vmime - - -#endif // VMIME_PLATFORM_IS_WINDOWS && VMIME_HAVE_MESSAGING_FEATURES - |
