2
0
Bond_009 6 жил өмнө
parent
commit
ffd6dac03a

+ 1 - 1
Emby.Dlna/Main/DlnaEntryPoint.cs

@@ -257,7 +257,7 @@ namespace Emby.Dlna.Main
 
                 var fullService = "urn:schemas-upnp-org:device:MediaServer:1";
 
-                _logger.LogInformation("Registering publisher for {0} on {1}", fullService, address.ToString());
+                _logger.LogInformation("Registering publisher for {0} on {1}", fullService, address);
 
                 var descriptorUri = "/dlna/" + udn + "/description.xml";
                 var uri = new Uri(_appHost.GetLocalApiUrl(address) + descriptorUri);

+ 14 - 19
MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs

@@ -99,29 +99,24 @@ namespace MediaBrowser.LocalMetadata.Parsers
             item.ResetPeople();
 
             using (var fileStream = File.OpenRead(metadataFile))
+            using (var streamReader = new StreamReader(fileStream, encoding))
+            using (var reader = XmlReader.Create(streamReader, settings))
             {
-                using (var streamReader = new StreamReader(fileStream, encoding))
+                reader.MoveToContent();
+                reader.Read();
+
+                // Loop through each element
+                while (!reader.EOF && reader.ReadState == ReadState.Interactive)
                 {
-                    // Use XmlReader for best performance
-                    using (var reader = XmlReader.Create(streamReader, settings))
+                    cancellationToken.ThrowIfCancellationRequested();
+
+                    if (reader.NodeType == XmlNodeType.Element)
+                    {
+                        FetchDataFromXmlNode(reader, item);
+                    }
+                    else
                     {
-                        reader.MoveToContent();
                         reader.Read();
-
-                        // Loop through each element
-                        while (!reader.EOF && reader.ReadState == ReadState.Interactive)
-                        {
-                            cancellationToken.ThrowIfCancellationRequested();
-
-                            if (reader.NodeType == XmlNodeType.Element)
-                            {
-                                FetchDataFromXmlNode(reader, item);
-                            }
-                            else
-                            {
-                                reader.Read();
-                            }
-                        }
                     }
                 }
             }

+ 33 - 36
MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs

@@ -246,52 +246,49 @@ namespace MediaBrowser.MediaEncoding.Probing
 
             // <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>cast</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>name</key>\n\t\t\t<string>Blender Foundation</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>name</key>\n\t\t\t<string>Janus Bager Kristensen</string>\n\t\t</dict>\n\t</array>\n\t<key>directors</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>name</key>\n\t\t\t<string>Sacha Goedegebure</string>\n\t\t</dict>\n\t</array>\n\t<key>studio</key>\n\t<string>Blender Foundation</string>\n</dict>\n</plist>\n
             using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(xml)))
+            using (var streamReader = new StreamReader(stream))
             {
-                using (var streamReader = new StreamReader(stream))
+                try
                 {
-                    try
+                    using (var reader = XmlReader.Create(streamReader))
                     {
-                        // Use XmlReader for best performance
-                        using (var reader = XmlReader.Create(streamReader))
-                        {
-                            reader.MoveToContent();
-                            reader.Read();
+                        reader.MoveToContent();
+                        reader.Read();
 
-                            // Loop through each element
-                            while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+                        // Loop through each element
+                        while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+                        {
+                            if (reader.NodeType == XmlNodeType.Element)
                             {
-                                if (reader.NodeType == XmlNodeType.Element)
+                                switch (reader.Name)
                                 {
-                                    switch (reader.Name)
-                                    {
-                                        case "dict":
-                                            if (reader.IsEmptyElement)
-                                            {
-                                                reader.Read();
-                                                continue;
-                                            }
-                                            using (var subtree = reader.ReadSubtree())
-                                            {
-                                                ReadFromDictNode(subtree, info);
-                                            }
-                                            break;
-                                        default:
-                                            reader.Skip();
-                                            break;
-                                    }
-                                }
-                                else
-                                {
-                                    reader.Read();
+                                    case "dict":
+                                        if (reader.IsEmptyElement)
+                                        {
+                                            reader.Read();
+                                            continue;
+                                        }
+                                        using (var subtree = reader.ReadSubtree())
+                                        {
+                                            ReadFromDictNode(subtree, info);
+                                        }
+                                        break;
+                                    default:
+                                        reader.Skip();
+                                        break;
                                 }
                             }
+                            else
+                            {
+                                reader.Read();
+                            }
                         }
                     }
-                    catch (XmlException)
-                    {
-                        // I've seen probe examples where the iTunMOVI value is just "<"
-                        // So we should not allow this to fail the entire probing operation
-                    }
+                }
+                catch (XmlException)
+                {
+                    // I've seen probe examples where the iTunMOVI value is just "<"
+                    // So we should not allow this to fail the entire probing operation
                 }
             }
         }

