Added windows platform handlers.
This commit is contained in:
parent
4ab9332ce6
commit
48397a91cf
@ -2,6 +2,10 @@
|
||||
VERSION 0.6.4cvs
|
||||
================
|
||||
|
||||
2005-03-27 Stefan Uhrig <stefanuhrig@gmx.net>
|
||||
|
||||
* Added Windows platform handlers.
|
||||
|
||||
2005-03-27 Vincent Richard <vincent@vincent-richard.net>
|
||||
|
||||
* messageIdSequence.{cpp|hpp}: added a new basic type "messageIdSequence" for
|
||||
|
60
config.hpp.msvc
Normal file
60
config.hpp.msvc
Normal file
@ -0,0 +1,60 @@
|
||||
|
||||
//
|
||||
// This file was automatically generated by configuration script.
|
||||
//
|
||||
|
||||
#ifndef VMIME_CONFIG_HPP_INCLUDED
|
||||
#define VMIME_CONFIG_HPP_INCLUDED
|
||||
|
||||
|
||||
// Name of package
|
||||
#define VMIME_PACKAGE "libvmime"
|
||||
|
||||
// Version number of package
|
||||
#define VMIME_VERSION "0.6.4"
|
||||
#define VMIME_API "6:4:6"
|
||||
|
||||
// Target OS and architecture
|
||||
#define VMIME_TARGET_ARCH "i686"
|
||||
#define VMIME_TARGET_OS "msvc"
|
||||
|
||||
// Set to 1 if debugging should be activated
|
||||
#define VMIME_DEBUG 0
|
||||
|
||||
// Byte order (set one or the other, but not both!)
|
||||
#define VMIME_BYTE_ORDER_BIG_ENDIAN 0
|
||||
#define VMIME_BYTE_ORDER_LITTLE_ENDIAN 1
|
||||
|
||||
// Generic types
|
||||
// -- 8-bit
|
||||
typedef signed char vmime_int8;
|
||||
typedef unsigned char vmime_uint8;
|
||||
// -- 16-bit
|
||||
typedef signed short vmime_int16;
|
||||
typedef unsigned short vmime_uint16;
|
||||
// -- 32-bit
|
||||
typedef signed int vmime_int32;
|
||||
typedef unsigned int vmime_uint32;
|
||||
|
||||
// Options
|
||||
// -- Wide characters support
|
||||
#define VMIME_WIDE_CHAR_SUPPORT 0
|
||||
#define VMIME_INLINE_TEMPLATE_SPECIALIZATION 1
|
||||
#define VMIME_NO_MULTIPLE_INHERITANCE 1
|
||||
// -- File-system support
|
||||
#define VMIME_HAVE_FILESYSTEM_FEATURES 1
|
||||
// -- Messaging support
|
||||
#define VMIME_HAVE_MESSAGING_FEATURES 1
|
||||
// -- Built-in messaging protocols
|
||||
#define VMIME_BUILTIN_MESSAGING_PROTOS " pop3 smtp imap maildir"
|
||||
#define VMIME_BUILTIN_MESSAGING_PROTO_POP3 1
|
||||
#define VMIME_BUILTIN_MESSAGING_PROTO_SMTP 1
|
||||
#define VMIME_BUILTIN_MESSAGING_PROTO_IMAP 1
|
||||
#define VMIME_BUILTIN_MESSAGING_PROTO_MAILDIR 1
|
||||
// -- Built-in platform handlers
|
||||
#define VMIME_BUILTIN_PLATFORMS " windows"
|
||||
#define VMIME_BUILTIN_PLATFORM_WINDOWS 1
|
||||
|
||||
|
||||
#endif // VMIME_CONFIG_HPP_INCLUDED
|
||||
|
460
src/platforms/windows/windowsFile.cpp
Normal file
460
src/platforms/windows/windowsFile.cpp
Normal file
@ -0,0 +1,460 @@
|
||||
//
|
||||
// VMime library (http://vmime.sourceforge.net)
|
||||
// Copyright (C) 2002-2005 Vincent Richard <vincent@vincent-richard.net>
|
||||
//
|
||||
// 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
|
213
src/platforms/windows/windowsHandler.cpp
Normal file
213
src/platforms/windows/windowsHandler.cpp
Normal file
@ -0,0 +1,213 @@
|
||||
//
|
||||
// VMime library (http://vmime.sourceforge.net)
|
||||
// Copyright (C) 2002-2005 Vincent Richard <vincent@vincent-richard.net>
|
||||
//
|
||||
// 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
|
181
src/platforms/windows/windowsSocket.cpp
Normal file
181
src/platforms/windows/windowsSocket.cpp
Normal file
@ -0,0 +1,181 @@
|
||||
//
|
||||
// VMime library (http://vmime.sourceforge.net)
|
||||
// Copyright (C) 2002-2005 Vincent Richard <vincent@vincent-richard.net>
|
||||
//
|
||||
// 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
|
186
vmime/platforms/windows/windowsFile.hpp
Normal file
186
vmime/platforms/windows/windowsFile.hpp
Normal file
@ -0,0 +1,186 @@
|
||||
//
|
||||
// VMime library (http://vmime.sourceforge.net)
|
||||
// Copyright (C) 2002-2005 Vincent Richard <vincent@vincent-richard.net>
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#ifndef VMIME_PLATFORMS_WINDOWS_FILE_HPP_INCLUDED
|
||||
#define VMIME_PLATFORMS_WINDOWS_FILE_HPP_INCLUDED
|
||||
|
||||
|
||||
#include "vmime/utility/file.hpp"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#if VMIME_HAVE_FILESYSTEM_FEATURES
|
||||
|
||||
|
||||
namespace vmime {
|
||||
namespace platforms {
|
||||
namespace windows {
|
||||
|
||||
|
||||
class windowsFileSystemFactory : public vmime::utility::fileSystemFactory
|
||||
{
|
||||
public:
|
||||
|
||||
vmime::utility::file* create(const vmime::utility::file::path& path) const;
|
||||
|
||||
const vmime::utility::file::path stringToPath(const vmime::string& str) const;
|
||||
const vmime::string pathToString(const vmime::utility::file::path& path) const;
|
||||
|
||||
static const vmime::utility::file::path stringToPathImpl(const vmime::string& str);
|
||||
static const vmime::string pathToStringImpl(const vmime::utility::file::path& path);
|
||||
|
||||
const bool isValidPathComponent(const vmime::utility::file::path::component& comp) const;
|
||||
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);
|
||||
|
||||
public:
|
||||
void createFile();
|
||||
void createDirectory(const bool createAll = false);
|
||||
|
||||
const bool isFile() const;
|
||||
const bool isDirectory() const;
|
||||
|
||||
const bool canRead() const;
|
||||
const bool canWrite() const;
|
||||
|
||||
const length_type getLength();
|
||||
|
||||
const path& getFullPath() const;
|
||||
|
||||
const bool exists() const;
|
||||
|
||||
const file* getParent() const;
|
||||
|
||||
void rename(const path& newName);
|
||||
void remove();
|
||||
|
||||
vmime::utility::fileWriter* getFileWriter();
|
||||
|
||||
vmime::utility::fileReader* getFileReader();
|
||||
|
||||
vmime::utility::fileIterator* getFiles() const;
|
||||
|
||||
private:
|
||||
static void createDirectoryImpl(const vmime::utility::file::path& fullPath, const vmime::utility::file::path& path, const bool recursive = false);
|
||||
|
||||
private:
|
||||
vmime::utility::file::path m_path;
|
||||
vmime::string m_nativePath;
|
||||
};
|
||||
|
||||
|
||||
class windowsFileIterator : public vmime::utility::fileIterator
|
||||
{
|
||||
public:
|
||||
windowsFileIterator(const vmime::utility::file::path& path, const vmime::string& nativePath);
|
||||
~windowsFileIterator();
|
||||
|
||||
const bool hasMoreElements() const;
|
||||
vmime::utility::file* nextElement();
|
||||
|
||||
private:
|
||||
void findFirst();
|
||||
void findNext();
|
||||
bool isCurrentOrParentDir() const;
|
||||
|
||||
private:
|
||||
vmime::utility::file::path m_path;
|
||||
vmime::string m_nativePath;
|
||||
WIN32_FIND_DATA m_findData;
|
||||
bool m_moreElements;
|
||||
HANDLE m_hFind;
|
||||
};
|
||||
|
||||
|
||||
class windowsFileReader : public vmime::utility::fileReader
|
||||
{
|
||||
public:
|
||||
windowsFileReader(const vmime::utility::file::path& path, const vmime::string& nativePath);
|
||||
|
||||
public:
|
||||
vmime::utility::inputStream* getInputStream();
|
||||
|
||||
private:
|
||||
vmime::utility::file::path m_path;
|
||||
vmime::string m_nativePath;
|
||||
};
|
||||
|
||||
|
||||
class windowsFileReaderInputStream : public vmime::utility::inputStream
|
||||
{
|
||||
public:
|
||||
windowsFileReaderInputStream(const vmime::utility::file::path& path, HANDLE hFile);
|
||||
~windowsFileReaderInputStream();
|
||||
|
||||
public:
|
||||
const bool eof() const;
|
||||
void reset();
|
||||
const size_type read(value_type* const data, const size_type count);
|
||||
const size_type skip(const size_type count);
|
||||
|
||||
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:
|
||||
vmime::utility::outputStream* getOutputStream();
|
||||
|
||||
private:
|
||||
vmime::utility::file::path m_path;
|
||||
vmime::string m_nativePath;
|
||||
};
|
||||
|
||||
|
||||
class windowsFileWriterOutputStream : public vmime::utility::outputStream
|
||||
{
|
||||
public:
|
||||
windowsFileWriterOutputStream(const vmime::utility::file::path& path, HANDLE hFile);
|
||||
~windowsFileWriterOutputStream();
|
||||
|
||||
public:
|
||||
void write(const value_type* const data, const size_type count);
|
||||
|
||||
private:
|
||||
const vmime::utility::file::path m_path;
|
||||
HANDLE m_hFile;
|
||||
};
|
||||
|
||||
} // windows
|
||||
} // platforms
|
||||
} // vmime
|
||||
|
||||
|
||||
#endif // VMIME_HAVE_FILESYSTEM_FEATURES
|
||||
|
||||
#endif // VMIME_PLATFORMS_WINDOWS_FILE_HPP_INCLUDED
|
87
vmime/platforms/windows/windowsHandler.hpp
Normal file
87
vmime/platforms/windows/windowsHandler.hpp
Normal file
@ -0,0 +1,87 @@
|
||||
//
|
||||
// VMime library (http://vmime.sourceforge.net)
|
||||
// Copyright (C) 2002-2005 Vincent Richard <vincent@vincent-richard.net>
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#ifndef VMIME_PLATFORMS_WINDOWS_HANDLER_HPP_INCLUDED
|
||||
#define VMIME_PLATFORMS_WINDOWS_HANDLER_HPP_INCLUDED
|
||||
|
||||
|
||||
#include "vmime/config.hpp"
|
||||
#include "vmime/platformDependant.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 windowsHandler : public vmime::platformDependant::handler
|
||||
{
|
||||
public:
|
||||
|
||||
windowsHandler();
|
||||
~windowsHandler();
|
||||
|
||||
const unsigned int getUnixTime() const;
|
||||
|
||||
const vmime::datetime getCurrentLocalTime() const;
|
||||
|
||||
const vmime::charset getLocaleCharset() const;
|
||||
|
||||
const vmime::string getHostName() const;
|
||||
|
||||
const unsigned int getProcessId() const;
|
||||
|
||||
#if VMIME_HAVE_MESSAGING_FEATURES
|
||||
vmime::messaging::socketFactory* getSocketFactory(const vmime::string& name) const;
|
||||
|
||||
vmime::messaging::timeoutHandlerFactory* getTimeoutHandlerFactory(const vmime::string& name) const;
|
||||
#endif
|
||||
|
||||
#if VMIME_HAVE_FILESYSTEM_FEATURES
|
||||
vmime::utility::fileSystemFactory* getFileSystemFactory() const;
|
||||
#endif
|
||||
|
||||
void wait() const;
|
||||
|
||||
private:
|
||||
|
||||
#if VMIME_HAVE_MESSAGING_FEATURES
|
||||
windowsSocketFactory* m_socketFactory;
|
||||
#endif
|
||||
|
||||
#if VMIME_HAVE_FILESYSTEM_FEATURES
|
||||
windowsFileSystemFactory* m_fileSysFactory;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
} // windows
|
||||
} // platforms
|
||||
} // vmime
|
||||
|
||||
|
||||
#endif // VMIME_PLATFORMS_WINDOWS_HANDLER_HPP_INCLUDED
|
74
vmime/platforms/windows/windowsSocket.hpp
Normal file
74
vmime/platforms/windows/windowsSocket.hpp
Normal file
@ -0,0 +1,74 @@
|
||||
//
|
||||
// VMime library (http://vmime.sourceforge.net)
|
||||
// Copyright (C) 2002-2005 Vincent Richard <vincent@vincent-richard.net>
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#ifndef VMIME_PLATFORMS_WINDOWS_SOCKET_HPP_INCLUDED
|
||||
#define VMIME_PLATFORMS_WINDOWS_SOCKET_HPP_INCLUDED
|
||||
|
||||
|
||||
#include <winsock2.h>
|
||||
#include "vmime/messaging/socket.hpp"
|
||||
|
||||
|
||||
#if VMIME_HAVE_MESSAGING_FEATURES
|
||||
|
||||
|
||||
namespace vmime {
|
||||
namespace platforms {
|
||||
namespace windows {
|
||||
|
||||
|
||||
class windowsSocket : public vmime::messaging::socket
|
||||
{
|
||||
public:
|
||||
windowsSocket();
|
||||
~windowsSocket();
|
||||
|
||||
public:
|
||||
void connect(const vmime::string& address, const vmime::port_t port);
|
||||
const bool isConnected() const;
|
||||
void disconnect();
|
||||
|
||||
void receive(vmime::string& buffer);
|
||||
const int receiveRaw(char* buffer, const int count);
|
||||
|
||||
void send(const vmime::string& buffer);
|
||||
void sendRaw(const char* buffer, const int count);
|
||||
|
||||
private:
|
||||
char m_buffer[65536];
|
||||
SOCKET m_desc;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class windowsSocketFactory : public vmime::messaging::socketFactory
|
||||
{
|
||||
public:
|
||||
vmime::messaging::socket* create();
|
||||
};
|
||||
|
||||
|
||||
} // windows
|
||||
} // platforms
|
||||
} // vmime
|
||||
|
||||
|
||||
#endif // VMIME_HAVE_MESSAGING_FEATURES
|
||||
|
||||
#endif // VMIME_PLATFORMS_WINDOWS_SOCKET_HPP_INCLUDED
|
Loading…
Reference in New Issue
Block a user