Skip to content

Commit

Permalink
fix: escape media URLs in MPD (shaka-project#1395)
Browse files Browse the repository at this point in the history
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 shaka-project#1107

---------

Co-authored-by: Joey Parrish <joeyparrish@users.noreply.github.com>
  • Loading branch information
cosmin and joeyparrish authored May 11, 2024
1 parent b7e96f7 commit 98b44d0
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 3 deletions.
1 change: 1 addition & 0 deletions packager/mpd/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ target_link_libraries(mpd_builder
media_base
mpd_media_info_proto
utils_clock
libcurl
)


Expand Down
2 changes: 1 addition & 1 deletion packager/mpd/base/mpd_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ std::optional<xml::XmlNode> MpdBuilder::GenerateMpd() {
// Add baseurls to MPD.
for (const std::string& base_url : base_urls_) {
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)))
return std::nullopt;
Expand Down
26 changes: 24 additions & 2 deletions packager/mpd/base/xml/xml_node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <absl/strings/escaping.h>
#include <absl/strings/numbers.h>
#include <absl/strings/str_format.h>
#include <curl/curl.h>
#include <libxml/tree.h>

#include <packager/macros/compiler.h>
Expand Down Expand Up @@ -53,6 +54,18 @@ const char kDTSCCodec[] = "dtsc";
const char kDTSECodec[] = "dtse";
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) {
return absl::StrFormat("%u-%u", range.begin(), range.end());
}
Expand Down Expand Up @@ -220,11 +233,19 @@ void XmlNode::AddContent(const std::string& content) {
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) {
DCHECK(impl_->node);
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> namespaces;
TraverseNodesAndCollectNamespaces(impl_->node.get(), &namespaces);
Expand Down Expand Up @@ -400,7 +421,7 @@ bool RepresentationXmlNode::AddVODOnlyInfo(const MediaInfo& media_info,

if (media_info.has_media_file_url() && !use_single_segment_url_with_media) {
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)));
}
Expand Down Expand Up @@ -452,7 +473,8 @@ bool RepresentationXmlNode::AddVODOnlyInfo(const MediaInfo& media_info,

if (use_single_segment_url_with_media) {
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)));
}

Expand Down
4 changes: 4 additions & 0 deletions packager/mpd/base/xml/xml_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ class XmlNode {
/// Similar to SetContent, but appends to the end of existing content.
void AddContent(const std::string& content);

void AddUrlEncodedContent(const std::string& content);

/// Set the contents of an XML element using a string.
/// This cannot set child elements because <> will become &lt; and &rt;
/// This should be used to set the text for the element, e.g. setting
Expand All @@ -91,6 +93,8 @@ class XmlNode {
/// be added to the element.
void SetContent(const std::string& content);

void SetUrlEncodedContent(const std::string& content);

/// @return namespaces used in the node and its descendents.
std::set<std::string> ExtractReferencedNamespaces() const;

Expand Down

0 comments on commit 98b44d0

Please sign in to comment.