| 98 | |
| 99 | |
| 100 | void PersistentData::processEntry(Exception& ex,Entry& entry) { |
| 101 | string directory(_rootPath); |
| 102 | |
| 103 | // Security => formalize entry.path to avoid possible /../.. issue |
| 104 | if (entry.path.empty() || (entry.path.front() != '/' && entry.path.front() != '\\')) |
| 105 | entry.path.insert(0, "/"); |
| 106 | |
| 107 | FileSystem::MakeFolder(directory.append(FileSystem::Resolve(entry.path))); |
| 108 | string name,file; |
| 109 | |
| 110 | if (!entry.toRemove) { |
| 111 | |
| 112 | // add entry |
| 113 | if (!FileSystem::CreateDirectory(ex, directory, FileSystem::HEAVY)) { |
| 114 | ex.set(Exception::FILE, "Impossible to create database directory ", directory); |
| 115 | return; |
| 116 | } |
| 117 | |
| 118 | // compute md5 |
| 119 | UInt8 result[16]; |
| 120 | EVP_Digest(entry.pBuffer->data(), entry.pBuffer->size(), result, NULL, EVP_md5(), NULL); |
| 121 | |
| 122 | Util::FormatHex(result, sizeof(result), name); |
| 123 | |
| 124 | // write the file |
| 125 | file.assign(directory).append(name); |
| 126 | #if defined(_WIN32) |
| 127 | wchar_t wFile[_MAX_PATH]; |
| 128 | MultiByteToWideChar(CP_UTF8, 0, file.c_str(), -1, wFile, _MAX_PATH); |
| 129 | ofstream ofile(wFile, ios::out | ios::binary); |
| 130 | #else |
| 131 | ofstream ofile(file, ios::out | ios::binary); |
| 132 | #endif |
| 133 | if (!ofile.good()) { |
| 134 | ex.set(Exception::FILE, "Impossible to write file ", file); |
| 135 | return; |
| 136 | } |
| 137 | ofile.write((const char*)entry.pBuffer->data(), entry.pBuffer->size()); |
| 138 | } |
| 139 | |
| 140 | // remove possible old value after writing to be safe! |
| 141 | bool hasData=false; |
| 142 | FileSystem::ForEach forEach([&ex, name, &file, &hasData](const string& path, UInt16 level){ |
| 143 | // Delete just hex file |
| 144 | if (FileSystem::IsFolder(path) || FileSystem::GetName(path, file).size() != 32 || file == name) { |
| 145 | hasData = true; |
| 146 | return; |
| 147 | } |
| 148 | // is MD5? |
| 149 | for (char c : file) { |
| 150 | if (!isxdigit(c) || (c > '9' && isupper(c))) { |
| 151 | hasData = true; |
| 152 | return; |
| 153 | } |
| 154 | } |
| 155 | if (!FileSystem::Delete(ex, path)) |
| 156 | hasData = true; |
| 157 | }); |