Skip to content

Commit 98b44d0

Browse files
cosminjoeyparrish
andauthored
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 <[email protected]>
1 parent b7e96f7 commit 98b44d0

File tree

4 files changed

+30
-3
lines changed

4 files changed

+30
-3
lines changed

packager/mpd/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ target_link_libraries(mpd_builder
5151
media_base
5252
mpd_media_info_proto
5353
utils_clock
54+
libcurl
5455
)
5556

5657

packager/mpd/base/mpd_builder.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ std::optional<xml::XmlNode> MpdBuilder::GenerateMpd() {
167167
// Add baseurls to MPD.
168168
for (const std::string& base_url : base_urls_) {
169169
XmlNode xml_base_url("BaseURL");
170-
xml_base_url.SetContent(base_url);
170+
xml_base_url.SetUrlEncodedContent(base_url);
171171

172172
if (!mpd.AddChild(std::move(xml_base_url)))
173173
return std::nullopt;

packager/mpd/base/xml/xml_node.cc

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <absl/strings/escaping.h>
1919
#include <absl/strings/numbers.h>
2020
#include <absl/strings/str_format.h>
21+
#include <curl/curl.h>
2122
#include <libxml/tree.h>
2223

2324
#include <packager/macros/compiler.h>
@@ -53,6 +54,18 @@ const char kDTSCCodec[] = "dtsc";
5354
const char kDTSECodec[] = "dtse";
5455
const char kDTSXCodec[] = "dtsx";
5556

57+
std::string urlEncode(const std::string& input) {
58+
// NOTE: According to the docs, "Since 7.82.0, the curl parameter is ignored".
59+
CURL* curl = NULL;
60+
char* output = curl_easy_escape(curl, input.c_str(), input.length());
61+
if (output) {
62+
std::string encodedUrl(output);
63+
curl_free(output); // Free the output string when done
64+
return encodedUrl;
65+
}
66+
return ""; // Return empty string if initialization fails
67+
}
68+
5669
std::string RangeToString(const Range& range) {
5770
return absl::StrFormat("%u-%u", range.begin(), range.end());
5871
}
@@ -220,11 +233,19 @@ void XmlNode::AddContent(const std::string& content) {
220233
xmlNodeAddContent(impl_->node.get(), BAD_CAST content.c_str());
221234
}
222235

236+
void XmlNode::AddUrlEncodedContent(const std::string& content) {
237+
AddContent(urlEncode(content));
238+
}
239+
223240
void XmlNode::SetContent(const std::string& content) {
224241
DCHECK(impl_->node);
225242
xmlNodeSetContent(impl_->node.get(), BAD_CAST content.c_str());
226243
}
227244

245+
void XmlNode::SetUrlEncodedContent(const std::string& content) {
246+
SetContent(urlEncode(content));
247+
}
248+
228249
std::set<std::string> XmlNode::ExtractReferencedNamespaces() const {
229250
std::set<std::string> namespaces;
230251
TraverseNodesAndCollectNamespaces(impl_->node.get(), &namespaces);
@@ -400,7 +421,7 @@ bool RepresentationXmlNode::AddVODOnlyInfo(const MediaInfo& media_info,
400421

401422
if (media_info.has_media_file_url() && !use_single_segment_url_with_media) {
402423
XmlNode base_url("BaseURL");
403-
base_url.SetContent(media_info.media_file_url());
424+
base_url.SetUrlEncodedContent(media_info.media_file_url());
404425

405426
RCHECK(AddChild(std::move(base_url)));
406427
}
@@ -452,7 +473,8 @@ bool RepresentationXmlNode::AddVODOnlyInfo(const MediaInfo& media_info,
452473

453474
if (use_single_segment_url_with_media) {
454475
XmlNode media_url("SegmentURL");
455-
RCHECK(media_url.SetStringAttribute("media", media_info.media_file_url()));
476+
RCHECK(media_url.SetStringAttribute(
477+
"media", urlEncode(media_info.media_file_url())));
456478
RCHECK(child.AddChild(std::move(media_url)));
457479
}
458480

packager/mpd/base/xml/xml_node.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ class XmlNode {
8383
/// Similar to SetContent, but appends to the end of existing content.
8484
void AddContent(const std::string& content);
8585

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

96+
void SetUrlEncodedContent(const std::string& content);
97+
9498
/// @return namespaces used in the node and its descendents.
9599
std::set<std::string> ExtractReferencedNamespaces() const;
96100

0 commit comments

Comments
 (0)