Added support for authentication in Calibre
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
#include "UrlUtils.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
namespace UrlUtils {
|
||||
|
||||
std::string ensureProtocol(const std::string& url) {
|
||||
@@ -38,4 +41,76 @@ std::string buildUrl(const std::string& serverUrl, const std::string& path) {
|
||||
return urlWithProtocol + "/" + path;
|
||||
}
|
||||
|
||||
std::string urlEncode(const std::string& value) {
|
||||
std::ostringstream escaped;
|
||||
escaped.fill('0');
|
||||
escaped << std::hex;
|
||||
|
||||
for (char c : value) {
|
||||
// Keep alphanumeric and other safe characters intact
|
||||
if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') {
|
||||
escaped << c;
|
||||
} else {
|
||||
// Encode special characters
|
||||
escaped << std::uppercase;
|
||||
escaped << '%' << std::setw(2) << int((unsigned char)c);
|
||||
escaped << std::nouppercase;
|
||||
}
|
||||
}
|
||||
|
||||
return escaped.str();
|
||||
}
|
||||
|
||||
std::string buildUrlWithAuth(const std::string& serverUrl, const std::string& path,
|
||||
const std::string& username, const std::string& password) {
|
||||
// If no credentials, use regular buildUrl
|
||||
if (username.empty() && password.empty()) {
|
||||
return buildUrl(serverUrl, path);
|
||||
}
|
||||
|
||||
std::string urlWithProtocol = ensureProtocol(serverUrl);
|
||||
|
||||
// Find protocol end
|
||||
const size_t protocolEnd = urlWithProtocol.find("://");
|
||||
if (protocolEnd == std::string::npos) {
|
||||
return buildUrl(serverUrl, path); // Fallback if no protocol
|
||||
}
|
||||
|
||||
// Extract protocol and host parts
|
||||
std::string protocol = urlWithProtocol.substr(0, protocolEnd + 3); // Include ://
|
||||
std::string hostAndPath = urlWithProtocol.substr(protocolEnd + 3);
|
||||
|
||||
// Check if auth already exists in URL
|
||||
const size_t atPos = hostAndPath.find('@');
|
||||
if (atPos != std::string::npos) {
|
||||
// Auth already in URL, remove it
|
||||
hostAndPath = hostAndPath.substr(atPos + 1);
|
||||
}
|
||||
|
||||
// Build auth string with URL encoding
|
||||
std::string auth;
|
||||
if (!username.empty() || !password.empty()) {
|
||||
auth = urlEncode(username) + ":" + urlEncode(password) + "@";
|
||||
}
|
||||
|
||||
// Reconstruct URL with auth
|
||||
std::string authenticatedUrl = protocol + auth + hostAndPath;
|
||||
|
||||
// Now apply path logic
|
||||
if (path.empty()) {
|
||||
return authenticatedUrl;
|
||||
}
|
||||
if (path[0] == '/') {
|
||||
// Absolute path - extract just protocol + auth + host
|
||||
const size_t firstSlash = hostAndPath.find('/');
|
||||
std::string hostOnly = (firstSlash == std::string::npos) ? hostAndPath : hostAndPath.substr(0, firstSlash);
|
||||
return protocol + auth + hostOnly + path;
|
||||
}
|
||||
// Relative path
|
||||
if (authenticatedUrl.back() == '/') {
|
||||
return authenticatedUrl + path;
|
||||
}
|
||||
return authenticatedUrl + "/" + path;
|
||||
}
|
||||
|
||||
} // namespace UrlUtils
|
||||
|
||||
Reference in New Issue
Block a user