make sure ._ osx files are properly ignored
This commit is contained in:
parent
60067b4c29
commit
6aa3313bc0
|
@ -1662,7 +1662,6 @@ namespace MediaBrowser.Api.Playback
|
||||||
state.InputContainer = mediaSource.Container;
|
state.InputContainer = mediaSource.Container;
|
||||||
state.InputFileSize = mediaSource.Size;
|
state.InputFileSize = mediaSource.Size;
|
||||||
state.InputBitrate = mediaSource.Bitrate;
|
state.InputBitrate = mediaSource.Bitrate;
|
||||||
state.ReadInputAtNativeFramerate = mediaSource.ReadAtNativeFramerate;
|
|
||||||
state.RunTimeTicks = mediaSource.RunTimeTicks;
|
state.RunTimeTicks = mediaSource.RunTimeTicks;
|
||||||
state.RemoteHttpHeaders = mediaSource.RequiredHttpHeaders;
|
state.RemoteHttpHeaders = mediaSource.RequiredHttpHeaders;
|
||||||
|
|
||||||
|
|
|
@ -173,11 +173,14 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
}
|
}
|
||||||
|
|
||||||
await ApiEntryPoint.Instance.TranscodingStartLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false);
|
await ApiEntryPoint.Instance.TranscodingStartLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false);
|
||||||
|
var released = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (FileSystem.FileExists(segmentPath))
|
if (FileSystem.FileExists(segmentPath))
|
||||||
{
|
{
|
||||||
job = ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType);
|
job = ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType);
|
||||||
|
ApiEntryPoint.Instance.TranscodingStartLock.Release();
|
||||||
|
released = true;
|
||||||
return await GetSegmentResult(state, playlistPath, segmentPath, requestedIndex, job, cancellationToken).ConfigureAwait(false);
|
return await GetSegmentResult(state, playlistPath, segmentPath, requestedIndex, job, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -238,7 +241,10 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
ApiEntryPoint.Instance.TranscodingStartLock.Release();
|
if (!released)
|
||||||
|
{
|
||||||
|
ApiEntryPoint.Instance.TranscodingStartLock.Release();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Logger.Info("waiting for {0}", segmentPath);
|
//Logger.Info("waiting for {0}", segmentPath);
|
||||||
|
|
|
@ -79,6 +79,7 @@ namespace MediaBrowser.Api.UserLibrary
|
||||||
|
|
||||||
var dtoOptions = GetDtoOptions(request);
|
var dtoOptions = GetDtoOptions(request);
|
||||||
dtoOptions.Fields = new List<ItemFields>();
|
dtoOptions.Fields = new List<ItemFields>();
|
||||||
|
dtoOptions.Fields.Add(ItemFields.PrimaryImageAspectRatio);
|
||||||
|
|
||||||
var user = _userManager.GetUserById(request.UserId);
|
var user = _userManager.GetUserById(request.UserId);
|
||||||
|
|
||||||
|
|
|
@ -557,9 +557,16 @@ namespace MediaBrowser.Controller.Library
|
||||||
/// Gets the items result.
|
/// Gets the items result.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="query">The query.</param>
|
/// <param name="query">The query.</param>
|
||||||
/// <param name="user">The user.</param>
|
|
||||||
/// <param name="parentIds">The parent ids.</param>
|
/// <param name="parentIds">The parent ids.</param>
|
||||||
/// <returns>QueryResult<BaseItem>.</returns>
|
/// <returns>QueryResult<BaseItem>.</returns>
|
||||||
QueryResult<BaseItem> GetItemsResult(InternalItemsQuery query, IEnumerable<string> parentIds);
|
QueryResult<BaseItem> GetItemsResult(InternalItemsQuery query, IEnumerable<string> parentIds);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Ignores the file.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="file">The file.</param>
|
||||||
|
/// <param name="parent">The parent.</param>
|
||||||
|
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
|
||||||
|
bool IgnoreFile(FileSystemMetadata file, BaseItem parent);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
using MediaBrowser.Controller.Library;
|
using CommonIO;
|
||||||
|
using MediaBrowser.Controller.Entities;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Resolvers
|
namespace MediaBrowser.Controller.Resolvers
|
||||||
{
|
{
|
||||||
|
@ -7,6 +8,6 @@ namespace MediaBrowser.Controller.Resolvers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IResolverIgnoreRule
|
public interface IResolverIgnoreRule
|
||||||
{
|
{
|
||||||
bool ShouldIgnore(ItemResolveArgs args);
|
bool ShouldIgnore(FileSystemMetadata fileInfo, BaseItem parent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ namespace MediaBrowser.Model.Configuration
|
||||||
{
|
{
|
||||||
DownMixAudioBoost = 2;
|
DownMixAudioBoost = 2;
|
||||||
EnableThrottling = true;
|
EnableThrottling = true;
|
||||||
ThrottleThresholdInSeconds = 120;
|
ThrottleThresholdInSeconds = 100;
|
||||||
EncodingThreadCount = -1;
|
EncodingThreadCount = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1235,6 +1235,7 @@ namespace MediaBrowser.Server.Implementations.Channels
|
||||||
{
|
{
|
||||||
BaseItem item;
|
BaseItem item;
|
||||||
bool isNew;
|
bool isNew;
|
||||||
|
bool forceUpdate = false;
|
||||||
|
|
||||||
if (info.Type == ChannelItemType.Folder)
|
if (info.Type == ChannelItemType.Folder)
|
||||||
{
|
{
|
||||||
|
@ -1265,6 +1266,7 @@ namespace MediaBrowser.Server.Implementations.Channels
|
||||||
item.ProviderIds = info.ProviderIds;
|
item.ProviderIds = info.ProviderIds;
|
||||||
item.OfficialRating = info.OfficialRating;
|
item.OfficialRating = info.OfficialRating;
|
||||||
item.DateCreated = info.DateCreated ?? DateTime.UtcNow;
|
item.DateCreated = info.DateCreated ?? DateTime.UtcNow;
|
||||||
|
item.Tags = info.Tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
var channelItem = (IChannelItem)item;
|
var channelItem = (IChannelItem)item;
|
||||||
|
@ -1273,7 +1275,7 @@ namespace MediaBrowser.Server.Implementations.Channels
|
||||||
|
|
||||||
if (item.ParentId != internalChannelId)
|
if (item.ParentId != internalChannelId)
|
||||||
{
|
{
|
||||||
isNew = true;
|
forceUpdate = true;
|
||||||
}
|
}
|
||||||
item.ParentId = internalChannelId;
|
item.ParentId = internalChannelId;
|
||||||
|
|
||||||
|
@ -1283,11 +1285,6 @@ namespace MediaBrowser.Server.Implementations.Channels
|
||||||
}
|
}
|
||||||
channelItem.ExternalId = info.Id;
|
channelItem.ExternalId = info.Id;
|
||||||
|
|
||||||
if (isNew)
|
|
||||||
{
|
|
||||||
channelItem.Tags = info.Tags;
|
|
||||||
}
|
|
||||||
|
|
||||||
var channelMediaItem = item as IChannelMediaItem;
|
var channelMediaItem = item as IChannelMediaItem;
|
||||||
|
|
||||||
if (channelMediaItem != null)
|
if (channelMediaItem != null)
|
||||||
|
@ -1315,6 +1312,10 @@ namespace MediaBrowser.Server.Implementations.Channels
|
||||||
await _libraryManager.UpdatePeople(item, info.People ?? new List<PersonInfo>()).ConfigureAwait(false);
|
await _libraryManager.UpdatePeople(item, info.People ?? new List<PersonInfo>()).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (forceUpdate)
|
||||||
|
{
|
||||||
|
await item.UpdateToRepository(ItemUpdateType.None, cancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,11 +47,14 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Shoulds the ignore.
|
/// Shoulds the ignore.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="args">The args.</param>
|
/// <param name="fileInfo">The file information.</param>
|
||||||
|
/// <param name="parent">The parent.</param>
|
||||||
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
|
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
|
||||||
public bool ShouldIgnore(ItemResolveArgs args)
|
public bool ShouldIgnore(FileSystemMetadata fileInfo, BaseItem parent)
|
||||||
{
|
{
|
||||||
var filename = args.FileInfo.Name;
|
var filename = fileInfo.Name;
|
||||||
|
var isHidden = (fileInfo.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden;
|
||||||
|
var path = fileInfo.FullName;
|
||||||
|
|
||||||
// Handle mac .DS_Store
|
// Handle mac .DS_Store
|
||||||
// https://github.com/MediaBrowser/MediaBrowser/issues/427
|
// https://github.com/MediaBrowser/MediaBrowser/issues/427
|
||||||
|
@ -61,21 +64,24 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore hidden files and folders
|
// Ignore hidden files and folders
|
||||||
if (args.IsHidden)
|
if (isHidden)
|
||||||
{
|
{
|
||||||
var parentFolderName = Path.GetFileName(Path.GetDirectoryName(args.Path));
|
if (parent != null)
|
||||||
|
{
|
||||||
|
var parentFolderName = Path.GetFileName(Path.GetDirectoryName(path));
|
||||||
|
|
||||||
if (string.Equals(parentFolderName, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(parentFolderName, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (string.Equals(parentFolderName, BaseItem.ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(parentFolderName, BaseItem.ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sometimes these are marked hidden
|
// Sometimes these are marked hidden
|
||||||
if (_fileSystem.IsRootPath(args.Path))
|
if (_fileSystem.IsRootPath(path))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -83,7 +89,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.IsDirectory)
|
if (fileInfo.IsDirectory)
|
||||||
{
|
{
|
||||||
// Ignore any folders in our list
|
// Ignore any folders in our list
|
||||||
if (IgnoreFolders.Contains(filename, StringComparer.OrdinalIgnoreCase))
|
if (IgnoreFolders.Contains(filename, StringComparer.OrdinalIgnoreCase))
|
||||||
|
@ -91,26 +97,29 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore trailer folders but allow it at the collection level
|
if (parent != null)
|
||||||
if (string.Equals(filename, BaseItem.TrailerFolderName, StringComparison.OrdinalIgnoreCase) &&
|
|
||||||
!(args.Parent is AggregateFolder) && !(args.Parent is UserRootFolder))
|
|
||||||
{
|
{
|
||||||
return true;
|
// Ignore trailer folders but allow it at the collection level
|
||||||
}
|
if (string.Equals(filename, BaseItem.TrailerFolderName, StringComparison.OrdinalIgnoreCase) &&
|
||||||
|
!(parent is AggregateFolder) && !(parent is UserRootFolder))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (string.Equals(filename, BaseItem.ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(filename, BaseItem.ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.Equals(filename, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(filename, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (args.Parent != null)
|
if (parent != null)
|
||||||
{
|
{
|
||||||
// Don't resolve these into audio files
|
// Don't resolve these into audio files
|
||||||
if (string.Equals(_fileSystem.GetFileNameWithoutExtension(filename), BaseItem.ThemeSongFilename) && _libraryManager.IsAudioFile(filename))
|
if (string.Equals(_fileSystem.GetFileNameWithoutExtension(filename), BaseItem.ThemeSongFilename) && _libraryManager.IsAudioFile(filename))
|
||||||
|
|
|
@ -580,7 +580,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
};
|
};
|
||||||
|
|
||||||
// Return null if ignore rules deem that we should do so
|
// Return null if ignore rules deem that we should do so
|
||||||
if (EntityResolutionIgnoreRules.Any(r => r.ShouldIgnore(args)))
|
if (IgnoreFile(args.FileInfo, args.Parent))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -616,6 +616,11 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
return ResolveItem(args);
|
return ResolveItem(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IgnoreFile(FileSystemMetadata file, BaseItem parent)
|
||||||
|
{
|
||||||
|
return EntityResolutionIgnoreRules.Any(r => r.ShouldIgnore(file, parent));
|
||||||
|
}
|
||||||
|
|
||||||
public IEnumerable<string> NormalizeRootPathList(IEnumerable<string> paths)
|
public IEnumerable<string> NormalizeRootPathList(IEnumerable<string> paths)
|
||||||
{
|
{
|
||||||
var list = paths.Select(_fileSystem.NormalizePath)
|
var list = paths.Select(_fileSystem.NormalizePath)
|
||||||
|
@ -646,7 +651,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
|
|
||||||
public IEnumerable<BaseItem> ResolvePaths(IEnumerable<FileSystemMetadata> files, IDirectoryService directoryService, Folder parent, string collectionType)
|
public IEnumerable<BaseItem> ResolvePaths(IEnumerable<FileSystemMetadata> files, IDirectoryService directoryService, Folder parent, string collectionType)
|
||||||
{
|
{
|
||||||
var fileList = files.ToList();
|
var fileList = files.Where(i => !IgnoreFile(i, parent)).ToList();
|
||||||
|
|
||||||
if (parent != null)
|
if (parent != null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -67,7 +67,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
|
||||||
string collectionType,
|
string collectionType,
|
||||||
IDirectoryService directoryService)
|
IDirectoryService directoryService)
|
||||||
{
|
{
|
||||||
if (IsInvalid(parent, collectionType, files))
|
if (IsInvalid(parent, collectionType))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -185,7 +185,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
|
||||||
{
|
{
|
||||||
var collectionType = args.GetCollectionType();
|
var collectionType = args.GetCollectionType();
|
||||||
|
|
||||||
if (IsInvalid(args.Parent, collectionType, args.FileSystemChildren))
|
if (IsInvalid(args.Parent, collectionType))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -193,14 +193,18 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
|
||||||
// Find movies with their own folders
|
// Find movies with their own folders
|
||||||
if (args.IsDirectory)
|
if (args.IsDirectory)
|
||||||
{
|
{
|
||||||
|
var files = args.FileSystemChildren
|
||||||
|
.Where(i => !LibraryManager.IgnoreFile(i, args.Parent))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return FindMovie<MusicVideo>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, collectionType);
|
return FindMovie<MusicVideo>(args.Path, args.Parent, files, args.DirectoryService, collectionType);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return FindMovie<Video>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, collectionType);
|
return FindMovie<Video>(args.Path, args.Parent, files, args.DirectoryService, collectionType);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(collectionType))
|
if (string.IsNullOrEmpty(collectionType))
|
||||||
|
@ -208,7 +212,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
|
||||||
// Owned items should just use the plain video type
|
// Owned items should just use the plain video type
|
||||||
if (args.Parent == null)
|
if (args.Parent == null)
|
||||||
{
|
{
|
||||||
return FindMovie<Video>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, collectionType);
|
return FindMovie<Video>(args.Path, args.Parent, files, args.DirectoryService, collectionType);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.HasParent<Series>())
|
if (args.HasParent<Series>())
|
||||||
|
@ -216,12 +220,12 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return FindMovie<Movie>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, collectionType);
|
return FindMovie<Movie>(args.Path, args.Parent, files, args.DirectoryService, collectionType);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return FindMovie<Movie>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, collectionType);
|
return FindMovie<Movie>(args.Path, args.Parent, files, args.DirectoryService, collectionType);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -494,7 +498,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsInvalid(Folder parent, string collectionType, IEnumerable<FileSystemMetadata> files)
|
private bool IsInvalid(Folder parent, string collectionType)
|
||||||
{
|
{
|
||||||
if (parent != null)
|
if (parent != null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -236,9 +236,6 @@
|
||||||
<Content Include="dashboard-ui\cordova\android\logging.js">
|
<Content Include="dashboard-ui\cordova\android\logging.js">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="dashboard-ui\cordova\android\newapp.js">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="dashboard-ui\cordova\fileupload.js">
|
<Content Include="dashboard-ui\cordova\fileupload.js">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
@ -468,6 +465,9 @@
|
||||||
<Content Include="dashboard-ui\thirdparty\emby-icons.html">
|
<Content Include="dashboard-ui\thirdparty\emby-icons.html">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
<Content Include="dashboard-ui\thirdparty\hls.min.js">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
<Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.5\jqm.checkbox.css">
|
<Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.5\jqm.checkbox.css">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user