src/request_handler/url_request_handler.cc
Rama master · réplica de lectura del repositorio original.
/*MT*
MediaTomb - http://www.mediatomb.cc/
url_request_handler.cc - this file is part of MediaTomb.
Copyright (C) 2005 Gena Batyan <bgeradz@mediatomb.cc>,
Sergey 'Jin' Bostandzhyan <jin@mediatomb.cc>
Copyright (C) 2006-2010 Gena Batyan <bgeradz@mediatomb.cc>,
Sergey 'Jin' Bostandzhyan <jin@mediatomb.cc>,
Leonhard Wimmer <leo@mediatomb.cc>
Copyright (C) 2016-2026 Gerbera Contributors
MediaTomb is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2
as published by the Free Software Foundation.
MediaTomb is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
version 2 along with MediaTomb; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
$Id$
*/
/// @file request_handler/url_request_handler.cc
#define GRB_LOG_FAC GrbLogFacility::requests
#ifdef HAVE_CURL
#include "url_request_handler.h" // API
#include "cds/cds_item.h"
#include "config/config.h"
#include "config/config_val.h"
#include "config/result/transcoding.h"
#include "content/content.h"
#include "exceptions.h"
#include "iohandler/curl_io_handler.h"
#include "transcoding/transcode_dispatcher.h"
#include "upnp/compat.h"
#include "upnp/xml_builder.h"
#include "util/tools.h"
#include "util/url.h"
#include "util/url_utils.h"
#ifdef ONLINE_SERVICES
#include "content/onlineservice/online_service_helper.h"
#endif
bool URLRequestHandler::getInfo(const char* filename, UpnpFileInfo* info)
{
log_debug("start");
auto params = URLUtils::parseParameters(filename, LINK_URL_REQUEST_HANDLER);
auto obj = loadObject(params);
if (!obj->isExternalItem()) {
throw_std_runtime_error("getInfo: object is not an external url item");
}
auto item = std::static_pointer_cast<CdsItemExternalURL>(obj);
std::string trProfile = getValueOrDefault(params, URL_PARAM_TRANSCODE_PROFILE_NAME);
std::string mimeType;
if (!trProfile.empty()) {
auto tp = config->getTranscodingProfileListOption(ConfigVal::TRANSCODING_PROFILE_LIST)
->getByName(trProfile);
if (!tp)
throw_std_runtime_error("Transcoding requested but no profile matching the name {} found", trProfile);
mimeType = tp->getTargetMimeType();
UpnpFileInfo_set_FileLength(info, -1);
} else {
#ifdef ONLINE_SERVICES
std::string url = item->hasFlag(ObjectFlag::OnlineService) ? OnlineServiceHelper::resolveURL(item) : item->getLocation().string();
#else
std::string url = item->getLocation().string();
#endif
log_debug("Online content url: {}", url);
try {
auto st = URL(url).getInfo();
UpnpFileInfo_set_FileLength(info, st.getSize());
log_debug("URL used for request: {}", st.getURL());
} catch (const std::runtime_error& ex) {
log_warning("{}", EX(ex));
UpnpFileInfo_set_FileLength(info, -1);
}
mimeType = item->getMimeType();
}
UpnpFileInfo_set_IsReadable(info, 1);
UpnpFileInfo_set_LastModified(info, 0);
UpnpFileInfo_set_IsDirectory(info, 0);
GrbUpnpFileInfoSetContentType(info, mimeType);
log_debug("end");
return quirks && quirks->getClient();
}
std::unique_ptr<IOHandler> URLRequestHandler::open(const char* filename, const std::shared_ptr<Quirks>& quirks, enum UpnpOpenFileMode mode)
{
log_debug("start");
// Currently we explicitly do not support UPNP_WRITE
// due to security reasons.
if (mode != UPNP_READ)
throw_std_runtime_error("UPNP_WRITE unsupported");
auto params = URLUtils::parseParameters(filename, LINK_URL_REQUEST_HANDLER);
auto obj = loadObject(params);
if (!obj->isExternalItem()) {
throw_std_runtime_error("object is not an external url item");
}
auto item = std::static_pointer_cast<CdsItemExternalURL>(obj);
#ifdef ONLINE_SERVICES
std::string url = item->hasFlag(ObjectFlag::OnlineService) ? OnlineServiceHelper::resolveURL(item) : item->getLocation().string();
#else
std::string url = item->getLocation().string();
#endif
log_debug("Online content url: {}", url);
auto it = params.find(CLIENT_GROUP_TAG);
std::string group = DEFAULT_CLIENT_GROUP;
if (it != params.end()) {
group = it->second;
}
std::string trProfile = getValueOrDefault(params, URL_PARAM_TRANSCODE_PROFILE_NAME);
if (!trProfile.empty()) {
auto tp = config->getTranscodingProfileListOption(ConfigVal::TRANSCODING_PROFILE_LIST)
->getByName(trProfile);
if (!tp)
throw_std_runtime_error("Transcoding of file {} but no profile matching the name {} found", url, trProfile);
auto trD = std::make_unique<TranscodeDispatcher>(content);
auto ioHandler = trD->serveContent(tp, url, item, group, "");
log_debug("end transcoding");
return ioHandler;
}
auto ioHandler = std::make_unique<CurlIOHandler>(config, url,
config->getIntOption(ConfigVal::URL_REQUEST_CURL_BUFFER_SIZE),
config->getIntOption(ConfigVal::URL_REQUEST_CURL_FILL_SIZE),
std::chrono::seconds(config->getLongOption(ConfigVal::URL_REQUEST_CURL_CONNECT_TIMEOUT)),
std::chrono::seconds(config->getLongOption(ConfigVal::URL_REQUEST_CURL_TIMEOUT)));
content->triggerPlayHook(group, obj);
log_debug("end");
return ioHandler;
}
#endif // HAVE_CURL