Merge pull request #2294 from MediaBrowser/dev

Dev
This commit is contained in:
Luke 2016-11-18 12:52:16 -05:00 committed by GitHub
commit 9ff2d7590e
38 changed files with 1543 additions and 1654 deletions

View File

@ -1,252 +0,0 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.IO;
using System.Threading.Tasks;
using Emby.Server.Core.Data;
using MediaBrowser.Controller;
using MediaBrowser.Model.Activity;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Querying;
namespace Emby.Server.Core.Activity
{
public class ActivityRepository : BaseSqliteRepository, IActivityRepository
{
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
public ActivityRepository(ILogManager logManager, IServerApplicationPaths appPaths, IDbConnector connector)
: base(logManager, connector)
{
DbFilePath = Path.Combine(appPaths.DataPath, "activitylog.db");
}
public async Task Initialize()
{
using (var connection = await CreateConnection().ConfigureAwait(false))
{
string[] queries = {
"create table if not exists ActivityLogEntries (Id GUID PRIMARY KEY, Name TEXT, Overview TEXT, ShortOverview TEXT, Type TEXT, ItemId TEXT, UserId TEXT, DateCreated DATETIME, LogSeverity TEXT)",
"create index if not exists idx_ActivityLogEntries on ActivityLogEntries(Id)"
};
connection.RunQueries(queries, Logger);
}
}
private const string BaseActivitySelectText = "select Id, Name, Overview, ShortOverview, Type, ItemId, UserId, DateCreated, LogSeverity from ActivityLogEntries";
public Task Create(ActivityLogEntry entry)
{
return Update(entry);
}
public async Task Update(ActivityLogEntry entry)
{
if (entry == null)
{
throw new ArgumentNullException("entry");
}
using (var connection = await CreateConnection().ConfigureAwait(false))
{
using (var saveActivityCommand = connection.CreateCommand())
{
saveActivityCommand.CommandText = "replace into ActivityLogEntries (Id, Name, Overview, ShortOverview, Type, ItemId, UserId, DateCreated, LogSeverity) values (@Id, @Name, @Overview, @ShortOverview, @Type, @ItemId, @UserId, @DateCreated, @LogSeverity)";
saveActivityCommand.Parameters.Add(saveActivityCommand, "@Id");
saveActivityCommand.Parameters.Add(saveActivityCommand, "@Name");
saveActivityCommand.Parameters.Add(saveActivityCommand, "@Overview");
saveActivityCommand.Parameters.Add(saveActivityCommand, "@ShortOverview");
saveActivityCommand.Parameters.Add(saveActivityCommand, "@Type");
saveActivityCommand.Parameters.Add(saveActivityCommand, "@ItemId");
saveActivityCommand.Parameters.Add(saveActivityCommand, "@UserId");
saveActivityCommand.Parameters.Add(saveActivityCommand, "@DateCreated");
saveActivityCommand.Parameters.Add(saveActivityCommand, "@LogSeverity");
IDbTransaction transaction = null;
try
{
transaction = connection.BeginTransaction();
var index = 0;
saveActivityCommand.GetParameter(index++).Value = new Guid(entry.Id);
saveActivityCommand.GetParameter(index++).Value = entry.Name;
saveActivityCommand.GetParameter(index++).Value = entry.Overview;
saveActivityCommand.GetParameter(index++).Value = entry.ShortOverview;
saveActivityCommand.GetParameter(index++).Value = entry.Type;
saveActivityCommand.GetParameter(index++).Value = entry.ItemId;
saveActivityCommand.GetParameter(index++).Value = entry.UserId;
saveActivityCommand.GetParameter(index++).Value = entry.Date;
saveActivityCommand.GetParameter(index++).Value = entry.Severity.ToString();
saveActivityCommand.Transaction = transaction;
saveActivityCommand.ExecuteNonQuery();
transaction.Commit();
}
catch (OperationCanceledException)
{
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
catch (Exception e)
{
Logger.ErrorException("Failed to save record:", e);
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
finally
{
if (transaction != null)
{
transaction.Dispose();
}
}
}
}
}
public QueryResult<ActivityLogEntry> GetActivityLogEntries(DateTime? minDate, int? startIndex, int? limit)
{
using (var connection = CreateConnection(true).Result)
{
using (var cmd = connection.CreateCommand())
{
cmd.CommandText = BaseActivitySelectText;
var whereClauses = new List<string>();
if (minDate.HasValue)
{
whereClauses.Add("DateCreated>=@DateCreated");
cmd.Parameters.Add(cmd, "@DateCreated", DbType.Date).Value = minDate.Value;
}
var whereTextWithoutPaging = whereClauses.Count == 0 ?
string.Empty :
" where " + string.Join(" AND ", whereClauses.ToArray());
if (startIndex.HasValue && startIndex.Value > 0)
{
var pagingWhereText = whereClauses.Count == 0 ?
string.Empty :
" where " + string.Join(" AND ", whereClauses.ToArray());
whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM ActivityLogEntries {0} ORDER BY DateCreated DESC LIMIT {1})",
pagingWhereText,
startIndex.Value.ToString(_usCulture)));
}
var whereText = whereClauses.Count == 0 ?
string.Empty :
" where " + string.Join(" AND ", whereClauses.ToArray());
cmd.CommandText += whereText;
cmd.CommandText += " ORDER BY DateCreated DESC";
if (limit.HasValue)
{
cmd.CommandText += " LIMIT " + limit.Value.ToString(_usCulture);
}
cmd.CommandText += "; select count (Id) from ActivityLogEntries" + whereTextWithoutPaging;
var list = new List<ActivityLogEntry>();
var count = 0;
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
{
while (reader.Read())
{
list.Add(GetEntry(reader));
}
if (reader.NextResult() && reader.Read())
{
count = reader.GetInt32(0);
}
}
return new QueryResult<ActivityLogEntry>()
{
Items = list.ToArray(),
TotalRecordCount = count
};
}
}
}
private ActivityLogEntry GetEntry(IDataReader reader)
{
var index = 0;
var info = new ActivityLogEntry
{
Id = reader.GetGuid(index).ToString("N")
};
index++;
if (!reader.IsDBNull(index))
{
info.Name = reader.GetString(index);
}
index++;
if (!reader.IsDBNull(index))
{
info.Overview = reader.GetString(index);
}
index++;
if (!reader.IsDBNull(index))
{
info.ShortOverview = reader.GetString(index);
}
index++;
if (!reader.IsDBNull(index))
{
info.Type = reader.GetString(index);
}
index++;
if (!reader.IsDBNull(index))
{
info.ItemId = reader.GetString(index);
}
index++;
if (!reader.IsDBNull(index))
{
info.UserId = reader.GetString(index);
}
index++;
info.Date = reader.GetDateTime(index).ToUniversalTime();
index++;
if (!reader.IsDBNull(index))
{
info.Severity = (LogSeverity)Enum.Parse(typeof(LogSeverity), reader.GetString(index), true);
}
return info;
}
}
}

View File

