|
|
|
@ -15,6 +15,8 @@ using System.Text;
|
|
|
|
|
using System.Text.RegularExpressions;
|
|
|
|
|
using System.Threading;
|
|
|
|
|
using System.Xml;
|
|
|
|
|
using MediaBrowser.Model.IO;
|
|
|
|
|
using MediaBrowser.Model.Xml;
|
|
|
|
|
|
|
|
|
|
namespace MediaBrowser.XbmcMetadata.Parsers
|
|
|
|
|
{
|
|
|
|
@ -25,7 +27,9 @@ namespace MediaBrowser.XbmcMetadata.Parsers
|
|
|
|
|
/// The logger
|
|
|
|
|
/// </summary>
|
|
|
|
|
protected ILogger Logger { get; private set; }
|
|
|
|
|
protected IFileSystem FileSystem { get; private set; }
|
|
|
|
|
protected IProviderManager ProviderManager { get; private set; }
|
|
|
|
|
protected IXmlReaderSettingsFactory XmlReaderSettingsFactory { get; private set; }
|
|
|
|
|
|
|
|
|
|
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
|
|
|
|
|
private readonly IConfigurationManager _config;
|
|
|
|
@ -34,13 +38,13 @@ namespace MediaBrowser.XbmcMetadata.Parsers
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Initializes a new instance of the <see cref="BaseNfoParser{T}" /> class.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="logger">The logger.</param>
|
|
|
|
|
/// <param name="config">The configuration.</param>
|
|
|
|
|
public BaseNfoParser(ILogger logger, IConfigurationManager config, IProviderManager providerManager)
|
|
|
|
|
public BaseNfoParser(ILogger logger, IConfigurationManager config, IProviderManager providerManager, IFileSystem fileSystem, IXmlReaderSettingsFactory xmlReaderSettingsFactory)
|
|
|
|
|
{
|
|
|
|
|
Logger = logger;
|
|
|
|
|
_config = config;
|
|
|
|
|
ProviderManager = providerManager;
|
|
|
|
|
FileSystem = fileSystem;
|
|
|
|
|
XmlReaderSettingsFactory = xmlReaderSettingsFactory;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
@ -63,15 +67,13 @@ namespace MediaBrowser.XbmcMetadata.Parsers
|
|
|
|
|
throw new ArgumentNullException();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var settings = new XmlReaderSettings
|
|
|
|
|
{
|
|
|
|
|
CheckCharacters = false,
|
|
|
|
|
IgnoreProcessingInstructions = true,
|
|
|
|
|
IgnoreComments = true,
|
|
|
|
|
ValidationType = ValidationType.None
|
|
|
|
|
};
|
|
|
|
|
var settings = XmlReaderSettingsFactory.Create(false);
|
|
|
|
|
|
|
|
|
|
_validProviderIds = _validProviderIds = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
|
|
|
|
|
settings.CheckCharacters = false;
|
|
|
|
|
settings.IgnoreProcessingInstructions = true;
|
|
|
|
|
settings.IgnoreComments = true;
|
|
|
|
|
|
|
|
|
|
_validProviderIds = _validProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
|
|
|
|
|
|
|
|
|
var idInfos = ProviderManager.GetExternalIdInfos(item.Item);
|
|
|
|
|
|
|
|
|
@ -108,23 +110,26 @@ namespace MediaBrowser.XbmcMetadata.Parsers
|
|
|
|
|
{
|
|
|
|
|
if (!SupportsUrlAfterClosingXmlTag)
|
|
|
|
|
{
|
|
|
|
|
using (var streamReader = BaseNfoSaver.GetStreamReader(metadataFile))
|
|
|
|
|
using (var fileStream = FileSystem.OpenRead(metadataFile))
|
|
|
|
|
{
|
|
|
|
|
// Use XmlReader for best performance
|
|
|
|
|
using (var reader = XmlReader.Create(streamReader, settings))
|
|
|
|
|
using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
|
|
|
|
|
{
|
|
|
|
|
item.ResetPeople();
|
|
|
|
|
|
|
|
|
|
reader.MoveToContent();
|
|
|
|
|
|
|
|
|
|
// Loop through each element
|
|
|
|
|
while (reader.Read())
|
|
|
|
|
// Use XmlReader for best performance
|
|
|
|
|
using (var reader = XmlReader.Create(streamReader, settings))
|
|
|
|
|
{
|
|
|
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
|
|
|
item.ResetPeople();
|
|
|
|
|
|
|
|
|
|
reader.MoveToContent();
|
|
|
|
|
|
|
|
|
|
if (reader.NodeType == XmlNodeType.Element)
|
|
|
|
|
// Loop through each element
|
|
|
|
|
while (reader.Read())
|
|
|
|
|
{
|
|
|
|
|
FetchDataFromXmlNode(reader, item);
|
|
|
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
|
|
|
|
|
|
|
|
if (reader.NodeType == XmlNodeType.Element)
|
|
|
|
|
{
|
|
|
|
|
FetchDataFromXmlNode(reader, item);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -132,78 +137,81 @@ namespace MediaBrowser.XbmcMetadata.Parsers
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
using (var streamReader = BaseNfoSaver.GetStreamReader(metadataFile))
|
|
|
|
|
using (var fileStream = FileSystem.OpenRead(metadataFile))
|
|
|
|
|
{
|
|
|
|
|
item.ResetPeople();
|
|
|
|
|
|
|
|
|
|
// Need to handle a url after the xml data
|
|
|
|
|
// http://kodi.wiki/view/NFO_files/movies
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
// If closing tag exists, move to end of Tag
|
|
|
|
|
if (index != -1)
|
|
|
|
|
using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
|
|
|
|
|
{
|
|
|
|
|
index = xml.IndexOf('>', index);
|
|
|
|
|
}
|
|
|
|
|
item.ResetPeople();
|
|
|
|
|
|
|
|
|
|
if (index != -1)
|
|
|
|
|
{
|
|
|
|
|
var endingXml = xml.Substring(index);
|
|
|
|
|
// Need to handle a url after the xml data
|
|
|
|
|
// http://kodi.wiki/view/NFO_files/movies
|
|
|
|
|
|
|
|
|
|
var xml = streamReader.ReadToEnd();
|
|
|
|
|
|
|
|
|
|
ParseProviderLinks(item.Item, endingXml);
|
|
|
|
|
// 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 the file is just an imdb url, don't go any further
|
|
|
|
|
if (index == 0)
|
|
|
|
|
// If closing tag exists, move to end of Tag
|
|
|
|
|
if (index != -1)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
index = xml.IndexOf('>', index);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
xml = xml.Substring(0, index + 1);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// If the file is just an Imdb url, handle that
|
|
|
|
|
if (index != -1)
|
|
|
|
|
{
|
|
|
|
|
var endingXml = xml.Substring(index);
|
|
|
|
|
|
|
|
|
|
ParseProviderLinks(item.Item, xml);
|
|
|
|
|
ParseProviderLinks(item.Item, endingXml);
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// If the file is just an imdb url, don't go any further
|
|
|
|
|
if (index == 0)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
using (var ms = new MemoryStream())
|
|
|
|
|
{
|
|
|
|
|
var bytes = Encoding.UTF8.GetBytes(xml);
|
|
|
|
|
xml = xml.Substring(0, index + 1);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// If the file is just an Imdb url, handle that
|
|
|
|
|
|
|
|
|
|
ms.Write(bytes, 0, bytes.Length);
|
|
|
|
|
ms.Position = 0;
|
|
|
|
|
ParseProviderLinks(item.Item, xml);
|
|
|
|
|
|
|
|
|
|
// These are not going to be valid xml so no sense in causing the provider to fail and spamming the log with exceptions
|
|
|
|
|
try
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
using (var ms = new MemoryStream())
|
|
|
|
|
{
|
|
|
|
|
// Use XmlReader for best performance
|
|
|
|
|
using (var reader = XmlReader.Create(ms, settings))
|
|
|
|
|
{
|
|
|
|
|
reader.MoveToContent();
|
|
|
|
|
var bytes = Encoding.UTF8.GetBytes(xml);
|
|
|
|
|
|
|
|
|
|
// Loop through each element
|
|
|
|
|
while (reader.Read())
|
|
|
|
|
ms.Write(bytes, 0, bytes.Length);
|
|
|
|
|
ms.Position = 0;
|
|
|
|
|
|
|
|
|
|
// These are not going to be valid xml so no sense in causing the provider to fail and spamming the log with exceptions
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
// Use XmlReader for best performance
|
|
|
|
|
using (var reader = XmlReader.Create(ms, settings))
|
|
|
|
|
{
|
|
|
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
|
|
|
reader.MoveToContent();
|
|
|
|
|
|
|
|
|
|
if (reader.NodeType == XmlNodeType.Element)
|
|
|
|
|
// Loop through each element
|
|
|
|
|
while (reader.Read())
|
|
|
|
|
{
|
|
|
|
|
FetchDataFromXmlNode(reader, item);
|
|
|
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
|
|
|
|
|
|
|
|
if (reader.NodeType == XmlNodeType.Element)
|
|
|
|
|
{
|
|
|
|
|
FetchDataFromXmlNode(reader, item);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (XmlException)
|
|
|
|
|
{
|
|
|
|
|
catch (XmlException)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|