aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Emby.Common.Implementations/EnvironmentInfo/EnvironmentInfo.cs6
-rw-r--r--Emby.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs20
-rw-r--r--Emby.Server.Core/ApplicationHost.cs5
-rw-r--r--Emby.Server.Implementations/HttpServer/HttpResultFactory.cs71
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs27
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs17
-rw-r--r--Emby.Server.Implementations/LiveTv/LiveTvManager.cs2
-rw-r--r--Emby.Server.Implementations/Sync/SyncManager.cs27
-rw-r--r--Emby.Server.Implementations/Sync/SyncNotificationEntryPoint.cs12
-rw-r--r--MediaBrowser.Api/Playback/Progressive/VideoService.cs2
-rw-r--r--MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs7
-rw-r--r--MediaBrowser.Providers/TV/MissingEpisodeProvider.cs2
-rw-r--r--MediaBrowser.Server.Mac/Main.cs5
-rw-r--r--MediaBrowser.Server.Mono/MonoAppHost.cs22
-rw-r--r--MediaBrowser.ServerApplication/Native/LnkShortcutHandler.cs69
-rw-r--r--MediaBrowser.ServerApplication/WindowsAppHost.cs24
-rw-r--r--SocketHttpListener.Portable/Net/HttpConnection.cs4
-rw-r--r--SocketHttpListener.Portable/Net/HttpListenerResponse.cs7
-rw-r--r--SocketHttpListener.Portable/Net/ResponseStream.cs12
19 files changed, 185 insertions, 156 deletions
diff --git a/Emby.Common.Implementations/EnvironmentInfo/EnvironmentInfo.cs b/Emby.Common.Implementations/EnvironmentInfo/EnvironmentInfo.cs
index 6cc4626ea..dcc974413 100644
--- a/Emby.Common.Implementations/EnvironmentInfo/EnvironmentInfo.cs
+++ b/Emby.Common.Implementations/EnvironmentInfo/EnvironmentInfo.cs
@@ -10,11 +10,17 @@ namespace Emby.Common.Implementations.EnvironmentInfo
public class EnvironmentInfo : IEnvironmentInfo
{
public MediaBrowser.Model.System.Architecture? CustomArchitecture { get; set; }
+ public MediaBrowser.Model.System.OperatingSystem? CustomOperatingSystem { get; set; }
public MediaBrowser.Model.System.OperatingSystem OperatingSystem
{
get
{
+ if (CustomOperatingSystem.HasValue)
+ {
+ return CustomOperatingSystem.Value;
+ }
+
#if NET46
switch (Environment.OSVersion.Platform)
{
diff --git a/Emby.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs
index cbc7c7c2d..de528a94f 100644
--- a/Emby.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs
+++ b/Emby.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs
@@ -282,9 +282,12 @@ namespace Emby.Common.Implementations.ScheduledTasks
throw new ArgumentNullException("value");
}
- SaveTriggers(value);
+ // This null check is not great, but is needed to handle bad user input, or user mucking with the config file incorrectly
+ var triggerList = value.Where(i => i != null).ToArray();
- InternalTriggers = value.Select(i => new Tuple<TaskTriggerInfo, ITaskTrigger>(i, GetTrigger(i))).ToArray();
+ SaveTriggers(triggerList);
+
+ InternalTriggers = triggerList.Select(i => new Tuple<TaskTriggerInfo, ITaskTrigger>(i, GetTrigger(i))).ToArray();
}
}
@@ -535,7 +538,8 @@ namespace Emby.Common.Implementations.ScheduledTasks
/// <returns>IEnumerable{BaseTaskTrigger}.</returns>
private Tuple<TaskTriggerInfo, ITaskTrigger>[] LoadTriggers()
{
- var settings = LoadTriggerSettings();
+ // This null check is not great, but is needed to handle bad user input, or user mucking with the config file incorrectly
+ var settings = LoadTriggerSettings().Where(i => i != null).ToArray();
return settings.Select(i => new Tuple<TaskTriggerInfo, ITaskTrigger>(i, GetTrigger(i))).ToArray();
}
@@ -544,8 +548,12 @@ namespace Emby.Common.Implementations.ScheduledTasks
{
try
{
- return JsonSerializer.DeserializeFromFile<IEnumerable<TaskTriggerInfo>>(GetConfigurationFilePath())
- .ToArray();
+ var list = JsonSerializer.DeserializeFromFile<IEnumerable<TaskTriggerInfo>>(GetConfigurationFilePath());
+
+ if (list != null)
+ {
+ return list.ToArray();
+ }
}
catch (FileNotFoundException)
{
@@ -555,8 +563,8 @@ namespace Emby.Common.Implementations.ScheduledTasks
catch (DirectoryNotFoundException)
{
// File doesn't exist. No biggie. Return defaults.
- return ScheduledTask.GetDefaultTriggers().ToArray();
}
+ return ScheduledTask.GetDefaultTriggers().ToArray();
}
/// <summary>
diff --git a/Emby.Server.Core/ApplicationHost.cs b/Emby.Server.Core/ApplicationHost.cs
index a0a7416e7..3590ade40 100644
--- a/Emby.Server.Core/ApplicationHost.cs
+++ b/Emby.Server.Core/ApplicationHost.cs
@@ -1583,7 +1583,8 @@ namespace Emby.Server.Core
public void LaunchUrl(string url)
{
- if (EnvironmentInfo.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Windows)
+ if (EnvironmentInfo.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Windows &&
+ EnvironmentInfo.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.OSX)
{
throw new NotImplementedException();
}
@@ -1591,7 +1592,7 @@ namespace Emby.Server.Core
var process = ProcessFactory.Create(new ProcessOptions
{
FileName = url,
- EnableRaisingEvents = true,
+ //EnableRaisingEvents = true,
UseShellExecute = true,
ErrorDialog = false
});
diff --git a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs
index 995dc7b7b..e78446bc8 100644
--- a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs
+++ b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs
@@ -203,20 +203,12 @@ namespace Emby.Server.Implementations.HttpServer
// Do not use the memoryStreamFactory here, they don't place nice with compression
using (var ms = new MemoryStream())
{
- using (var compressionStream = GetCompressionStream(ms, compressionType))
- {
- ContentTypes.Instance.SerializeToStream(request, dto, compressionStream);
- compressionStream.Dispose();
-
- var compressedBytes = ms.ToArray();
+ ContentTypes.Instance.SerializeToStream(request, dto, ms);
+ ms.Position = 0;
- var httpResult = new StreamWriter(compressedBytes, request.ResponseContentType, _logger);
+ var responseHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
- //httpResult.Headers["Content-Length"] = compressedBytes.Length.ToString(UsCulture);
- httpResult.Headers["Content-Encoding"] = compressionType;
-
- return httpResult;
- }
+ return GetCompressedResult(ms, compressionType, responseHeaders, false, request.ResponseContentType).Result;
}
}
@@ -591,45 +583,53 @@ namespace Emby.Server.Implementations.HttpServer
};
}
- string content;
-
using (var stream = await factoryFn().ConfigureAwait(false))
{
- using (var reader = new StreamReader(stream))
+ return await GetCompressedResult(stream, requestedCompressionType, responseHeaders, isHeadRequest, contentType).ConfigureAwait(false);
+ }
+ }
+
+ private async Task<IHasHeaders> GetCompressedResult(Stream stream,
+ string requestedCompressionType,
+ IDictionary<string,string> responseHeaders,
+ bool isHeadRequest,
+ string contentType)
+ {
+ using (var reader = new MemoryStream())
+ {
+ await stream.CopyToAsync(reader).ConfigureAwait(false);
+
+ reader.Position = 0;
+ var content = reader.ToArray();
+
+ if (content.Length >= 1024)
{
- content = await reader.ReadToEndAsync().ConfigureAwait(false);
+ content = Compress(content, requestedCompressionType);
+ responseHeaders["Content-Encoding"] = requestedCompressionType;
}
- }
- var contents = Compress(content, requestedCompressionType);
+ responseHeaders["Content-Length"] = content.Length.ToString(UsCulture);
- responseHeaders["Content-Length"] = contents.Length.ToString(UsCulture);
- responseHeaders["Content-Encoding"] = requestedCompressionType;
+ if (isHeadRequest)
+ {
+ return GetHttpResult(new byte[] { }, contentType, true);
+ }
- if (isHeadRequest)
- {
- return GetHttpResult(new byte[] { }, contentType, true);
+ return GetHttpResult(content, contentType, true, responseHeaders);
}
-
- return GetHttpResult(contents, contentType, true, responseHeaders);
}
- private byte[] Compress(string text, string compressionType)
+ private byte[] Compress(byte[] bytes, string compressionType)
{
if (compressionType == "deflate")
- return Deflate(text);
+ return Deflate(bytes);
if (compressionType == "gzip")
- return GZip(text);
+ return GZip(bytes);
throw new NotSupportedException(compressionType);
}
- private byte[] Deflate(string text)
- {
- return Deflate(Encoding.UTF8.GetBytes(text));
- }
-
private byte[] Deflate(byte[] bytes)
{
// In .NET FX incompat-ville, you can't access compressed bytes without closing DeflateStream
@@ -644,11 +644,6 @@ namespace Emby.Server.Implementations.HttpServer
}
}
- private byte[] GZip(string text)
- {
- return GZip(Encoding.UTF8.GetBytes(text));
- }
-
private byte[] GZip(byte[] buffer)
{
using (var ms = new MemoryStream())
diff --git a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
index 55a63b4e5..b791311f9 100644
--- a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
@@ -74,21 +74,21 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase))
{
- return ResolveVideos<MusicVideo>(parent, files, directoryService, false);
+ return ResolveVideos<MusicVideo>(parent, files, directoryService, false, collectionType);
}
if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase) ||
string.Equals(collectionType, CollectionType.Photos, StringComparison.OrdinalIgnoreCase))
{
- return ResolveVideos<Video>(parent, files, directoryService, false);
+ return ResolveVideos<Video>(parent, files, directoryService, false, collectionType);
}
- if (string.IsNullOrEmpty(collectionType))
+ if (string.IsNullOrWhiteSpace(collectionType))
{
// Owned items should just use the plain video type
if (parent == null)
{
- return ResolveVideos<Video>(parent, files, directoryService, false);
+ return ResolveVideos<Video>(parent, files, directoryService, false, collectionType);
}
if (parent is Series || parent.GetParents().OfType<Series>().Any())
@@ -96,18 +96,18 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
return null;
}
- return ResolveVideos<Movie>(parent, files, directoryService, false);
+ return ResolveVideos<Movie>(parent, files, directoryService, false, collectionType);
}
if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase))
{
- return ResolveVideos<Movie>(parent, files, directoryService, true);
+ return ResolveVideos<Movie>(parent, files, directoryService, true, collectionType);
}
return null;
}
- private MultiItemResolverResult ResolveVideos<T>(Folder parent, IEnumerable<FileSystemMetadata> fileSystemEntries, IDirectoryService directoryService, bool suppportMultiEditions)
+ private MultiItemResolverResult ResolveVideos<T>(Folder parent, IEnumerable<FileSystemMetadata> fileSystemEntries, IDirectoryService directoryService, bool suppportMultiEditions, string collectionType)
where T : Video, new()
{
var files = new List<FileSystemMetadata>();
@@ -117,6 +117,16 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
// Loop through each child file/folder and see if we find a video
foreach (var child in fileSystemEntries)
{
+ // This is a hack but currently no better way to resolve a sometimes ambiguous situation
+ if (string.IsNullOrWhiteSpace(collectionType))
+ {
+ if (string.Equals(child.Name, "tvshow.nfo", StringComparison.OrdinalIgnoreCase) ||
+ string.Equals(child.Name, "season.nfo", StringComparison.OrdinalIgnoreCase))
+ {
+ return null;
+ }
+ }
+
if (child.IsDirectory)
{
leftOver.Add(child);
@@ -408,7 +418,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
!string.Equals(collectionType, CollectionType.Photos) &&
!string.Equals(collectionType, CollectionType.MusicVideos);
- var result = ResolveVideos<T>(parent, fileSystemEntries, directoryService, supportsMultiVersion);
+ var result = ResolveVideos<T>(parent, fileSystemEntries, directoryService, supportsMultiVersion, collectionType) ??
+ new MultiItemResolverResult();
if (result.Items.Count == 1)
{
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs
index 04fc78c95..e2446b16f 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs
@@ -422,7 +422,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
}
var showType = details.showType ?? string.Empty;
-
+
var info = new ProgramInfo
{
ChannelId = channel,
@@ -440,10 +440,23 @@ namespace Emby.Server.Implementations.LiveTv.Listings
IsKids = string.Equals(details.audience, "children", StringComparison.OrdinalIgnoreCase),
IsSports = showType.IndexOf("sports", StringComparison.OrdinalIgnoreCase) != -1,
IsMovie = showType.IndexOf("movie", StringComparison.OrdinalIgnoreCase) != -1 || showType.IndexOf("film", StringComparison.OrdinalIgnoreCase) != -1,
- ShowId = programInfo.programID,
Etag = programInfo.md5
};
+ var showId = programInfo.programID ?? string.Empty;
+
+ // According to SchedulesDirect, these are generic, unidentified episodes
+ // SH005316560000
+ var hasUniqueShowId = !showId.StartsWith("SH", StringComparison.OrdinalIgnoreCase) ||
+ !showId.EndsWith("0000", StringComparison.OrdinalIgnoreCase);
+
+ if (!hasUniqueShowId)
+ {
+ showId = newID;
+ }
+
+ info.ShowId = showId;
+
if (programInfo.videoProperties != null)
{
info.IsHD = programInfo.videoProperties.Contains("hdtv", StringComparer.OrdinalIgnoreCase);
diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
index 525db4036..62a0738c7 100644
--- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
+++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
@@ -2647,7 +2647,7 @@ namespace Emby.Server.Implementations.LiveTv
public GuideInfo GetGuideInfo()
{
var startDate = DateTime.UtcNow;
- var endDate = startDate.AddDays(14);
+ var endDate = startDate.AddDays(GetGuideDays());
return new GuideInfo
{
diff --git a/Emby.Server.Implementations/Sync/SyncManager.cs b/Emby.Server.Implementations/Sync/SyncManager.cs
index 13f60f5ee..061129e5f 100644
--- a/Emby.Server.Implementations/Sync/SyncManager.cs
+++ b/Emby.Server.Implementations/Sync/SyncManager.cs
@@ -1042,10 +1042,7 @@ namespace Emby.Server.Implementations.Sync
throw new ArgumentException("Operation is not valid for this job item");
}
- if (jobItem.Status != SyncJobItemStatus.Synced)
- {
- jobItem.Status = SyncJobItemStatus.Cancelled;
- }
+ jobItem.Status = SyncJobItemStatus.Cancelled;
jobItem.Progress = 0;
jobItem.IsMarkedForRemoval = true;
@@ -1071,18 +1068,18 @@ namespace Emby.Server.Implementations.Sync
_logger.ErrorException("Error deleting directory {0}", ex, path);
}
- //var jobItemsResult = GetJobItems(new SyncJobItemQuery
- //{
- // AddMetadata = false,
- // JobId = jobItem.JobId,
- // Limit = 0,
- // Statuses = new[] { SyncJobItemStatus.Converting, SyncJobItemStatus.Failed, SyncJobItemStatus.Queued, SyncJobItemStatus.ReadyToTransfer, SyncJobItemStatus.Synced, SyncJobItemStatus.Transferring }
- //});
+ var jobItemsResult = GetJobItems(new SyncJobItemQuery
+ {
+ AddMetadata = false,
+ JobId = jobItem.JobId,
+ Limit = 0,
+ Statuses = new[] { SyncJobItemStatus.Converting, SyncJobItemStatus.Queued, SyncJobItemStatus.ReadyToTransfer, SyncJobItemStatus.Synced, SyncJobItemStatus.Transferring }
+ });
- //if (jobItemsResult.TotalRecordCount == 0)
- //{
- // await CancelJob(jobItem.JobId).ConfigureAwait(false);
- //}
+ if (jobItemsResult.TotalRecordCount == 0)
+ {
+ await CancelJob(jobItem.JobId).ConfigureAwait(false);
+ }
}
public Task MarkJobItemForRemoval(string id)
diff --git a/Emby.Server.Implementations/Sync/SyncNotificationEntryPoint.cs b/Emby.Server.Implementations/Sync/SyncNotificationEntryPoint.cs
index 46cdb28a4..06e0e66a9 100644
--- a/Emby.Server.Implementations/Sync/SyncNotificationEntryPoint.cs
+++ b/Emby.Server.Implementations/Sync/SyncNotificationEntryPoint.cs
@@ -38,6 +38,18 @@ namespace Emby.Server.Implementations.Sync
}
}
+
+ if (item.Status == SyncJobItemStatus.Cancelled)
+ {
+ try
+ {
+ await _sessionManager.SendMessageToUserDeviceSessions(item.TargetId, "SyncJobItemCancelled", item, CancellationToken.None).ConfigureAwait(false);
+ }
+ catch
+ {
+
+ }
+ }
}
public void Dispose()
diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs
index e29aa7d5a..7ae64b834 100644
--- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs
+++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs
@@ -153,7 +153,7 @@ namespace MediaBrowser.Api.Playback.Progressive
if (!state.RunTimeTicks.HasValue)
{
- args += " -fflags +genpts -flags +global_header";
+ args += " -flags -global_header -fflags +genpts";
}
return args;
diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
index 23e63dad0..116a6a7cf 100644
--- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
@@ -95,6 +95,11 @@ namespace MediaBrowser.MediaEncoding.Encoder
int defaultImageExtractionTimeoutMs,
bool enableEncoderFontFile, IEnvironmentInfo environmentInfo)
{
+ if (jsonSerializer == null)
+ {
+ throw new ArgumentNullException("jsonSerializer");
+ }
+
_logger = logger;
_jsonSerializer = jsonSerializer;
ConfigurationManager = configurationManager;
@@ -632,7 +637,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
var result = _jsonSerializer.DeserializeFromStream<InternalMediaInfoResult>(process.StandardOutput.BaseStream);
- if (result.streams == null && result.format == null)
+ if (result == null || (result.streams == null && result.format == null))
{
throw new Exception("ffprobe failed - streams and format are both null.");
}
diff --git a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs
index 4992675da..538512557 100644
--- a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs
+++ b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs
@@ -238,7 +238,7 @@ namespace MediaBrowser.Providers.TV
var targetSeries = DetermineAppropriateSeries(series, tuple.Item1);
var seasonOffset = TvdbSeriesProvider.GetSeriesOffset(targetSeries.ProviderIds) ?? ((targetSeries.AnimeSeriesIndex ?? 1) - 1);
- var unairedThresholdDays = 1;
+ var unairedThresholdDays = 2;
now = now.AddDays(0 - unairedThresholdDays);
if (airDate.Value < now)
diff --git a/MediaBrowser.Server.Mac/Main.cs b/MediaBrowser.Server.Mac/Main.cs
index cda6f459a..6d02c7a1a 100644
--- a/MediaBrowser.Server.Mac/Main.cs
+++ b/MediaBrowser.Server.Mac/Main.cs
@@ -142,7 +142,10 @@ namespace MediaBrowser.Server.Mac
private static EnvironmentInfo GetEnvironmentInfo()
{
- var info = new EnvironmentInfo();
+ var info = new EnvironmentInfo()
+ {
+ CustomOperatingSystem = MediaBrowser.Model.System.OperatingSystem.OSX
+ };
var uname = GetUnixName();
diff --git a/MediaBrowser.Server.Mono/MonoAppHost.cs b/MediaBrowser.Server.Mono/MonoAppHost.cs
index 8def1ca2b..932e2d6cd 100644
--- a/MediaBrowser.Server.Mono/MonoAppHost.cs
+++ b/MediaBrowser.Server.Mono/MonoAppHost.cs
@@ -51,8 +51,11 @@ namespace MediaBrowser.Server.Mono
}
else if (environment.OperatingSystem == Model.System.OperatingSystem.Linux)
{
+ info.FFMpegFilename = "ffmpeg";
+ info.FFProbeFilename = "ffprobe";
info.ArchiveType = "7z";
info.Version = "20160215";
+ info.DownloadUrls = GetDownloadUrls();
}
// No version available - user requirement
@@ -61,6 +64,25 @@ namespace MediaBrowser.Server.Mono
return info;
}
+ private string[] GetDownloadUrls()
+ {
+ switch (EnvironmentInfo.SystemArchitecture)
+ {
+ case Architecture.X64:
+ return new[]
+ {
+ "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/linux/ffmpeg-git-20160215-64bit-static.7z"
+ };
+ case Architecture.X86:
+ return new[]
+ {
+ "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/linux/ffmpeg-git-20160215-32bit-static.7z"
+ };
+ }
+
+ return new string[] { };
+ }
+
protected override void RestartInternal()
{
MainClass.Restart(StartupOptions);
diff --git a/MediaBrowser.ServerApplication/Native/LnkShortcutHandler.cs b/MediaBrowser.ServerApplication/Native/LnkShortcutHandler.cs
index 91ff7033e..b4a87b9b4 100644
--- a/MediaBrowser.ServerApplication/Native/LnkShortcutHandler.cs
+++ b/MediaBrowser.ServerApplication/Native/LnkShortcutHandler.cs
@@ -1,6 +1,7 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.ComTypes;
using System.Security;
using System.Text;
using MediaBrowser.Model.IO;
@@ -52,7 +53,7 @@ namespace MediaBrowser.ServerApplication.Native
/// <summary>
/// The STG m_ READ
/// </summary>
- public const uint STGM_READ = 0;
+ public const int STGM_READ = 0;
}
/// <summary>
@@ -319,72 +320,6 @@ namespace MediaBrowser.ServerApplication.Native
}
- /// <summary>
- /// Interface IPersist
- /// </summary>
- [ComImport, Guid("0000010c-0000-0000-c000-000000000046"),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface IPersist
- {
- /// <summary>
- /// Gets the class ID.
- /// </summary>
- /// <param name="pClassID">The p class ID.</param>
- [PreserveSig]
- void GetClassID(out Guid pClassID);
- }
-
- /// <summary>
- /// Interface IPersistFile
- /// </summary>
- [ComImport, Guid("0000010b-0000-0000-C000-000000000046"),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface IPersistFile : IPersist
- {
- /// <summary>
- /// Gets the class ID.
- /// </summary>
- /// <param name="pClassID">The p class ID.</param>
- new void GetClassID(out Guid pClassID);
- /// <summary>
- /// Determines whether this instance is dirty.
- /// </summary>
- [PreserveSig]
- int IsDirty();
-
- /// <summary>
- /// Loads the specified PSZ file name.
- /// </summary>
- /// <param name="pszFileName">Name of the PSZ file.</param>
- /// <param name="dwMode">The dw mode.</param>
- [PreserveSig]
- void Load([In, MarshalAs(UnmanagedType.LPWStr)]
- string pszFileName, uint dwMode);
-
- /// <summary>
- /// Saves the specified PSZ file name.
- /// </summary>
- /// <param name="pszFileName">Name of the PSZ file.</param>
- /// <param name="remember">if set to <c>true</c> [remember].</param>
- [PreserveSig]
- void Save([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName,
- [In, MarshalAs(UnmanagedType.Bool)] bool remember);
-
- /// <summary>
- /// Saves the completed.
- /// </summary>
- /// <param name="pszFileName">Name of the PSZ file.</param>
- [PreserveSig]
- void SaveCompleted([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName);
-
- /// <summary>
- /// Gets the cur file.
- /// </summary>
- /// <param name="ppszFileName">Name of the PPSZ file.</param>
- [PreserveSig]
- void GetCurFile([In, MarshalAs(UnmanagedType.LPWStr)] string ppszFileName);
- }
-
// CLSID_ShellLink from ShlGuid.h
/// <summary>
/// Class ShellLink
diff --git a/MediaBrowser.ServerApplication/WindowsAppHost.cs b/MediaBrowser.ServerApplication/WindowsAppHost.cs
index c2cdb9ab0..398d21f32 100644
--- a/MediaBrowser.ServerApplication/WindowsAppHost.cs
+++ b/MediaBrowser.ServerApplication/WindowsAppHost.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
+using System.Runtime.InteropServices.ComTypes;
using Emby.Server.Core;
using Emby.Server.Implementations;
using Emby.Server.Implementations.EntryPoints;
@@ -93,21 +94,30 @@ namespace MediaBrowser.ServerApplication
protected override void ConfigureAutoRunInternal(bool autorun)
{
- var shortcutPath = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.StartMenu), "Emby", "Emby Server.lnk");
-
var startupPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Startup);
- if (autorun)
+ if (autorun && !MainStartup.IsRunningAsService)
{
//Copy our shortut into the startup folder for this user
- var targetPath = Path.Combine(startupPath, Path.GetFileName(shortcutPath) ?? "Emby Server.lnk");
- FileSystemManager.CreateDirectory(Path.GetDirectoryName(targetPath));
- File.Copy(shortcutPath, targetPath, true);
+ var targetPath = Path.Combine(startupPath, "Emby Server.lnk");
+
+ IShellLinkW link = (IShellLinkW)new ShellLink();
+
+ var appPath = Process.GetCurrentProcess().MainModule.FileName;
+
+ // setup shortcut information
+ link.SetDescription(Name);
+ link.SetPath(appPath);
+ link.SetWorkingDirectory(Path.GetDirectoryName(appPath));
+
+ // save it
+ IPersistFile file = (IPersistFile)link;
+ file.Save(targetPath, false);
}
else
{
//Remove our shortcut from the startup folder for this user
- FileSystemManager.DeleteFile(Path.Combine(startupPath, Path.GetFileName(shortcutPath) ?? "Emby Server.lnk"));
+ FileSystemManager.DeleteFile(Path.Combine(startupPath, "Emby Server.lnk"));
}
}
diff --git a/SocketHttpListener.Portable/Net/HttpConnection.cs b/SocketHttpListener.Portable/Net/HttpConnection.cs
index bc4286dc8..3baffd258 100644
--- a/SocketHttpListener.Portable/Net/HttpConnection.cs
+++ b/SocketHttpListener.Portable/Net/HttpConnection.cs
@@ -209,7 +209,7 @@ namespace SocketHttpListener.Net
// TODO: can we get this stream before reading the input?
if (o_stream == null)
{
- context.Response.DetermineIfChunked();
+ //context.Response.DetermineIfChunked();
if (context.Response.SendChunked || isExpect100Continue || context.Request.IsWebSocketRequest || true)
{
@@ -508,7 +508,7 @@ namespace SocketHttpListener.Net
{
force_close |= !context.Request.KeepAlive;
if (!force_close)
- force_close = (context.Response.Headers["connection"] == "close");
+ force_close = (string.Equals(context.Response.Headers["connection"], "close", StringComparison.OrdinalIgnoreCase));
/*
if (!force_close) {
// bool conn_close = (status_code == 400 || status_code == 408 || status_code == 411 ||
diff --git a/SocketHttpListener.Portable/Net/HttpListenerResponse.cs b/SocketHttpListener.Portable/Net/HttpListenerResponse.cs
index c1182de34..9a5862cb9 100644
--- a/SocketHttpListener.Portable/Net/HttpListenerResponse.cs
+++ b/SocketHttpListener.Portable/Net/HttpListenerResponse.cs
@@ -386,7 +386,7 @@ namespace SocketHttpListener.Net
if (content_type != null)
{
- if (content_encoding != null && content_type.IndexOf("charset=", StringComparison.Ordinal) == -1)
+ if (content_encoding != null && content_type.IndexOf("charset=", StringComparison.OrdinalIgnoreCase) == -1)
{
string enc_name = content_encoding.WebName;
headers.SetInternal("Content-Type", content_type + "; charset=" + enc_name);
@@ -429,9 +429,10 @@ namespace SocketHttpListener.Net
* HttpStatusCode.InternalServerError 500
* HttpStatusCode.ServiceUnavailable 503
*/
- bool conn_close = (status_code == 408 || status_code == 411 ||
+ bool conn_close = status_code == 400 || status_code == 408 || status_code == 411 ||
status_code == 413 || status_code == 414 ||
- status_code == 503);
+ status_code == 500 ||
+ status_code == 503;
if (conn_close == false)
conn_close = !context.Request.KeepAlive;
diff --git a/SocketHttpListener.Portable/Net/ResponseStream.cs b/SocketHttpListener.Portable/Net/ResponseStream.cs
index 6067a89ec..a79a18791 100644
--- a/SocketHttpListener.Portable/Net/ResponseStream.cs
+++ b/SocketHttpListener.Portable/Net/ResponseStream.cs
@@ -136,6 +136,11 @@ namespace SocketHttpListener.Net
if (disposed)
throw new ObjectDisposedException(GetType().ToString());
+ if (count == 0)
+ {
+ //return;
+ }
+
byte[] bytes = null;
MemoryStream ms = GetHeaders(response, _memoryStreamFactory, false);
bool chunked = response.SendChunked;
@@ -176,6 +181,11 @@ namespace SocketHttpListener.Net
if (disposed)
throw new ObjectDisposedException(GetType().ToString());
+ if (count == 0)
+ {
+ //return;
+ }
+
byte[] bytes = null;
MemoryStream ms = GetHeaders(response, _memoryStreamFactory, false);
bool chunked = response.SendChunked;
@@ -206,7 +216,7 @@ namespace SocketHttpListener.Net
await stream.WriteAsync(buffer, offset, count, cancellationToken).ConfigureAwait(false);
}
- if (response.SendChunked)
+ if (chunked)
stream.Write(crlf, 0, 2);
}