+ 2 - 0
MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs

@@ -192,6 +192,7 @@ namespace MediaBrowser.Providers.TV.TheTVDB
                     Type = PersonType.Director
                 });
             }
+
             foreach (var person in episode.GuestStars)
             {
                 var index = person.IndexOf('(');
@@ -212,6 +213,7 @@ namespace MediaBrowser.Providers.TV.TheTVDB
                     Role = role
                 });
             }
+
             foreach (var writer in episode.Writers)
             {
                 result.AddPerson(new PersonInfo

+ 0 - 396
MediaBrowser.Providers/TV/TheTVDB/TvdbPrescanTask.cs

@@ -1,396 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Xml;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.TV;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.IO;
-using MediaBrowser.Model.Net;
-using MediaBrowser.Providers.TV.TheTVDB;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Providers.TV
-{
-    /// <summary>
-    /// Class TvdbPrescanTask
-    /// </summary>
-    public class TvdbPrescanTask : ILibraryPostScanTask
-    {
-        public const string TvdbBaseUrl = "https://thetvdb.com/";
-
-        /// <summary>
-        /// The server time URL
-        /// </summary>
-        private const string ServerTimeUrl = TvdbBaseUrl + "api/Updates.php?type=none";
-
-        /// <summary>
-        /// The updates URL
-        /// </summary>
-        private const string UpdatesUrl = TvdbBaseUrl + "api/Updates.php?type=all&time={0}";
-
-        /// <summary>
-        /// The _HTTP client
-        /// </summary>
-        private readonly IHttpClient _httpClient;
-        /// <summary>
-        /// The _logger
-        /// </summary>
-        private readonly ILogger _logger;
-        /// <summary>
-        /// The _config
-        /// </summary>
-        private readonly IServerConfigurationManager _config;
-        private readonly IFileSystem _fileSystem;
-        private readonly ILibraryManager _libraryManager;
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="TvdbPrescanTask"/> class.
-        /// </summary>
-        /// <param name="logger">The logger.</param>
-        /// <param name="httpClient">The HTTP client.</param>
-        /// <param name="config">The config.</param>
-        public TvdbPrescanTask(ILogger logger, IHttpClient httpClient, IServerConfigurationManager config, IFileSystem fileSystem, ILibraryManager libraryManager)
-        {
-            _logger = logger;
-            _httpClient = httpClient;
-            _config = config;
-            _fileSystem = fileSystem;
-            _libraryManager = libraryManager;
-        }
-
-        protected readonly CultureInfo UsCulture = new CultureInfo("en-US");
-
-        /// <summary>
-        /// Runs the specified progress.
-        /// </summary>
-        /// <param name="progress">The progress.</param>
-        /// <param name="cancellationToken">The cancellation token.</param>
-        /// <returns>Task.</returns>
-        public async Task Run(IProgress<double> progress, CancellationToken cancellationToken)
-        {
-            var path = TvdbSeriesProvider.GetSeriesDataPath(_config.CommonApplicationPaths);
-
-            Directory.CreateDirectory(path);
-
-            var timestampFile = Path.Combine(path, "time.txt");
-
-            var timestampFileInfo = _fileSystem.GetFileInfo(timestampFile);
-
-            // Don't check for tvdb updates anymore frequently than 24 hours
-            if (timestampFileInfo.Exists && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(timestampFileInfo)).TotalDays < 1)
-            {
-                return;
-            }
-
-            // Find out the last time we queried tvdb for updates
-            var lastUpdateTime = timestampFileInfo.Exists ? File.ReadAllText(timestampFile, Encoding.UTF8) : string.Empty;
-
-            string newUpdateTime;
-
-            var existingDirectories = _fileSystem.GetDirectoryPaths(path)
-                .Select(Path.GetFileName)
-                .ToList();
-
-            var seriesList = _libraryManager.GetItemList(new InternalItemsQuery()
-            {
-                IncludeItemTypes = new[] { typeof(Series).Name },
-                Recursive = true,
-                GroupByPresentationUniqueKey = false,
-                DtoOptions = new DtoOptions(false)
-                {
-                    EnableImages = false
-                }
-
-            }).Cast<Series>()
-            .ToList();
-
-            var seriesIdsInLibrary = seriesList
-               .Where(i => !string.IsNullOrEmpty(i.GetProviderId(MetadataProviders.Tvdb)))
-               .Select(i => i.GetProviderId(MetadataProviders.Tvdb))
-               .ToList();
-
-            var missingSeries = seriesIdsInLibrary.Except(existingDirectories, StringComparer.OrdinalIgnoreCase)
-                .ToList();
-
-            var enableInternetProviders = seriesList.Count == 0 ? false : seriesList[0].IsMetadataFetcherEnabled(_libraryManager.GetLibraryOptions(seriesList[0]), TvdbSeriesProvider.Current.Name);
-            if (!enableInternetProviders)
-            {
-                progress.Report(100);
-                return;
-            }
-
-            // If this is our first time, update all series
-            if (string.IsNullOrEmpty(lastUpdateTime))
-            {
-                // First get tvdb server time
-                using (var response = await _httpClient.SendAsync(new HttpRequestOptions
-                {
-                    Url = ServerTimeUrl,
-                    CancellationToken = cancellationToken,
-                    EnableHttpCompression = true,
-                    BufferContent = false
-
-                }, "GET").ConfigureAwait(false))
-                {
-                    // First get tvdb server time
-                    using (var stream = response.Content)
-                    {
-                        newUpdateTime = GetUpdateTime(stream);
-                    }
-                }
-
-                existingDirectories.AddRange(missingSeries);
-
-                await UpdateSeries(existingDirectories, path, null, progress, cancellationToken).ConfigureAwait(false);
-            }
-            else
-            {
-                var seriesToUpdate = await GetSeriesIdsToUpdate(existingDirectories, lastUpdateTime, cancellationToken).ConfigureAwait(false);
-
-                newUpdateTime = seriesToUpdate.Item2;
-
-                long.TryParse(lastUpdateTime, NumberStyles.Any, UsCulture, out var lastUpdateValue);
-
-                var nullableUpdateValue = lastUpdateValue == 0 ? (long?)null : lastUpdateValue;
-
-                var listToUpdate = seriesToUpdate.Item1.ToList();
-                listToUpdate.AddRange(missingSeries);
-
-                await UpdateSeries(listToUpdate, path, nullableUpdateValue, progress, cancellationToken).ConfigureAwait(false);
-            }
-
-            File.WriteAllText(timestampFile, newUpdateTime, Encoding.UTF8);
-            progress.Report(100);
-        }
-
-        /// <summary>
-        /// Gets the update time.
-        /// </summary>
-        /// <param name="response">The response.</param>
-        /// <returns>System.String.</returns>
-        private string GetUpdateTime(Stream response)
-        {
-            // Use XmlReader for best performance
-            var settings = new XmlReaderSettings()
-            {
-                ValidationType = ValidationType.None,
-                CheckCharacters = false,
-                IgnoreProcessingInstructions = true,
-                IgnoreComments = true
-            };
-
-            using (var streamReader = new StreamReader(response, Encoding.UTF8))
-            using (var reader = XmlReader.Create(streamReader, settings))
-            {
-                reader.MoveToContent();
-                reader.Read();
-
-                // Loop through each element
-                while (!reader.EOF && reader.ReadState == ReadState.Interactive)
-                {
-                    if (reader.NodeType == XmlNodeType.Element)
-                    {
-                        switch (reader.Name)
-                        {
-                            case "Time":
-                                {
-                                    return (reader.ReadElementContentAsString() ?? string.Empty).Trim();
-                                }
-                            default:
-                                reader.Skip();
-                                break;
-                        }
-                    }
-                    else
-                    {
-                        reader.Read();
-                    }
-                }
-            }
-
-            return null;
-        }
-
-        /// <summary>
-        /// Gets the series ids to update.
-        /// </summary>
-        /// <param name="existingSeriesIds">The existing series ids.</param>
-        /// <param name="lastUpdateTime">The last update time.</param>
-        /// <param name="cancellationToken">The cancellation token.</param>
-        /// <returns>Task{IEnumerable{System.String}}.</returns>
-        private async Task<Tuple<IEnumerable<string>, string>> GetSeriesIdsToUpdate(IEnumerable<string> existingSeriesIds, string lastUpdateTime, CancellationToken cancellationToken)
-        {
-            // First get last time
-            using (var response = await _httpClient.SendAsync(new HttpRequestOptions
-            {
-                Url = string.Format(UpdatesUrl, lastUpdateTime),
-                CancellationToken = cancellationToken,
-                EnableHttpCompression = true,
-                BufferContent = false
-
-            }, "GET").ConfigureAwait(false))
-            {
-                using (var stream = response.Content)
-                {
-                    var data = GetUpdatedSeriesIdList(stream);
-
-                    var existingDictionary = existingSeriesIds.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
-
-                    var seriesList = data.ids
-                        .Where(i => !string.IsNullOrWhiteSpace(i) && existingDictionary.ContainsKey(i));
-
-                    return new Tuple<IEnumerable<string>, string>(seriesList, data.updateTime);
-                }
-            }
-        }
-
-        private (List<string> ids, string updateTime) GetUpdatedSeriesIdList(Stream stream)
-        {
-            string updateTime = null;
-            var idList = new List<string>();
-
-            // Use XmlReader for best performance
-            var settings = new XmlReaderSettings()
-            {
-                ValidationType = ValidationType.None,
-                CheckCharacters = false,
-                IgnoreProcessingInstructions = true,
-                IgnoreComments = true
-            };
-
-            using (var streamReader = new StreamReader(stream, Encoding.UTF8))
-            using (var reader = XmlReader.Create(streamReader, settings))
-            {
-                reader.MoveToContent();
-                reader.Read();
-
-                // Loop through each element
-                while (!reader.EOF && reader.ReadState == ReadState.Interactive)
-                {
-                    if (reader.NodeType == XmlNodeType.Element)
-                    {
-                        switch (reader.Name)
-                        {
-                            case "Time":
-                                {
-                                    updateTime = (reader.ReadElementContentAsString() ?? string.Empty).Trim();
-                                    break;
-                                }
-                            case "Series":
-                                {
-                                    var id = (reader.ReadElementContentAsString() ?? string.Empty).Trim();
-                                    idList.Add(id);
-                                    break;
-                                }
-                            default:
-                                reader.Skip();
-                                break;
-                        }
-                    }
-                    else
-                    {
-                        reader.Read();
-                    }
-                }
-            }
-
-            return (idList, updateTime);
-        }
-
-        /// <summary>
-        /// Updates the series.
-        /// </summary>
-        /// <param name="seriesIds">The series ids.</param>
-        /// <param name="seriesDataPath">The series data path.</param>
-        /// <param name="lastTvDbUpdateTime">The last tv db update time.</param>
-        /// <param name="progress">The progress.</param>
-        /// <param name="cancellationToken">The cancellation token.</param>
-        /// <returns>Task.</returns>
-        private async Task UpdateSeries(List<string> seriesIds, string seriesDataPath, long? lastTvDbUpdateTime, IProgress<double> progress, CancellationToken cancellationToken)
-        {
-            var numComplete = 0;
-
-            var seriesList = _libraryManager.GetItemList(new InternalItemsQuery()
-            {
-                IncludeItemTypes = new[] { typeof(Series).Name },
-                Recursive = true,
-                GroupByPresentationUniqueKey = false,
-                DtoOptions = new DtoOptions(false)
-                {
-                    EnableImages = false
-                }
-
-            }).Cast<Series>();
-
-            // Gather all series into a lookup by tvdb id
-            var allSeries = seriesList
-                .Where(i => !string.IsNullOrEmpty(i.GetProviderId(MetadataProviders.Tvdb)))
-                .ToLookup(i => i.GetProviderId(MetadataProviders.Tvdb));
-
-            foreach (var seriesId in seriesIds)
-            {
-                // Find the preferred language(s) for the movie in the library
-                var languages = allSeries[seriesId]
-                    .Select(i => i.GetPreferredMetadataLanguage())
-                    .Distinct(StringComparer.OrdinalIgnoreCase)
-                    .ToList();
-
-                foreach (var language in languages)
-                {
-                    try
-                    {
-                        await UpdateSeries(seriesId, seriesDataPath, lastTvDbUpdateTime, language, cancellationToken).ConfigureAwait(false);
-                    }
-                    catch (HttpException ex)
-                    {
-                        _logger.LogError(ex, "Error updating tvdb series id {ID}, language {Language}", seriesId, language);
-
-                        // Already logged at lower levels, but don't fail the whole operation, unless timed out
-                        // We have to fail this to make it run again otherwise new episode data could potentially be missing
-                        if (ex.IsTimedOut)
-                        {
-                            throw;
-                        }
-                    }
-                }
-
-                numComplete++;
-                double percent = numComplete;
-                percent /= seriesIds.Count;
-                percent *= 100;
-
-                progress.Report(percent);
-            }
-        }
-
-        /// <summary>
-        /// Updates the series.
-        /// </summary>
-        /// <param name="id">The id.</param>
-        /// <param name="seriesDataPath">The series data path.</param>
-        /// <param name="lastTvDbUpdateTime">The last tv db update time.</param>
-        /// <param name="preferredMetadataLanguage">The preferred metadata language.</param>
-        /// <param name="cancellationToken">The cancellation token.</param>
-        /// <returns>Task.</returns>
-        private Task UpdateSeries(string id, string seriesDataPath, long? lastTvDbUpdateTime, string preferredMetadataLanguage, CancellationToken cancellationToken)
-        {
-            _logger.LogInformation("Updating series from tvdb " + id + ", language " + preferredMetadataLanguage);
-
-            seriesDataPath = Path.Combine(seriesDataPath, id);
-
-            Directory.CreateDirectory(seriesDataPath);
-
-            return TvdbSeriesProvider.Current.DownloadSeriesZip(id, MetadataProviders.Tvdb.ToString(), null, null, seriesDataPath, lastTvDbUpdateTime, preferredMetadataLanguage, cancellationToken);
-        }
-    }
-}

+ 1 - 1
MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs

@@ -145,6 +145,7 @@ namespace MediaBrowser.Providers.TV.TheTVDB
 
         private async Task<string> GetSeriesByRemoteId(string id, string idType, string language, CancellationToken cancellationToken)
         {
+
             TvDbResponse<SeriesSearchResult[]> result = null;
 
             try
@@ -333,7 +334,6 @@ namespace MediaBrowser.Providers.TV.TheTVDB
             result.ResultLanguage = metadataLanguage;
             series.AirDays = TVUtils.GetAirDays(tvdbSeries.AirsDayOfWeek);
             series.AirTime = tvdbSeries.AirsTime;
-
             series.CommunityRating = (float?)tvdbSeries.SiteRating;
             series.SetProviderId(MetadataProviders.Imdb, tvdbSeries.ImdbId);
             series.SetProviderId(MetadataProviders.Zap2It, tvdbSeries.Zap2itId);

+ 76 - 85
MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs

@@ -62,14 +62,6 @@ namespace MediaBrowser.XbmcMetadata.Parsers
                 throw new ArgumentException("The metadata file was empty or null.", nameof(metadataFile));
             }
 
-            var settings = new XmlReaderSettings()
-            {
-                ValidationType = ValidationType.None,
-                CheckCharacters = false,
-                IgnoreProcessingInstructions = true,
-                IgnoreComments = true
-            };
-
             _validProviderIds = _validProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
 
             var idInfos = ProviderManager.GetExternalIdInfos(item.Item);
@@ -88,7 +80,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers
             _validProviderIds.Add("tmdbcolid", "TmdbCollection");
             _validProviderIds.Add("imdb_id", "Imdb");
 
-            Fetch(item, metadataFile, settings, cancellationToken);
+            Fetch(item, metadataFile, GetXmlReaderSettings(), cancellationToken);
         }
 
         protected virtual bool SupportsUrlAfterClosingXmlTag => false;
