mirror of
https://github.com/crosspoint-reader/crosspoint-reader.git
synced 2026-04-29 10:26:52 -07:00
fix: relative opds paths and query param with copyparty (#1535)
## Summary * **What is the goal of this PR?** This PR fixes bugs when using Copyparty as an OPDS server. https://github.com/9001/copyparty?tab=readme-ov-file#opds-feeds OPDS uses a query parameter `?opds` to differentiate between HTML requests and OPDS requests for the same path. It also uses relative paths in the responses instead of full paths. Crosspoint didn't handle these two cases. * **What changes are included?** Fixes to the two issues above. ## Additional Context * Add any other information that might be helpful for the reviewer (e.g., performance implications, potential risks, specific areas to focus on). Here is some example XML from my Copyparty instance: https://gist.github.com/philips/9ecec29dfb69ed0591b032f16e799675 ### AI Usage While CrossPoint doesn't have restrictions on AI tools in contributing, please be transparent about their usage as it helps set the right context for reviewers. Did you use AI tools to help write this code? _**< YES | PARTIALLY | NO >**_ Partially. I used Claude code to write the fix. I am not a strong C++ programmer. But, I manually compiled and tested. --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
1a145fe085
commit
c0ee096841
@@ -225,7 +225,10 @@ void OpdsBookBrowserActivity::fetchFeed(const std::string& path) {
|
||||
|
||||
void OpdsBookBrowserActivity::navigateToEntry(const OpdsEntry& entry) {
|
||||
navigationHistory.push_back(currentPath);
|
||||
currentPath = entry.href;
|
||||
// Resolve to a full URL so sub-sub-navigation retains parent path context
|
||||
const std::string feedUrl = UrlUtils::buildUrl(SETTINGS.opdsServerUrl, currentPath);
|
||||
currentPath = UrlUtils::buildUrl(feedUrl, entry.href);
|
||||
|
||||
state = BrowserState::LOADING;
|
||||
statusMessage = tr(STR_LOADING);
|
||||
entries.clear();
|
||||
@@ -255,10 +258,12 @@ void OpdsBookBrowserActivity::downloadBook(const OpdsEntry& book) {
|
||||
downloadProgress = downloadTotal = 0;
|
||||
requestUpdate(true);
|
||||
|
||||
std::string downloadUrl =
|
||||
(book.href.find("http") == 0) ? book.href : UrlUtils::buildUrl(SETTINGS.opdsServerUrl, book.href);
|
||||
// Build full download URL relative to the current feed, not the root server URL
|
||||
const std::string feedUrl = UrlUtils::buildUrl(SETTINGS.opdsServerUrl, currentPath);
|
||||
std::string downloadUrl = UrlUtils::buildUrl(feedUrl, book.href);
|
||||
std::string filename =
|
||||
"/" + StringUtils::sanitizeFilename(book.title + (book.author.empty() ? "" : " - " + book.author)) + ".epub";
|
||||
LOG_DBG("OPDS", "Downloading: %s -> %s", downloadUrl.c_str(), filename.c_str());
|
||||
|
||||
const auto result =
|
||||
HttpDownloader::downloadToFile(downloadUrl, filename, [this](const size_t downloaded, const size_t total) {
|
||||
|
||||
@@ -37,11 +37,16 @@ std::string buildUrl(const std::string& serverUrl, const std::string& path) {
|
||||
// Absolute path - use just the host
|
||||
return extractHost(urlWithProtocol) + path;
|
||||
}
|
||||
// Relative path - append to server URL
|
||||
if (urlWithProtocol.back() == '/') {
|
||||
return urlWithProtocol + path;
|
||||
// Relative path - strip query string from base before appending
|
||||
std::string base = urlWithProtocol;
|
||||
const size_t queryPos = base.find('?');
|
||||
if (queryPos != std::string::npos) {
|
||||
base.resize(queryPos);
|
||||
}
|
||||
return urlWithProtocol + "/" + path;
|
||||
if (base.back() == '/') {
|
||||
return base + path;
|
||||
}
|
||||
return base + "/" + path;
|
||||
}
|
||||
|
||||
} // namespace UrlUtils
|
||||
|
||||
Reference in New Issue
Block a user