diff options
Diffstat (limited to 'vmime-master/src/vmime/platforms/windows/windowsFile.cpp')
-rw-r--r-- | vmime-master/src/vmime/platforms/windows/windowsFile.cpp | 712 |
1 files changed, 712 insertions, 0 deletions
diff --git a/vmime-master/src/vmime/platforms/windows/windowsFile.cpp b/vmime-master/src/vmime/platforms/windows/windowsFile.cpp new file mode 100644 index 0000000..774731c --- /dev/null +++ b/vmime-master/src/vmime/platforms/windows/windowsFile.cpp @@ -0,0 +1,712 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard <vincent@vmime.org> +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules is making +// a combined work based on this library. Thus, the terms and conditions of +// the GNU General Public License cover the whole combination. +// + +#include "vmime/config.hpp" + + +#if VMIME_PLATFORM_IS_WINDOWS && VMIME_HAVE_FILESYSTEM_FEATURES + + +#include "vmime/platforms/windows/windowsFile.hpp" + +#include <windows.h> +#include <string.h> + +#include "vmime/exception.hpp" +#include "vmime/utility/stringUtils.hpp" + + +namespace vmime { +namespace platforms { +namespace windows { + + +shared_ptr <vmime::utility::file> windowsFileSystemFactory::create( + const vmime::utility::file::path& path +) const { + + return make_shared <windowsFile>(path); +} + + +const vmime::utility::file::path windowsFileSystemFactory::stringToPath( + const vmime::string& str +) const { + + return stringToPathImpl(str); +} + + +const vmime::string windowsFileSystemFactory::pathToString( + const vmime::utility::file::path& path +) const { + + return pathToStringImpl(path); +} + + +const vmime::utility::file::path windowsFileSystemFactory::stringToPathImpl( + const vmime::string& str +) { + + vmime::size_t offset = 0; + vmime::size_t prev = 0; + + vmime::utility::file::path path; + + while ((offset = str.find_first_of("\\", offset)) != vmime::string::npos) { + + if (offset != prev) { + + path.appendComponent( + vmime::utility::file::path::component( + vmime::string(str.begin() + prev, str.begin() + offset) + ) + ); + } + + prev = offset + 1; + offset++; + } + + if (prev < str.length()) { + + path.appendComponent( + vmime::utility::file::path::component( + vmime::string(str.begin() + prev, str.end()) + ) + ); + } + + return path; +} + + +const vmime::string windowsFileSystemFactory::pathToStringImpl( + const vmime::utility::file::path& path +) { + + vmime::string native = ""; + + for (int i = 0 ; i < path.getSize() ; ++i) { + + if (i > 0) { + native += "\\"; + } + + native += path[i].getBuffer(); + } + + return native; +} + + +bool windowsFileSystemFactory::isValidPathComponent( + const vmime::utility::file::path::component& comp +) const { + + return isValidPathComponent(comp, false); +} + + +bool windowsFileSystemFactory::isValidPathComponent( + const vmime::utility::file::path::component& comp, + bool firstComponent +) const { + + const string& buffer = comp.getBuffer(); + + // If first component, check if component is a drive + if (firstComponent && (buffer.length() == 2) && (buffer[1] == ':')) { + + char drive = tolower(buffer[0]); + + if ((drive >= 'a') && (drive <= 'z')) { + return true; + } + } + + // Check for invalid characters + for (size_t i = 0 ; i < buffer.length() ; ++i) { + + const unsigned char c = buffer[i]; + + switch (c) { + + // Reserved characters + case '<': case '>': case ':': + case '"': case '/': case '\\': + case '|': case '$': case '*': + + return false; + + default: + + if (c <= 31) { + return false; + } + } + } + + string upperBuffer = vmime::utility::stringUtils::toUpper(buffer); + + // Check for reserved names + if (upperBuffer.length() == 3) { + + if (upperBuffer == "CON" || buffer == "PRN" || buffer == "AUX" || buffer == "NUL") { + return false; + } + + } else if (upperBuffer.length() == 4) { + + if ((upperBuffer.substr(0, 3) == "COM") && // COM0 to COM9 + (upperBuffer[3] >= '0') && (upperBuffer[3] <= '9')) { + + return false; + + } else if ((upperBuffer.substr(0, 3) == "LPT") && // LPT0 to LPT9 + (upperBuffer[3] >= '0') && (upperBuffer[3] <= '9')) { + + return false; + } + } + + return true; +} + + +bool windowsFileSystemFactory::isValidPath(const vmime::utility::file::path& path) const { + + for (int i = 0 ; i < path.getSize() ; ++i) { + + if (!isValidPathComponent(path[i], (i == 0))) { + return false; + } + } + + return true; +} + + +void windowsFileSystemFactory::reportError(const vmime::utility::path& path, const int err) { + + vmime::string desc; + + LPVOID lpMsgBuf; + + if (FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + err, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, + 0, + NULL)) { + + desc = (char*) lpMsgBuf; + LocalFree(lpMsgBuf); + } + + throw vmime::exceptions::filesystem_exception(desc, path); +} + + + + +windowsFile::windowsFile(const vmime::utility::file::path& path) + : m_path(path), + m_nativePath(windowsFileSystemFactory::pathToStringImpl(path)) { + +} + + +void windowsFile::createFile() { + + HANDLE hFile = CreateFile( + m_nativePath.c_str(), + GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + + if (hFile == INVALID_HANDLE_VALUE) { + windowsFileSystemFactory::reportError(m_path, GetLastError()); + } + + CloseHandle(hFile); +} + + +void windowsFile::createDirectory(const bool createAll) { + + createDirectoryImpl(m_path, m_path, createAll); +} + + +bool windowsFile::isFile() const { + + DWORD dwFileAttribute = GetFileAttributes(m_nativePath.c_str()); + + if (dwFileAttribute == INVALID_FILE_ATTRIBUTES) { + return false; + } + + return (dwFileAttribute & FILE_ATTRIBUTE_DIRECTORY) == 0; +} + + +bool windowsFile::isDirectory() const { + + DWORD dwFileAttribute = GetFileAttributes(m_nativePath.c_str()); + + if (dwFileAttribute == INVALID_FILE_ATTRIBUTES) { + return false; + } + + return (dwFileAttribute & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY; +} + + +bool windowsFile::canRead() const { + + HANDLE hFile = CreateFile( + m_nativePath.c_str(), + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + + if (hFile == INVALID_HANDLE_VALUE) { + return false; + } + + CloseHandle(hFile); + + return true; +} + + +bool windowsFile::canWrite() const { + + HANDLE hFile = CreateFile( + m_nativePath.c_str(), + GENERIC_WRITE, + FILE_SHARE_WRITE, + NULL, + OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + + if (hFile == INVALID_HANDLE_VALUE) { + return false; + } + + CloseHandle(hFile); + + return true; +} + + +windowsFile::length_type windowsFile::getLength() { + + HANDLE hFile = CreateFile( + m_nativePath.c_str(), + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + + if (hFile == INVALID_HANDLE_VALUE) { + windowsFileSystemFactory::reportError(m_path, GetLastError()); + } + + DWORD dwSize = GetFileSize(hFile, NULL); + + CloseHandle(hFile); + + return dwSize; +} + + +const vmime::utility::path& windowsFile::getFullPath() const { + + return m_path; +} + + +bool windowsFile::exists() const { + + WIN32_FIND_DATA findData; + HANDLE hFind = FindFirstFile(m_nativePath.c_str(), &findData); + + if (hFind != INVALID_HANDLE_VALUE) { + FindClose(hFind); + return true; + } + + return false; +} + + +shared_ptr <vmime::utility::file> windowsFile::getParent() const { + + if (m_path.isEmpty()) { + return null; + } else { + return make_shared <windowsFile>(m_path.getParent()); + } +} + + +void windowsFile::rename(const path& newName) { + + const vmime::string newNativeName = windowsFileSystemFactory::pathToStringImpl(newName); + + if (MoveFile(m_nativePath.c_str(), newNativeName.c_str())) { + + m_path = newName; + m_nativePath = newNativeName; + + } else { + + windowsFileSystemFactory::reportError(m_path, GetLastError()); + } +} + + +void windowsFile::remove() { + + if (!DeleteFile(m_nativePath.c_str())) { + windowsFileSystemFactory::reportError(m_path, GetLastError()); + } +} + + +shared_ptr <vmime::utility::fileWriter> windowsFile::getFileWriter() { + + return make_shared <windowsFileWriter>(m_path, m_nativePath); +} + + +shared_ptr <vmime::utility::fileReader> windowsFile::getFileReader() { + + return make_shared <windowsFileReader>(m_path, m_nativePath); +} + + +shared_ptr <vmime::utility::fileIterator> windowsFile::getFiles() const { + + return make_shared <windowsFileIterator>(m_path, m_nativePath); +} + + +void windowsFile::createDirectoryImpl( + const vmime::utility::file::path& fullPath, + const vmime::utility::file::path& path, + const bool recursive +) { + + const vmime::string nativePath = windowsFileSystemFactory::pathToStringImpl(path); + + windowsFile tmp(path); + + if (tmp.isDirectory()) { + return; + } + + if (!path.isEmpty() && recursive) { + createDirectoryImpl(fullPath, path.getParent(), true); + } + + if (!CreateDirectory(nativePath.c_str(), NULL)) { + windowsFileSystemFactory::reportError(fullPath, GetLastError()); + } +} + + + +windowsFileIterator::windowsFileIterator( + const vmime::utility::file::path& path, + const vmime::string& nativePath +) + : m_path(path), + m_nativePath(nativePath), + m_moreElements(false), + m_hFind(INVALID_HANDLE_VALUE) { + + findFirst(); +} + + +windowsFileIterator::~windowsFileIterator() { + + if (m_hFind != INVALID_HANDLE_VALUE) { + FindClose(m_hFind); + } +} + + +bool windowsFileIterator::hasMoreElements() const { + + return m_moreElements; +} + + +shared_ptr <vmime::utility::file> windowsFileIterator::nextElement() { + + shared_ptr <vmime::utility::file> pFile = make_shared <windowsFile>( + m_path / vmime::utility::file::path::component(m_findData.cFileName) + ); + + findNext(); + + return pFile; +} + + +void windowsFileIterator::findFirst() { + + m_hFind = FindFirstFile(m_nativePath.c_str(), &m_findData); + + if (m_hFind == INVALID_HANDLE_VALUE) { + m_moreElements = false; + return; + } + + m_moreElements = true; + + if (isCurrentOrParentDir()) { + findNext(); + } +} + + +void windowsFileIterator::findNext() { + + do { + + if (!FindNextFile(m_hFind, &m_findData)) { + m_moreElements = false; + return; + } + + } while (isCurrentOrParentDir()); +} + + +bool windowsFileIterator::isCurrentOrParentDir() const { + + vmime::string s(m_findData.cFileName); + + if ((s == ".") || (s == "..")) { + return true; + } + + return false; +} + + + +windowsFileReader::windowsFileReader( + const vmime::utility::file::path& path, + const vmime::string& nativePath +) + : m_path(path), + m_nativePath(nativePath) { + +} + + +shared_ptr <vmime::utility::inputStream> windowsFileReader::getInputStream() { + + HANDLE hFile = CreateFile( + m_nativePath.c_str(), + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + 0, + NULL + ); + + if (hFile == INVALID_HANDLE_VALUE) { + windowsFileSystemFactory::reportError(m_path, GetLastError()); + } + + return make_shared <windowsFileReaderInputStream>(m_path, hFile); +} + + +windowsFileReaderInputStream::windowsFileReaderInputStream( + const vmime::utility::file::path& path, + HANDLE hFile +) + : m_path(path), + m_hFile(hFile) { + +} + +windowsFileReaderInputStream::~windowsFileReaderInputStream() { + + CloseHandle(m_hFile); +} + + +bool windowsFileReaderInputStream::eof() const { + + DWORD dwSize = GetFileSize(m_hFile, NULL); + DWORD dwPosition = SetFilePointer(m_hFile, 0, NULL, FILE_CURRENT); + + return dwSize == dwPosition; +} + + +void windowsFileReaderInputStream::reset() { + + SetFilePointer(m_hFile, 0, NULL, FILE_BEGIN); +} + + +size_t windowsFileReaderInputStream::read(byte_t* const data, const size_t count) { + + DWORD dwBytesRead; + + if (!ReadFile(m_hFile, (LPVOID) data, (DWORD) count, &dwBytesRead, NULL)) { + windowsFileSystemFactory::reportError(m_path, GetLastError()); + } + + return dwBytesRead; +} + + +size_t windowsFileReaderInputStream::skip(const size_t count) { + + DWORD dwCurPos = SetFilePointer(m_hFile, 0, NULL, FILE_CURRENT); + DWORD dwNewPos = SetFilePointer(m_hFile, (LONG) count, NULL, FILE_CURRENT); + + return dwNewPos - dwCurPos; +} + + +size_t windowsFileReaderInputStream::getPosition() const { + + DWORD dwCurPos = SetFilePointer(m_hFile, 0, NULL, FILE_CURRENT); + + if (dwCurPos == INVALID_SET_FILE_POINTER) { + windowsFileSystemFactory::reportError(m_path, GetLastError()); + } + + return static_cast <size_t>(dwCurPos); +} + +void windowsFileReaderInputStream::seek(const size_t pos) { + + DWORD dwNewPos = SetFilePointer(m_hFile, (LONG) pos, NULL, FILE_BEGIN); + + if (dwNewPos == INVALID_SET_FILE_POINTER) { + windowsFileSystemFactory::reportError(m_path, GetLastError()); + } +} + + + +windowsFileWriter::windowsFileWriter( + const vmime::utility::file::path& path, + const vmime::string& nativePath +) + : m_path(path), + m_nativePath(nativePath) { + +} + +shared_ptr <vmime::utility::outputStream> windowsFileWriter::getOutputStream() { + + HANDLE hFile = CreateFile( + m_nativePath.c_str(), + GENERIC_WRITE, + FILE_SHARE_WRITE, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + + if (hFile == INVALID_HANDLE_VALUE) { + windowsFileSystemFactory::reportError(m_path, GetLastError()); + } + + return make_shared <windowsFileWriterOutputStream>(m_path, hFile); +} + + +windowsFileWriterOutputStream::windowsFileWriterOutputStream( + const vmime::utility::file::path& path, + HANDLE hFile +) + : m_path(path), + m_hFile(hFile) { + +} + + +windowsFileWriterOutputStream::~windowsFileWriterOutputStream() { + + CloseHandle(m_hFile); +} + + +void windowsFileWriterOutputStream::writeImpl(const byte_t* const data, const size_t count) { + + DWORD dwBytesWritten; + + if (!WriteFile(m_hFile, data, (DWORD) count, &dwBytesWritten, NULL)) { + windowsFileSystemFactory::reportError(m_path, GetLastError()); + } +} + + +void windowsFileWriterOutputStream::flush() { + + // TODO +} + + +} // windows +} // platforms +} // vmime + + +#endif // VMIME_PLATFORM_IS_WINDOWS && VMIME_HAVE_FILESYSTEM_FEATURES + |