diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 18:07:22 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 18:07:22 +0000 |
commit | c04dcc2e7d834218ef2d4194331e383402495ae1 (patch) | |
tree | 7333e38d10d75386e60f336b80c2443c1166031d /xbmc/network/httprequesthandler/HTTPWebinterfaceHandler.cpp | |
parent | Initial commit. (diff) | |
download | kodi-c04dcc2e7d834218ef2d4194331e383402495ae1.tar.xz kodi-c04dcc2e7d834218ef2d4194331e383402495ae1.zip |
Adding upstream version 2:20.4+dfsg.upstream/2%20.4+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'xbmc/network/httprequesthandler/HTTPWebinterfaceHandler.cpp')
-rw-r--r-- | xbmc/network/httprequesthandler/HTTPWebinterfaceHandler.cpp | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/xbmc/network/httprequesthandler/HTTPWebinterfaceHandler.cpp b/xbmc/network/httprequesthandler/HTTPWebinterfaceHandler.cpp new file mode 100644 index 0000000..fe6e760 --- /dev/null +++ b/xbmc/network/httprequesthandler/HTTPWebinterfaceHandler.cpp @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2011-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "HTTPWebinterfaceHandler.h" + +#include "ServiceBroker.h" +#include "addons/AddonManager.h" +#include "addons/AddonSystemSettings.h" +#include "addons/Webinterface.h" +#include "addons/addoninfo/AddonType.h" +#include "filesystem/Directory.h" +#include "utils/FileUtils.h" +#include "utils/StringUtils.h" +#include "utils/URIUtils.h" + +#define WEBSERVER_DIRECTORY_SEPARATOR "/" + +CHTTPWebinterfaceHandler::CHTTPWebinterfaceHandler(const HTTPRequest &request) + : CHTTPFileHandler(request) +{ + // resolve the URL into a file path and a HTTP response status + std::string file; + int responseStatus = ResolveUrl(request.pathUrl, file); + + // set the file and the HTTP response status + SetFile(file, responseStatus); +} + +bool CHTTPWebinterfaceHandler::CanHandleRequest(const HTTPRequest &request) const +{ + return true; +} + +int CHTTPWebinterfaceHandler::ResolveUrl(const std::string &url, std::string &path) +{ + ADDON::AddonPtr dummyAddon; + return ResolveUrl(url, path, dummyAddon); +} + +int CHTTPWebinterfaceHandler::ResolveUrl(const std::string &url, std::string &path, ADDON::AddonPtr &addon) +{ + // determine the addon and addon's path + if (!ResolveAddon(url, addon, path)) + return MHD_HTTP_NOT_FOUND; + + if (XFILE::CDirectory::Exists(path)) + { + if (URIUtils::GetFileName(path).empty()) + { + // determine the actual file path using the default entry point + if (addon != NULL && addon->Type() == ADDON::AddonType::WEB_INTERFACE) + path = std::dynamic_pointer_cast<ADDON::CWebinterface>(addon)->GetEntryPoint(path); + } + else + { + URIUtils::AddSlashAtEnd(path); + return MHD_HTTP_FOUND; + } + } + + if (!CFileUtils::CheckFileAccessAllowed(path)) + return MHD_HTTP_NOT_FOUND; + + if (!CFileUtils::Exists(path)) + return MHD_HTTP_NOT_FOUND; + + return MHD_HTTP_OK; +} + +bool CHTTPWebinterfaceHandler::ResolveAddon(const std::string &url, ADDON::AddonPtr &addon) +{ + std::string addonPath; + return ResolveAddon(url, addon, addonPath); +} + +bool CHTTPWebinterfaceHandler::ResolveAddon(const std::string &url, ADDON::AddonPtr &addon, std::string &addonPath) +{ + std::string path = url; + + // check if the URL references a specific addon + if (url.find("/addons/") == 0 && url.size() > 8) + { + std::vector<std::string> components; + StringUtils::Tokenize(path, components, WEBSERVER_DIRECTORY_SEPARATOR); + if (components.size() <= 1) + return false; + + if (!CServiceBroker::GetAddonMgr().GetAddon(components.at(1), addon, + ADDON::OnlyEnabled::CHOICE_YES) || + addon == NULL) + return false; + + addonPath = addon->Path(); + if (addon->Type() != + ADDON::AddonType::WEB_INTERFACE) // No need to append /htdocs for web interfaces + addonPath = URIUtils::AddFileToFolder(addonPath, "/htdocs/"); + + // remove /addons/<addon-id> from the path + components.erase(components.begin(), components.begin() + 2); + + // determine the path within the addon + path = StringUtils::Join(components, WEBSERVER_DIRECTORY_SEPARATOR); + } + else if (!ADDON::CAddonSystemSettings::GetInstance().GetActive(ADDON::AddonType::WEB_INTERFACE, + addon) || + addon == NULL) + return false; + + // get the path of the addon + addonPath = addon->Path(); + + // add /htdocs/ to the addon's path if it's not a webinterface + if (addon->Type() != ADDON::AddonType::WEB_INTERFACE) + addonPath = URIUtils::AddFileToFolder(addonPath, "/htdocs/"); + + // append the path within the addon to the path of the addon + addonPath = URIUtils::AddFileToFolder(addonPath, path); + + // ensure that we don't have a directory traversal hack here + // by checking if the resolved absolute path is inside the addon path + std::string realPath = URIUtils::GetRealPath(addonPath); + std::string realAddonPath = URIUtils::GetRealPath(addon->Path()); + if (!URIUtils::PathHasParent(realPath, realAddonPath, true)) + return false; + + return true; +} |