#include "../include/FileManager.h" #include #include #include #include "../include/Config.h" FileManager::FileManager() : deleteAllowed(Config::getValue("deleteAllowed") == "true"), fileDirectory(Config::getValue("filedirectory") + ((Config::getValue("filedirectory").back() != '/') ? "/" : "")) {} FileManager::~FileManager() { cancelPut(); closeGetFile(); } bool FileManager::isUploading() { return this->putFile.is_open(); } bool FileManager::isDownloading() { return this->getFile.is_open(); } bool FileManager::openPutFile(const std::string &filename) { this->putBaseFileName = filename; this->putFileName = this->fileDirectory; this->putFileName.append(filename); std::ifstream ifile(this->putFileName); if (ifile.is_open()) { // file alread exists ifile.close(); closePutFile(); return false; } // open file and test if it already exists this->putFile.open(this->putFileName, std::ios::app | std::ios::binary); return true; } std::pair FileManager::openGetFile(const std::string &filename) { this->getBaseFileName = filename; std::string file = this->fileDirectory; file.append(filename); this->getFile.open(file, std::ios::ate | std::ios::binary); if (this->getFile.is_open() == 0) { // file does not exist or cannot be opened return std::pair(false, -1); } else { this->getFileSize = this->getFile.tellg(); int chunks = this->getFileSize / max_data_length + (this->getFileSize % max_data_length == 0 ? 0 : 1); this->getFile.seekg(std::ios::beg); return std::pair(true, chunks); } } void FileManager::closePutFile() { this->putFile.close(); } void FileManager::closeGetFile() { this->getFile.close(); } void FileManager::cancelPut() { if (isUploading()) { closePutFile(); std::remove(this->putFileName.c_str()); } } bool FileManager::checkFilename(const std::string &name) { return name.find('/') == std::string::npos; } std::string FileManager::getGetBaseFileName() { return this->getBaseFileName; } std::string FileManager::getPutBaseFileName() { return this->putBaseFileName; } void FileManager::writePut(const std::vector &data) { this->putFile.write(data.data(), data.size()); } std::vector FileManager::readGet() { // store position before read std::streamoff read = this->getFile.tellg(); if (read + max_data_length > this->getFileSize) { read = this->getFileSize % max_data_length; } else { read = max_data_length; } std::vector data; data.resize(read); this->getFile.read(data.data(), read); return data; } int FileManager::openList() { // add empty chunk vector this->list.push_back(std::vector()); int cursize = 0; for (const auto &entry : boost::filesystem::directory_iterator(this->fileDirectory)) { // getting filename from if (boost::filesystem::is_directory(entry.path())) continue; const std::string s = entry.path().filename().string(); // check if the size is too big if (s.length() > max_data_length) return -1; cursize += s.length() + 3; if (cursize > max_data_length) { this->list.push_back(std::vector()); cursize = 0; } // add string to its chunk this->list.back().push_back(s); } // empty list if no file was read if (this->list.size() == 1 && this->list.back().size() == 0) { this->list.clear(); } return this->list.size(); } int FileManager::getRemainingListChunks() { return this->list.size(); } int FileManager::getListSize() { int size = 0; for (const std::vector &l : this->list) { size += l.size(); } return size; } std::vector FileManager::getNextChunkFromList() { if (getRemainingListChunks() == 0) { // This should never happen!!! return std::vector(); } std::vector ret = this->list.back(); this->list.pop_back(); return ret; } void FileManager::cancelList() { this->list.clear(); } std::pair, FileManager::Error> FileManager::getBytesFromFile(const std::string &filename, int numOfBytes) { std::ifstream file; std::string fname = this->fileDirectory; fname.append(filename); file.open(fname, std::ios::ate | std::ios::binary); std::vector bytes; if (!file.is_open()) { return std::make_pair(bytes, FileManager::Error::no_such_file); } auto size = file.tellg(); if (size < numOfBytes) { return std::make_pair(bytes, FileManager::Error::file_too_small); } bytes.resize(numOfBytes); file.seekg(0, std::ios::beg); file.read(bytes.data(), numOfBytes); file.close(); return std::make_pair(bytes, FileManager::Error::no_error); } FileManager::Error FileManager::deleteFile(const std::string &filename) { if (!this->deleteAllowed) { return not_allowed; } std::string fname = this->fileDirectory; fname.append(filename); if (!boost::filesystem::exists(fname)) { return no_such_file; } boost::filesystem::remove(fname); return no_error; } int FileManager::openExtendedList() { this->extendedlist.push_back(std::vector>()); int cursize = 0; for (const auto &entry : boost::filesystem::directory_iterator(this->fileDirectory)) { // getting filename from if (boost::filesystem::is_directory(entry.path())) continue; const std::string name = entry.path().filename().string(); // calc head std::string head; std::pair, FileManager::Error> h = getBytesFromFile(name, 32); if (h.second == FileManager::file_too_small) h = getBytesFromFile(name, 4); if (h.second == FileManager::no_error) { std::string s(h.first.begin(), h.first.end()); head = s; } else head = ""; // calc size in kbyte std::string fname = this->fileDirectory; fname.append(name); std::ifstream file(fname, std::ios::ate | std::ios::binary); double size = (double)((double)file.tellg() / (double)1000.0); cursize += name.length() + head.length() + std::to_string(size).length() + 7; if (cursize > max_data_length) { this->extendedlist.push_back(std::vector>()); cursize = 0; } std::tuple p = std::tuple(name, head, size); this->extendedlist.back().push_back(p); } if (this->extendedlist.size() == 1 && this->extendedlist.back().size() == 0) { this->extendedlist.clear(); } return this->extendedlist.size(); } int FileManager::getRemainingExtendedListChunks() { return this->extendedlist.size(); } std::vector> FileManager::getNextChunkFromExtendedList() { if (getRemainingExtendedListChunks() == 0) return std::vector>(); std::vector> ret = this->extendedlist.back(); this->extendedlist.pop_back(); return ret; } int FileManager::getExtendedListSize() { int size = 0; for (const std::vector> v : this->extendedlist) size += v.size(); return size; } void FileManager::cancelExtendedList() { this->extendedlist.clear(); }