@@ -105,31 +97,26 @@ namespace MediaBrowser.XbmcMetadata.Parsers
             if (!SupportsUrlAfterClosingXmlTag)
             {
                 using (var fileStream = File.OpenRead(metadataFile))
+                using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
+                using (var reader = XmlReader.Create(streamReader, settings))
                 {
-                    using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
-                    {
-                        // Use XmlReader for best performance
-                        using (var reader = XmlReader.Create(streamReader, settings))
-                        {
-                            item.ResetPeople();
+                    item.ResetPeople();
 
-                            reader.MoveToContent();
-                            reader.Read();
+                    reader.MoveToContent();
+                    reader.Read();
 
-                            // Loop through each element
-                            while (!reader.EOF && reader.ReadState == ReadState.Interactive)
-                            {
-                                cancellationToken.ThrowIfCancellationRequested();
+                    // Loop through each element
+                    while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+                    {
+                        cancellationToken.ThrowIfCancellationRequested();
 
-                                if (reader.NodeType == XmlNodeType.Element)
-                                {
-                                    FetchDataFromXmlNode(reader, item);
-                                }
-                                else
-                                {
-                                    reader.Read();
-                                }
-                            }
+                        if (reader.NodeType == XmlNodeType.Element)
+                        {
+                            FetchDataFromXmlNode(reader, item);
+                        }
+                        else
+                        {
+                            reader.Read();
                         }
                     }
                 }
@@ -137,81 +124,76 @@ namespace MediaBrowser.XbmcMetadata.Parsers
             }
 
             using (var fileStream = File.OpenRead(metadataFile))
+            using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
             {
-                using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
-                {
-                    item.ResetPeople();
+                item.ResetPeople();
 
-                    // Need to handle a url after the xml data
-                    // http://kodi.wiki/view/NFO_files/movies
+                // Need to handle a url after the xml data
+                // http://kodi.wiki/view/NFO_files/movies
 
-                    var xml = streamReader.ReadToEnd();
+                var xml = streamReader.ReadToEnd();
 
-                    // Find last closing Tag
-                    // Need to do this in two steps to account for random > characters after the closing xml
-                    var index = xml.LastIndexOf(@"</", StringComparison.Ordinal);
+                // Find last closing Tag
+                // Need to do this in two steps to account for random > characters after the closing xml
+                var index = xml.LastIndexOf(@"</", StringComparison.Ordinal);
 
-                    // If closing tag exists, move to end of Tag
-                    if (index != -1)
-                    {
-                        index = xml.IndexOf('>', index);
-                    }
-
-                    if (index != -1)
-                    {
-                        var endingXml = xml.Substring(index);
+                // If closing tag exists, move to end of Tag
+                if (index != -1)
+                {
+                    index = xml.IndexOf('>', index);
+                }
 
-                        ParseProviderLinks(item.Item, endingXml);
+                if (index != -1)
+                {
+                    var endingXml = xml.Substring(index);
 
-                        // If the file is just an imdb url, don't go any further
-                        if (index == 0)
-                        {
-                            return;
-                        }
+                    ParseProviderLinks(item.Item, endingXml);
 
-                        xml = xml.Substring(0, index + 1);
-                    }
-                    else
+                    // If the file is just an imdb url, don't go any further
+                    if (index == 0)
                     {
-                        // If the file is just an Imdb url, handle that
-
-                        ParseProviderLinks(item.Item, xml);
-
                         return;
                     }
 
-                    // These are not going to be valid xml so no sense in causing the provider to fail and spamming the log with exceptions
-                    try
+                    xml = xml.Substring(0, index + 1);
+                }
+                else
+                {
+                    // If the file is just an Imdb url, handle that
+
+                    ParseProviderLinks(item.Item, xml);
+
+                    return;
+                }
+
+                // These are not going to be valid xml so no sense in causing the provider to fail and spamming the log with exceptions
+                try
+                {
+                    using (var stringReader = new StringReader(xml))
+                    using (var reader = XmlReader.Create(stringReader, settings))
                     {
-                        using (var stringReader = new StringReader(xml))
+                        reader.MoveToContent();
+                        reader.Read();
+
+                        // Loop through each element
+                        while (!reader.EOF && reader.ReadState == ReadState.Interactive)
                         {
-                            // Use XmlReader for best performance
-                            using (var reader = XmlReader.Create(stringReader, settings))
+                            cancellationToken.ThrowIfCancellationRequested();
+
+                            if (reader.NodeType == XmlNodeType.Element)
+                            {
+                                FetchDataFromXmlNode(reader, item);
+                            }
+                            else
                             {
-                                reader.MoveToContent();
                                 reader.Read();
-
-                                // Loop through each element
-                                while (!reader.EOF && reader.ReadState == ReadState.Interactive)
-                                {
-                                    cancellationToken.ThrowIfCancellationRequested();
-
-                                    if (reader.NodeType == XmlNodeType.Element)
-                                    {
-                                        FetchDataFromXmlNode(reader, item);
-                                    }
-                                    else
-                                    {
-                                        reader.Read();
-                                    }
-                                }
                             }
                         }
                     }
-                    catch (XmlException)
-                    {
+                }
+                catch (XmlException)
+                {
 
-                    }
                 }
             }
         }
@@ -916,6 +898,15 @@ namespace MediaBrowser.XbmcMetadata.Parsers
             };
         }
 
+        internal XmlReaderSettings GetXmlReaderSettings()
+            => new XmlReaderSettings()
+            {
+                ValidationType = ValidationType.None,
+                CheckCharacters = false,
+                IgnoreProcessingInstructions = true,
+                IgnoreComments = true
+            };
+
         /// <summary>
         /// Used to split names of comma or pipe delimeted genres and people
         /// </summary>

+ 29 - 34
MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs

@@ -27,53 +27,48 @@ namespace MediaBrowser.XbmcMetadata.Parsers
         protected override void Fetch(MetadataResult<Episode> item, string metadataFile, XmlReaderSettings settings, CancellationToken cancellationToken)
         {
             using (var fileStream = File.OpenRead(metadataFile))
+            using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
             {
-                using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
-                {
-                    item.ResetPeople();
+                item.ResetPeople();
 
-                    var xml = streamReader.ReadToEnd();
+                var xml = streamReader.ReadToEnd();
 
-                    var srch = "</episodedetails>";
-                    var index = xml.IndexOf(srch, StringComparison.OrdinalIgnoreCase);
+                var srch = "</episodedetails>";
+                var index = xml.IndexOf(srch, StringComparison.OrdinalIgnoreCase);
 
-                    if (index != -1)
-                    {
-                        xml = xml.Substring(0, index + srch.Length);
-                    }
+                if (index != -1)
+                {
+                    xml = xml.Substring(0, index + srch.Length);
+                }
 
-                    // These are not going to be valid xml so no sense in causing the provider to fail and spamming the log with exceptions
-                    try
+                // These are not going to be valid xml so no sense in causing the provider to fail and spamming the log with exceptions
+                try
+                {
+                    using (var stringReader = new StringReader(xml))
+                    using (var reader = XmlReader.Create(stringReader, settings))
                     {
-                        using (var stringReader = new StringReader(xml))
+                        reader.MoveToContent();
+                        reader.Read();
+
+                        // Loop through each element
+                        while (!reader.EOF && reader.ReadState == ReadState.Interactive)
                         {
-                            // Use XmlReader for best performance
-                            using (var reader = XmlReader.Create(stringReader, settings))
+                            cancellationToken.ThrowIfCancellationRequested();
+
+                            if (reader.NodeType == XmlNodeType.Element)
+                            {
+                                FetchDataFromXmlNode(reader, item);
+                            }
+                            else
                             {
-                                reader.MoveToContent();
                                 reader.Read();
-
-                                // Loop through each element
-                                while (!reader.EOF && reader.ReadState == ReadState.Interactive)
-                                {
-                                    cancellationToken.ThrowIfCancellationRequested();
-
-                                    if (reader.NodeType == XmlNodeType.Element)
-                                    {
-                                        FetchDataFromXmlNode(reader, item);
-                                    }
-                                    else
-                                    {
-                                        reader.Read();
-                                    }
-                                }
                             }
                         }
                     }
-                    catch (XmlException)
-                    {
+                }
+                catch (XmlException)
+                {
 
-                    }
                 }
             }
         }

+ 1 - 10
MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs

@@ -122,18 +122,9 @@ namespace MediaBrowser.XbmcMetadata.Parsers
             using (var stringReader = new StringReader("<set>" + xml + "</set>"))
             {
                 // These are not going to be valid xml so no sense in causing the provider to fail and spamming the log with exceptions
-                var settings = new XmlReaderSettings()
-                {
-                    ValidationType = ValidationType.None,
-                    CheckCharacters = false,
-                    IgnoreProcessingInstructions = true,
-                    IgnoreComments = true
-                };
-
                 try
                 {
-                    // Use XmlReader for best performance
-                    using (var reader = XmlReader.Create(stringReader, settings))
+                    using (var reader = XmlReader.Create(stringReader, GetXmlReaderSettings()))
                     {
                         reader.MoveToContent();
                         reader.Read();

+ 0 - 1
MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs

@@ -964,7 +964,6 @@ namespace MediaBrowser.XbmcMetadata.Savers
 
         private void AddCustomTags(string path, List<string> xmlTagsUsed, XmlWriter writer, ILogger logger, IFileSystem fileSystem)
         {
-            // Use XmlReader for best performance
             var settings = new XmlReaderSettings()
             {
                 ValidationType = ValidationType.None,