@ -83,23 +83,20 @@ using Emby.Dlna.Main;
using Emby.Dlna.MediaReceiverRegistrar;
using Emby.Dlna.Ssdp;
using Emby.Server.Core;
using Emby.Server.Core.Activity;
using Emby.Server.Implementations.Activity;
using Emby.Server.Core.Configuration;
using Emby.Server.Core.Data;
using Emby.Server.Core.Devices;
using Emby.Server.Implementations.Devices;
using Emby.Server.Core.FFMpeg;
using Emby.Server.Core.IO;
using Emby.Server.Core.Localization;
using Emby.Server.Core.Migrations;
using Emby.Server.Core.Notifications;
using Emby.Server.Core.Security;
using Emby.Server.Core.Social;
using Emby.Server.Implementations.Security;
using Emby.Server.Implementations.Social;
using Emby.Server.Core.Sync;
using Emby.Server.Implementations.Activity;
using Emby.Server.Implementations.Channels;
using Emby.Server.Implementations.Collections;
using Emby.Server.Implementations.Connect;
using Emby.Server.Implementations.Devices;
using Emby.Server.Implementations.Dto;
using Emby.Server.Implementations.EntryPoints;
using Emby.Server.Implementations.FileOrganization;
@ -110,7 +107,7 @@ using Emby.Server.Implementations.LiveTv;
using Emby.Server.Implementations.Localization;
using Emby.Server.Implementations.MediaEncoder;
using Emby.Server.Implementations.Notifications;
using Emby.Server.Implementations.Persistence;
using Emby.Server.Implementations.Data;
using Emby.Server.Implementations.Playlists;
using Emby.Server.Implementations.Security;
using Emby.Server.Implementations.ServerManager;
@ -136,6 +133,7 @@ using ServiceStack;
using SocketHttpListener.Primitives;
using StringExtensions = MediaBrowser.Controller.Extensions.StringExtensions;
using Emby.Drawing;
using Emby.Server.Implementations.Migrations;
namespace Emby.Server.Core
{
@ -282,12 +280,12 @@ namespace Emby.Server.Core
INetworkManager networkManager,
Action<string, string> certificateGenerator,
Func<string> defaultUsernameFactory)
: base(applicationPaths,
logManager,
fileSystem,
environmentInfo,
systemEvents,
memoryStreamFactory,
: base(applicationPaths,
logManager,
fileSystem,
environmentInfo,
systemEvents,
memoryStreamFactory,
networkManager)
{
StartupOptions = options;
@ -556,7 +554,7 @@ namespace Emby.Server.Core
UserRepository = await GetUserRepository().ConfigureAwait(false);
var displayPreferencesRepo = new SqliteDisplayPreferencesRepository(LogManager, JsonSerializer, ApplicationPaths, GetDbConnector(), MemoryStreamFactory);
var displayPreferencesRepo = new SqliteDisplayPreferencesRepository(LogManager.GetLogger("SqliteDisplayPreferencesRepository"), JsonSerializer, ApplicationPaths, MemoryStreamFactory);
DisplayPreferencesRepository = displayPreferencesRepo;
RegisterSingleInstance(DisplayPreferencesRepository);
@ -683,11 +681,11 @@ namespace Emby.Server.Core
EncodingManager = new EncodingManager(FileSystemManager, Logger, MediaEncoder, ChapterManager, LibraryManager);
RegisterSingleInstance(EncodingManager);
var sharingRepo = new SharingRepository(LogManager, ApplicationPaths, GetDbConnector());
await sharingRepo.Initialize().ConfigureAwait(false);
var sharingRepo = new SharingRepository(LogManager.GetLogger("SharingRepository"), ApplicationPaths);
sharingRepo.Initialize();
RegisterSingleInstance<ISharingManager>(new SharingManager(sharingRepo, ServerConfigurationManager, LibraryManager, this));
var activityLogRepo = await GetActivityLogRepository().ConfigureAwait(false);
var activityLogRepo = GetActivityLogRepository();
RegisterSingleInstance(activityLogRepo);
RegisterSingleInstance<IActivityManager>(new ActivityManager(LogManager.GetLogger("ActivityManager"), activityLogRepo, UserManager));
@ -701,14 +699,14 @@ namespace Emby.Server.Core
SubtitleEncoder = new SubtitleEncoder(LibraryManager, LogManager.GetLogger("SubtitleEncoder"), ApplicationPaths, FileSystemManager, MediaEncoder, JsonSerializer, HttpClient, MediaSourceManager, MemoryStreamFactory, ProcessFactory, textEncoding);
RegisterSingleInstance(SubtitleEncoder);
await displayPreferencesRepo.Initialize().ConfigureAwait(false);
displayPreferencesRepo.Initialize();
var userDataRepo = new SqliteUserDataRepository(LogManager, ApplicationPaths, GetDbConnector());
((UserDataManager)UserDataManager).Repository = userDataRepo;
await itemRepo.Initialize(userDataRepo).ConfigureAwait(false);
((LibraryManager)LibraryManager).ItemRepository = ItemRepository;
await ConfigureNotificationsRepository().ConfigureAwait(false);
ConfigureNotificationsRepository();
progress.Report(100);
SetStaticProperties();
@ -792,7 +790,7 @@ namespace Emby.Server.Core
() => SubtitleEncoder,
() => MediaSourceManager,
HttpClient,
ZipClient,
ZipClient,
MemoryStreamFactory,
ProcessFactory,
(Environment.ProcessorCount > 2 ? 14000 : 40000),
@ -830,18 +828,18 @@ namespace Emby.Server.Core
private async Task<IAuthenticationRepository> GetAuthenticationRepository()
{
var repo = new AuthenticationRepository(LogManager, ServerConfigurationManager.ApplicationPaths, GetDbConnector());
var repo = new AuthenticationRepository(LogManager.GetLogger("AuthenticationRepository"), ServerConfigurationManager.ApplicationPaths);
await repo.Initialize().ConfigureAwait(false);
repo.Initialize();
return repo;
}
private async Task<IActivityRepository> GetActivityLogRepository()
private IActivityRepository GetActivityLogRepository()
{
var repo = new ActivityRepository(LogManager, ServerConfigurationManager.ApplicationPaths, GetDbConnector());
var repo = new ActivityRepository(LogManager.GetLogger("ActivityRepository"), ServerConfigurationManager.ApplicationPaths);
await repo.Initialize().ConfigureAwait(false);
repo.Initialize();
return repo;
}
@ -858,11 +856,11 @@ namespace Emby.Server.Core
/// <summary>
/// Configures the repositories.
/// </summary>
private async Task ConfigureNotificationsRepository()
private void ConfigureNotificationsRepository()
{
var repo = new SqliteNotificationsRepository(LogManager, ApplicationPaths, GetDbConnector());
var repo = new SqliteNotificationsRepository(LogManager.GetLogger("SqliteNotificationsRepository"), ServerConfigurationManager.ApplicationPaths);
await repo.Initialize().ConfigureAwait(false);
repo.Initialize();
NotificationsRepository = repo;

View File

@ -1,312 +0,0 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
namespace Emby.Server.Core.Data
{
/// <summary>
/// Class SQLiteDisplayPreferencesRepository
/// </summary>
public class SqliteDisplayPreferencesRepository : BaseSqliteRepository, IDisplayPreferencesRepository
{
private readonly IMemoryStreamFactory _memoryStreamProvider;
public SqliteDisplayPreferencesRepository(ILogManager logManager, IJsonSerializer jsonSerializer, IApplicationPaths appPaths, IDbConnector dbConnector, IMemoryStreamFactory memoryStreamProvider)
: base(logManager, dbConnector)
{
_jsonSerializer = jsonSerializer;
_memoryStreamProvider = memoryStreamProvider;
DbFilePath = Path.Combine(appPaths.DataPath, "displaypreferences.db");
}
/// <summary>
/// Gets the name of the repository
/// </summary>
/// <value>The name.</value>
public string Name
{
get
{
return "SQLite";
}
}
/// <summary>
/// The _json serializer
/// </summary>
private readonly IJsonSerializer _jsonSerializer;
/// <summary>
/// Opens the connection to the database
/// </summary>
/// <returns>Task.</returns>
public async Task Initialize()
{
using (var connection = await CreateConnection().ConfigureAwait(false))
{
string[] queries = {
"create table if not exists userdisplaypreferences (id GUID, userId GUID, client text, data BLOB)",
"create unique index if not exists userdisplaypreferencesindex on userdisplaypreferences (id, userId, client)"
};
connection.RunQueries(queries, Logger);
}
}
/// <summary>
/// Save the display preferences associated with an item in the repo
/// </summary>
/// <param name="displayPreferences">The display preferences.</param>
/// <param name="userId">The user id.</param>
/// <param name="client">The client.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
/// <exception cref="System.ArgumentNullException">item</exception>
public async Task SaveDisplayPreferences(DisplayPreferences displayPreferences, Guid userId, string client, CancellationToken cancellationToken)
{
if (displayPreferences == null)
{
throw new ArgumentNullException("displayPreferences");
}
if (string.IsNullOrWhiteSpace(displayPreferences.Id))
{
throw new ArgumentNullException("displayPreferences.Id");
}
cancellationToken.ThrowIfCancellationRequested();
var serialized = _jsonSerializer.SerializeToBytes(displayPreferences, _memoryStreamProvider);
using (var connection = await CreateConnection().ConfigureAwait(false))
{
IDbTransaction transaction = null;
try
{
transaction = connection.BeginTransaction();
using (var cmd = connection.CreateCommand())
{
cmd.CommandText = "replace into userdisplaypreferences (id, userid, client, data) values (@1, @2, @3, @4)";
cmd.Parameters.Add(cmd, "@1", DbType.Guid).Value = new Guid(displayPreferences.Id);
cmd.Parameters.Add(cmd, "@2", DbType.Guid).Value = userId;
cmd.Parameters.Add(cmd, "@3", DbType.String).Value = client;
cmd.Parameters.Add(cmd, "@4", DbType.Binary).Value = serialized;
cmd.Transaction = transaction;
cmd.ExecuteNonQuery();
}
transaction.Commit();
}
catch (OperationCanceledException)
{
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
catch (Exception e)
{
Logger.ErrorException("Failed to save display preferences:", e);
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
finally
{
if (transaction != null)
{
transaction.Dispose();
}
}
}
}
/// <summary>
/// Save all display preferences associated with a user in the repo
/// </summary>
/// <param name="displayPreferences">The display preferences.</param>
/// <param name="userId">The user id.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
/// <exception cref="System.ArgumentNullException">item</exception>
public async Task SaveAllDisplayPreferences(IEnumerable<DisplayPreferences> displayPreferences, Guid userId, CancellationToken cancellationToken)
{
if (displayPreferences == null)
{
throw new ArgumentNullException("displayPreferences");
}
cancellationToken.ThrowIfCancellationRequested();
using (var connection = await CreateConnection().ConfigureAwait(false))
{
IDbTransaction transaction = null;
try
{
transaction = connection.BeginTransaction();
foreach (var displayPreference in displayPreferences)
{
var serialized = _jsonSerializer.SerializeToBytes(displayPreference, _memoryStreamProvider);
using (var cmd = connection.CreateCommand())
{
cmd.CommandText = "replace into userdisplaypreferences (id, userid, client, data) values (@1, @2, @3, @4)";
cmd.Parameters.Add(cmd, "@1", DbType.Guid).Value = new Guid(displayPreference.Id);
cmd.Parameters.Add(cmd, "@2", DbType.Guid).Value = userId;
cmd.Parameters.Add(cmd, "@3", DbType.String).Value = displayPreference.Client;
cmd.Parameters.Add(cmd, "@4", DbType.Binary).Value = serialized;
cmd.Transaction = transaction;
cmd.ExecuteNonQuery();
}
}
transaction.Commit();
}
catch (OperationCanceledException)
{
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
catch (Exception e)
{
Logger.ErrorException("Failed to save display preferences:", e);
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
finally
{
if (transaction != null)
{
transaction.Dispose();
}
}
}
}
/// <summary>
/// Gets the display preferences.
/// </summary>
/// <param name="displayPreferencesId">The display preferences id.</param>
/// <param name="userId">The user id.</param>
/// <param name="client">The client.</param>
/// <returns>Task{DisplayPreferences}.</returns>
/// <exception cref="System.ArgumentNullException">item</exception>
public DisplayPreferences GetDisplayPreferences(string displayPreferencesId, Guid userId, string client)
{
if (string.IsNullOrWhiteSpace(displayPreferencesId))
{
throw new ArgumentNullException("displayPreferencesId");
}
var guidId = displayPreferencesId.GetMD5();
using (var connection = CreateConnection(true).Result)
{
using (var cmd = connection.CreateCommand())
{
cmd.CommandText = "select data from userdisplaypreferences where id = @id and userId=@userId and client=@client";
cmd.Parameters.Add(cmd, "@id", DbType.Guid).Value = guidId;
cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId;
cmd.Parameters.Add(cmd, "@client", DbType.String).Value = client;
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow))
{
if (reader.Read())
{
using (var stream = reader.GetMemoryStream(0, _memoryStreamProvider))
{
return _jsonSerializer.DeserializeFromStream<DisplayPreferences>(stream);
}
}
}
return new DisplayPreferences
{
Id = guidId.ToString("N")
};
}
}
}
/// <summary>
/// Gets all display preferences for the given user.
/// </summary>
/// <param name="userId">The user id.</param>
/// <returns>Task{DisplayPreferences}.</returns>
/// <exception cref="System.ArgumentNullException">item</exception>
public IEnumerable<DisplayPreferences> GetAllDisplayPreferences(Guid userId)
{
var list = new List<DisplayPreferences>();
using (var connection = CreateConnection(true).Result)
{
using (var cmd = connection.CreateCommand())
{
cmd.CommandText = "select data from userdisplaypreferences where userId=@userId";
cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId;
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
{
while (reader.Read())
{
using (var stream = reader.GetMemoryStream(0, _memoryStreamProvider))
{
list.Add(_jsonSerializer.DeserializeFromStream<DisplayPreferences>(stream));
}
}
}
}
}
return list;
}
public Task SaveDisplayPreferences(DisplayPreferences displayPreferences, string userId, string client, CancellationToken cancellationToken)
{
return SaveDisplayPreferences(displayPreferences, new Guid(userId), client, cancellationToken);
}
public DisplayPreferences GetDisplayPreferences(string displayPreferencesId, string userId, string client)
{
return GetDisplayPreferences(displayPreferencesId, new Guid(userId), client);
}
}
}

View File

@ -87,9 +87,6 @@ namespace Emby.Server.Core.Data
private IDbCommand _deleteItemValuesCommand;
private IDbCommand _saveItemValuesCommand;
private IDbCommand _deleteImagesCommand;
private IDbCommand _saveImagesCommand;
private IDbCommand _updateInheritedTagsCommand;
public const int LatestSchemaVersion = 109;
@ -162,9 +159,6 @@ namespace Emby.Server.Core.Data
"create table if not exists ItemValues (ItemId GUID, Type INT, Value TEXT, CleanValue TEXT)",
"create table if not exists Images (ItemId GUID NOT NULL, Path TEXT NOT NULL, ImageType INT NOT NULL, DateModified DATETIME, IsPlaceHolder BIT NOT NULL, SortOrder INT)",
"create index if not exists idx_Images on Images(ItemId)",
"create table if not exists People (ItemId GUID, Name TEXT NOT NULL, Role TEXT, PersonType TEXT, SortOrder int, ListOrder int)",
"drop index if exists idxPeopleItemId",
@ -309,6 +303,8 @@ namespace Emby.Server.Core.Data
"drop table if exists UserDataKeys",
"drop table if exists ProviderIds",
"drop index if exists Idx_ProviderIds1",
"drop table if exists Images",
"drop index if exists idx_Images",
"create index if not exists idx_PathTypedBaseItems on TypedBaseItems(Path)",
"create index if not exists idx_ParentIdTypedBaseItems on TypedBaseItems(ParentId)",
@ -664,20 +660,6 @@ namespace Emby.Server.Core.Data
_saveItemValuesCommand.Parameters.Add(_saveItemValuesCommand, "@Type");
_saveItemValuesCommand.Parameters.Add(_saveItemValuesCommand, "@Value");
_saveItemValuesCommand.Parameters.Add(_saveItemValuesCommand, "@CleanValue");
// images
_deleteImagesCommand = _connection.CreateCommand();
_deleteImagesCommand.CommandText = "delete from Images where ItemId=@Id";
_deleteImagesCommand.Parameters.Add(_deleteImagesCommand, "@Id");
_saveImagesCommand = _connection.CreateCommand();
_saveImagesCommand.CommandText = "insert into Images (ItemId, ImageType, Path, DateModified, IsPlaceHolder, SortOrder) values (@ItemId, @ImageType, @Path, @DateModified, @IsPlaceHolder, @SortOrder)";
_saveImagesCommand.Parameters.Add(_saveImagesCommand, "@ItemId");
_saveImagesCommand.Parameters.Add(_saveImagesCommand, "@ImageType");
_saveImagesCommand.Parameters.Add(_saveImagesCommand, "@Path");
_saveImagesCommand.Parameters.Add(_saveImagesCommand, "@DateModified");
_saveImagesCommand.Parameters.Add(_saveImagesCommand, "@IsPlaceHolder");
_saveImagesCommand.Parameters.Add(_saveImagesCommand, "@SortOrder");
}
/// <summary>
@ -1101,7 +1083,6 @@ namespace Emby.Server.Core.Data
UpdateAncestors(item.Id, item.GetAncestorIds().Distinct().ToList(), transaction);
}
UpdateImages(item.Id, item.ImageInfos, transaction);
UpdateItemValues(item.Id, GetItemValuesToSave(item), transaction);
}
@ -3475,14 +3456,9 @@ namespace Emby.Server.Core.Data
if (query.ImageTypes.Length > 0 && _config.Configuration.SchemaVersion >= 87)
{
var requiredImageIndex = 0;
foreach (var requiredImage in query.ImageTypes)
{
var paramName = "@RequiredImageType" + requiredImageIndex;
whereClauses.Add("(select path from images where ItemId=Guid and ImageType=" + paramName + " limit 1) not null");
cmd.Parameters.Add(cmd, paramName, DbType.Int32).Value = (int)requiredImage;
requiredImageIndex++;
whereClauses.Add("Images like '%" + requiredImage + "%'");
}
}
@ -4255,11 +4231,6 @@ namespace Emby.Server.Core.Data
_deleteItemValuesCommand.Transaction = transaction;
_deleteItemValuesCommand.ExecuteNonQuery();
// Delete images
_deleteImagesCommand.GetParameter(0).Value = id;
_deleteImagesCommand.Transaction = transaction;
_deleteImagesCommand.ExecuteNonQuery();
// Delete the item
_deleteItemCommand.GetParameter(0).Value = id;
_deleteItemCommand.Transaction = transaction;
@ -4875,58 +4846,6 @@ namespace Emby.Server.Core.Data
return list;
}
private void UpdateImages(Guid itemId, List<ItemImageInfo> images, IDbTransaction transaction)
{
if (itemId == Guid.Empty)
{
throw new ArgumentNullException("itemId");
}
if (images == null)
{
throw new ArgumentNullException("images");
}
CheckDisposed();
// First delete
_deleteImagesCommand.GetParameter(0).Value = itemId;
_deleteImagesCommand.Transaction = transaction;
_deleteImagesCommand.ExecuteNonQuery();
var index = 0;
foreach (var image in images)
{
if (string.IsNullOrWhiteSpace(image.Path))
{
// Invalid
continue;
}
_saveImagesCommand.GetParameter(0).Value = itemId;
_saveImagesCommand.GetParameter(1).Value = image.Type;
_saveImagesCommand.GetParameter(2).Value = image.Path;
if (image.DateModified == default(DateTime))
{
_saveImagesCommand.GetParameter(3).Value = null;
}
else
{
_saveImagesCommand.GetParameter(3).Value = image.DateModified;
}
_saveImagesCommand.GetParameter(4).Value = image.IsPlaceholder;
_saveImagesCommand.GetParameter(5).Value = index;
_saveImagesCommand.Transaction = transaction;
_saveImagesCommand.ExecuteNonQuery();
index++;
}
}
private void UpdateItemValues(Guid itemId, List<Tuple<int, string>> values, IDbTransaction transaction)
{
if (itemId == Guid.Empty)

View File

@ -1,8 +1,9 @@
using System.Threading.Tasks;
using Emby.Server.Implementations.Persistence;
using Emby.Server.Implementations.Data;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Model.Tasks;
using Emby.Server.Core.Data;
using Emby.Server.Implementations.Migrations;
namespace Emby.Server.Core.Migrations
{

View File

@ -9,6 +9,7 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Updates;
using Emby.Server.Implementations.Migrations;
namespace Emby.Server.Core.Migrations
{

View File

@ -1,470 +0,0 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Emby.Server.Core.Data;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Notifications;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Notifications;
namespace Emby.Server.Core.Notifications
{
public class SqliteNotificationsRepository : BaseSqliteRepository, INotificationsRepository
{
public SqliteNotificationsRepository(ILogManager logManager, IServerApplicationPaths appPaths, IDbConnector dbConnector) : base(logManager, dbConnector)
{
DbFilePath = Path.Combine(appPaths.DataPath, "notifications.db");
}
public event EventHandler<NotificationUpdateEventArgs> NotificationAdded;
public event EventHandler<NotificationReadEventArgs> NotificationsMarkedRead;
////public event EventHandler<NotificationUpdateEventArgs> NotificationUpdated;
public async Task Initialize()
{
using (var connection = await CreateConnection().ConfigureAwait(false))
{
string[] queries = {
"create table if not exists Notifications (Id GUID NOT NULL, UserId GUID NOT NULL, Date DATETIME NOT NULL, Name TEXT NOT NULL, Description TEXT NULL, Url TEXT NULL, Level TEXT NOT NULL, IsRead BOOLEAN NOT NULL, Category TEXT NOT NULL, RelatedId TEXT NULL, PRIMARY KEY (Id, UserId))",
"create index if not exists idx_Notifications1 on Notifications(Id)",
"create index if not exists idx_Notifications2 on Notifications(UserId)"
};
connection.RunQueries(queries, Logger);
}
}
/// <summary>
/// Gets the notifications.
/// </summary>
/// <param name="query">The query.</param>
/// <returns>NotificationResult.</returns>
public NotificationResult GetNotifications(NotificationQuery query)
{
var result = new NotificationResult();
using (var connection = CreateConnection(true).Result)
{
using (var cmd = connection.CreateCommand())
{
var clauses = new List<string>();
if (query.IsRead.HasValue)
{
clauses.Add("IsRead=@IsRead");
cmd.Parameters.Add(cmd, "@IsRead", DbType.Boolean).Value = query.IsRead.Value;
}
clauses.Add("UserId=@UserId");
cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = new Guid(query.UserId);
var whereClause = " where " + string.Join(" And ", clauses.ToArray());
cmd.CommandText = string.Format("select count(Id) from Notifications{0};select Id,UserId,Date,Name,Description,Url,Level,IsRead,Category,RelatedId from Notifications{0} order by IsRead asc, Date desc", whereClause);
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
{
if (reader.Read())
{
result.TotalRecordCount = reader.GetInt32(0);
}
if (reader.NextResult())
{
var notifications = GetNotifications(reader);
if (query.StartIndex.HasValue)
{
notifications = notifications.Skip(query.StartIndex.Value);
}
if (query.Limit.HasValue)
{
notifications = notifications.Take(query.Limit.Value);
}
result.Notifications = notifications.ToArray();
}
}
return result;
}
}
}
public NotificationsSummary GetNotificationsSummary(string userId)
{
var result = new NotificationsSummary();
using (var connection = CreateConnection(true).Result)
{
using (var cmd = connection.CreateCommand())
{
cmd.CommandText = "select Level from Notifications where UserId=@UserId and IsRead=@IsRead";
cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = new Guid(userId);
cmd.Parameters.Add(cmd, "@IsRead", DbType.Boolean).Value = false;
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
{
var levels = new List<NotificationLevel>();
while (reader.Read())
{
levels.Add(GetLevel(reader, 0));
}
result.UnreadCount = levels.Count;
if (levels.Count > 0)
{
result.MaxUnreadNotificationLevel = levels.Max();
}
}
return result;
}
}
}
/// <summary>
/// Gets the notifications.
/// </summary>
/// <param name="reader">The reader.</param>
/// <returns>IEnumerable{Notification}.</returns>
private IEnumerable<Notification> GetNotifications(IDataReader reader)
{
var list = new List<Notification>();
while (reader.Read())
{
list.Add(GetNotification(reader));
}
return list;
}
private Notification GetNotification(IDataReader reader)
{
var notification = new Notification
{
Id = reader.GetGuid(0).ToString("N"),
UserId = reader.GetGuid(1).ToString("N"),
Date = reader.GetDateTime(2).ToUniversalTime(),
Name = reader.GetString(3)
};
if (!reader.IsDBNull(4))
{
notification.Description = reader.GetString(4);
}
if (!reader.IsDBNull(5))
{
notification.Url = reader.GetString(5);
}
notification.Level = GetLevel(reader, 6);
notification.IsRead = reader.GetBoolean(7);
return notification;
}
/// <summary>
/// Gets the level.
/// </summary>
/// <param name="reader">The reader.</param>
/// <param name="index">The index.</param>
/// <returns>NotificationLevel.</returns>
private NotificationLevel GetLevel(IDataReader reader, int index)
{
NotificationLevel level;
var val = reader.GetString(index);
Enum.TryParse(val, true, out level);
return level;
}
/// <summary>
/// Adds the notification.
/// </summary>
/// <param name="notification">The notification.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
public async Task AddNotification(Notification notification, CancellationToken cancellationToken)
{
await ReplaceNotification(notification, cancellationToken).ConfigureAwait(false);
if (NotificationAdded != null)
{
try
{
NotificationAdded(this, new NotificationUpdateEventArgs
{
Notification = notification
});
}
catch (Exception ex)
{
Logger.ErrorException("Error in NotificationAdded event handler", ex);
}
}
}
/// <summary>
/// Replaces the notification.
/// </summary>
/// <param name="notification">The notification.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
private async Task ReplaceNotification(Notification notification, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(notification.Id))
{
notification.Id = Guid.NewGuid().ToString("N");
}
if (string.IsNullOrEmpty(notification.UserId))
{
throw new ArgumentException("The notification must have a user id");
}
cancellationToken.ThrowIfCancellationRequested();
using (var connection = await CreateConnection().ConfigureAwait(false))
{
using (var replaceNotificationCommand = connection.CreateCommand())
{
replaceNotificationCommand.CommandText = "replace into Notifications (Id, UserId, Date, Name, Description, Url, Level, IsRead, Category, RelatedId) values (@Id, @UserId, @Date, @Name, @Description, @Url, @Level, @IsRead, @Category, @RelatedId)";
replaceNotificationCommand.Parameters.Add(replaceNotificationCommand, "@Id");
replaceNotificationCommand.Parameters.Add(replaceNotificationCommand, "@UserId");
replaceNotificationCommand.Parameters.Add(replaceNotificationCommand, "@Date");
replaceNotificationCommand.Parameters.Add(replaceNotificationCommand, "@Name");
replaceNotificationCommand.Parameters.Add(replaceNotificationCommand, "@Description");
replaceNotificationCommand.Parameters.Add(replaceNotificationCommand, "@Url");
replaceNotificationCommand.Parameters.Add(replaceNotificationCommand, "@Level");
replaceNotificationCommand.Parameters.Add(replaceNotificationCommand, "@IsRead");
replaceNotificationCommand.Parameters.Add(replaceNotificationCommand, "@Category");
replaceNotificationCommand.Parameters.Add(replaceNotificationCommand, "@RelatedId");
IDbTransaction transaction = null;
try
{
transaction = connection.BeginTransaction();
replaceNotificationCommand.GetParameter("@Id").Value = new Guid(notification.Id);
replaceNotificationCommand.GetParameter("@UserId").Value = new Guid(notification.UserId);
replaceNotificationCommand.GetParameter("@Date").Value = notification.Date.ToUniversalTime();
replaceNotificationCommand.GetParameter("@Name").Value = notification.Name;
replaceNotificationCommand.GetParameter("@Description").Value = notification.Description;
replaceNotificationCommand.GetParameter("@Url").Value = notification.Url;
replaceNotificationCommand.GetParameter("@Level").Value = notification.Level.ToString();
replaceNotificationCommand.GetParameter("@IsRead").Value = notification.IsRead;
replaceNotificationCommand.GetParameter("@Category").Value = string.Empty;
replaceNotificationCommand.GetParameter("@RelatedId").Value = string.Empty;
replaceNotificationCommand.Transaction = transaction;
replaceNotificationCommand.ExecuteNonQuery();
transaction.Commit();
}
catch (OperationCanceledException)
{
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
catch (Exception e)
{
Logger.ErrorException("Failed to save notification:", e);
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
finally
{
if (transaction != null)
{
transaction.Dispose();
}
}
}
}
}
/// <summary>
/// Marks the read.
/// </summary>
/// <param name="notificationIdList">The notification id list.</param>
/// <param name="userId">The user id.</param>
/// <param name="isRead">if set to <c>true</c> [is read].</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
public async Task MarkRead(IEnumerable<string> notificationIdList, string userId, bool isRead, CancellationToken cancellationToken)
{
var list = notificationIdList.ToList();
var idArray = list.Select(i => new Guid(i)).ToArray();
await MarkReadInternal(idArray, userId, isRead, cancellationToken).ConfigureAwait(false);
if (NotificationsMarkedRead != null)
{
try
{
NotificationsMarkedRead(this, new NotificationReadEventArgs
{
IdList = list.ToArray(),
IsRead = isRead,
UserId = userId
});
}
catch (Exception ex)
{
Logger.ErrorException("Error in NotificationsMarkedRead event handler", ex);
}
}
}
public async Task MarkAllRead(string userId, bool isRead, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
using (var connection = await CreateConnection().ConfigureAwait(false))
{
using (var markAllReadCommand = connection.CreateCommand())
{
markAllReadCommand.CommandText = "update Notifications set IsRead=@IsRead where UserId=@UserId";
markAllReadCommand.Parameters.Add(markAllReadCommand, "@UserId");
markAllReadCommand.Parameters.Add(markAllReadCommand, "@IsRead");
IDbTransaction transaction = null;
try
{
cancellationToken.ThrowIfCancellationRequested();
transaction = connection.BeginTransaction();
markAllReadCommand.GetParameter(0).Value = new Guid(userId);
markAllReadCommand.GetParameter(1).Value = isRead;
markAllReadCommand.ExecuteNonQuery();
transaction.Commit();
}
catch (OperationCanceledException)
{
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
catch (Exception e)
{
Logger.ErrorException("Failed to save notification:", e);
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
finally
{
if (transaction != null)
{
transaction.Dispose();
}
}
}
}
}
private async Task MarkReadInternal(IEnumerable<Guid> notificationIdList, string userId, bool isRead, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
using (var connection = await CreateConnection().ConfigureAwait(false))
{
using (var markReadCommand = connection.CreateCommand())
{
markReadCommand.CommandText = "update Notifications set IsRead=@IsRead where Id=@Id and UserId=@UserId";
markReadCommand.Parameters.Add(markReadCommand, "@UserId");
markReadCommand.Parameters.Add(markReadCommand, "@IsRead");
markReadCommand.Parameters.Add(markReadCommand, "@Id");
IDbTransaction transaction = null;
try
{
cancellationToken.ThrowIfCancellationRequested();
transaction = connection.BeginTransaction();
markReadCommand.GetParameter(0).Value = new Guid(userId);
markReadCommand.GetParameter(1).Value = isRead;
foreach (var id in notificationIdList)
{
markReadCommand.GetParameter(2).Value = id;
markReadCommand.Transaction = transaction;
markReadCommand.ExecuteNonQuery();
}
transaction.Commit();
}
catch (OperationCanceledException)
{
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
catch (Exception e)
{
Logger.ErrorException("Failed to save notification:", e);
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
finally
{
if (transaction != null)
{
transaction.Dispose();
}
}
}
}
}
}
}

View File

@ -1,315 +0,0 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Emby.Server.Core.Data;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Security;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Querying;
namespace Emby.Server.Core.Security
{
public class AuthenticationRepository : BaseSqliteRepository, IAuthenticationRepository
{
private readonly IServerApplicationPaths _appPaths;
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
public AuthenticationRepository(ILogManager logManager, IServerApplicationPaths appPaths, IDbConnector connector)
: base(logManager, connector)
{
_appPaths = appPaths;
DbFilePath = Path.Combine(appPaths.DataPath, "authentication.db");
}
public async Task Initialize()
{
using (var connection = await CreateConnection().ConfigureAwait(false))
{
string[] queries = {
"create table if not exists AccessTokens (Id GUID PRIMARY KEY, AccessToken TEXT NOT NULL, DeviceId TEXT, AppName TEXT, AppVersion TEXT, DeviceName TEXT, UserId TEXT, IsActive BIT, DateCreated DATETIME NOT NULL, DateRevoked DATETIME)",
"create index if not exists idx_AccessTokens on AccessTokens(Id)"
};
connection.RunQueries(queries, Logger);
connection.AddColumn(Logger, "AccessTokens", "AppVersion", "TEXT");
}
}
public Task Create(AuthenticationInfo info, CancellationToken cancellationToken)
{
info.Id = Guid.NewGuid().ToString("N");
return Update(info, cancellationToken);
}
public async Task Update(AuthenticationInfo info, CancellationToken cancellationToken)
{
if (info == null)
{
throw new ArgumentNullException("info");
}
cancellationToken.ThrowIfCancellationRequested();
using (var connection = await CreateConnection().ConfigureAwait(false))
{
using (var saveInfoCommand = connection.CreateCommand())
{
saveInfoCommand.CommandText = "replace into AccessTokens (Id, AccessToken, DeviceId, AppName, AppVersion, DeviceName, UserId, IsActive, DateCreated, DateRevoked) values (@Id, @AccessToken, @DeviceId, @AppName, @AppVersion, @DeviceName, @UserId, @IsActive, @DateCreated, @DateRevoked)";
saveInfoCommand.Parameters.Add(saveInfoCommand, "@Id");
saveInfoCommand.Parameters.Add(saveInfoCommand, "@AccessToken");
saveInfoCommand.Parameters.Add(saveInfoCommand, "@DeviceId");
saveInfoCommand.Parameters.Add(saveInfoCommand, "@AppName");
saveInfoCommand.Parameters.Add(saveInfoCommand, "@AppVersion");
saveInfoCommand.Parameters.Add(saveInfoCommand, "@DeviceName");
saveInfoCommand.Parameters.Add(saveInfoCommand, "@UserId");
saveInfoCommand.Parameters.Add(saveInfoCommand, "@IsActive");
saveInfoCommand.Parameters.Add(saveInfoCommand, "@DateCreated");
saveInfoCommand.Parameters.Add(saveInfoCommand, "@DateRevoked");
IDbTransaction transaction = null;
try
{
transaction = connection.BeginTransaction();
saveInfoCommand.GetParameter("@Id").Value = new Guid(info.Id);
saveInfoCommand.GetParameter("@AccessToken").Value = info.AccessToken;
saveInfoCommand.GetParameter("@DeviceId").Value = info.DeviceId;
saveInfoCommand.GetParameter("@AppName").Value = info.AppName;
saveInfoCommand.GetParameter("@AppVersion").Value = info.AppVersion;
saveInfoCommand.GetParameter("@DeviceName").Value = info.DeviceName;
saveInfoCommand.GetParameter("@UserId").Value = info.UserId;
saveInfoCommand.GetParameter("@IsActive").Value = info.IsActive;
saveInfoCommand.GetParameter("@DateCreated").Value = info.DateCreated;
saveInfoCommand.GetParameter("@DateRevoked").Value = info.DateRevoked;
saveInfoCommand.Transaction = transaction;
saveInfoCommand.ExecuteNonQuery();
transaction.Commit();
}
catch (OperationCanceledException)
{
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
catch (Exception e)
{
Logger.ErrorException("Failed to save record:", e);
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
finally
{
if (transaction != null)
{
transaction.Dispose();
}
}
}
}
}
private const string BaseSelectText = "select Id, AccessToken, DeviceId, AppName, AppVersion, DeviceName, UserId, IsActive, DateCreated, DateRevoked from AccessTokens";
public QueryResult<AuthenticationInfo> Get(AuthenticationInfoQuery query)
{
if (query == null)
{
throw new ArgumentNullException("query");
}
using (var connection = CreateConnection(true).Result)
{
using (var cmd = connection.CreateCommand())
{
cmd.CommandText = BaseSelectText;
var whereClauses = new List<string>();
var startIndex = query.StartIndex ?? 0;
if (!string.IsNullOrWhiteSpace(query.AccessToken))
{
whereClauses.Add("AccessToken=@AccessToken");
cmd.Parameters.Add(cmd, "@AccessToken", DbType.String).Value = query.AccessToken;
}
if (!string.IsNullOrWhiteSpace(query.UserId))
{
whereClauses.Add("UserId=@UserId");
cmd.Parameters.Add(cmd, "@UserId", DbType.String).Value = query.UserId;
}
if (!string.IsNullOrWhiteSpace(query.DeviceId))
{
whereClauses.Add("DeviceId=@DeviceId");
cmd.Parameters.Add(cmd, "@DeviceId", DbType.String).Value = query.DeviceId;
}
if (query.IsActive.HasValue)
{
whereClauses.Add("IsActive=@IsActive");
cmd.Parameters.Add(cmd, "@IsActive", DbType.Boolean).Value = query.IsActive.Value;
}
if (query.HasUser.HasValue)
{
if (query.HasUser.Value)
{
whereClauses.Add("UserId not null");
}
else
{
whereClauses.Add("UserId is null");
}
}
var whereTextWithoutPaging = whereClauses.Count == 0 ?
string.Empty :
" where " + string.Join(" AND ", whereClauses.ToArray());
if (startIndex > 0)
{
var pagingWhereText = whereClauses.Count == 0 ?
string.Empty :
" where " + string.Join(" AND ", whereClauses.ToArray());
whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM AccessTokens {0} ORDER BY DateCreated LIMIT {1})",
pagingWhereText,
startIndex.ToString(_usCulture)));
}
var whereText = whereClauses.Count == 0 ?
string.Empty :
" where " + string.Join(" AND ", whereClauses.ToArray());
cmd.CommandText += whereText;
cmd.CommandText += " ORDER BY DateCreated";
if (query.Limit.HasValue)
{
cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(_usCulture);
}
cmd.CommandText += "; select count (Id) from AccessTokens" + whereTextWithoutPaging;
var list = new List<AuthenticationInfo>();
var count = 0;
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
{
while (reader.Read())
{
list.Add(Get(reader));
}
if (reader.NextResult() && reader.Read())
{
count = reader.GetInt32(0);
}
}
return new QueryResult<AuthenticationInfo>()
{
Items = list.ToArray(),
TotalRecordCount = count
};
}
}
}
public AuthenticationInfo Get(string id)
{
if (string.IsNullOrEmpty(id))
{
throw new ArgumentNullException("id");
}
using (var connection = CreateConnection(true).Result)
{
var guid = new Guid(id);
using (var cmd = connection.CreateCommand())
{
cmd.CommandText = BaseSelectText + " where Id=@Id";
cmd.Parameters.Add(cmd, "@Id", DbType.Guid).Value = guid;
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow))
{
if (reader.Read())
{
return Get(reader);
}
}
}
return null;
}
}
private AuthenticationInfo Get(IDataReader reader)
{
var info = new AuthenticationInfo
{
Id = reader.GetGuid(0).ToString("N"),
AccessToken = reader.GetString(1)
};
if (!reader.IsDBNull(2))
{
info.DeviceId = reader.GetString(2);
}
if (!reader.IsDBNull(3))
{
info.AppName = reader.GetString(3);
}
if (!reader.IsDBNull(4))
{
info.AppVersion = reader.GetString(4);
}
if (!reader.IsDBNull(5))
{
info.DeviceName = reader.GetString(5);
}
if (!reader.IsDBNull(6))
{
info.UserId = reader.GetString(6);
}
info.IsActive = reader.GetBoolean(7);
info.DateCreated = reader.GetDateTime(8).ToUniversalTime();
if (!reader.IsDBNull(9))
{
info.DateRevoked = reader.GetDateTime(9).ToUniversalTime();
}
return info;
}
}
}

View File

@ -1,158 +0,0 @@
using System;
using System.Data;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Emby.Server.Core.Data;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Social;
namespace Emby.Server.Core.Social
{
public class SharingRepository : BaseSqliteRepository, ISharingRepository
{
public SharingRepository(ILogManager logManager, IApplicationPaths appPaths, IDbConnector dbConnector)
: base(logManager, dbConnector)
{
DbFilePath = Path.Combine(appPaths.DataPath, "shares.db");
}
/// <summary>
/// Opens the connection to the database
/// </summary>
/// <returns>Task.</returns>
public async Task Initialize()
{
using (var connection = await CreateConnection().ConfigureAwait(false))
{
string[] queries = {
"create table if not exists Shares (Id GUID, ItemId TEXT, UserId TEXT, ExpirationDate DateTime, PRIMARY KEY (Id))",
"create index if not exists idx_Shares on Shares(Id)",
"pragma shrink_memory"
};
connection.RunQueries(queries, Logger);
}
}
public async Task CreateShare(SocialShareInfo info)
{
if (info == null)
{
throw new ArgumentNullException("info");
}
if (string.IsNullOrWhiteSpace(info.Id))
{
throw new ArgumentNullException("info.Id");
}
var cancellationToken = CancellationToken.None;
cancellationToken.ThrowIfCancellationRequested();
using (var connection = await CreateConnection().ConfigureAwait(false))
{
using (var saveShareCommand = connection.CreateCommand())
{
saveShareCommand.CommandText = "replace into Shares (Id, ItemId, UserId, ExpirationDate) values (@Id, @ItemId, @UserId, @ExpirationDate)";
saveShareCommand.Parameters.Add(saveShareCommand, "@Id");
saveShareCommand.Parameters.Add(saveShareCommand, "@ItemId");
saveShareCommand.Parameters.Add(saveShareCommand, "@UserId");
saveShareCommand.Parameters.Add(saveShareCommand, "@ExpirationDate");
IDbTransaction transaction = null;
try
{
transaction = connection.BeginTransaction();
saveShareCommand.GetParameter(0).Value = new Guid(info.Id);
saveShareCommand.GetParameter(1).Value = info.ItemId;
saveShareCommand.GetParameter(2).Value = info.UserId;
saveShareCommand.GetParameter(3).Value = info.ExpirationDate;
saveShareCommand.Transaction = transaction;
saveShareCommand.ExecuteNonQuery();
transaction.Commit();
}
catch (OperationCanceledException)
{
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
catch (Exception e)
{
Logger.ErrorException("Failed to save share:", e);
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
finally
{
if (transaction != null)
{
transaction.Dispose();
}
}
}
}
}
public SocialShareInfo GetShareInfo(string id)
{
if (string.IsNullOrWhiteSpace(id))
{
throw new ArgumentNullException("id");
}
using (var connection = CreateConnection(true).Result)
{
var cmd = connection.CreateCommand();
cmd.CommandText = "select Id, ItemId, UserId, ExpirationDate from Shares where id = @id";
cmd.Parameters.Add(cmd, "@id", DbType.Guid).Value = new Guid(id);
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow))
{
if (reader.Read())
{
return GetSocialShareInfo(reader);
}
}
return null;
}
}
private SocialShareInfo GetSocialShareInfo(IDataReader reader)
{
var info = new SocialShareInfo();
info.Id = reader.GetGuid(0).ToString("N");
info.ItemId = reader.GetString(1);
info.UserId = reader.GetString(2);
info.ExpirationDate = reader.GetDateTime(3).ToUniversalTime();
return info;
}
public async Task DeleteShare(string id)
{
}
}
}

View File

@ -0,0 +1,197 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Emby.Server.Implementations.Data;
using MediaBrowser.Controller;
using MediaBrowser.Model.Activity;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Querying;
using SQLitePCL.pretty;
namespace Emby.Server.Implementations.Activity
{
public class ActivityRepository : BaseSqliteRepository, IActivityRepository
{
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
public ActivityRepository(ILogger logger, IServerApplicationPaths appPaths)
: base(logger)
{
DbFilePath = Path.Combine(appPaths.DataPath, "activitylog.db");
}
public void Initialize()
{
using (var connection = CreateConnection())
{
string[] queries = {
"create table if not exists ActivityLogEntries (Id GUID PRIMARY KEY, Name TEXT, Overview TEXT, ShortOverview TEXT, Type TEXT, ItemId TEXT, UserId TEXT, DateCreated DATETIME, LogSeverity TEXT)",
"create index if not exists idx_ActivityLogEntries on ActivityLogEntries(Id)"
};
connection.RunQueries(queries);
}
}
private const string BaseActivitySelectText = "select Id, Name, Overview, ShortOverview, Type, ItemId, UserId, DateCreated, LogSeverity from ActivityLogEntries";
public Task Create(ActivityLogEntry entry)
{
return Update(entry);
}
public async Task Update(ActivityLogEntry entry)
{
if (entry == null)
{
throw new ArgumentNullException("entry");
}
lock (WriteLock)
{
using (var connection = CreateConnection())
{
connection.RunInTransaction(db =>
{
var commandText = "replace into ActivityLogEntries (Id, Name, Overview, ShortOverview, Type, ItemId, UserId, DateCreated, LogSeverity) values (?, ?, ?, ?, ?, ?, ?, ?, ?)";
db.Execute(commandText,
entry.Id.ToGuidParamValue(),
entry.Name,
entry.Overview,
entry.ShortOverview,
entry.Type,
entry.ItemId,
entry.UserId,
entry.Date.ToDateTimeParamValue(),
entry.Severity.ToString());
});
}
}
}
public QueryResult<ActivityLogEntry> GetActivityLogEntries(DateTime? minDate, int? startIndex, int? limit)
{
lock (WriteLock)
{
using (var connection = CreateConnection(true))
{
var commandText = BaseActivitySelectText;
var whereClauses = new List<string>();
var paramList = new List<object>();
if (minDate.HasValue)
{
whereClauses.Add("DateCreated>=@DateCreated");
paramList.Add(minDate.Value.ToDateTimeParamValue());
}
var whereTextWithoutPaging = whereClauses.Count == 0 ?
string.Empty :
" where " + string.Join(" AND ", whereClauses.ToArray());
if (startIndex.HasValue && startIndex.Value > 0)
{
var pagingWhereText = whereClauses.Count == 0 ?
string.Empty :
" where " + string.Join(" AND ", whereClauses.ToArray());
whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM ActivityLogEntries {0} ORDER BY DateCreated DESC LIMIT {1})",
pagingWhereText,
startIndex.Value.ToString(_usCulture)));
}
var whereText = whereClauses.Count == 0 ?
string.Empty :
" where " + string.Join(" AND ", whereClauses.ToArray());
commandText += whereText;
commandText += " ORDER BY DateCreated DESC";
if (limit.HasValue)
{
commandText += " LIMIT " + limit.Value.ToString(_usCulture);
}
var totalRecordCount = connection.Query("select count (Id) from ActivityLogEntries" + whereTextWithoutPaging, paramList.ToArray()).SelectScalarInt().First();
var list = new List<ActivityLogEntry>();
foreach (var row in connection.Query(commandText, paramList.ToArray()))
{
list.Add(GetEntry(row));
}
return new QueryResult<ActivityLogEntry>()
{
Items = list.ToArray(),
TotalRecordCount = totalRecordCount
};
}
}
}
private ActivityLogEntry GetEntry(IReadOnlyList<IResultSetValue> reader)
{
var index = 0;
var info = new ActivityLogEntry
{
Id = reader[index].ReadGuid().ToString("N")
};
index++;
if (reader[index].SQLiteType != SQLiteType.Null)
{
info.Name = reader[index].ToString();
}
index++;
if (reader[index].SQLiteType != SQLiteType.Null)
{
info.Overview = reader[index].ToString();
}
index++;
if (reader[index].SQLiteType != SQLiteType.Null)
{
info.ShortOverview = reader[index].ToString();
}
index++;
if (reader[index].SQLiteType != SQLiteType.Null)
{
info.Type = reader[index].ToString();
}
index++;
if (reader[index].SQLiteType != SQLiteType.Null)
{
info.ItemId = reader[index].ToString();
}
index++;
if (reader[index].SQLiteType != SQLiteType.Null)
{
info.UserId = reader[index].ToString();
}
index++;
info.Date = reader[index].ReadDateTime();
index++;
if (reader[index].SQLiteType != SQLiteType.Null)
{
info.Severity = (LogSeverity)Enum.Parse(typeof(LogSeverity), reader[index].ToString(), true);
}
return info;
}
}
}

View File

@ -0,0 +1,145 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Model.Logging;
using SQLitePCL.pretty;
namespace Emby.Server.Implementations.Data
{
public abstract class BaseSqliteRepository : IDisposable
{
protected string DbFilePath { get; set; }
protected SemaphoreSlim WriteLock = new SemaphoreSlim(1, 1);
protected ILogger Logger { get; private set; }
protected BaseSqliteRepository(ILogger logger)
{
Logger = logger;
}
protected virtual bool EnableConnectionPooling
{
get { return true; }
}
protected virtual SQLiteDatabaseConnection CreateConnection(bool isReadOnly = false)
{
SQLite3.EnableSharedCache = false;
ConnectionFlags connectionFlags;
if (isReadOnly)
{
connectionFlags = ConnectionFlags.ReadOnly;
//connectionFlags = ConnectionFlags.Create;
//connectionFlags |= ConnectionFlags.ReadWrite;
}
else
{
connectionFlags = ConnectionFlags.Create;
connectionFlags |= ConnectionFlags.ReadWrite;
}
if (EnableConnectionPooling)
{
connectionFlags |= ConnectionFlags.SharedCached;
}
else
{
connectionFlags |= ConnectionFlags.PrivateCache;
}
connectionFlags |= ConnectionFlags.NoMutex;
var db = SQLite3.Open(DbFilePath, connectionFlags, null);
var queries = new[]
{
"PRAGMA page_size=4096",
"PRAGMA journal_mode=WAL",
"PRAGMA temp_store=memory",
"PRAGMA synchronous=Normal",
//"PRAGMA cache size=-10000"
};
//foreach (var query in queries)
//{
// db.Execute(query);
//}
db.ExecuteAll(string.Join(";", queries));
return db;
}
private bool _disposed;
protected void CheckDisposed()
{
if (_disposed)
{
throw new ObjectDisposedException(GetType().Name + " has been disposed and cannot be accessed.");
}
}
public void Dispose()
{
_disposed = true;
Dispose(true);
GC.SuppressFinalize(this);
}
private readonly object _disposeLock = new object();
/// <summary>
/// Releases unmanaged and - optionally - managed resources.
/// </summary>
/// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
protected virtual void Dispose(bool dispose)
{
if (dispose)
{
try
{
lock (_disposeLock)
{
WriteLock.Wait();
CloseConnection();
}
}
catch (Exception ex)
{
Logger.ErrorException("Error disposing database", ex);
}
}
}
protected virtual void CloseConnection()
{
}
protected void AddColumn(IDatabaseConnection connection, string table, string columnName, string type)
{
foreach (var row in connection.Query("PRAGMA table_info(" + table + ")"))
{
if (row[1].SQLiteType != SQLiteType.Null)
{
var name = row[1].ToString();
if (string.Equals(name, columnName, StringComparison.OrdinalIgnoreCase))
{
return;
}
}
}
connection.ExecuteAll(string.Join(";", new string[]
{
"alter table " + table,
"add column " + columnName + " " + type + " NULL"
}));
}
}
}

View File

@ -22,7 +22,7 @@ using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.Tasks;
using Emby.Server.Implementations.ScheduledTasks;
namespace Emby.Server.Implementations.Persistence
namespace Emby.Server.Implementations.Data
{
public class CleanDatabaseScheduledTask : IScheduledTask
{

View File

@ -0,0 +1,228 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
using SQLitePCL.pretty;
namespace Emby.Server.Implementations.Data
{
/// <summary>
/// Class SQLiteDisplayPreferencesRepository
/// </summary>
public class SqliteDisplayPreferencesRepository : BaseSqliteRepository, IDisplayPreferencesRepository
{
private readonly IMemoryStreamFactory _memoryStreamProvider;
public SqliteDisplayPreferencesRepository(ILogger logger, IJsonSerializer jsonSerializer, IApplicationPaths appPaths, IMemoryStreamFactory memoryStreamProvider)
: base(logger)
{
_jsonSerializer = jsonSerializer;
_memoryStreamProvider = memoryStreamProvider;
DbFilePath = Path.Combine(appPaths.DataPath, "displaypreferences.db");
}
/// <summary>
/// Gets the name of the repository
/// </summary>
/// <value>The name.</value>
public string Name
{
get
{
return "SQLite";
}
}
/// <summary>
/// The _json serializer
/// </summary>
private readonly IJsonSerializer _jsonSerializer;
/// <summary>
/// Opens the connection to the database
/// </summary>
/// <returns>Task.</returns>
public void Initialize()
{
using (var connection = CreateConnection())
{
string[] queries = {
"create table if not exists userdisplaypreferences (id GUID, userId GUID, client text, data BLOB)",
"create unique index if not exists userdisplaypreferencesindex on userdisplaypreferences (id, userId, client)"
};
connection.RunQueries(queries);
}
}
/// <summary>
/// Save the display preferences associated with an item in the repo
/// </summary>
/// <param name="displayPreferences">The display preferences.</param>
/// <param name="userId">The user id.</param>
/// <param name="client">The client.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
/// <exception cref="System.ArgumentNullException">item</exception>
public async Task SaveDisplayPreferences(DisplayPreferences displayPreferences, Guid userId, string client, CancellationToken cancellationToken)
{
if (displayPreferences == null)
{
throw new ArgumentNullException("displayPreferences");
}
if (string.IsNullOrWhiteSpace(displayPreferences.Id))
{
throw new ArgumentNullException("displayPreferences.Id");
}
cancellationToken.ThrowIfCancellationRequested();
lock (WriteLock)
{
using (var connection = CreateConnection())
{
connection.RunInTransaction(db =>
{
SaveDisplayPreferences(displayPreferences, userId, client, db);
});
}
}
}
private void SaveDisplayPreferences(DisplayPreferences displayPreferences, Guid userId, string client, IDatabaseConnection connection)
{
var commandText = "replace into userdisplaypreferences (id, userid, client, data) values (?, ?, ?, ?)";
var serialized = _jsonSerializer.SerializeToBytes(displayPreferences, _memoryStreamProvider);
connection.Execute(commandText,
displayPreferences.Id.ToGuidParamValue(),
userId.ToGuidParamValue(),
client,
serialized);
}
/// <summary>
/// Save all display preferences associated with a user in the repo
/// </summary>
/// <param name="displayPreferences">The display preferences.</param>
/// <param name="userId">The user id.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
/// <exception cref="System.ArgumentNullException">item</exception>
public async Task SaveAllDisplayPreferences(IEnumerable<DisplayPreferences> displayPreferences, Guid userId, CancellationToken cancellationToken)
{
if (displayPreferences == null)
{
throw new ArgumentNullException("displayPreferences");
}
cancellationToken.ThrowIfCancellationRequested();
lock (WriteLock)
{
using (var connection = CreateConnection())
{
connection.RunInTransaction(db =>
{
foreach (var displayPreference in displayPreferences)
{
SaveDisplayPreferences(displayPreference, userId, displayPreference.Client, db);
}
});
}
}
}
/// <summary>
/// Gets the display preferences.
/// </summary>
/// <param name="displayPreferencesId">The display preferences id.</param>
/// <param name="userId">The user id.</param>
/// <param name="client">The client.</param>
/// <returns>Task{DisplayPreferences}.</returns>
/// <exception cref="System.ArgumentNullException">item</exception>
public DisplayPreferences GetDisplayPreferences(string displayPreferencesId, Guid userId, string client)
{
if (string.IsNullOrWhiteSpace(displayPreferencesId))
{
throw new ArgumentNullException("displayPreferencesId");
}
var guidId = displayPreferencesId.GetMD5();
using (var connection = CreateConnection(true))
{
var commandText = "select data from userdisplaypreferences where id = ? and userId=? and client=?";
var paramList = new List<object>();
paramList.Add(guidId.ToGuidParamValue());
paramList.Add(userId.ToGuidParamValue());
paramList.Add(client);
foreach (var row in connection.Query(commandText, paramList.ToArray()))
{
return Get(row);
}
return new DisplayPreferences
{
Id = guidId.ToString("N")
};
}
}
/// <summary>
/// Gets all display preferences for the given user.
/// </summary>
/// <param name="userId">The user id.</param>
/// <returns>Task{DisplayPreferences}.</returns>
/// <exception cref="System.ArgumentNullException">item</exception>
public IEnumerable<DisplayPreferences> GetAllDisplayPreferences(Guid userId)
{
var list = new List<DisplayPreferences>();
using (var connection = CreateConnection(true))
{
var commandText = "select data from userdisplaypreferences where userId=?";
var paramList = new List<object>();
paramList.Add(userId.ToGuidParamValue());
foreach (var row in connection.Query(commandText, paramList.ToArray()))
{
list.Add(Get(row));
}
}
return list;
}
private DisplayPreferences Get(IReadOnlyList<IResultSetValue> row)
{
using (var stream = _memoryStreamProvider.CreateNew(row[0].ToBlob()))
{
stream.Position = 0;
return _jsonSerializer.DeserializeFromStream<DisplayPreferences>(stream);
}
}
public Task SaveDisplayPreferences(DisplayPreferences displayPreferences, string userId, string client, CancellationToken cancellationToken)
{
return SaveDisplayPreferences(displayPreferences, new Guid(userId), client, cancellationToken);
}
public DisplayPreferences GetDisplayPreferences(string displayPreferencesId, string userId, string client)
{
return GetDisplayPreferences(displayPreferencesId, new Guid(userId), client);
}
}
}

View File

@ -0,0 +1,131 @@
using System;
using System.Globalization;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Serialization;
using SQLitePCL.pretty;
namespace Emby.Server.Implementations.Data
{
public static class SqliteExtensions
{
public static void RunQueries(this SQLiteDatabaseConnection connection, string[] queries)
{
if (queries == null)
{
throw new ArgumentNullException("queries");
}
connection.RunInTransaction(conn =>
{
//foreach (var query in queries)
//{
// conn.Execute(query);
//}
conn.ExecuteAll(string.Join(";", queries));
});
}
public static byte[] ToGuidParamValue(this string str)
{
return ToGuidParamValue(new Guid(str));
}
public static byte[] ToGuidParamValue(this Guid guid)
{
return guid.ToByteArray();
}
public static Guid ReadGuid(this IResultSetValue result)
{
return new Guid(result.ToBlob());
}
public static string ToDateTimeParamValue(this DateTime dateValue)
{
var kind = DateTimeKind.Utc;
return (dateValue.Kind == DateTimeKind.Unspecified)
? DateTime.SpecifyKind(dateValue, kind).ToString(
GetDateTimeKindFormat(kind),
CultureInfo.InvariantCulture)
: dateValue.ToString(
GetDateTimeKindFormat(dateValue.Kind),
CultureInfo.InvariantCulture);
}
private static string GetDateTimeKindFormat(
DateTimeKind kind)
{
return (kind == DateTimeKind.Utc) ? _datetimeFormatUtc : _datetimeFormatLocal;
}
/// <summary>
/// An array of ISO-8601 DateTime formats that we support parsing.
/// </summary>
private static string[] _datetimeFormats = new string[] {
"THHmmssK",
"THHmmK",
"HH:mm:ss.FFFFFFFK",
"HH:mm:ssK",
"HH:mmK",
"yyyy-MM-dd HH:mm:ss.FFFFFFFK", /* NOTE: UTC default (5). */
"yyyy-MM-dd HH:mm:ssK",
"yyyy-MM-dd HH:mmK",
"yyyy-MM-ddTHH:mm:ss.FFFFFFFK",
"yyyy-MM-ddTHH:mmK",
"yyyy-MM-ddTHH:mm:ssK",
"yyyyMMddHHmmssK",
"yyyyMMddHHmmK",
"yyyyMMddTHHmmssFFFFFFFK",
"THHmmss",
"THHmm",
"HH:mm:ss.FFFFFFF",
"HH:mm:ss",
"HH:mm",
"yyyy-MM-dd HH:mm:ss.FFFFFFF", /* NOTE: Non-UTC default (19). */
"yyyy-MM-dd HH:mm:ss",
"yyyy-MM-dd HH:mm",
"yyyy-MM-ddTHH:mm:ss.FFFFFFF",
"yyyy-MM-ddTHH:mm",
"yyyy-MM-ddTHH:mm:ss",
"yyyyMMddHHmmss",
"yyyyMMddHHmm",
"yyyyMMddTHHmmssFFFFFFF",
"yyyy-MM-dd",
"yyyyMMdd",
"yy-MM-dd"
};
private static string _datetimeFormatUtc = _datetimeFormats[5];
private static string _datetimeFormatLocal = _datetimeFormats[19];
public static DateTime ReadDateTime(this IResultSetValue result)
{
var dateText = result.ToString();
return DateTime.ParseExact(
dateText, _datetimeFormats,
DateTimeFormatInfo.InvariantInfo,
DateTimeStyles.None).ToUniversalTime();
}
/// <summary>
/// Serializes to bytes.
/// </summary>
/// <returns>System.Byte[][].</returns>
/// <exception cref="System.ArgumentNullException">obj</exception>
public static byte[] SerializeToBytes(this IJsonSerializer json, object obj, IMemoryStreamFactory streamProvider)
{
if (obj == null)
{
throw new ArgumentNullException("obj");
}
using (var stream = streamProvider.CreateNew())
{
json.SerializeToStream(obj, stream);
return stream.ToArray();
}
}
}
}

View File

@ -12,7 +12,7 @@ using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Session;
namespace Emby.Server.Core.Devices
namespace Emby.Server.Implementations.Devices
{
public class DeviceRepository : IDeviceRepository
{
@ -147,7 +147,7 @@ namespace Emby.Server.Core.Devices
{
_fileSystem.DeleteDirectory(path, true);
}
catch (DirectoryNotFoundException)
catch (IOException)
{
}

View File

@ -34,6 +34,7 @@
<ItemGroup>
<Compile Include="Activity\ActivityLogEntryPoint.cs" />
<Compile Include="Activity\ActivityManager.cs" />
<Compile Include="Activity\ActivityRepository.cs" />
<Compile Include="Branding\BrandingConfigurationFactory.cs" />
<Compile Include="Channels\ChannelConfigurations.cs" />
<Compile Include="Channels\ChannelDynamicMediaSourceProvider.cs" />
@ -49,8 +50,10 @@
<Compile Include="Connect\ConnectManager.cs" />
<Compile Include="Connect\Responses.cs" />
<Compile Include="Connect\Validator.cs" />
<Compile Include="Data\SqliteDisplayPreferencesRepository.cs" />
<Compile Include="Devices\CameraUploadsDynamicFolder.cs" />
<Compile Include="Devices\DeviceManager.cs" />
<Compile Include="Devices\DeviceRepository.cs" />
<Compile Include="Dto\DtoService.cs" />
<Compile Include="EntryPoints\AutomaticRestartEntryPoint.cs" />
<Compile Include="EntryPoints\KeepServerAwake.cs" />
@ -165,6 +168,7 @@
<Compile Include="LiveTv\TunerHosts\QueueStream.cs" />
<Compile Include="Localization\LocalizationManager.cs" />
<Compile Include="MediaEncoder\EncodingManager.cs" />
<Compile Include="Migrations\IVersionMigration.cs" />
<Compile Include="News\NewsEntryPoint.cs" />
<Compile Include="News\NewsService.cs" />
<Compile Include="Notifications\CoreNotificationTypes.cs" />
@ -173,8 +177,11 @@
<Compile Include="Notifications\NotificationConfigurationFactory.cs" />
<Compile Include="Notifications\NotificationManager.cs" />
<Compile Include="Notifications\Notifications.cs" />
<Compile Include="Notifications\SqliteNotificationsRepository.cs" />
<Compile Include="Notifications\WebSocketNotifier.cs" />
<Compile Include="Persistence\CleanDatabaseScheduledTask.cs" />
<Compile Include="Data\BaseSqliteRepository.cs" />
<Compile Include="Data\CleanDatabaseScheduledTask.cs" />
<Compile Include="Data\SqliteExtensions.cs" />
<Compile Include="Photos\PhotoAlbumImageProvider.cs" />
<Compile Include="Playlists\PlaylistImageProvider.cs" />
<Compile Include="Playlists\PlaylistManager.cs" />
@ -186,6 +193,7 @@
<Compile Include="ScheduledTasks\RefreshIntrosTask.cs" />
<Compile Include="ScheduledTasks\RefreshMediaLibraryTask.cs" />
<Compile Include="ScheduledTasks\SystemUpdateTask.cs" />
<Compile Include="Security\AuthenticationRepository.cs" />
<Compile Include="Security\EncryptionManager.cs" />
<Compile Include="Security\MBLicenseFile.cs" />
<Compile Include="Security\PluginSecurityManager.cs" />
@ -197,6 +205,7 @@
<Compile Include="Session\SessionWebSocketListener.cs" />
<Compile Include="Session\WebSocketController.cs" />
<Compile Include="Social\SharingManager.cs" />
<Compile Include="Social\SharingRepository.cs" />
<Compile Include="Sorting\AiredEpisodeOrderComparer.cs" />
<Compile Include="Sorting\AirTimeComparer.cs" />
<Compile Include="Sorting\AlbumArtistComparer.cs" />
@ -291,6 +300,14 @@
<HintPath>..\packages\MediaBrowser.Naming.1.0.2\lib\portable-net45+win8\MediaBrowser.Naming.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="SQLitePCL.pretty, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\SQLitePCL.pretty.1.1.0\lib\portable-net45+netcore45+wpa81+wp8\SQLitePCL.pretty.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="SQLitePCLRaw.core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1488e028ca7ab535, processorArchitecture=MSIL">
<HintPath>..\packages\SQLitePCLRaw.core.1.1.0\lib\portable-net45+netcore45+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SQLitePCLRaw.core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="UniversalDetector, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\UniversalDetector.1.0.1\lib\portable-net45+sl4+wp71+win8+wpa81\UniversalDetector.dll</HintPath>
<Private>True</Private>

View File

@ -127,7 +127,11 @@ namespace Emby.Server.Implementations.Library.Validators
{
var item = _libraryManager.GetPerson(person.Key);
var options = new MetadataRefreshOptions(_fileSystem);
var options = new MetadataRefreshOptions(_fileSystem)
{
ImageRefreshMode = ImageRefreshMode.ValidationOnly,
MetadataRefreshMode = MetadataRefreshMode.ValidationOnly
};
await item.RefreshMetadata(options, cancellationToken).ConfigureAwait(false);
}

View File

@ -13,6 +13,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Entities.TV;
namespace Emby.Server.Implementations.LiveTv
{
@ -130,6 +131,38 @@ namespace Emby.Server.Implementations.LiveTv
dto.DayPattern = info.Days == null ? null : GetDayPattern(info.Days);
FillImages(dto, info);
return dto;
}
private void FillImages(SeriesTimerInfoDto dto, SeriesTimerInfo info)
{
var librarySeries = _libraryManager.GetItemList(new InternalItemsQuery
{
IncludeItemTypes = new string[] { typeof(Series).Name },
Name = info.Name,
Limit = 1,
ImageTypes = new ImageType[] { ImageType.Thumb }
}).FirstOrDefault();
if (librarySeries != null)
{
var image = librarySeries.GetImageInfo(ImageType.Thumb, 0);
if (image != null)
{
try
{
dto.ParentThumbImageTag = _imageProcessor.GetImageCacheTag(librarySeries, image);
dto.ParentThumbItemId = librarySeries.Id.ToString("N");
}
catch (Exception ex)
{
}
}
}
if (!string.IsNullOrWhiteSpace(info.SeriesId))
{
var program = _libraryManager.GetItemList(new InternalItemsQuery
@ -157,8 +190,6 @@ namespace Emby.Server.Implementations.LiveTv
}
}
}
return dto;
}
public DayPattern? GetDayPattern(List<DayOfWeek> days)

View File

@ -1,6 +1,6 @@
using System.Threading.Tasks;
namespace Emby.Server.Core.Migrations
namespace Emby.Server.Implementations.Migrations
{
public interface IVersionMigration
{

View File

@ -0,0 +1,309 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Emby.Server.Implementations.Data;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Notifications;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Notifications;
using SQLitePCL.pretty;
namespace Emby.Server.Implementations.Notifications
{
public class SqliteNotificationsRepository : BaseSqliteRepository, INotificationsRepository
{
public SqliteNotificationsRepository(ILogger logger, IServerApplicationPaths appPaths) : base(logger)
{
DbFilePath = Path.Combine(appPaths.DataPath, "notifications.db");
}
public event EventHandler<NotificationUpdateEventArgs> NotificationAdded;
public event EventHandler<NotificationReadEventArgs> NotificationsMarkedRead;
////public event EventHandler<NotificationUpdateEventArgs> NotificationUpdated;
public void Initialize()
{
using (var connection = CreateConnection())
{
string[] queries = {
"create table if not exists Notifications (Id GUID NOT NULL, UserId GUID NOT NULL, Date DATETIME NOT NULL, Name TEXT NOT NULL, Description TEXT NULL, Url TEXT NULL, Level TEXT NOT NULL, IsRead BOOLEAN NOT NULL, Category TEXT NOT NULL, RelatedId TEXT NULL, PRIMARY KEY (Id, UserId))",
"create index if not exists idx_Notifications1 on Notifications(Id)",
"create index if not exists idx_Notifications2 on Notifications(UserId)"
};
connection.RunQueries(queries);
}
}
/// <summary>
/// Gets the notifications.
/// </summary>
/// <param name="query">The query.</param>
/// <returns>NotificationResult.</returns>
public NotificationResult GetNotifications(NotificationQuery query)
{
var result = new NotificationResult();
lock (WriteLock)
{
using (var connection = CreateConnection(true))
{
var clauses = new List<string>();
var paramList = new List<object>();
if (query.IsRead.HasValue)
{
clauses.Add("IsRead=?");
paramList.Add(query.IsRead.Value);
}
clauses.Add("UserId=?");
paramList.Add(query.UserId.ToGuidParamValue());
var whereClause = " where " + string.Join(" And ", clauses.ToArray());
result.TotalRecordCount = connection.Query("select count(Id) from Notifications" + whereClause, paramList.ToArray()).SelectScalarInt().First();
var commandText = string.Format("select Id,UserId,Date,Name,Description,Url,Level,IsRead,Category,RelatedId from Notifications{0} order by IsRead asc, Date desc", whereClause);
if (query.Limit.HasValue || query.StartIndex.HasValue)
{
var offset = query.StartIndex ?? 0;
if (query.Limit.HasValue || offset > 0)
{
commandText += " LIMIT " + (query.Limit ?? int.MaxValue).ToString(CultureInfo.InvariantCulture);
}
if (offset > 0)
{
commandText += " OFFSET " + offset.ToString(CultureInfo.InvariantCulture);
}
}
var resultList = new List<Notification>();
foreach (var row in connection.Query(commandText, paramList.ToArray()))
{
resultList.Add(GetNotification(row));
}
result.Notifications = resultList.ToArray();
}
}
return result;
}
public NotificationsSummary GetNotificationsSummary(string userId)
{
var result = new NotificationsSummary();
lock (WriteLock)
{
using (var connection = CreateConnection(true))
{
foreach (var row in connection.Query("select Level from Notifications where UserId=? and IsRead=?", userId.ToGuidParamValue(), false))
{
var levels = new List<NotificationLevel>();
levels.Add(GetLevel(row, 0));
result.UnreadCount = levels.Count;
if (levels.Count > 0)
{
result.MaxUnreadNotificationLevel = levels.Max();
}
}
return result;
}
}
}
private Notification GetNotification(IReadOnlyList<IResultSetValue> reader)
{
var notification = new Notification
{
Id = reader[0].ReadGuid().ToString("N"),
UserId = reader[1].ReadGuid().ToString("N"),
Date = reader[2].ReadDateTime(),
Name = reader[3].ToString()
};
if (reader[4].SQLiteType != SQLiteType.Null)
{
notification.Description = reader[4].ToString();
}
if (reader[5].SQLiteType != SQLiteType.Null)
{
notification.Url = reader[5].ToString();
}
notification.Level = GetLevel(reader, 6);
notification.IsRead = reader[7].ToBool();
return notification;
}
/// <summary>
/// Gets the level.
/// </summary>
/// <param name="reader">The reader.</param>
/// <param name="index">The index.</param>
/// <returns>NotificationLevel.</returns>
private NotificationLevel GetLevel(IReadOnlyList<IResultSetValue> reader, int index)
{
NotificationLevel level;
var val = reader[index].ToString();
Enum.TryParse(val, true, out level);
return level;
}
/// <summary>
/// Adds the notification.
/// </summary>
/// <param name="notification">The notification.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
public async Task AddNotification(Notification notification, CancellationToken cancellationToken)
{
await ReplaceNotification(notification, cancellationToken).ConfigureAwait(false);
if (NotificationAdded != null)
{
try
{
NotificationAdded(this, new NotificationUpdateEventArgs
{
Notification = notification
});
}
catch (Exception ex)
{
Logger.ErrorException("Error in NotificationAdded event handler", ex);
}
}
}
/// <summary>
/// Replaces the notification.
/// </summary>
/// <param name="notification">The notification.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
private async Task ReplaceNotification(Notification notification, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(notification.Id))
{
notification.Id = Guid.NewGuid().ToString("N");
}
if (string.IsNullOrEmpty(notification.UserId))
{
throw new ArgumentException("The notification must have a user id");
}
cancellationToken.ThrowIfCancellationRequested();
lock (WriteLock)
{
using (var connection = CreateConnection())
{
connection.RunInTransaction(conn =>
{
conn.Execute("replace into Notifications (Id, UserId, Date, Name, Description, Url, Level, IsRead, Category, RelatedId) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
notification.Id.ToGuidParamValue(),
notification.UserId.ToGuidParamValue(),
notification.Date.ToDateTimeParamValue(),
notification.Name,
notification.Description,
notification.Url,
notification.Level.ToString(),
notification.IsRead,
string.Empty,
string.Empty);
});
}
}
}
/// <summary>
/// Marks the read.
/// </summary>
/// <param name="notificationIdList">The notification id list.</param>
/// <param name="userId">The user id.</param>
/// <param name="isRead">if set to <c>true</c> [is read].</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
public async Task MarkRead(IEnumerable<string> notificationIdList, string userId, bool isRead, CancellationToken cancellationToken)
{
var list = notificationIdList.ToList();
var idArray = list.Select(i => new Guid(i)).ToArray();
await MarkReadInternal(idArray, userId, isRead, cancellationToken).ConfigureAwait(false);
if (NotificationsMarkedRead != null)
{
try
{
NotificationsMarkedRead(this, new NotificationReadEventArgs
{
IdList = list.ToArray(),
IsRead = isRead,
UserId = userId
});
}
catch (Exception ex)
{
Logger.ErrorException("Error in NotificationsMarkedRead event handler", ex);
}
}
}
public async Task MarkAllRead(string userId, bool isRead, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
lock (WriteLock)
{
using (var connection = CreateConnection())
{
connection.RunInTransaction(conn =>
{
conn.Execute("update Notifications set IsRead=? where UserId=?", userId.ToGuidParamValue(), isRead);
});
}
}
}
private async Task MarkReadInternal(IEnumerable<Guid> notificationIdList, string userId, bool isRead, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
lock (WriteLock)
{
using (var connection = CreateConnection())
{
connection.RunInTransaction(conn =>
{
var userIdParam = userId.ToGuidParamValue();
foreach (var id in notificationIdList)
{
conn.Execute("update Notifications set IsRead=? where UserId=? and Id=?", userIdParam, isRead, id);
}
});
}
}
}
}
}

View File

@ -0,0 +1,258 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Emby.Server.Implementations.Data;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Security;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Querying;
using SQLitePCL.pretty;
namespace Emby.Server.Implementations.Security
{
public class AuthenticationRepository : BaseSqliteRepository, IAuthenticationRepository
{
private readonly IServerApplicationPaths _appPaths;
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
public AuthenticationRepository(ILogger logger, IServerApplicationPaths appPaths)
: base(logger)
{
_appPaths = appPaths;
DbFilePath = Path.Combine(appPaths.DataPath, "authentication.db");
}
public void Initialize()
{
using (var connection = CreateConnection())
{
string[] queries = {
"create table if not exists AccessTokens (Id GUID PRIMARY KEY, AccessToken TEXT NOT NULL, DeviceId TEXT, AppName TEXT, AppVersion TEXT, DeviceName TEXT, UserId TEXT, IsActive BIT, DateCreated DATETIME NOT NULL, DateRevoked DATETIME)",
"create index if not exists idx_AccessTokens on AccessTokens(Id)"
};
connection.RunQueries(queries);
connection.RunInTransaction(db =>
{
AddColumn(db, "AccessTokens", "AppVersion", "TEXT");
});
}
}
public Task Create(AuthenticationInfo info, CancellationToken cancellationToken)
{
info.Id = Guid.NewGuid().ToString("N");
return Update(info, cancellationToken);
}
public async Task Update(AuthenticationInfo info, CancellationToken cancellationToken)
{
if (info == null)
{
throw new ArgumentNullException("info");
}
cancellationToken.ThrowIfCancellationRequested();
lock (WriteLock)
{
using (var connection = CreateConnection())
{
connection.RunInTransaction(db =>
{
var commandText = "replace into AccessTokens (Id, AccessToken, DeviceId, AppName, AppVersion, DeviceName, UserId, IsActive, DateCreated, DateRevoked) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
db.Execute(commandText,
info.Id.ToGuidParamValue(),
info.AccessToken,
info.DeviceId,
info.AppName,
info.AppVersion,
info.DeviceName,
info.UserId,
info.IsActive,
info.DateCreated.ToDateTimeParamValue(),
info.DateRevoked.HasValue ? info.DateRevoked.Value.ToDateTimeParamValue() : null);
});
}
}
}
private const string BaseSelectText = "select Id, AccessToken, DeviceId, AppName, AppVersion, DeviceName, UserId, IsActive, DateCreated, DateRevoked from AccessTokens";
public QueryResult<AuthenticationInfo> Get(AuthenticationInfoQuery query)
{
if (query == null)
{
throw new ArgumentNullException("query");
}
using (var connection = CreateConnection(true))
{
var commandText = BaseSelectText;
var paramList = new List<object>();
var whereClauses = new List<string>();
var startIndex = query.StartIndex ?? 0;
if (!string.IsNullOrWhiteSpace(query.AccessToken))
{
whereClauses.Add("AccessToken=?");
paramList.Add(query.AccessToken);
}
if (!string.IsNullOrWhiteSpace(query.UserId))
{
whereClauses.Add("UserId=?");
paramList.Add(query.UserId);
}
if (!string.IsNullOrWhiteSpace(query.DeviceId))
{
whereClauses.Add("DeviceId=?");
paramList.Add(query.DeviceId);
}
if (query.IsActive.HasValue)
{
whereClauses.Add("IsActive=?");
paramList.Add(query.IsActive.Value);
}
if (query.HasUser.HasValue)
{
if (query.HasUser.Value)
{
whereClauses.Add("UserId not null");
}
else
{
whereClauses.Add("UserId is null");
}
}
var whereTextWithoutPaging = whereClauses.Count == 0 ?
string.Empty :
" where " + string.Join(" AND ", whereClauses.ToArray());
if (startIndex > 0)
{
var pagingWhereText = whereClauses.Count == 0 ?
string.Empty :
" where " + string.Join(" AND ", whereClauses.ToArray());
whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM AccessTokens {0} ORDER BY DateCreated LIMIT {1})",
pagingWhereText,
startIndex.ToString(_usCulture)));
}
var whereText = whereClauses.Count == 0 ?
string.Empty :
" where " + string.Join(" AND ", whereClauses.ToArray());
commandText += whereText;
commandText += " ORDER BY DateCreated";
if (query.Limit.HasValue)
{
commandText += " LIMIT " + query.Limit.Value.ToString(_usCulture);
}
var list = new List<AuthenticationInfo>();
foreach (var row in connection.Query(commandText, paramList.ToArray()))
{
list.Add(Get(row));
}
var count = connection.Query("select count (Id) from AccessTokens" + whereTextWithoutPaging, paramList.ToArray())
.SelectScalarInt()
.First();
return new QueryResult<AuthenticationInfo>()
{
Items = list.ToArray(),
TotalRecordCount = count
};
}
}
public AuthenticationInfo Get(string id)
{
if (string.IsNullOrEmpty(id))
{
throw new ArgumentNullException("id");
}
lock (WriteLock)
{
using (var connection = CreateConnection(true))
{
var commandText = BaseSelectText + " where Id=?";
var paramList = new List<object>();
paramList.Add(id.ToGuidParamValue());
foreach (var row in connection.Query(commandText, paramList.ToArray()))
{
return Get(row);
}
return null;
}
}
}
private AuthenticationInfo Get(IReadOnlyList<IResultSetValue> reader)
{
var info = new AuthenticationInfo
{
Id = reader[0].ReadGuid().ToString("N"),
AccessToken = reader[1].ToString()
};
if (reader[2].SQLiteType != SQLiteType.Null)
{
info.DeviceId = reader[2].ToString();
}
if (reader[3].SQLiteType != SQLiteType.Null)
{
info.AppName = reader[3].ToString();
}
if (reader[4].SQLiteType != SQLiteType.Null)
{
info.AppVersion = reader[4].ToString();
}
if (reader[5].SQLiteType != SQLiteType.Null)
{
info.DeviceName = reader[5].ToString();
}
if (reader[6].SQLiteType != SQLiteType.Null)
{
info.UserId = reader[6].ToString();
}
info.IsActive = reader[7].ToBool();
info.DateCreated = reader[8].ReadDateTime();
if (reader[9].SQLiteType != SQLiteType.Null)
{
info.DateRevoked = reader[9].ReadDateTime();
}
return info;
}
}
}

View File

@ -0,0 +1,114 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Emby.Server.Implementations.Data;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Social;
using SQLitePCL.pretty;
namespace Emby.Server.Implementations.Social
{
public class SharingRepository : BaseSqliteRepository, ISharingRepository
{
public SharingRepository(ILogger logger, IApplicationPaths appPaths)
: base(logger)
{
DbFilePath = Path.Combine(appPaths.DataPath, "shares.db");
}
/// <summary>
/// Opens the connection to the database
/// </summary>
/// <returns>Task.</returns>
public void Initialize()
{
using (var connection = CreateConnection())
{
string[] queries = {
"create table if not exists Shares (Id GUID, ItemId TEXT, UserId TEXT, ExpirationDate DateTime, PRIMARY KEY (Id))",
"create index if not exists idx_Shares on Shares(Id)",
"pragma shrink_memory"
};
connection.RunQueries(queries);
}
}
public async Task CreateShare(SocialShareInfo info)
{
if (info == null)
{
throw new ArgumentNullException("info");
}
if (string.IsNullOrWhiteSpace(info.Id))
{
throw new ArgumentNullException("info.Id");
}
lock (WriteLock)
{
using (var connection = CreateConnection())
{
connection.RunInTransaction(db =>
{
var commandText = "replace into Shares (Id, ItemId, UserId, ExpirationDate) values (?, ?, ?, ?)";
db.Execute(commandText,
info.Id.ToGuidParamValue(),
info.ItemId,
info.UserId,
info.ExpirationDate.ToDateTimeParamValue());
});
}
}
}
public SocialShareInfo GetShareInfo(string id)
{
if (string.IsNullOrWhiteSpace(id))
{
throw new ArgumentNullException("id");
}
lock (WriteLock)
{
using (var connection = CreateConnection(true))
{
var commandText = "select Id, ItemId, UserId, ExpirationDate from Shares where id = ?";
var paramList = new List<object>();
paramList.Add(id.ToGuidParamValue());
foreach (var row in connection.Query(commandText, paramList.ToArray()))
{
return GetSocialShareInfo(row);
}
}
}
return null;
}
private SocialShareInfo GetSocialShareInfo(IReadOnlyList<IResultSetValue> reader)
{
var info = new SocialShareInfo();
info.Id = reader[0].ReadGuid().ToString("N");
info.ItemId = reader[1].ToString();
info.UserId = reader[2].ToString();
info.ExpirationDate = reader[3].ReadDateTime();
return info;
}
public async Task DeleteShare(string id)
{
}
}
}

View File

@ -2,5 +2,7 @@
<packages>
<package id="Emby.XmlTv" version="1.0.1" targetFramework="portable45-net45+win8" />
<package id="MediaBrowser.Naming" version="1.0.2" targetFramework="portable45-net45+win8" />
<package id="SQLitePCL.pretty" version="1.1.0" targetFramework="portable45-net45+win8" />
<package id="SQLitePCLRaw.core" version="1.1.0" targetFramework="portable45-net45+win8" />
<package id="UniversalDetector" version="1.0.1" targetFramework="portable45-net45+win8" />
</packages>

View File

@ -227,7 +227,8 @@ namespace MediaBrowser.Api
ImageRefreshMode = ImageRefreshMode.FullRefresh,
ReplaceAllMetadata = true,
ReplaceAllImages = request.ReplaceAllImages,
SearchResult = request
SearchResult = request,
ForceEnableInternetMetadata = true
}, CancellationToken.None);
Task.WaitAll(task);

View File

@ -264,9 +264,9 @@ namespace MediaBrowser.Controller.LiveTv
if (listings != null)
{
if (!string.IsNullOrWhiteSpace(listings.MoviePrefix))
if (!string.IsNullOrWhiteSpace(listings.MoviePrefix) && name.StartsWith(listings.MoviePrefix, StringComparison.OrdinalIgnoreCase))
{
name = name.Replace(listings.MoviePrefix, string.Empty, StringComparison.OrdinalIgnoreCase).Trim();
name = name.Substring(listings.MoviePrefix.Length).Trim();
}
}

View File

@ -12,6 +12,7 @@ namespace MediaBrowser.Controller.Providers
public List<ImageType> ReplaceImages { get; set; }
public bool IsAutomated { get; set; }
public bool ForceEnableInternetMetadata { get; set; }
public ImageRefreshOptions(IDirectoryService directoryService)
{

View File

@ -141,8 +141,14 @@ namespace MediaBrowser.MediaEncoding.Subtitles
.ConfigureAwait(false);
var inputFormat = subtitle.Item2;
var writer = TryGetWriter(outputFormat);
if (string.Equals(inputFormat, outputFormat, StringComparison.OrdinalIgnoreCase) && TryGetWriter(outputFormat) == null)
if (string.Equals(inputFormat, outputFormat, StringComparison.OrdinalIgnoreCase) && writer == null)
{
return subtitle.Item1;
}
if (writer == null)
{
return subtitle.Item1;
}

View File

@ -22,7 +22,7 @@ namespace MediaBrowser.Model.Logging
var messageText = new StringBuilder();
messageText.AppendLine(exception.Message);
messageText.AppendLine(exception.ToString());
messageText.AppendLine(exception.GetType().FullName);
@ -71,7 +71,7 @@ namespace MediaBrowser.Model.Logging
private static void AppendInnerException(StringBuilder messageText, Exception e)
{
messageText.AppendLine("InnerException: " + e.GetType().FullName);
messageText.AppendLine(e.Message);
messageText.AppendLine(e.ToString());
LogExceptionData(messageText, e);

View File

@ -272,17 +272,17 @@ namespace MediaBrowser.Providers.Manager
{
var options = GetMetadataOptions(item);
return GetMetadataProvidersInternal<T>(item, options, false, true);
return GetMetadataProvidersInternal<T>(item, options, false, false, true);
}
private IEnumerable<IMetadataProvider<T>> GetMetadataProvidersInternal<T>(IHasMetadata item, MetadataOptions options, bool includeDisabled, bool checkIsOwnedItem)
private IEnumerable<IMetadataProvider<T>> GetMetadataProvidersInternal<T>(IHasMetadata item, MetadataOptions options, bool includeDisabled, bool forceEnableInternetMetadata, bool checkIsOwnedItem)
where T : IHasMetadata
{
// Avoid implicitly captured closure
var currentOptions = options;
return _metadataProviders.OfType<IMetadataProvider<T>>()
.Where(i => CanRefresh(i, item, currentOptions, includeDisabled, checkIsOwnedItem))
.Where(i => CanRefresh(i, item, currentOptions, includeDisabled, forceEnableInternetMetadata, checkIsOwnedItem))
.OrderBy(i => GetConfiguredOrder(i, options))
.ThenBy(GetDefaultOrder);
}
@ -294,7 +294,7 @@ namespace MediaBrowser.Providers.Manager
return GetImageProviders(item, options, new ImageRefreshOptions(new DirectoryService(_logger, _fileSystem)), includeDisabled).OfType<IRemoteImageProvider>();
}
private bool CanRefresh(IMetadataProvider provider, IHasMetadata item, MetadataOptions options, bool includeDisabled, bool checkIsOwnedItem)
private bool CanRefresh(IMetadataProvider provider, IHasMetadata item, MetadataOptions options, bool includeDisabled, bool forceEnableInternetMetadata, bool checkIsOwnedItem)
{
if (!includeDisabled)
{
@ -306,7 +306,7 @@ namespace MediaBrowser.Providers.Manager
if (provider is IRemoteMetadataProvider)
{
if (!item.IsInternetMetadataEnabled())
if (!forceEnableInternetMetadata && !item.IsInternetMetadataEnabled())
{
return false;
}
@ -357,7 +357,7 @@ namespace MediaBrowser.Providers.Manager
if (provider is IRemoteImageProvider)
{
if (!item.IsInternetMetadataEnabled())
if (!refreshOptions.ForceEnableInternetMetadata && !item.IsInternetMetadataEnabled())
{
return false;
}
@ -501,7 +501,7 @@ namespace MediaBrowser.Providers.Manager
private void AddMetadataPlugins<T>(List<MetadataPlugin> list, T item, MetadataOptions options)
where T : IHasMetadata
{
var providers = GetMetadataProvidersInternal<T>(item, options, true, false).ToList();
var providers = GetMetadataProvidersInternal<T>(item, options, true, false, false).ToList();
// Locals
list.AddRange(providers.Where(i => (i is ILocalMetadataProvider)).Select(i => new MetadataPlugin
@ -715,7 +715,7 @@ namespace MediaBrowser.Providers.Manager
var options = GetMetadataOptions(dummy);
var providers = GetMetadataProvidersInternal<TItemType>(dummy, options, searchInfo.IncludeDisabledProviders, false)
var providers = GetMetadataProvidersInternal<TItemType>(dummy, options, searchInfo.IncludeDisabledProviders, false, false)
.OfType<IRemoteSearchProvider<TLookupType>>();
if (!string.IsNullOrEmpty(searchInfo.SearchProviderName))

View File

@ -983,6 +983,9 @@
<BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\README.md">
<Link>Resources\dashboard-ui\bower_components\emby-webcomponents\README.md</Link>
</BundleResource>
<BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\animations.css">
<Link>Resources\dashboard-ui\bower_components\emby-webcomponents\animations.css</Link>
</BundleResource>
<BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\appsettings.js">
<Link>Resources\dashboard-ui\bower_components\emby-webcomponents\appsettings.js</Link>
</BundleResource>
@ -1451,6 +1454,12 @@
<BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\itemidentifier\itemidentifier.template.html">
<Link>Resources\dashboard-ui\bower_components\emby-webcomponents\itemidentifier\itemidentifier.template.html</Link>
</BundleResource>
<BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\lazyloader\lazyloader-intersectionobserver.js">
<Link>Resources\dashboard-ui\bower_components\emby-webcomponents\lazyloader\lazyloader-intersectionobserver.js</Link>
</BundleResource>
<BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\lazyloader\lazyloader-scroll.js">
<Link>Resources\dashboard-ui\bower_components\emby-webcomponents\lazyloader\lazyloader-scroll.js</Link>
</BundleResource>
<BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\listview\listview.css">
<Link>Resources\dashboard-ui\bower_components\emby-webcomponents\listview\listview.css</Link>
</BundleResource>

View File

@ -84,6 +84,14 @@
<HintPath>..\packages\SimpleInjector.3.2.4\lib\net45\SimpleInjector.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="SQLitePCLRaw.core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1488e028ca7ab535, processorArchitecture=MSIL">
<HintPath>..\packages\SQLitePCLRaw.core.1.1.0\lib\net45\SQLitePCLRaw.core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="SQLitePCLRaw.provider.sqlite3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=62684c7b4f184e3f, processorArchitecture=MSIL">
<HintPath>..\packages\SQLitePCLRaw.provider.sqlite3.net45.1.1.0\lib\net45\SQLitePCLRaw.provider.sqlite3.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="MediaBrowser.IsoMounting.Linux">
<HintPath>..\ThirdParty\MediaBrowser.IsoMounting.Linux\MediaBrowser.IsoMounting.Linux.dll</HintPath>

View File

@ -34,6 +34,8 @@ namespace MediaBrowser.Server.Mono
public static void Main(string[] args)
{
SQLitePCL.raw.SetProvider(new SQLitePCL.SQLite3Provider_sqlite3());
var applicationPath = Assembly.GetEntryAssembly().Location;
var options = new StartupOptions();

View File

@ -5,4 +5,6 @@
<package id="ServiceStack.Text" version="4.5.4" targetFramework="net46" />
<package id="SharpCompress" version="0.14.0" targetFramework="net46" />
<package id="SimpleInjector" version="3.2.4" targetFramework="net46" />
<package id="SQLitePCLRaw.core" version="1.1.0" targetFramework="net46" />
<package id="SQLitePCLRaw.provider.sqlite3.net45" version="1.1.0" targetFramework="net46" />
</packages>

View File

@ -90,6 +90,8 @@ namespace MediaBrowser.ServerApplication
var success = SetDllDirectory(architecturePath);
SQLitePCL.raw.SetProvider(new SQLitePCL.SQLite3Provider_sqlite3());
var appPaths = CreateApplicationPaths(ApplicationPath, IsRunningAsService);
var logManager = new NlogManager(appPaths.LogDirectoryPath, "server");

View File

@ -90,13 +90,21 @@
<HintPath>..\packages\SimpleInjector.3.2.4\lib\net45\SimpleInjector.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="SQLitePCLRaw.core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1488e028ca7ab535, processorArchitecture=MSIL">
<HintPath>..\packages\SQLitePCLRaw.core.1.1.0\lib\net45\SQLitePCLRaw.core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="SQLitePCLRaw.provider.sqlite3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=62684c7b4f184e3f, processorArchitecture=MSIL">
<HintPath>..\packages\SQLitePCLRaw.provider.sqlite3.net45.1.1.0\lib\net45\SQLitePCLRaw.provider.sqlite3.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Configuration.Install" />
<Reference Include="System.Core" />
<Reference Include="System.Data.SQLite, Version=1.0.103.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=MSIL">
<HintPath>..\packages\System.Data.SQLite.Core.1.0.103\lib\net46\System.Data.SQLite.dll</HintPath>
<Private>True</Private>
<SpecificVersion>False</SpecificVersion>
<HintPath>..\ThirdParty\System.Data.SQLite.ManagedOnly\1.0.94.0\System.Data.SQLite.dll</HintPath>
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.IO.Compression" />
@ -623,6 +631,9 @@
<Content Include="x64\IM_MOD_RL_yuv_.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="x64\sqlite3.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="x86\CORE_RL_bzlib_.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@ -1063,6 +1074,9 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Resources\Images\mb3logo800.png" />
<Content Include="x86\sqlite3.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BDInfo\BDInfo.csproj">
@ -1163,13 +1177,6 @@
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
<Import Project="..\packages\System.Data.SQLite.Core.1.0.103\build\net46\System.Data.SQLite.Core.targets" Condition="Exists('..\packages\System.Data.SQLite.Core.1.0.103\build\net46\System.Data.SQLite.Core.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\System.Data.SQLite.Core.1.0.103\build\net46\System.Data.SQLite.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\System.Data.SQLite.Core.1.0.103\build\net46\System.Data.SQLite.Core.targets'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">

View File

@ -5,5 +5,6 @@
<package id="ServiceStack.Text" version="4.5.4" targetFramework="net462" />
<package id="SharpCompress" version="0.14.0" targetFramework="net462" />
<package id="SimpleInjector" version="3.2.4" targetFramework="net462" />
<package id="System.Data.SQLite.Core" version="1.0.103" targetFramework="net462" />
<package id="SQLitePCLRaw.core" version="1.1.0" targetFramework="net462" />
<package id="SQLitePCLRaw.provider.sqlite3.net45" version="1.1.0" targetFramework="net462" />
</packages>

View File

@ -50,6 +50,7 @@ namespace Emby.Server
//var success = SetDllDirectory(architecturePath);
var appPaths = CreateApplicationPaths(baseDirectory);
SQLitePCL.raw.SetProvider(new SQLitePCL.SQLite3Provider_sqlite3());
var logManager = new NlogManager(appPaths.LogDirectoryPath, "server");
logManager.ReloadLogger(LogSeverity.Debug);

View File

@ -15,7 +15,8 @@
"Microsoft.Win32.Registry": "4.0.0",
"System.Runtime.Extensions": "4.1.0",
"System.Diagnostics.Process": "4.1.0",
"Microsoft.Data.SQLite": "1.1.0-preview1-final"
"Microsoft.Data.SQLite": "1.1.0-preview1-final",
"SQLitePCLRaw.provider.sqlite3.netstandard11": "1.1.0"
},
"frameworks": {