fix: escape media URLs in MPD (#1395)
Currently `media_info.media_file_url()` is not escaped when placed into MPD for things like BaseURL. This for example breaks when trying to us a file name that contains special characters like &. Since these are supposed to be URLs let's URL encode them. Fixes #1107 --------- Co-authored-by: Joey Parrish <joeyparrish@users.noreply.github.com>
This commit is contained in:
parent
b7e96f7d93
commit
98b44d01df
|
@ -51,6 +51,7 @@ target_link_libraries(mpd_builder
|
||||||
media_base
|
media_base
|
||||||
mpd_media_info_proto
|
mpd_media_info_proto
|
||||||
utils_clock
|
utils_clock
|
||||||
|
libcurl
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -167,7 +167,7 @@ std::optional<xml::XmlNode> MpdBuilder::GenerateMpd() {
|
||||||
// Add baseurls to MPD.
|
// Add baseurls to MPD.
|
||||||
for (const std::string& base_url : base_urls_) {
|
for (const std::string& base_url : base_urls_) {
|
||||||
XmlNode xml_base_url("BaseURL");
|
XmlNode xml_base_url("BaseURL");
|
||||||
xml_base_url.SetContent(base_url);
|
xml_base_url.SetUrlEncodedContent(base_url);
|
||||||
|
|
||||||
if (!mpd.AddChild(std::move(xml_base_url)))
|
if (!mpd.AddChild(std::move(xml_base_url)))
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <absl/strings/escaping.h>
|
#include <absl/strings/escaping.h>
|
||||||
#include <absl/strings/numbers.h>
|
#include <absl/strings/numbers.h>
|
||||||
#include <absl/strings/str_format.h>
|
#include <absl/strings/str_format.h>
|
||||||
|
#include <curl/curl.h>
|
||||||
#include <libxml/tree.h>
|
#include <libxml/tree.h>
|
||||||
|
|
||||||
#include <packager/macros/compiler.h>
|
#include <packager/macros/compiler.h>
|
||||||
|
@ -53,6 +54,18 @@ const char kDTSCCodec[] = "dtsc";
|
||||||
const char kDTSECodec[] = "dtse";
|
const char kDTSECodec[] = "dtse";
|
||||||
const char kDTSXCodec[] = "dtsx";
|
const char kDTSXCodec[] = "dtsx";
|
||||||
|
|
||||||
|
std::string urlEncode(const std::string& input) {
|
||||||
|
// NOTE: According to the docs, "Since 7.82.0, the curl parameter is ignored".
|
||||||
|
CURL* curl = NULL;
|
||||||
|
char* output = curl_easy_escape(curl, input.c_str(), input.length());
|
||||||
|
if (output) {
|
||||||
|
std::string encodedUrl(output);
|
||||||
|
curl_free(output); // Free the output string when done
|
||||||
|
return encodedUrl;
|
||||||
|
}
|
||||||
|
return ""; // Return empty string if initialization fails
|
||||||
|
}
|
||||||
|
|
||||||
std::string RangeToString(const Range& range) {
|
std::string RangeToString(const Range& range) {
|
||||||
return absl::StrFormat("%u-%u", range.begin(), range.end());
|
return absl::StrFormat("%u-%u", range.begin(), range.end());
|
||||||
}
|
}
|
||||||
|
@ -220,11 +233,19 @@ void XmlNode::AddContent(const std::string& content) {
|
||||||
xmlNodeAddContent(impl_->node.get(), BAD_CAST content.c_str());
|
xmlNodeAddContent(impl_->node.get(), BAD_CAST content.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void XmlNode::AddUrlEncodedContent(const std::string& content) {
|
||||||
|
AddContent(urlEncode(content));
|
||||||
|
}
|
||||||
|
|
||||||
void XmlNode::SetContent(const std::string& content) {
|
void XmlNode::SetContent(const std::string& content) {
|
||||||
DCHECK(impl_->node);
|
DCHECK(impl_->node);
|
||||||
xmlNodeSetContent(impl_->node.get(), BAD_CAST content.c_str());
|
xmlNodeSetContent(impl_->node.get(), BAD_CAST content.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void XmlNode::SetUrlEncodedContent(const std::string& content) {
|
||||||
|
SetContent(urlEncode(content));
|
||||||
|
}
|
||||||
|
|
||||||
std::set<std::string> XmlNode::ExtractReferencedNamespaces() const {
|
std::set<std::string> XmlNode::ExtractReferencedNamespaces() const {
|
||||||
std::set<std::string> namespaces;
|
std::set<std::string> namespaces;
|
||||||
TraverseNodesAndCollectNamespaces(impl_->node.get(), &namespaces);
|
TraverseNodesAndCollectNamespaces(impl_->node.get(), &namespaces);
|
||||||
|
@ -400,7 +421,7 @@ bool RepresentationXmlNode::AddVODOnlyInfo(const MediaInfo& media_info,
|
||||||
|
|
||||||
if (media_info.has_media_file_url() && !use_single_segment_url_with_media) {
|
if (media_info.has_media_file_url() && !use_single_segment_url_with_media) {
|
||||||
XmlNode base_url("BaseURL");
|
XmlNode base_url("BaseURL");
|
||||||
base_url.SetContent(media_info.media_file_url());
|
base_url.SetUrlEncodedContent(media_info.media_file_url());
|
||||||
|
|
||||||
RCHECK(AddChild(std::move(base_url)));
|
RCHECK(AddChild(std::move(base_url)));
|
||||||
}
|
}
|
||||||
|
@ -452,7 +473,8 @@ bool RepresentationXmlNode::AddVODOnlyInfo(const MediaInfo& media_info,
|
||||||
|
|
||||||
if (use_single_segment_url_with_media) {
|
if (use_single_segment_url_with_media) {
|
||||||
XmlNode media_url("SegmentURL");
|
XmlNode media_url("SegmentURL");
|
||||||
RCHECK(media_url.SetStringAttribute("media", media_info.media_file_url()));
|
RCHECK(media_url.SetStringAttribute(
|
||||||
|
"media", urlEncode(media_info.media_file_url())));
|
||||||
RCHECK(child.AddChild(std::move(media_url)));
|
RCHECK(child.AddChild(std::move(media_url)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -83,6 +83,8 @@ class XmlNode {
|
||||||
/// Similar to SetContent, but appends to the end of existing content.
|
/// Similar to SetContent, but appends to the end of existing content.
|
||||||
void AddContent(const std::string& content);
|
void AddContent(const std::string& content);
|
||||||
|
|
||||||
|
void AddUrlEncodedContent(const std::string& content);
|
||||||
|
|
||||||
/// Set the contents of an XML element using a string.
|
/// Set the contents of an XML element using a string.
|
||||||
/// This cannot set child elements because <> will become < and &rt;
|
/// This cannot set child elements because <> will become < and &rt;
|
||||||
/// This should be used to set the text for the element, e.g. setting
|
/// This should be used to set the text for the element, e.g. setting
|
||||||
|
@ -91,6 +93,8 @@ class XmlNode {
|
||||||
/// be added to the element.
|
/// be added to the element.
|
||||||
void SetContent(const std::string& content);
|
void SetContent(const std::string& content);
|
||||||
|
|
||||||
|
void SetUrlEncodedContent(const std::string& content);
|
||||||
|
|
||||||
/// @return namespaces used in the node and its descendents.
|
/// @return namespaces used in the node and its descendents.
|
||||||
std::set<std::string> ExtractReferencedNamespaces() const;
|
std::set<std::string> ExtractReferencedNamespaces() const;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue