diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs index 2d42832efcd..c1c877d06df 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs @@ -82,26 +82,54 @@ 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 = ""; + + // 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. + // Legacy process is done for non-Vimeo content. + // First of all, url domain is checked. + 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("www.youtube.com", StringComparison.OrdinalIgnoreCase); + + if (vimeo) { + // Add api url to original url provided as a parameter + 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://" + uri.Host + "/oembed?format=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 + } } } } @@ -137,8 +165,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); } @@ -167,8 +194,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) { @@ -203,7 +229,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(); } @@ -213,8 +239,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) { @@ -238,5 +263,22 @@ public ActionResult Replace(int replaceId, string url, string document) { return RedirectToAction("Index", new { folderPath = replaceMedia.FolderPath, replaceId = replaceMedia.Id }); } + + private Uri GetRedirectUri(string 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