From 4faaa4476a9e986bfcc4b7d9f096071cf283ce1d Mon Sep 17 00:00:00 2001 From: Andrea Piovanelli Date: Wed, 18 Sep 2024 10:50:05 +0200 Subject: [PATCH 1/7] Verified is video is imported from Vimeo. If it's the case, added the api url to the call to properly download video metadata. --- .../Controllers/OEmbedController.cs | 58 ++++++++++++------- 1 file changed, 38 insertions(+), 20 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs index 2d42832efcd..95d08a7360b 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs @@ -82,26 +82,44 @@ public ActionResult IndexPOST(string folderPath, string url, string type, string try { // - var source = webClient.DownloadString(url); - - // seek type="text/xml+oembed" or application/xml+oembed - var oembedSignature = source.IndexOf("type=\"text/xml+oembed\"", StringComparison.OrdinalIgnoreCase); - if (oembedSignature == -1) { - oembedSignature = source.IndexOf("type=\"application/xml+oembed\"", StringComparison.OrdinalIgnoreCase); - } - if (oembedSignature != -1) { - var tagStart = source.Substring(0, oembedSignature).LastIndexOf('<'); - var tagEnd = source.IndexOf('>', oembedSignature); - var tag = source.Substring(tagStart, tagEnd - tagStart); - var matches = new Regex("href=\"([^\"]+)\"").Matches(tag); - if (matches.Count > 0) { - var href = matches[0].Groups[1].Value; - try { - var content = webClient.DownloadString(Server.HtmlDecode(href)); - viewModel.Content = XDocument.Parse(content); - } - catch { - // bubble exception + var source = ""; + + // Vimeo doesn't consent anymore the scraping of web pages, so the direct api call has to be enforced. + // In this case, the downloaded string is already the expected xml, in the format that needs to be parsed. + // Legacy process is done either way. + // At the end of it, oembedSignature value will still be -1. + // So the downloaded string is parsed. + // Check if url is inside Vimeo domain. + var uri = new Uri(url); + var vimeo = uri.Host.Equals("vimeo.com", StringComparison.OrdinalIgnoreCase) || + uri.Host.Equals("www.vimeo.com", StringComparison.OrdinalIgnoreCase); + if (vimeo) { + // Add api url to original url provided as a parameter + url = "http://vimeo.com/api/oembed.xml?url=" + url; + source = webClient.DownloadString(url); + + viewModel.Content = XDocument.Parse(source); + } else { + source = webClient.DownloadString(url); + + // seek type="text/xml+oembed" or application/xml+oembed + var oembedSignature = source.IndexOf("type=\"text/xml+oembed\"", StringComparison.OrdinalIgnoreCase); + if (oembedSignature == -1) { + oembedSignature = source.IndexOf("type=\"application/xml+oembed\"", StringComparison.OrdinalIgnoreCase); + } + if (oembedSignature != -1) { + var tagStart = source.Substring(0, oembedSignature).LastIndexOf('<'); + var tagEnd = source.IndexOf('>', oembedSignature); + var tag = source.Substring(tagStart, tagEnd - tagStart); + var matches = new Regex("href=\"([^\"]+)\"").Matches(tag); + if (matches.Count > 0) { + var href = matches[0].Groups[1].Value; + try { + var content = webClient.DownloadString(Server.HtmlDecode(href)); + viewModel.Content = XDocument.Parse(content); + } catch { + // bubble exception + } } } } From 28512e46444e25dfb12816e13e95209ceea3b15a Mon Sep 17 00:00:00 2001 From: Andrea Piovanelli Date: Wed, 18 Sep 2024 11:05:00 +0200 Subject: [PATCH 2/7] Correction to comment text. --- .../Orchard.MediaLibrary/Controllers/OEmbedController.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs index 95d08a7360b..d2034542d5b 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs @@ -86,10 +86,8 @@ public ActionResult IndexPOST(string folderPath, string url, string type, string // Vimeo doesn't consent anymore the scraping of web pages, so the direct api call has to be enforced. // In this case, the downloaded string is already the expected xml, in the format that needs to be parsed. - // Legacy process is done either way. - // At the end of it, oembedSignature value will still be -1. - // So the downloaded string is parsed. - // Check if url is inside Vimeo domain. + // Legacy process is done for non-Vimeo content. + // First of all, url domain is checked. var uri = new Uri(url); var vimeo = uri.Host.Equals("vimeo.com", StringComparison.OrdinalIgnoreCase) || uri.Host.Equals("www.vimeo.com", StringComparison.OrdinalIgnoreCase); From 7b5c5943812f762a961198b207467a38165d2bf9 Mon Sep 17 00:00:00 2001 From: Andrea Piovanelli Date: Thu, 10 Oct 2024 16:36:14 +0200 Subject: [PATCH 3/7] Changed Youtube video importing to directly call the apis after recent changes to Youtube page markup --- .../Controllers/OEmbedController.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs index d2034542d5b..d57d8adda42 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs @@ -91,11 +91,24 @@ public ActionResult IndexPOST(string folderPath, string url, string type, string var uri = new Uri(url); var vimeo = uri.Host.Equals("vimeo.com", StringComparison.OrdinalIgnoreCase) || uri.Host.Equals("www.vimeo.com", StringComparison.OrdinalIgnoreCase); + + // Youtube changed the markup of the page of its videos, so the direct api call has to be enforced + // Api url is built based on the requested video + var youtube = uri.Host.Equals("youtu.be", StringComparison.OrdinalIgnoreCase) || + uri.Host.Equals("youtube.com", StringComparison.OrdinalIgnoreCase) || + uri.Host.Equals("www.youtube.com", StringComparison.OrdinalIgnoreCase); + if (vimeo) { // Add api url to original url provided as a parameter url = "http://vimeo.com/api/oembed.xml?url=" + url; source = webClient.DownloadString(url); + viewModel.Content = XDocument.Parse(source); + } else if (youtube) { + // Add api url to original url provided as a parameter + url = "https://www.youtube.com/oembed?format=xml&url=" + url; + source = webClient.DownloadString(url); + viewModel.Content = XDocument.Parse(source); } else { source = webClient.DownloadString(url); From 4b3bc0d92ea4cd75ae53d7ce39c67f393a3fe52d Mon Sep 17 00:00:00 2001 From: Andrea Piovanelli Date: Thu, 17 Oct 2024 10:54:07 +0200 Subject: [PATCH 4/7] Added a function to get redirect url for embed videos and build from there the correct api url. --- .../Controllers/OEmbedController.cs | 43 ++++++++++++------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs index d57d8adda42..1c904c79d96 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs @@ -56,6 +56,25 @@ public ActionResult Index(string folderPath, string type, int? replaceId) { return View(viewModel); } + private Uri GetRedirectUrl(string url) { + var redirectedUrl = url; + + Uri myUri = new Uri(url); + // Create a 'HttpWebRequest' object for the specified url. + HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create(myUri); + // Send the request and wait for response. + HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse(); + + if (!myUri.Equals(myHttpWebResponse.ResponseUri)) { + myUri = myHttpWebResponse.ResponseUri; + } + + // Release resources of response object. + myHttpWebResponse.Close(); + + return myUri; + } + [HttpPost] [ActionName("Index")] [ValidateInput(false)] @@ -88,25 +107,22 @@ public ActionResult IndexPOST(string folderPath, string url, string type, string // In this case, the downloaded string is already the expected xml, in the format that needs to be parsed. // Legacy process is done for non-Vimeo content. // First of all, url domain is checked. - var uri = new Uri(url); - var vimeo = uri.Host.Equals("vimeo.com", StringComparison.OrdinalIgnoreCase) || - uri.Host.Equals("www.vimeo.com", StringComparison.OrdinalIgnoreCase); + var uri = GetRedirectUrl(url); + var vimeo = uri.Host.Equals("vimeo.com", StringComparison.OrdinalIgnoreCase); // Youtube changed the markup of the page of its videos, so the direct api call has to be enforced // Api url is built based on the requested video - var youtube = uri.Host.Equals("youtu.be", StringComparison.OrdinalIgnoreCase) || - uri.Host.Equals("youtube.com", StringComparison.OrdinalIgnoreCase) || - uri.Host.Equals("www.youtube.com", StringComparison.OrdinalIgnoreCase); + var youtube = uri.Host.Equals("www.youtube.com", StringComparison.OrdinalIgnoreCase); if (vimeo) { // Add api url to original url provided as a parameter - url = "http://vimeo.com/api/oembed.xml?url=" + url; + url = "https://" + uri.Host + "/api/oembed.xml?url=" + url; source = webClient.DownloadString(url); viewModel.Content = XDocument.Parse(source); } else if (youtube) { // Add api url to original url provided as a parameter - url = "https://www.youtube.com/oembed?format=xml&url=" + url; + url = "https://" + uri.Host + "/oembed?format=xml&url=" + url; source = webClient.DownloadString(url); viewModel.Content = XDocument.Parse(source); @@ -166,8 +182,7 @@ public ActionResult IndexPOST(string folderPath, string url, string type, string root.El("description", description); } Response.AddHeader("X-XSS-Protection", "0"); // Prevents Chrome from freaking out over embedded preview - } - catch { + } catch { return View(viewModel); } @@ -196,8 +211,7 @@ public ActionResult Import(string folderPath, string url, string document) { if (oembed.Element("title") != null) { part.Title = oembed.Element("title").Value; - } - else { + } else { part.Title = oembed.Element("url").Value; } if (oembed.Element("description") != null) { @@ -232,7 +246,7 @@ public ActionResult Replace(int replaceId, string url, string document) { return HttpNotFound(); // Check permission - if (!(_mediaLibraryService.CheckMediaFolderPermission(Permissions.EditMediaContent, replaceMedia.FolderPath) && _mediaLibraryService.CheckMediaFolderPermission(Permissions.ImportMediaContent, replaceMedia.FolderPath)) + if (!(_mediaLibraryService.CheckMediaFolderPermission(Permissions.EditMediaContent, replaceMedia.FolderPath) && _mediaLibraryService.CheckMediaFolderPermission(Permissions.ImportMediaContent, replaceMedia.FolderPath)) && !_mediaLibraryService.CanManageMediaFolder(replaceMedia.FolderPath)) { return new HttpUnauthorizedResult(); } @@ -242,8 +256,7 @@ public ActionResult Replace(int replaceId, string url, string document) { if (oembed.Element("title") != null) { replaceMedia.Title = oembed.Element("title").Value; - } - else { + } else { replaceMedia.Title = oembed.Element("url").Value; } if (oembed.Element("description") != null) { From b89810ac9a3057a9f030602c0342e915d27a62e5 Mon Sep 17 00:00:00 2001 From: Andrea Piovanelli Date: Thu, 17 Oct 2024 14:27:58 +0200 Subject: [PATCH 5/7] Minor refactoring --- .../Orchard.MediaLibrary/Controllers/OEmbedController.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs index 1c904c79d96..35e136ec629 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs @@ -103,11 +103,12 @@ public ActionResult IndexPOST(string folderPath, string url, string type, string var source = ""; + var uri = GetRedirectUrl(url); + // Vimeo doesn't consent anymore the scraping of web pages, so the direct api call has to be enforced. // In this case, the downloaded string is already the expected xml, in the format that needs to be parsed. // Legacy process is done for non-Vimeo content. // First of all, url domain is checked. - var uri = GetRedirectUrl(url); var vimeo = uri.Host.Equals("vimeo.com", StringComparison.OrdinalIgnoreCase); // Youtube changed the markup of the page of its videos, so the direct api call has to be enforced From 0b76c0ef43dd1fdfce388cbdf9fc01259c4c66a7 Mon Sep 17 00:00:00 2001 From: Andrea Piovanelli Date: Fri, 18 Oct 2024 10:06:53 +0200 Subject: [PATCH 6/7] Code refactoring: changed GetRedirectUrl to GetRedirectUri --- .../Controllers/OEmbedController.cs | 41 ++++++++++--------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs index 35e136ec629..7425ba4e87c 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs @@ -56,25 +56,6 @@ public ActionResult Index(string folderPath, string type, int? replaceId) { return View(viewModel); } - private Uri GetRedirectUrl(string url) { - var redirectedUrl = url; - - Uri myUri = new Uri(url); - // Create a 'HttpWebRequest' object for the specified url. - HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create(myUri); - // Send the request and wait for response. - HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse(); - - if (!myUri.Equals(myHttpWebResponse.ResponseUri)) { - myUri = myHttpWebResponse.ResponseUri; - } - - // Release resources of response object. - myHttpWebResponse.Close(); - - return myUri; - } - [HttpPost] [ActionName("Index")] [ValidateInput(false)] @@ -103,7 +84,8 @@ public ActionResult IndexPOST(string folderPath, string url, string type, string var source = ""; - var uri = GetRedirectUrl(url); + // Get the proper uri the provider redirects to + var uri = GetRedirectUri(url); // Vimeo doesn't consent anymore the scraping of web pages, so the direct api call has to be enforced. // In this case, the downloaded string is already the expected xml, in the format that needs to be parsed. @@ -281,5 +263,24 @@ public ActionResult Replace(int replaceId, string url, string document) { return RedirectToAction("Index", new { folderPath = replaceMedia.FolderPath, replaceId = replaceMedia.Id }); } + + private Uri GetRedirectUri(string url) { + var redirectedUrl = url; + + Uri myUri = new Uri(url); + // Create a 'HttpWebRequest' object for the specified url. + HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create(myUri); + // Send the request and wait for response. + HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse(); + + if (!myUri.Equals(myHttpWebResponse.ResponseUri)) { + myUri = myHttpWebResponse.ResponseUri; + } + + // Release resources of response object. + myHttpWebResponse.Close(); + + return myUri; + } } } \ No newline at end of file From f6e198315f016aa1bebdcfb9e9ab5c98c814bfdb Mon Sep 17 00:00:00 2001 From: Andrea Piovanelli Date: Fri, 18 Oct 2024 10:09:49 +0200 Subject: [PATCH 7/7] Removed unused variable --- .../Orchard.MediaLibrary/Controllers/OEmbedController.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs index 7425ba4e87c..c1c877d06df 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs @@ -265,8 +265,6 @@ public ActionResult Replace(int replaceId, string url, string document) { } private Uri GetRedirectUri(string url) { - var redirectedUrl = url; - Uri myUri = new Uri(url); // Create a 'HttpWebRequest' object for the specified url. HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create(myUri);