Downloads: set the last modifier date/time of the files to the current UTC time, no need to expose the actual date/time
This commit is contained in:
@@ -22,6 +22,9 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
|
#include <Wt/WDate.h>
|
||||||
|
#include <Wt/WTime.h>
|
||||||
|
|
||||||
#include "utils/Path.hpp"
|
#include "utils/Path.hpp"
|
||||||
|
|
||||||
// Done using specs from https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT
|
// Done using specs from https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT
|
||||||
@@ -56,6 +59,7 @@ namespace Zip
|
|||||||
void write8(std::size_t offset, std::uint8_t value);
|
void write8(std::size_t offset, std::uint8_t value);
|
||||||
void write16(std::size_t offset, std::uint16_t value);
|
void write16(std::size_t offset, std::uint16_t value);
|
||||||
void write32(std::size_t offset, std::uint32_t value);
|
void write32(std::size_t offset, std::uint32_t value);
|
||||||
|
void writeDateTime(std::size_t offset, const Wt::WDateTime& time);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::byte* _buffer {};
|
std::byte* _buffer {};
|
||||||
@@ -84,6 +88,24 @@ namespace Zip
|
|||||||
_buffer[offset + 3] = static_cast<std::byte>(value >> 24);
|
_buffer[offset + 3] = static_cast<std::byte>(value >> 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ZipHeader::writeDateTime(std::size_t offset, const Wt::WDateTime& dateTime)
|
||||||
|
{
|
||||||
|
std::uint32_t encodedDateTime{};
|
||||||
|
|
||||||
|
// Date
|
||||||
|
encodedDateTime |= ((dateTime.date().year() - 1980) << 25);
|
||||||
|
encodedDateTime |= (dateTime.date().month() << 21);
|
||||||
|
encodedDateTime |= (dateTime.date().day() << 16);
|
||||||
|
|
||||||
|
// Time
|
||||||
|
encodedDateTime |= (dateTime.time().hour() << 11);
|
||||||
|
encodedDateTime |= (dateTime.time().minute() << 5);
|
||||||
|
encodedDateTime |= (dateTime.time().second() << 1);
|
||||||
|
|
||||||
|
write32(offset, encodedDateTime);
|
||||||
|
}
|
||||||
|
|
||||||
class LocalFileHeader : public ZipHeader
|
class LocalFileHeader : public ZipHeader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -94,11 +116,7 @@ namespace Zip
|
|||||||
void setVersionNeededToExtract(unsigned major, unsigned minor) { assert(minor < 10); write16(4, major*10 + minor); }
|
void setVersionNeededToExtract(unsigned major, unsigned minor) { assert(minor < 10); write16(4, major*10 + minor); }
|
||||||
void setGeneralPurposeFlags(std::uint16_t flags) { write16(6, flags); }
|
void setGeneralPurposeFlags(std::uint16_t flags) { write16(6, flags); }
|
||||||
void setCompressionMethod(CompressionMethod compressionMethod) { write16(8, compressionMethod); }
|
void setCompressionMethod(CompressionMethod compressionMethod) { write16(8, compressionMethod); }
|
||||||
void setLastModifiedDateTime()
|
void setLastModifiedDateTime(const Wt::WDateTime& dateTime) { writeDateTime(10, dateTime); }
|
||||||
{ // TODO
|
|
||||||
write16(10, 0); // time
|
|
||||||
write16(12, 0); // date
|
|
||||||
}
|
|
||||||
void setCrc32UncompressedData(std::uint32_t crc) { write32(14, crc); }
|
void setCrc32UncompressedData(std::uint32_t crc) { write32(14, crc); }
|
||||||
void setCompressedSize(std::size_t size) { write32(18, size); }
|
void setCompressedSize(std::size_t size) { write32(18, size); }
|
||||||
void setUncompressedSize(std::size_t size) { write32(22, size); }
|
void setUncompressedSize(std::size_t size) { write32(22, size); }
|
||||||
@@ -129,11 +147,7 @@ namespace Zip
|
|||||||
void setVersionNeededToExtract(unsigned major, unsigned minor) { assert(minor < 10); write16(6, major*10 + minor); }
|
void setVersionNeededToExtract(unsigned major, unsigned minor) { assert(minor < 10); write16(6, major*10 + minor); }
|
||||||
void setGeneralPurposeFlags(std::uint16_t flags) { write16(8, flags); }
|
void setGeneralPurposeFlags(std::uint16_t flags) { write16(8, flags); }
|
||||||
void setCompressionMethod(CompressionMethod method) { write16(10, method); }
|
void setCompressionMethod(CompressionMethod method) { write16(10, method); }
|
||||||
void setLastModifiedDateTime()
|
void setLastModifiedDateTime(const Wt::WDateTime& dateTime) { writeDateTime(12, dateTime); }
|
||||||
{
|
|
||||||
write16(12, 0); // time
|
|
||||||
write16(14, 0); // date
|
|
||||||
}
|
|
||||||
void setCrc32UncompressedData(std::uint32_t crc32) { write32(16, crc32); }
|
void setCrc32UncompressedData(std::uint32_t crc32) { write32(16, crc32); }
|
||||||
void setCompressedSize(std::size_t size) { write32(20, size); }
|
void setCompressedSize(std::size_t size) { write32(20, size); }
|
||||||
void setUncompressedSize(std::size_t size) { write32(24, size); }
|
void setUncompressedSize(std::size_t size) { write32(24, size); }
|
||||||
@@ -163,7 +177,7 @@ namespace Zip
|
|||||||
static constexpr std::size_t getHeaderSize() { return 22; }
|
static constexpr std::size_t getHeaderSize() { return 22; }
|
||||||
};
|
};
|
||||||
|
|
||||||
Zipper::Zipper(const std::map<std::string, std::filesystem::path>& files)
|
Zipper::Zipper(const std::map<std::string, std::filesystem::path>& files, const Wt::WDateTime& lastModifiedTime)
|
||||||
{
|
{
|
||||||
for (const auto& [filename, filePath] : files)
|
for (const auto& [filename, filePath] : files)
|
||||||
{
|
{
|
||||||
@@ -175,6 +189,11 @@ namespace Zip
|
|||||||
if (ec)
|
if (ec)
|
||||||
throw ZipperException {"Cannot get file size for '" + filePath.string() + "': " + ec.message()};
|
throw ZipperException {"Cannot get file size for '" + filePath.string() + "': " + ec.message()};
|
||||||
|
|
||||||
|
if (lastModifiedTime.isValid())
|
||||||
|
fileContext.lastModifiedTime = lastModifiedTime;
|
||||||
|
else
|
||||||
|
fileContext.lastModifiedTime = getLastWriteTime(filePath);
|
||||||
|
|
||||||
_files[filename] = std::move(fileContext);
|
_files[filename] = std::move(fileContext);
|
||||||
|
|
||||||
_totalZipSize += LocalFileHeader::getHeaderSize();
|
_totalZipSize += LocalFileHeader::getHeaderSize();
|
||||||
@@ -279,7 +298,7 @@ namespace Zip
|
|||||||
header.setCrc32UncompressedData(ZipHeader::UnknownCrc32);
|
header.setCrc32UncompressedData(ZipHeader::UnknownCrc32);
|
||||||
header.setCompressedSize(ZipHeader::UnknownFileSize);
|
header.setCompressedSize(ZipHeader::UnknownFileSize);
|
||||||
header.setUncompressedSize(ZipHeader::UnknownFileSize);
|
header.setUncompressedSize(ZipHeader::UnknownFileSize);
|
||||||
header.setLastModifiedDateTime(); // getLastWriteTime(*_currentFile));
|
header.setLastModifiedDateTime(_currentFile->second.lastModifiedTime);
|
||||||
header.setFileNameLength(_currentFile->first.size());
|
header.setFileNameLength(_currentFile->first.size());
|
||||||
header.setExtraFieldLength(0);
|
header.setExtraFieldLength(0);
|
||||||
|
|
||||||
@@ -393,7 +412,7 @@ namespace Zip
|
|||||||
header.setCompressionMethod(ZipHeader::CompressionMethod::NoCompression);
|
header.setCompressionMethod(ZipHeader::CompressionMethod::NoCompression);
|
||||||
header.setCompressedSize(_currentFile->second.fileSize);
|
header.setCompressedSize(_currentFile->second.fileSize);
|
||||||
header.setUncompressedSize(_currentFile->second.fileSize);
|
header.setUncompressedSize(_currentFile->second.fileSize);
|
||||||
header.setLastModifiedDateTime(); // getLastWriteTime(*_currentFile));
|
header.setLastModifiedDateTime(_currentFile->second.lastModifiedTime);
|
||||||
header.setCrc32UncompressedData(_currentFile->second.fileCrc32.getResult());
|
header.setCrc32UncompressedData(_currentFile->second.fileCrc32.getResult());
|
||||||
header.setFileNameLength(_currentFile->first.size());
|
header.setFileNameLength(_currentFile->first.size());
|
||||||
header.setExtraFieldLength(0);
|
header.setExtraFieldLength(0);
|
||||||
|
|||||||
@@ -23,6 +23,8 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
|
#include <Wt/WDateTime.h>
|
||||||
|
|
||||||
#include "Exception.hpp"
|
#include "Exception.hpp"
|
||||||
#include "utils/Crc32Calculator.hpp"
|
#include "utils/Crc32Calculator.hpp"
|
||||||
|
|
||||||
@@ -41,7 +43,7 @@ namespace Zip
|
|||||||
|
|
||||||
using SizeZype = std::uint64_t;
|
using SizeZype = std::uint64_t;
|
||||||
|
|
||||||
Zipper(const std::map<std::string, std::filesystem::path>& files);
|
Zipper(const std::map<std::string, std::filesystem::path>& files, const Wt::WDateTime& lastModifiedTime = {});
|
||||||
|
|
||||||
static constexpr std::size_t minOutputBufferSize = 64;
|
static constexpr std::size_t minOutputBufferSize = 64;
|
||||||
std::size_t writeSome(std::byte* buffer, std::size_t bufferSize);
|
std::size_t writeSome(std::byte* buffer, std::size_t bufferSize);
|
||||||
@@ -64,6 +66,7 @@ namespace Zip
|
|||||||
{
|
{
|
||||||
std::filesystem::path filePath;
|
std::filesystem::path filePath;
|
||||||
std::size_t fileSize;
|
std::size_t fileSize;
|
||||||
|
Wt::WDateTime lastModifiedTime;
|
||||||
Utils::Crc32Calculator fileCrc32;
|
Utils::Crc32Calculator fileCrc32;
|
||||||
std::size_t localFileHeaderOffset {};
|
std::size_t localFileHeaderOffset {};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -22,8 +22,8 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
|
||||||
#include <Wt/WApplication.h>
|
|
||||||
#include <Wt/Http/Response.h>
|
#include <Wt/Http/Response.h>
|
||||||
|
#include <Wt/WLocalDateTime.h>
|
||||||
|
|
||||||
#include "database/Artist.hpp"
|
#include "database/Artist.hpp"
|
||||||
#include "database/Release.hpp"
|
#include "database/Release.hpp"
|
||||||
@@ -165,7 +165,7 @@ createZipper(const std::vector<Database::Track::pointer>& tracks)
|
|||||||
files.emplace(fileName, track->getPath());
|
files.emplace(fileName, track->getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_unique<Zip::Zipper>(files);
|
return std::make_unique<Zip::Zipper>(files, Wt::WLocalDateTime::currentDateTime().toUTC());
|
||||||
}
|
}
|
||||||
|
|
||||||
DownloadReleaseResource::DownloadReleaseResource(Database::IdType releaseId)
|
DownloadReleaseResource::DownloadReleaseResource(Database::IdType releaseId)
|
||||||
|
|||||||
Reference in New Issue
Block a user