using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Entities; using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Security; using System.Text; using System.Xml; namespace MediaBrowser.Providers.Savers { /// /// Class XmlHelpers /// public static class XmlSaverHelpers { /// /// The us culture /// private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); /// /// Saves the specified XML. /// /// The XML. /// The path. /// The XML tags used. public static void Save(StringBuilder xml, string path, IEnumerable xmlTagsUsed) { if (File.Exists(path)) { var tags = xmlTagsUsed.ToList(); tags.AddRange(new[] { "MediaInfo", "ContentRating", "MPAARating", "certification", "Persons", "Type", "Overview", "CustomRating", "LocalTitle", "SortTitle", "PremiereDate", "EndDate", "Budget", "Revenue", "Rating", "ProductionYear", "Website", "AspectRatio", "Language", "RunningTime", "Runtime", "TagLine", "Taglines", "IMDB_ID", "IMDB", "IMDbId", "TMDbId", "TVcomId", "RottenTomatoesId", "MusicbrainzId", "CollectionNumber", "Genres", "Genre", "Studios", "Tags", "Added", "LockData", "Trailer", "CriticRating", "CriticRatingSummary", "GamesDbId", "BirthDate", "DeathDate", "LockedFields", "Chapters" }); var position = xml.ToString().LastIndexOf(" /// Gets the custom tags. /// /// The path. /// The XML tags used. /// System.String. private static string GetCustomTags(string path, ICollection xmlTagsUsed) { var doc = new XmlDocument(); doc.Load(path); var nodes = doc.DocumentElement.ChildNodes.Cast() .Where(i => !xmlTagsUsed.Contains(i.Name)) .Select(i => i.OuterXml) .ToArray(); return string.Join(Environment.NewLine, nodes); } /// /// Adds the common nodes. /// /// The item. /// The builder. public static void AddCommonNodes(BaseItem item, StringBuilder builder) { if (!string.IsNullOrEmpty(item.OfficialRating)) { builder.Append("" + SecurityElement.Escape(item.OfficialRating) + ""); builder.Append("" + SecurityElement.Escape(item.OfficialRating) + ""); builder.Append("" + SecurityElement.Escape(item.OfficialRating) + ""); } builder.Append("" + SecurityElement.Escape(item.DateCreated.ToLocalTime().ToString("G")) + ""); builder.Append("" + item.DontFetchMeta.ToString().ToLower() + ""); if (item.LockedFields.Count > 0) { builder.Append("" + string.Join("|", item.LockedFields.Select(i => i.ToString()).ToArray()) + ""); } if (!string.IsNullOrEmpty(item.DisplayMediaType)) { builder.Append("" + SecurityElement.Escape(item.DisplayMediaType) + ""); } if (item.CriticRating.HasValue) { builder.Append("" + SecurityElement.Escape(item.CriticRating.Value.ToString(UsCulture)) + ""); } if (!string.IsNullOrEmpty(item.CriticRatingSummary)) { builder.Append(""); } if (!string.IsNullOrEmpty(item.Overview)) { builder.Append(""); } if (!string.IsNullOrEmpty(item.CustomRating)) { builder.Append("" + SecurityElement.Escape(item.CustomRating) + ""); } if (!string.IsNullOrEmpty(item.Name) && !(item is Episode)) { builder.Append("" + SecurityElement.Escape(item.Name) + ""); } if (!string.IsNullOrEmpty(item.ForcedSortName)) { builder.Append("" + SecurityElement.Escape(item.ForcedSortName) + ""); } if (item.PremiereDate.HasValue) { if (item is Person) { builder.Append("" + SecurityElement.Escape(item.PremiereDate.Value.ToString("yyyy-MM-dd")) + ""); } else if (!(item is Episode)) { builder.Append("" + SecurityElement.Escape(item.PremiereDate.Value.ToString("yyyy-MM-dd")) + ""); } } if (item.EndDate.HasValue) { if (item is Person) { builder.Append("" + SecurityElement.Escape(item.EndDate.Value.ToString("yyyy-MM-dd")) + ""); } else if (!(item is Episode)) { builder.Append("" + SecurityElement.Escape(item.EndDate.Value.ToString("yyyy-MM-dd")) + ""); } } if (item.RemoteTrailers.Count > 0) { builder.Append("" + SecurityElement.Escape(item.RemoteTrailers[0].Url) + ""); } if (item.Budget.HasValue) { builder.Append("" + SecurityElement.Escape(item.Budget.Value.ToString(UsCulture)) + ""); } if (item.Revenue.HasValue) { builder.Append("" + SecurityElement.Escape(item.Revenue.Value.ToString(UsCulture)) + ""); } if (item.CommunityRating.HasValue) { builder.Append("" + SecurityElement.Escape(item.CommunityRating.Value.ToString(UsCulture)) + ""); } if (item.ProductionYear.HasValue && !(item is Person)) { builder.Append("" + SecurityElement.Escape(item.ProductionYear.Value.ToString(UsCulture)) + ""); } if (!string.IsNullOrEmpty(item.HomePageUrl)) { builder.Append("" + SecurityElement.Escape(item.HomePageUrl) + ""); } if (!string.IsNullOrEmpty(item.AspectRatio)) { builder.Append("" + SecurityElement.Escape(item.AspectRatio) + ""); } if (!string.IsNullOrEmpty(item.Language)) { builder.Append("" + SecurityElement.Escape(item.Language) + ""); } // Use original runtime here, actual file runtime later in MediaInfo var runTimeTicks = item.OriginalRunTimeTicks ?? item.RunTimeTicks; if (runTimeTicks.HasValue) { var timespan = TimeSpan.FromTicks(runTimeTicks.Value); builder.Append("" + Convert.ToInt32(timespan.TotalMinutes).ToString(UsCulture) + ""); builder.Append("" + Convert.ToInt32(timespan.TotalMinutes).ToString(UsCulture) + ""); } var imdb = item.GetProviderId(MetadataProviders.Imdb); if (!string.IsNullOrEmpty(imdb)) { builder.Append("" + SecurityElement.Escape(imdb) + ""); builder.Append("" + SecurityElement.Escape(imdb) + ""); builder.Append("" + SecurityElement.Escape(imdb) + ""); } var tmdb = item.GetProviderId(MetadataProviders.Tmdb); if (!string.IsNullOrEmpty(tmdb)) { builder.Append("" + SecurityElement.Escape(tmdb) + ""); } if (!(item is Series)) { var tvdb = item.GetProviderId(MetadataProviders.Tvdb); if (!string.IsNullOrEmpty(tvdb)) { builder.Append("" + SecurityElement.Escape(tvdb) + ""); } } var tvcom = item.GetProviderId(MetadataProviders.Tvcom); if (!string.IsNullOrEmpty(tvcom)) { builder.Append("" + SecurityElement.Escape(tvcom) + ""); } var rt = item.GetProviderId(MetadataProviders.RottenTomatoes); if (!string.IsNullOrEmpty(rt)) { builder.Append("" + SecurityElement.Escape(rt) + ""); } var mbz = item.GetProviderId(MetadataProviders.Musicbrainz); if (!string.IsNullOrEmpty(mbz)) { builder.Append("" + SecurityElement.Escape(mbz) + ""); } var gamesdb = item.GetProviderId(MetadataProviders.Gamesdb); if (!string.IsNullOrEmpty(gamesdb)) { builder.Append("" + SecurityElement.Escape(gamesdb) + ""); } var tmdbCollection = item.GetProviderId(MetadataProviders.TmdbCollection); if (!string.IsNullOrEmpty(tmdbCollection)) { builder.Append("" + SecurityElement.Escape(tmdbCollection) + ""); } if (item.Taglines.Count > 0) { builder.Append("" + SecurityElement.Escape(item.Taglines[0]) + ""); builder.Append(""); foreach (var tagline in item.Taglines) { builder.Append("" + SecurityElement.Escape(tagline) + ""); } builder.Append(""); } if (item.Genres.Count > 0) { builder.Append(""); foreach (var genre in item.Genres) { builder.Append("" + SecurityElement.Escape(genre) + ""); } builder.Append(""); builder.Append("" + SecurityElement.Escape(string.Join("|", item.Genres.ToArray())) + ""); } if (item.Studios.Count > 0) { builder.Append(""); foreach (var studio in item.Studios) { builder.Append("" + SecurityElement.Escape(studio) + ""); } builder.Append(""); } if (item.Tags.Count > 0) { builder.Append(""); foreach (var tag in item.Tags) { builder.Append("" + SecurityElement.Escape(tag) + ""); } builder.Append(""); } if (item.People.Count > 0) { builder.Append(""); foreach (var person in item.People) { builder.Append(""); builder.Append("" + SecurityElement.Escape(person.Name) + ""); builder.Append("" + SecurityElement.Escape(person.Type) + ""); builder.Append("" + SecurityElement.Escape(person.Role) + ""); builder.Append(""); } builder.Append(""); } } public static void AddChapters(Video item, StringBuilder builder, IItemRepository repository) { var chapters = repository.GetChapters(item.Id); builder.Append(""); foreach (var chapter in chapters) { builder.Append(""); builder.Append("" + SecurityElement.Escape(chapter.Name) + ""); var time = TimeSpan.FromTicks(chapter.StartPositionTicks); var ms = Convert.ToInt64(time.TotalMilliseconds); builder.Append("" + SecurityElement.Escape(ms.ToString(UsCulture)) + ""); builder.Append(""); } builder.Append(""); } /// /// Appends the media info. /// /// /// The item. /// The builder. public static void AddMediaInfo(T item, StringBuilder builder) where T : BaseItem, IHasMediaStreams { builder.Append(""); foreach (var stream in item.MediaStreams) { builder.Append("<" + stream.Type + ">"); if (!string.IsNullOrEmpty(stream.Codec)) { builder.Append("" + SecurityElement.Escape(stream.Codec) + ""); builder.Append("" + SecurityElement.Escape(stream.Codec) + ""); } if (stream.BitRate.HasValue) { builder.Append("" + stream.BitRate.Value.ToString(UsCulture) + ""); } if (stream.Width.HasValue) { builder.Append("" + stream.Width.Value.ToString(UsCulture) + ""); } if (stream.Height.HasValue) { builder.Append("" + stream.Height.Value.ToString(UsCulture) + ""); } if (!string.IsNullOrEmpty(stream.AspectRatio)) { builder.Append("" + SecurityElement.Escape(stream.AspectRatio) + ""); } var framerate = stream.AverageFrameRate ?? stream.RealFrameRate; if (framerate.HasValue) { builder.Append("" + framerate.Value.ToString(UsCulture) + ""); } if (!string.IsNullOrEmpty(stream.Language)) { builder.Append("" + SecurityElement.Escape(stream.Language) + ""); } if (!string.IsNullOrEmpty(stream.ScanType)) { builder.Append("" + SecurityElement.Escape(stream.ScanType) + ""); } if (stream.Channels.HasValue) { builder.Append("" + stream.Channels.Value.ToString(UsCulture) + ""); } if (stream.SampleRate.HasValue) { builder.Append("" + stream.SampleRate.Value.ToString(UsCulture) + ""); } builder.Append("" + SecurityElement.Escape(stream.IsDefault.ToString()) + ""); builder.Append("" + SecurityElement.Escape(stream.IsForced.ToString()) + ""); if (stream.Type == MediaStreamType.Video) { if (item.RunTimeTicks.HasValue) { var timespan = TimeSpan.FromTicks(item.RunTimeTicks.Value); builder.Append("" + Convert.ToInt32(timespan.TotalMinutes).ToString(UsCulture) + ""); builder.Append("" + Convert.ToInt32(timespan.TotalSeconds).ToString(UsCulture) + ""); } var video = item as Video; if (video != null && video.Video3DFormat.HasValue) { switch (video.Video3DFormat.Value) { case Video3DFormat.FullSideBySide: builder.Append("FSBS"); break; case Video3DFormat.FullTopAndBottom: builder.Append("FTAB"); break; case Video3DFormat.HalfSideBySide: builder.Append("HSBS"); break; case Video3DFormat.HalfTopAndBottom: builder.Append("HTAB"); break; } } } builder.Append(""); } builder.Append(""); } } }