From aa4d426b4d3527d7e166df1a05058c9a4a0f6683 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Fri, 30 Apr 2021 00:33:56 +0200 Subject: initial/final commit --- .../vmime/platforms/windows/windowsCodepages.hpp | 197 ++++++ .../platforms/windows/windowsCriticalSection.cpp | 67 ++ .../platforms/windows/windowsCriticalSection.hpp | 68 ++ .../src/vmime/platforms/windows/windowsFile.cpp | 712 +++++++++++++++++++++ .../src/vmime/platforms/windows/windowsFile.hpp | 225 +++++++ .../src/vmime/platforms/windows/windowsHandler.cpp | 315 +++++++++ .../src/vmime/platforms/windows/windowsHandler.hpp | 101 +++ .../src/vmime/platforms/windows/windowsSocket.cpp | 547 ++++++++++++++++ .../src/vmime/platforms/windows/windowsSocket.hpp | 117 ++++ 9 files changed, 2349 insertions(+) create mode 100644 vmime-master/src/vmime/platforms/windows/windowsCodepages.hpp create mode 100644 vmime-master/src/vmime/platforms/windows/windowsCriticalSection.cpp create mode 100644 vmime-master/src/vmime/platforms/windows/windowsCriticalSection.hpp create mode 100644 vmime-master/src/vmime/platforms/windows/windowsFile.cpp create mode 100644 vmime-master/src/vmime/platforms/windows/windowsFile.hpp create mode 100644 vmime-master/src/vmime/platforms/windows/windowsHandler.cpp create mode 100644 vmime-master/src/vmime/platforms/windows/windowsHandler.hpp create mode 100644 vmime-master/src/vmime/platforms/windows/windowsSocket.cpp create mode 100644 vmime-master/src/vmime/platforms/windows/windowsSocket.hpp (limited to 'vmime-master/src/vmime/platforms/windows') 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 +// +// 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 + + +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 +// +// 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 +// +// 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 + + +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 +// +// 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 +#include + +#include "vmime/exception.hpp" +#include "vmime/utility/stringUtils.hpp" + + +namespace vmime { +namespace platforms { +namespace windows { + + +shared_ptr windowsFileSystemFactory::create( + const vmime::utility::file::path& path +) const { + + return make_shared (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 windowsFile::getParent() const { + + if (m_path.isEmpty()) { + return null; + } else { + return make_shared (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 windowsFile::getFileWriter() { + + return make_shared (m_path, m_nativePath); +} + + +shared_ptr windowsFile::getFileReader() { + + return make_shared (m_path, m_nativePath); +} + + +shared_ptr windowsFile::getFiles() const { + + return make_shared (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 windowsFileIterator::nextElement() { + + shared_ptr pFile = make_shared ( + 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 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 (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 (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 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 (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 +// +// 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 + + +namespace vmime { +namespace platforms { +namespace windows { + + +class windowsFileSystemFactory : public vmime::utility::fileSystemFactory { + +public: + + shared_ptr 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 getParent() const; + + void rename(const path& newName); + void remove(); + + shared_ptr getFileWriter(); + + shared_ptr getFileReader(); + + shared_ptr 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 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 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 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 +// +// 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 +#include +#include +#include // for WSAStartup() +#include // for winnls.h +#include +#include + +#if VMIME_HAVE_MLANG +# include +#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 (); +#endif +#if VMIME_HAVE_FILESYSTEM_FEATURES + m_fileSysFactory = make_shared (); +#endif + +} + + +windowsHandler::~windowsHandler() { + + WSACleanup(); +} + + +unsigned long windowsHandler::getUnixTime() const { + + return static_cast (::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 (::GetCurrentProcessId()); +} + + +unsigned int windowsHandler::getThreadId() const { + + return static_cast (::GetCurrentThreadId()); +} + + +#if VMIME_HAVE_MESSAGING_FEATURES + +shared_ptr windowsHandler::getSocketFactory() { + + return m_socketFactory; +} + +#endif + + +#if VMIME_HAVE_FILESYSTEM_FEATURES + +shared_ptr windowsHandler::getFileSystemFactory() { + + return m_fileSysFactory; +} + + +shared_ptr 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 (count), static_cast (buffer)); + CryptReleaseContext(cryptProvider, 0); +} + + +shared_ptr windowsHandler::createCriticalSection() { + + return make_shared (); +} + + +} // 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 +// +// 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 getSocketFactory(); +#endif + +#if VMIME_HAVE_FILESYSTEM_FEATURES + shared_ptr getFileSystemFactory(); + + shared_ptr getChildProcessFactory(); +#endif + + void generateRandomBytes(unsigned char* buffer, const unsigned int count); + + shared_ptr createCriticalSection(); + +private: + +#if VMIME_HAVE_MESSAGING_FEATURES + shared_ptr m_socketFactory; +#endif + +#if VMIME_HAVE_FILESYSTEM_FEATURES + shared_ptr 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 +// +// 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 + + +namespace vmime { +namespace platforms { +namespace windows { + + +// +// windowsSocket +// + +windowsSocket::windowsSocket(shared_ptr 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 (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 (-1)) { + + ::hostent* hostInfo = ::gethostbyname(address.c_str()); + + if (!hostInfo) { + // Error: cannot resolve address + throw vmime::exceptions::connection_error("Cannot resolve address."); + } + + memcpy(reinterpret_cast (&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 (&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 (&peer), &peerLen); + + // Convert to numerical presentation format + char host[NI_MAXHOST + 1]; + char service[NI_MAXSERV + 1]; + + if (getnameinfo(reinterpret_cast (&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 (&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 (&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 (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 (buffer.data()), buffer.length()); +} + + +void windowsSocket::send(const char* str) { + + sendRaw(reinterpret_cast (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 (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 (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 windowsSocket::getTimeoutHandler() { + + return m_timeoutHandler; +} + + +void windowsSocket::setTracer(const shared_ptr & tracer) { + + m_tracer = tracer; +} + + +shared_ptr windowsSocket::getTracer() { + + return m_tracer; +} + + + +// +// posixSocketFactory +// + +shared_ptr windowsSocketFactory::create() { + + shared_ptr th; + return make_shared (th); +} + + +shared_ptr windowsSocketFactory::create(const shared_ptr & th) { + + return make_shared (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 +// +// 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 +#include "vmime/net/socket.hpp" + + +namespace vmime { +namespace platforms { +namespace windows { + + +class windowsSocket : public vmime::net::socket { + +public: + + windowsSocket(); + windowsSocket(shared_ptr 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 getTimeoutHandler(); + shared_ptr m_tracer; + + void setTracer(const shared_ptr & tracer); + shared_ptr getTracer(); + +protected: + + void throwSocketError(const int err); + + bool waitForData(const bool read, const bool write, const int msecs); + +private: + + shared_ptr 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 create(); + shared_ptr create(const shared_ptr & th); +}; + + +} // windows +} // platforms +} // vmime + + +#endif // VMIME_PLATFORM_IS_WINDOWS && VMIME_HAVE_MESSAGING_FEATURES + +#endif // VMIME_PLATFORMS_WINDOWS_SOCKET_HPP_INCLUDED -- cgit v1.2.3