Handle permission denied errors.
This commit is contained in:
+17
-2
@@ -207,7 +207,13 @@ std::vector<DbFileInfo> AudioDirectoryInfoImpl::QueryTracks()
|
||||
std::vector<AudioFileMetadata> AudioDirectoryInfoImpl::GetFiles()
|
||||
{
|
||||
OpenAudioDb();
|
||||
std::vector<DbFileInfo> dbFiles = UpdateDbFiles();
|
||||
std::vector<DbFileInfo> dbFiles;
|
||||
try {
|
||||
dbFiles = UpdateDbFiles();
|
||||
} catch (const std::exception &e) {
|
||||
Lv2Log::error("Error updating audio file info: %s - %s",
|
||||
path.string().c_str(), e.what());
|
||||
}
|
||||
std::vector<AudioFileMetadata> metadataResults;
|
||||
for (const auto &dbFile : dbFiles)
|
||||
{
|
||||
@@ -298,7 +304,16 @@ std::vector<DbFileInfo> AudioDirectoryInfoImpl::UpdateDbFiles()
|
||||
|
||||
for (auto dirEntry : fs::directory_iterator(path))
|
||||
{
|
||||
if (!dirEntry.is_directory())
|
||||
bool isDirectory;
|
||||
try {
|
||||
isDirectory = dirEntry.is_directory();
|
||||
} catch (
|
||||
const std::filesystem::filesystem_error &e) {
|
||||
Lv2Log::error("Error accessing directory entry: %s - %s", dirEntry.path().string().c_str(), e.what());
|
||||
continue; // skip this entry if we cannot access it.
|
||||
}
|
||||
|
||||
if (!isDirectory)
|
||||
{
|
||||
auto path = dirEntry.path();
|
||||
std::string name = path.filename();
|
||||
|
||||
+51
-44
@@ -142,25 +142,27 @@ uint32_t FileMetadataFeature::getFileMetadata(
|
||||
json_variant jsonData;
|
||||
std::string result;
|
||||
|
||||
if (fs::exists(path))
|
||||
try
|
||||
{
|
||||
try
|
||||
if (fs::exists(path))
|
||||
{
|
||||
std::ifstream f(path);
|
||||
json_reader reader(f);
|
||||
reader.read(&jsonData);
|
||||
result = jsonData.as_object()->at(std::string(key)).as_string();
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
else
|
||||
{
|
||||
Lv2Log::debug(SS("No metadata file found for " << absolute_path << " key: " << key));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
Lv2Log::debug(SS("No metadata file found for " << absolute_path << " key: " << key));
|
||||
Lv2Log::debug(SS("Permission denied for " << absolute_path << " key: " << key));
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t len = result.length() + 1; // +1 for null terminator
|
||||
if (len > fileMetadataSize || fileMetadata == nullptr)
|
||||
{
|
||||
@@ -168,7 +170,7 @@ uint32_t FileMetadataFeature::getFileMetadata(
|
||||
return len;
|
||||
}
|
||||
memcpy(fileMetadata, result.c_str(), len);
|
||||
Lv2Log::debug(SS("Get file metadata for " << absolute_path << " key: " << key << " value: " << result));
|
||||
Lv2Log::debug(SS("Get file metadata for " << absolute_path << " key: " << key << " value: " << result));
|
||||
return len;
|
||||
}
|
||||
PIPEDAL_FileMetadata_Status FileMetadataFeature::deleteFileMetadata(
|
||||
@@ -181,52 +183,57 @@ PIPEDAL_FileMetadata_Status FileMetadataFeature::deleteFileMetadata(
|
||||
}
|
||||
Lv2Log::debug(SS("Delete file metadata for " << absolute_path << " key: " << key));
|
||||
|
||||
std::filesystem::path path{SS(absolute_path << ".mdata")};
|
||||
try {
|
||||
std::filesystem::path path{SS(absolute_path << ".mdata")};
|
||||
|
||||
if (!fs::exists(path))
|
||||
{
|
||||
return PIPEDAL_FILE_METADATA_NOT_FOUND; // Metadata file does not exist
|
||||
}
|
||||
if (!fs::exists(path))
|
||||
{
|
||||
return PIPEDAL_FILE_METADATA_NOT_FOUND; // Metadata file does not exist
|
||||
}
|
||||
|
||||
json_variant jsonData;
|
||||
try
|
||||
{
|
||||
std::ifstream f(path);
|
||||
json_reader reader(f);
|
||||
reader.read(&jsonData);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
return PIPEDAL_FILE_METADATA_NOT_FOUND; // Failed to read existing metadata
|
||||
}
|
||||
json_variant jsonData;
|
||||
try
|
||||
{
|
||||
std::ifstream f(path);
|
||||
json_reader reader(f);
|
||||
reader.read(&jsonData);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
return PIPEDAL_FILE_METADATA_NOT_FOUND; // Failed to read existing metadata
|
||||
}
|
||||
|
||||
auto obj = jsonData.as_object();
|
||||
auto it = obj->find(std::string(key));
|
||||
if (it == obj->end())
|
||||
{
|
||||
return PIPEDAL_FILE_METADATA_NOT_FOUND; // Key not found
|
||||
}
|
||||
auto obj = jsonData.as_object();
|
||||
auto it = obj->find(std::string(key));
|
||||
if (it == obj->end())
|
||||
{
|
||||
return PIPEDAL_FILE_METADATA_NOT_FOUND; // Key not found
|
||||
}
|
||||
|
||||
obj->erase(it);
|
||||
obj->erase(it);
|
||||
|
||||
if (obj->begin() == obj->end())
|
||||
{
|
||||
// If the object is empty, delete the metadata file
|
||||
fs::remove(path);
|
||||
return PIPEDAL_FILE_METADATA_SUCCESS; // Metadata deleted successfully
|
||||
}
|
||||
if (obj->begin() == obj->end())
|
||||
{
|
||||
// If the object is empty, delete the metadata file
|
||||
fs::remove(path);
|
||||
return PIPEDAL_FILE_METADATA_SUCCESS; // Metadata deleted successfully
|
||||
}
|
||||
|
||||
std::ofstream f(path);
|
||||
if (!f.is_open())
|
||||
{
|
||||
Lv2Log::error(SS("Failed to write metadata file " << path));
|
||||
std::ofstream f(path);
|
||||
if (!f.is_open())
|
||||
{
|
||||
Lv2Log::error(SS("Failed to write metadata file " << path));
|
||||
return PIPEDAL_FILE_METADATA_PERMISSION_DENIED; // Failed to open existing metadata
|
||||
}
|
||||
|
||||
json_writer writer(f);
|
||||
writer.write(jsonData);
|
||||
|
||||
return PIPEDAL_FILE_METADATA_SUCCESS;
|
||||
} catch (const std::exception &e) {
|
||||
Lv2Log::error(SS("Exception while deleting metadata: " << e.what()));
|
||||
return PIPEDAL_FILE_METADATA_PERMISSION_DENIED; // Failed to open existing metadata
|
||||
}
|
||||
|
||||
json_writer writer(f);
|
||||
writer.write(jsonData);
|
||||
|
||||
return PIPEDAL_FILE_METADATA_SUCCESS;
|
||||
}
|
||||
|
||||
PIPEDAL_FileMetadata_Status FileMetadataFeature::S_setFileMetadata(
|
||||
|
||||
+76
-50
@@ -1690,7 +1690,8 @@ static void AddFilesToResult(
|
||||
}
|
||||
catch (const std::exception &error)
|
||||
{
|
||||
throw std::logic_error("GetFileList failed. Directory not found: " + rootPath.string());
|
||||
throw std::logic_error(
|
||||
SS("GetFileList failed. " << rootPath.string() << " - " << error.what()));
|
||||
}
|
||||
|
||||
// sort lexicographically
|
||||
@@ -1723,7 +1724,7 @@ static void AddTracksToResult(
|
||||
std::set<std::string> validExtensions = fileProperty.GetPermittedFileExtensions(
|
||||
modDirectoryInfo ? modDirectoryInfo->modType : "");
|
||||
|
||||
if (validExtensions.size() == 0)
|
||||
if (validExtensions.size() == 0)
|
||||
{
|
||||
const auto &audioExtensions = MimeTypes::instance().AudioExtensions();
|
||||
validExtensions.insert(audioExtensions.begin(), audioExtensions.end());
|
||||
@@ -1733,54 +1734,76 @@ static void AddTracksToResult(
|
||||
try
|
||||
{
|
||||
// Add directories first.
|
||||
for (auto const &dir_entry : std::filesystem::directory_iterator(rootPath))
|
||||
try
|
||||
{
|
||||
if (!IsValidUtf8(dir_entry.path().string()))
|
||||
for (auto const &dir_entry : std::filesystem::directory_iterator(rootPath))
|
||||
{
|
||||
Lv2Log::warning("Invalid UTF-8 name in directory: " + dir_entry.path().string());
|
||||
continue; // skip invalid UTF-8 names.
|
||||
}
|
||||
const auto &path = dir_entry.path();
|
||||
auto name = path.filename().string();
|
||||
if (dir_entry.is_directory())
|
||||
{
|
||||
resultFiles.push_back(FileEntry{path, name, true, fs::is_symlink(path)});
|
||||
if (!IsValidUtf8(dir_entry.path().string()))
|
||||
{
|
||||
Lv2Log::warning("Invalid UTF-8 name in directory: " + dir_entry.path().string());
|
||||
continue; // skip invalid UTF-8 names.
|
||||
}
|
||||
const auto &path = dir_entry.path();
|
||||
auto name = path.filename().string();
|
||||
try {
|
||||
if (dir_entry.is_directory())
|
||||
{
|
||||
resultFiles.push_back(FileEntry{path, name, true, dir_entry.is_symlink()});
|
||||
}
|
||||
} catch (const std::exception &e)
|
||||
{
|
||||
Lv2Log::warning(SS("Failed to add directory entry: " << path.string() << " - " << e.what()));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::exception &error)
|
||||
{
|
||||
throw std::logic_error(
|
||||
SS("AddTracksToResult failed to enumerate directories. " << rootPath.string() << " - " << error.what()));
|
||||
}
|
||||
auto collator = Locale::GetInstance()->GetCollator();
|
||||
std::sort(
|
||||
resultFiles.begin(),
|
||||
resultFiles.begin(),
|
||||
resultFiles.end(),
|
||||
[collator](const FileEntry &l, const FileEntry &r)
|
||||
{
|
||||
if (l.isDirectory_ != r.isDirectory_)
|
||||
{
|
||||
return l.isDirectory_ > r.isDirectory_;
|
||||
}
|
||||
return collator->Compare(l.displayName_ ,r.displayName_) < 0;
|
||||
});
|
||||
if (l.isDirectory_ != r.isDirectory_)
|
||||
{
|
||||
return l.isDirectory_ > r.isDirectory_;
|
||||
}
|
||||
return collator->Compare(l.displayName_, r.displayName_) < 0;
|
||||
});
|
||||
// Add audio files.
|
||||
auto audioFiles = AudioDirectoryInfo::Create(rootPath,
|
||||
GetShadowIndexDirectory(audioRootDirectory,rootPath)
|
||||
);
|
||||
for (const auto &audioFile : audioFiles->GetFiles())
|
||||
GetShadowIndexDirectory(audioRootDirectory, rootPath));
|
||||
|
||||
try
|
||||
{
|
||||
fs::path audioFilePath = rootPath / audioFile.fileName();
|
||||
std::string extension = UiFileProperty::GetFileExtension(audioFilePath);
|
||||
if (validExtensions.size() == 0 || validExtensions.contains(extension) || validExtensions.contains(".*"))
|
||||
for (const auto &audioFile : audioFiles->GetFiles())
|
||||
{
|
||||
resultFiles.push_back(
|
||||
FileEntry(
|
||||
audioFilePath,
|
||||
audioFile.title(),
|
||||
false,
|
||||
std::make_shared<AudioFileMetadata>(audioFile)));
|
||||
fs::path audioFilePath = rootPath / audioFile.fileName();
|
||||
std::string extension = UiFileProperty::GetFileExtension(audioFilePath);
|
||||
if (validExtensions.size() == 0 || validExtensions.contains(extension) || validExtensions.contains(".*"))
|
||||
{
|
||||
resultFiles.push_back(
|
||||
FileEntry(
|
||||
audioFilePath,
|
||||
audioFile.title(),
|
||||
false,
|
||||
std::make_shared<AudioFileMetadata>(audioFile)));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::exception &error)
|
||||
{
|
||||
throw std::logic_error(
|
||||
SS("AddTracksToResult failed to enumerate audio files. " << rootPath.string() << " - " << error.what()));
|
||||
}
|
||||
|
||||
}
|
||||
catch (const std::exception &error)
|
||||
{
|
||||
throw std::logic_error("GetFileList failed. Directory not found: " + rootPath.string());
|
||||
throw std::logic_error(SS("GetFileList failed. " << error.what() << "(" << rootPath.string() << ")"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1869,7 +1892,7 @@ FileRequestResult Storage::GetModFileList2(const std::string &relativePath, cons
|
||||
|
||||
if (IsInAudioTracksDirectory(relativePath))
|
||||
{
|
||||
AddTracksToResult(this->GetPluginUploadDirectory(),result, rootModDirectory, fileProperty, relativePath);
|
||||
AddTracksToResult(this->GetPluginUploadDirectory(), result, rootModDirectory, fileProperty, relativePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2046,7 +2069,7 @@ void Storage::DeleteSampleFile(const std::filesystem::path &fileName)
|
||||
else
|
||||
{
|
||||
std::filesystem::remove(fileName);
|
||||
if (IsInAudioTracksDirectory(fileName))
|
||||
if (IsInAudioTracksDirectory(fileName))
|
||||
{
|
||||
// remove the metadata file as well.
|
||||
std::filesystem::remove(fileName.string() + ".mdata");
|
||||
@@ -2074,13 +2097,12 @@ std::filesystem::path Storage::MakeUserFilePath(const std::string &directory, co
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool Storage::IsValidArtworkFile(const std::filesystem::path& fullPath)
|
||||
bool Storage::IsValidArtworkFile(const std::filesystem::path &fullPath)
|
||||
{
|
||||
if (IsInAudioTracksDirectory(fullPath) && isArtworkFileName(fullPath.filename().string()))
|
||||
{
|
||||
// allow artwork files.
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -2208,9 +2230,10 @@ std::string Storage::RenameFilePropertyFile(
|
||||
}
|
||||
|
||||
std::filesystem::rename(oldPath, newPath);
|
||||
if (fs::exists(oldPath.string()+".mdata")) {
|
||||
if (fs::exists(oldPath.string() + ".mdata"))
|
||||
{
|
||||
// rename the metadata file as well.
|
||||
std::filesystem::rename(oldPath.string()+".mdata", newPath.string()+".mdata");
|
||||
std::filesystem::rename(oldPath.string() + ".mdata", newPath.string() + ".mdata");
|
||||
}
|
||||
return newPath;
|
||||
}
|
||||
@@ -2222,12 +2245,13 @@ fs::path MakeVersionedPath(const fs::path &path)
|
||||
return path; // no need to version a non-existing file.
|
||||
}
|
||||
fs::path newPath = path;
|
||||
auto stem = newPath.stem().string();;
|
||||
auto stem = newPath.stem().string();
|
||||
;
|
||||
if (stem.ends_with(")"))
|
||||
{
|
||||
// remove the trailing (n) from the file name.
|
||||
size_t pos = stem.find_last_of('(');
|
||||
std::string stemVersion = stem.substr(pos+1, stem.length()-1-(pos+1));
|
||||
std::string stemVersion = stem.substr(pos + 1, stem.length() - 1 - (pos + 1));
|
||||
// check if it is a number.
|
||||
if (stemVersion.find_first_not_of("0123456789") == std::string::npos)
|
||||
{
|
||||
@@ -2237,7 +2261,7 @@ fs::path MakeVersionedPath(const fs::path &path)
|
||||
{
|
||||
// remove trailing space.
|
||||
stem = stem.substr(0, stem.length() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2246,12 +2270,15 @@ fs::path MakeVersionedPath(const fs::path &path)
|
||||
{
|
||||
// append (n) to the file name.
|
||||
std::string newFileName;
|
||||
if (version == 0) {
|
||||
if (version == 0)
|
||||
{
|
||||
newFileName = SS(stem << newPath.extension().string());
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// append (n) to the file name.
|
||||
newFileName = SS(stem << " (" << std::to_string(version) << ")" << newPath.extension().string());
|
||||
}
|
||||
}
|
||||
newPath = newPath.parent_path() / newFileName;
|
||||
++version;
|
||||
}
|
||||
@@ -2280,7 +2307,6 @@ std::string Storage::CopyFilePropertyFile(
|
||||
|
||||
std::filesystem::path newPath = this->GetPluginUploadDirectory() / uiFileProperty.directory() / newRelativePath;
|
||||
|
||||
|
||||
if (!this->IsValidSampleFileName(newPath))
|
||||
{
|
||||
throw std::runtime_error("Invalid file name.");
|
||||
@@ -2299,14 +2325,14 @@ std::string Storage::CopyFilePropertyFile(
|
||||
|
||||
std::filesystem::create_hard_link(oldPath, newPath);
|
||||
|
||||
if (IsInAudioTracksDirectory(oldPath)
|
||||
&& IsInAudioTracksDirectory(newPath))
|
||||
if (IsInAudioTracksDirectory(oldPath) && IsInAudioTracksDirectory(newPath))
|
||||
{
|
||||
std::filesystem::path metadataPath = SS(oldPath.string() << ".mdata");
|
||||
if (fs::exists(metadataPath)) {
|
||||
if (fs::exists(metadataPath))
|
||||
{
|
||||
// copy the metadata file as well.
|
||||
std::filesystem::copy_file(
|
||||
metadataPath,
|
||||
metadataPath,
|
||||
SS(newPath.string() << ".mdata"),
|
||||
fs::copy_options::overwrite_existing);
|
||||
}
|
||||
|
||||
+81
-76
@@ -52,15 +52,13 @@ static const std::string PLUGIN_PRESETS_MIME_TYPE = "application/vnd.pipedal.plu
|
||||
static const std::string PRESET_MIME_TYPE = "application/vnd.pipedal.preset";
|
||||
static const std::string BANK_MIME_TYPE = "application/vnd.pipedal.bank";
|
||||
|
||||
static const std::string CACHE_CONTROL_INDEFINITELY = "max-age=31536000,public,immutable"; // 1 year
|
||||
static const std::string CACHE_CONTROL_SHORT = "max-age=300,public"; // 5 minutes
|
||||
|
||||
static const std::string CACHE_CONTROL_INDEFINITELY = "max-age=31536000,public,immutable"; // 1 year
|
||||
static const std::string CACHE_CONTROL_SHORT = "max-age=300,public"; // 5 minutes
|
||||
|
||||
using namespace pipedal;
|
||||
using namespace boost::system;
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
|
||||
class UserUploadResponse
|
||||
{
|
||||
public:
|
||||
@@ -87,7 +85,7 @@ int32_t ConvertThumbnailSize(const std::string ¶m)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return static_cast<int32_t > (std::stoi(param));
|
||||
return static_cast<int32_t>(std::stoi(param));
|
||||
}
|
||||
|
||||
static bool IsZipFile(const std::filesystem::path &path)
|
||||
@@ -128,7 +126,6 @@ private:
|
||||
std::vector<std::string> extensions;
|
||||
};
|
||||
|
||||
|
||||
class DownloadIntercept : public RequestHandler
|
||||
{
|
||||
PiPedalModel *model;
|
||||
@@ -392,16 +389,15 @@ public:
|
||||
{
|
||||
auto lastModified = std::filesystem::last_write_time(path);
|
||||
res.set(HttpField::LastModified, HtmlHelper::timeToHttpDate(lastModified));
|
||||
}
|
||||
AudioDirectoryInfo::Ptr CreateDirectoryInfo(const fs::path &path) {
|
||||
}
|
||||
AudioDirectoryInfo::Ptr CreateDirectoryInfo(const fs::path &path)
|
||||
{
|
||||
return AudioDirectoryInfo::Create(path,
|
||||
GetShadowIndexDirectory(
|
||||
this->model->GetPluginUploadDirectory(),
|
||||
path));
|
||||
GetShadowIndexDirectory(
|
||||
this->model->GetPluginUploadDirectory(),
|
||||
path));
|
||||
}
|
||||
|
||||
|
||||
|
||||
virtual void get_response(
|
||||
const uri &request_uri,
|
||||
HttpRequest &req,
|
||||
@@ -500,89 +496,98 @@ public:
|
||||
throw PiPedalException("File not found.");
|
||||
}
|
||||
AudioDirectoryInfo::Ptr audioDirectory = CreateDirectoryInfo(path.parent_path());
|
||||
auto files = audioDirectory->GetFiles();
|
||||
for (const auto &file : files)
|
||||
try
|
||||
{
|
||||
std::string fileNameOnly = path.filename();
|
||||
if (file.fileName() == fileNameOnly)
|
||||
auto files = audioDirectory->GetFiles();
|
||||
for (const auto &file : files)
|
||||
{
|
||||
std::stringstream ss;
|
||||
json_writer writer(ss);
|
||||
writer.write(file);
|
||||
res.setBody(ss.str());
|
||||
return;
|
||||
std::string fileNameOnly = path.filename();
|
||||
if (file.fileName() == fileNameOnly)
|
||||
{
|
||||
std::stringstream ss;
|
||||
json_writer writer(ss);
|
||||
writer.write(file);
|
||||
res.setBody(ss.str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
Lv2Log::error("Error getting audio directory info: %s - (%s)", path.c_str(), e.what());
|
||||
throw e;
|
||||
}
|
||||
// If we get here, the file was not found in the directory.
|
||||
throw PiPedalException("File not found in directory.");
|
||||
}
|
||||
else if (segment == "Thumbnail")
|
||||
{
|
||||
ThumbnailTemporaryFile thumbnailTemporaryFile;
|
||||
try
|
||||
{
|
||||
fs::path path = request_uri.query("path");
|
||||
if (path.empty() ||
|
||||
!fs::exists(path) ||
|
||||
!this->model->IsInUploadsDirectory(path) ||
|
||||
HasDotDot(path))
|
||||
std::shared_ptr<TemporaryFile> thumbnail;
|
||||
try
|
||||
{
|
||||
// path for folder thumbnails.
|
||||
path = request_uri.query("ffile");
|
||||
|
||||
std::shared_ptr<TemporaryFile> thumbnail;
|
||||
|
||||
if (!path.empty() && fs::exists(path) &&
|
||||
this->model->IsInUploadsDirectory(path) &&
|
||||
!HasDotDot(path))
|
||||
fs::path path = request_uri.query("path");
|
||||
if (path.empty() ||
|
||||
!fs::exists(path) ||
|
||||
!this->model->IsInUploadsDirectory(path) ||
|
||||
HasDotDot(path))
|
||||
{
|
||||
// path is a folder.
|
||||
thumbnail = std::make_shared<TemporaryFile>();
|
||||
thumbnail->SetNonDeletedPath(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto t = AudioDirectoryInfo::DefaultThumbnailTemporaryFile();
|
||||
thumbnail = std::make_shared<TemporaryFile>();
|
||||
thumbnail->SetNonDeletedPath(t.Path());
|
||||
|
||||
std::shared_ptr<TemporaryFile> thumbnail;
|
||||
// path for folder thumbnails.
|
||||
path = request_uri.query("ffile");
|
||||
|
||||
if (!path.empty() && fs::exists(path) &&
|
||||
this->model->IsInUploadsDirectory(path) &&
|
||||
!HasDotDot(path))
|
||||
{
|
||||
// path is a folder.
|
||||
thumbnail = std::make_shared<TemporaryFile>();
|
||||
thumbnail->SetNonDeletedPath(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto t = AudioDirectoryInfo::DefaultThumbnailTemporaryFile();
|
||||
thumbnail = std::make_shared<TemporaryFile>();
|
||||
thumbnail->SetNonDeletedPath(t.Path());
|
||||
}
|
||||
|
||||
res.set(HttpField::content_type, MimeTypes::instance().MimeTypeFromExtension(path.extension()));
|
||||
res.set(HttpField::cache_control, CACHE_CONTROL_INDEFINITELY); // URL is cache-busted, and will change if the file ismodified.
|
||||
setLastModifiedFromFile(res, thumbnail->Path());
|
||||
res.set(HttpField::content_length, std::to_string(fs::file_size(thumbnail->Path())));
|
||||
res.setBodyFile(thumbnail);
|
||||
return;
|
||||
}
|
||||
|
||||
res.set(HttpField::content_type, MimeTypes::instance().MimeTypeFromExtension(path.extension()));
|
||||
res.set(HttpField::cache_control, CACHE_CONTROL_INDEFINITELY); // URL is cache-busted, and will change if the file ismodified.
|
||||
setLastModifiedFromFile(res,thumbnail->Path());
|
||||
res.set(HttpField::content_length, std::to_string(fs::file_size(thumbnail->Path())));
|
||||
res.setBodyFile(thumbnail);
|
||||
return;
|
||||
int32_t width = ConvertThumbnailSize(request_uri.query("w"));
|
||||
int32_t height = ConvertThumbnailSize(request_uri.query("h"));
|
||||
|
||||
AudioDirectoryInfo::Ptr audioDirectory = CreateDirectoryInfo(
|
||||
path.parent_path());
|
||||
audioDirectory->GetFiles(); // ensure that the .index file is up to date.
|
||||
|
||||
thumbnailTemporaryFile = audioDirectory->GetThumbnail(path.filename(), width, height);
|
||||
}
|
||||
|
||||
|
||||
int32_t width = ConvertThumbnailSize(request_uri.query("w"));
|
||||
int32_t height = ConvertThumbnailSize(request_uri.query("h"));
|
||||
|
||||
AudioDirectoryInfo::Ptr audioDirectory = CreateDirectoryInfo(
|
||||
path.parent_path());
|
||||
audioDirectory->GetFiles(); // ensure that the .index file is up to date.
|
||||
|
||||
ThumbnailTemporaryFile thumbnail;
|
||||
try {
|
||||
thumbnail = audioDirectory->GetThumbnail(path.filename(), width, height);
|
||||
} catch (const std::exception &e) {
|
||||
thumbnail = audioDirectory->DefaultThumbnailTemporaryFile();
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
fs::path defaultThumbnail = model->GetWebRoot() / "img/missing_thumbnail.jpg";
|
||||
thumbnailTemporaryFile.SetNonDeletedPath(defaultThumbnail, "image/jpeg");
|
||||
}
|
||||
res.set(HttpField::content_type, thumbnail.GetMimeType());
|
||||
res.set(HttpField::content_type, thumbnailTemporaryFile.GetMimeType());
|
||||
|
||||
res.set(HttpField::cache_control, CACHE_CONTROL_INDEFINITELY); // URL is cache-busted with time-stamp.
|
||||
setLastModifiedFromFile(res, path);
|
||||
res.set(HttpField::content_length, std::to_string(fs::file_size(thumbnail.Path())));
|
||||
setLastModifiedFromFile(res, thumbnailTemporaryFile.Path());
|
||||
res.set(HttpField::content_length, std::to_string(fs::file_size(thumbnailTemporaryFile.Path())));
|
||||
|
||||
std::filesystem::path t = thumbnail.Path();
|
||||
res.setBodyFile(t,thumbnail.DeleteFile());
|
||||
thumbnail.Detach();
|
||||
std::filesystem::path t = thumbnailTemporaryFile.Path();
|
||||
res.setBodyFile(t, thumbnailTemporaryFile.DeleteFile());
|
||||
thumbnailTemporaryFile.Detach();
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
Lv2Log::error("Error getting thumbnail: %s - (%s)", request_uri.str().c_str(), e.what());
|
||||
Lv2Log::error("Error getting thumbnail: %s - (%s)", request_uri.str().c_str(), e.what());
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
@@ -605,11 +610,11 @@ public:
|
||||
{
|
||||
result = (directoryPath / result).string();
|
||||
}
|
||||
|
||||
|
||||
// json-encode the result.
|
||||
std::stringstream ss;
|
||||
json_writer writer(ss);
|
||||
writer.write(result);
|
||||
writer.write(result);
|
||||
|
||||
res.setBody(ss.str());
|
||||
}
|
||||
@@ -637,11 +642,11 @@ public:
|
||||
{
|
||||
result = (directoryPath / result).string();
|
||||
}
|
||||
|
||||
|
||||
// json-encode the result.
|
||||
std::stringstream ss;
|
||||
json_writer writer(ss);
|
||||
writer.write(result);
|
||||
writer.write(result);
|
||||
|
||||
res.setBody(ss.str());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user