diff options
Diffstat (limited to '')
-rw-r--r-- | src/platforms/windows/windowsFile.cpp | 460 | ||||
-rw-r--r-- | src/platforms/windows/windowsHandler.cpp | 213 | ||||
-rw-r--r-- | src/platforms/windows/windowsSocket.cpp | 181 |
3 files changed, 854 insertions, 0 deletions
diff --git a/src/platforms/windows/windowsFile.cpp b/src/platforms/windows/windowsFile.cpp new file mode 100644 index 00000000..04298120 --- /dev/null +++ b/src/platforms/windows/windowsFile.cpp @@ -0,0 +1,460 @@ +// +// VMime library (http://vmime.sourceforge.net) +// Copyright (C) 2002-2005 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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "vmime/platforms/windows/windowsFile.hpp" + +#include <windows.h> +#include <string.h> + +#include "vmime/exception.hpp" + + +#if VMIME_HAVE_FILESYSTEM_FEATURES + + +namespace vmime { +namespace platforms { +namespace windows { + + +vmime::utility::file* windowsFileSystemFactory::create(const vmime::utility::file::path& path) const +{ + return new 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::string::size_type offset = 0; + vmime::string::size_type 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); +} + + +const bool windowsFileSystemFactory::isValidPathComponent(const vmime::utility::file::path::component& comp) const +{ + return (comp.getBuffer().find_first_of("\\*") == vmime::string::npos); +} + + +const bool windowsFileSystemFactory::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 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, + 0, + 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); +} + +const bool windowsFile::isFile() const +{ + DWORD dwFileAttribute = GetFileAttributes(m_nativePath.c_str()); + if (dwFileAttribute == INVALID_FILE_ATTRIBUTES) + return false; + return (dwFileAttribute & FILE_ATTRIBUTE_DIRECTORY) == 0; +} + +const 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; +} + +const bool windowsFile::canRead() const +{ + HANDLE hFile = CreateFile( + m_nativePath.c_str(), + GENERIC_READ, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (hFile == INVALID_HANDLE_VALUE) + return false; + CloseHandle(hFile); + return true; +} + +const bool windowsFile::canWrite() const +{ + HANDLE hFile = CreateFile( + m_nativePath.c_str(), + GENERIC_WRITE, + 0, + NULL, + OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (hFile == INVALID_HANDLE_VALUE) + return false; + CloseHandle(hFile); + return true; +} + +const windowsFile::length_type windowsFile::getLength() +{ + HANDLE hFile = CreateFile( + m_nativePath.c_str(), + GENERIC_READ, + 0, + 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; +} + +const 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; +} + +const vmime::utility::file* windowsFile::getParent() const +{ + if (m_path.isEmpty()) + return NULL; + else + return new 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()); +} + +vmime::utility::fileWriter* windowsFile::getFileWriter() +{ + return new windowsFileWriter(m_path, m_nativePath); +} + +vmime::utility::fileReader* windowsFile::getFileReader() +{ + return new windowsFileReader(m_path, m_nativePath); +} + +vmime::utility::fileIterator* windowsFile::getFiles() const +{ + return new 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); +} + +const bool windowsFileIterator::hasMoreElements() const +{ + return m_moreElements; +} + +vmime::utility::file* windowsFileIterator::nextElement() +{ + vmime::utility::file* pFile = new 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) +{ +} + +vmime::utility::inputStream* windowsFileReader::getInputStream() +{ + HANDLE hFile = CreateFile( + m_nativePath.c_str(), + GENERIC_READ, + 0, + NULL, + OPEN_EXISTING, + 0, + NULL); + if (hFile == INVALID_HANDLE_VALUE) + windowsFileSystemFactory::reportError(m_path, GetLastError()); + return new 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); +} + +const 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); +} + +const vmime::utility::stream::size_type windowsFileReaderInputStream::read(value_type* const data, const size_type count) +{ + DWORD dwBytesRead; + if (!ReadFile(m_hFile, (LPVOID)data, (DWORD)count, &dwBytesRead, NULL)) + windowsFileSystemFactory::reportError(m_path, GetLastError()); + return dwBytesRead; +} + +const vmime::utility::stream::size_type windowsFileReaderInputStream::skip(const size_type count) +{ + DWORD dwCurPos = SetFilePointer(m_hFile, 0, NULL, FILE_CURRENT); + DWORD dwNewPos = SetFilePointer(m_hFile, (LONG)count, NULL, FILE_CURRENT); + return (dwNewPos - dwCurPos); +} + +windowsFileWriter::windowsFileWriter(const vmime::utility::file::path& path, const vmime::string& nativePath) +: m_path(path), m_nativePath(nativePath) +{ +} + +vmime::utility::outputStream* windowsFileWriter::getOutputStream() +{ + HANDLE hFile = CreateFile( + m_nativePath.c_str(), + GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (hFile == INVALID_HANDLE_VALUE) + windowsFileSystemFactory::reportError(m_path, GetLastError()); + return new 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::write(const value_type* const data, const size_type count) +{ + DWORD dwBytesWritten; + if (!WriteFile(m_hFile, data, (DWORD)count, &dwBytesWritten, NULL)) + windowsFileSystemFactory::reportError(m_path, GetLastError()); +} + +} // windows +} // platforms +} // vmime + + +#endif // VMIME_HAVE_FILESYSTEM_FEATURES diff --git a/src/platforms/windows/windowsHandler.cpp b/src/platforms/windows/windowsHandler.cpp new file mode 100644 index 00000000..6b84f59f --- /dev/null +++ b/src/platforms/windows/windowsHandler.cpp @@ -0,0 +1,213 @@ +// +// VMime library (http://vmime.sourceforge.net) +// Copyright (C) 2002-2005 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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "vmime/platforms/windows/windowsHandler.hpp" + +#include <time.h> +#include <locale.h> +#include <process.h> +#include <mlang.h> + +namespace vmime { +namespace platforms { +namespace windows { + + +windowsHandler::windowsHandler() +{ +#if VMIME_HAVE_MESSAGING_FEATURES + m_socketFactory = new windowsSocketFactory(); +#endif +#if VMIME_HAVE_FILESYSTEM_FEATURES + m_fileSysFactory = new windowsFileSystemFactory(); +#endif +} + + +windowsHandler::~windowsHandler() +{ +#if VMIME_HAVE_MESSAGING_FEATURES + delete (m_socketFactory); +#endif +#if VMIME_HAVE_FILESYSTEM_FEATURES + delete (m_fileSysFactory); +#endif +} + + +const unsigned int windowsHandler::getUnixTime() const +{ + return (unsigned int)::time(NULL); +} + + +const vmime::datetime windowsHandler::getCurrentLocalTime() const +{ + const time_t t(::time(NULL)); + + // Get the local time +#ifdef _REENTRANT + tm local; + ::localtime_r(&t, &local); +#else + tm local = *::localtime(&t); // WARNING: this is not thread-safe! +#endif + + // Get the UTC time +#ifdef _REENTRANT + 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::getLocaleCharset() const +{ + 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); +} + + +const vmime::string windowsHandler::getHostName() const +{ + std::vector <vmime::string> hostnames; + char buffer[256]; + + // Try with 'gethostname' + ::gethostname(buffer, sizeof(buffer)); + buffer[sizeof(buffer) - 1] = '\0'; + + if (::strlen(buffer) == 0) + ::strcpy(buffer, "localhost"); + + hostnames.push_back(buffer); + + // And with 'gethostbyname' + struct hostent* he = ::gethostbyname(buffer); + + if (he != NULL) + { + if (::strlen(he->h_name) != 0) + hostnames.push_back(he->h_name); + + char** alias = he->h_aliases; + + while (alias && *alias) + { + if (::strlen(*alias) != 0) + hostnames.push_back(*alias); + + ++alias; + } + } + + // Find a Fully-Qualified Domain Name (FQDN) + for (unsigned int i = 0 ; i < hostnames.size() ; ++i) + { + if (hostnames[i].find_first_of(".") != vmime::string::npos) + return (hostnames[i]); + } + + return (hostnames[0]); +} + + +const unsigned int windowsHandler::getProcessId() const +{ + return (::getpid()); +} + + +#if VMIME_HAVE_MESSAGING_FEATURES + +vmime::messaging::socketFactory* windowsHandler::getSocketFactory + (const vmime::string& /* name */) const +{ + return (m_socketFactory); +} + + +vmime::messaging::timeoutHandlerFactory* windowsHandler::getTimeoutHandlerFactory + (const vmime::string& /* name */) const +{ + // Not used by default + return (NULL); +} + +#endif + + +#if VMIME_HAVE_FILESYSTEM_FEATURES + +vmime::utility::fileSystemFactory* windowsHandler::getFileSystemFactory() const +{ + return (m_fileSysFactory); +} + +#endif + + +void windowsHandler::wait() const +{ + ::Sleep(1000); +} + + +} // posix +} // platforms +} // vmime diff --git a/src/platforms/windows/windowsSocket.cpp b/src/platforms/windows/windowsSocket.cpp new file mode 100644 index 00000000..a572a271 --- /dev/null +++ b/src/platforms/windows/windowsSocket.cpp @@ -0,0 +1,181 @@ +// +// VMime library (http://vmime.sourceforge.net) +// Copyright (C) 2002-2005 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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#pragma warning(disable: 4267) + +#include "vmime/platforms/windows/windowsSocket.hpp" + +#include "vmime/exception.hpp" + +#if VMIME_HAVE_MESSAGING_FEATURES + +namespace vmime { +namespace platforms { +namespace windows { + + +// +// posixSocket +// + +windowsSocket::windowsSocket() + : m_desc(-1) +{ + WSAData wsaData; + WSAStartup(MAKEWORD(1, 1), &wsaData); +} + + +windowsSocket::~windowsSocket() +{ + if (m_desc != -1) + ::closesocket(m_desc); + WSACleanup(); +} + + +void windowsSocket::connect(const vmime::string& address, const vmime::port_t port) +{ + // Close current connection, if any + if (m_desc != -1) + { + ::closesocket(m_desc); + m_desc = -1; + } + + // 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); + } + + // Get a new socket + m_desc = ::socket(AF_INET, SOCK_STREAM, 0); + + if (m_desc == -1) + throw vmime::exceptions::connection_error("Error while creating socket."); + + // Start connection + if (::connect(m_desc, reinterpret_cast <sockaddr*>(&addr), sizeof(addr)) == -1) + { + ::closesocket(m_desc); + m_desc = -1; + + // Error + throw vmime::exceptions::connection_error("Error while connecting socket."); + } +} + + +const bool windowsSocket::isConnected() const +{ + return (m_desc != -1); +} + + +void windowsSocket::disconnect() +{ + if (m_desc != -1) + { + ::shutdown(m_desc, SD_BOTH); + ::closesocket(m_desc); + + m_desc = -1; + } +} + + +void windowsSocket::receive(vmime::string& buffer) +{ + int ret = ::recv(m_desc, m_buffer, sizeof(m_buffer), 0); + + if (ret == -1) + { + // Error or no data + return; + } + else if (ret > 0) + { + buffer = vmime::string(m_buffer, ret); + } +} + + +const int windowsSocket::receiveRaw(char* buffer, const int count) +{ + int ret = ::recv(m_desc, buffer, count, 0); + + if (ret == -1) + { + // Error or no data + return (0); + } + else + { + return (ret); + } +} + + +void windowsSocket::send(const vmime::string& buffer) +{ + ::send(m_desc, buffer.data(), buffer.length(), 0); +} + + +void windowsSocket::sendRaw(const char* buffer, const int count) +{ + ::send(m_desc, buffer, count, 0); +} + + + + +// +// posixSocketFactory +// + +vmime::messaging::socket* windowsSocketFactory::create() +{ + return new windowsSocket(); +} + + +} // posix +} // platforms +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES |