ApplicationHost.cs 93 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570
  1. using Emby.Common.Implementations.Serialization;
  2. using Emby.Drawing;
  3. using Emby.Photos;
  4. using Emby.Dlna;
  5. using Emby.Dlna.Main;
  6. using Emby.Dlna.Ssdp;
  7. using Emby.Server.Implementations.Activity;
  8. using Emby.Server.Implementations.Archiving;
  9. using Emby.Server.Implementations.Channels;
  10. using Emby.Server.Implementations.Collections;
  11. using Emby.Server.Implementations.Configuration;
  12. using Emby.Server.Implementations.Cryptography;
  13. using Emby.Server.Implementations.Data;
  14. using Emby.Server.Implementations.Devices;
  15. using Emby.Server.Implementations.Diagnostics;
  16. using Emby.Server.Implementations.Dto;
  17. using Emby.Server.Implementations.FFMpeg;
  18. using Emby.Server.Implementations.HttpServer;
  19. using Emby.Server.Implementations.HttpServer.Security;
  20. using Emby.Server.Implementations.IO;
  21. using Emby.Server.Implementations.Library;
  22. using Emby.Server.Implementations.LiveTv;
  23. using Emby.Server.Implementations.Localization;
  24. using Emby.Server.Implementations.MediaEncoder;
  25. using Emby.Server.Implementations.Net;
  26. using Emby.Notifications;
  27. using Emby.Server.Implementations.Playlists;
  28. using Emby.Server.Implementations.Reflection;
  29. using Emby.Server.Implementations.ScheduledTasks;
  30. using Emby.Server.Implementations.Security;
  31. using Emby.Server.Implementations.Serialization;
  32. using Emby.Server.Implementations.Session;
  33. using Emby.Server.Implementations.Threading;
  34. using Emby.Server.Implementations.TV;
  35. using Emby.Server.Implementations.Updates;
  36. using Emby.Server.Implementations.Xml;
  37. using Emby.Server.MediaEncoding.Subtitles;
  38. using MediaBrowser.Api;
  39. using MediaBrowser.Common;
  40. using MediaBrowser.Common.Configuration;
  41. using MediaBrowser.Common.Events;
  42. using MediaBrowser.Common.Extensions;
  43. using MediaBrowser.Common.Net;
  44. using MediaBrowser.Common.Plugins;
  45. using MediaBrowser.Model.Extensions;
  46. using MediaBrowser.Common.Security;
  47. using MediaBrowser.Common.Updates;
  48. using MediaBrowser.Controller;
  49. using MediaBrowser.Controller.Channels;
  50. using MediaBrowser.Controller.Chapters;
  51. using MediaBrowser.Controller.Collections;
  52. using MediaBrowser.Controller.Configuration;
  53. using MediaBrowser.Controller.Connect;
  54. using MediaBrowser.Controller.Devices;
  55. using MediaBrowser.Controller.Dlna;
  56. using MediaBrowser.Controller.Drawing;
  57. using MediaBrowser.Controller.Dto;
  58. using MediaBrowser.Controller.Entities;
  59. using MediaBrowser.Controller.IO;
  60. using MediaBrowser.Controller.Library;
  61. using MediaBrowser.Controller.LiveTv;
  62. using MediaBrowser.Controller.MediaEncoding;
  63. using MediaBrowser.Controller.Net;
  64. using MediaBrowser.Controller.Notifications;
  65. using MediaBrowser.Controller.Persistence;
  66. using MediaBrowser.Controller.Playlists;
  67. using MediaBrowser.Controller.Plugins;
  68. using MediaBrowser.Controller.Providers;
  69. using MediaBrowser.Controller.Resolvers;
  70. using MediaBrowser.Controller.Security;
  71. using MediaBrowser.Controller.Session;
  72. using MediaBrowser.Controller.Sorting;
  73. using MediaBrowser.Controller.Subtitles;
  74. using MediaBrowser.Controller.TV;
  75. using MediaBrowser.LocalMetadata.Savers;
  76. using MediaBrowser.MediaEncoding.BdInfo;
  77. using MediaBrowser.Model.Activity;
  78. using MediaBrowser.Model.Configuration;
  79. using MediaBrowser.Model.Cryptography;
  80. using MediaBrowser.Model.Diagnostics;
  81. using MediaBrowser.Model.Dlna;
  82. using MediaBrowser.Model.Events;
  83. using MediaBrowser.Model.Globalization;
  84. using MediaBrowser.Model.IO;
  85. using MediaBrowser.Model.Logging;
  86. using MediaBrowser.Model.MediaInfo;
  87. using MediaBrowser.Model.Net;
  88. using MediaBrowser.Model.News;
  89. using MediaBrowser.Model.Reflection;
  90. using MediaBrowser.Model.Serialization;
  91. using MediaBrowser.Model.Services;
  92. using MediaBrowser.Model.System;
  93. using MediaBrowser.Model.Tasks;
  94. using MediaBrowser.Model.Text;
  95. using MediaBrowser.Model.Threading;
  96. using MediaBrowser.Model.Updates;
  97. using MediaBrowser.Model.Xml;
  98. using MediaBrowser.Providers.Chapters;
  99. using MediaBrowser.Providers.Manager;
  100. using MediaBrowser.Providers.Subtitles;
  101. using MediaBrowser.WebDashboard.Api;
  102. using MediaBrowser.XbmcMetadata.Providers;
  103. using ServiceStack;
  104. using System;
  105. using System.Collections.Concurrent;
  106. using System.Collections.Generic;
  107. using System.Globalization;
  108. using System.IO;
  109. using System.Linq;
  110. using System.Net;
  111. using System.Reflection;
  112. using System.Runtime.InteropServices;
  113. using System.Security.Cryptography.X509Certificates;
  114. using System.Text;
  115. using System.Threading;
  116. using System.Threading.Tasks;
  117. using StringExtensions = MediaBrowser.Controller.Extensions.StringExtensions;
  118. using X509Certificate = System.Security.Cryptography.X509Certificates.X509Certificate;
  119. using MediaBrowser.Controller.Authentication;
  120. using System.Diagnostics;
  121. using ServiceStack.Text.Jsv;
  122. namespace Emby.Server.Implementations
  123. {
  124. /// <summary>
  125. /// Class CompositionRoot
  126. /// </summary>
  127. public abstract class ApplicationHost : IServerApplicationHost, IDisposable
  128. {
  129. /// <summary>
  130. /// Gets a value indicating whether this instance can self restart.
  131. /// </summary>
  132. /// <value><c>true</c> if this instance can self restart; otherwise, <c>false</c>.</value>
  133. public abstract bool CanSelfRestart { get; }
  134. /// <summary>
  135. /// Gets or sets a value indicating whether this instance can self update.
  136. /// </summary>
  137. /// <value><c>true</c> if this instance can self update; otherwise, <c>false</c>.</value>
  138. public virtual bool CanSelfUpdate
  139. {
  140. get
  141. {
  142. return false;
  143. }
  144. }
  145. public virtual bool CanLaunchWebBrowser
  146. {
  147. get
  148. {
  149. if (!Environment.UserInteractive)
  150. {
  151. return false;
  152. }
  153. if (StartupOptions.ContainsOption("-service"))
  154. {
  155. return false;
  156. }
  157. if (EnvironmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.Windows)
  158. {
  159. return true;
  160. }
  161. if (EnvironmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.OSX)
  162. {
  163. return true;
  164. }
  165. return false;
  166. }
  167. }
  168. /// <summary>
  169. /// Occurs when [has pending restart changed].
  170. /// </summary>
  171. public event EventHandler HasPendingRestartChanged;
  172. /// <summary>
  173. /// Occurs when [application updated].
  174. /// </summary>
  175. public event EventHandler<GenericEventArgs<PackageVersionInfo>> ApplicationUpdated;
  176. /// <summary>
  177. /// Gets or sets a value indicating whether this instance has changes that require the entire application to restart.
  178. /// </summary>
  179. /// <value><c>true</c> if this instance has pending application restart; otherwise, <c>false</c>.</value>
  180. public bool HasPendingRestart { get; private set; }
  181. public bool IsShuttingDown { get; private set; }
  182. /// <summary>
  183. /// Gets or sets the logger.
  184. /// </summary>
  185. /// <value>The logger.</value>
  186. protected ILogger Logger { get; set; }
  187. /// <summary>
  188. /// Gets or sets the plugins.
  189. /// </summary>
  190. /// <value>The plugins.</value>
  191. public IPlugin[] Plugins { get; protected set; }
  192. /// <summary>
  193. /// Gets or sets the log manager.
  194. /// </summary>
  195. /// <value>The log manager.</value>
  196. public ILogManager LogManager { get; protected set; }
  197. /// <summary>
  198. /// Gets the application paths.
  199. /// </summary>
  200. /// <value>The application paths.</value>
  201. protected ServerApplicationPaths ApplicationPaths { get; set; }
  202. /// <summary>
  203. /// Gets all concrete types.
  204. /// </summary>
  205. /// <value>All concrete types.</value>
  206. public Tuple<Type, string>[] AllConcreteTypes { get; protected set; }
  207. /// <summary>
  208. /// The disposable parts
  209. /// </summary>
  210. protected readonly List<IDisposable> DisposableParts = new List<IDisposable>();
  211. /// <summary>
  212. /// Gets the configuration manager.
  213. /// </summary>
  214. /// <value>The configuration manager.</value>
  215. protected IConfigurationManager ConfigurationManager { get; set; }
  216. public IFileSystem FileSystemManager { get; set; }
  217. protected IEnvironmentInfo EnvironmentInfo { get; set; }
  218. private IBlurayExaminer BlurayExaminer { get; set; }
  219. public PackageVersionClass SystemUpdateLevel
  220. {
  221. get
  222. {
  223. #if BETA
  224. return PackageVersionClass.Beta;
  225. #endif
  226. return PackageVersionClass.Release;
  227. }
  228. }
  229. public virtual string OperatingSystemDisplayName
  230. {
  231. get { return EnvironmentInfo.OperatingSystemName; }
  232. }
  233. /// <summary>
  234. /// The container
  235. /// </summary>
  236. protected readonly SimpleInjector.Container Container = new SimpleInjector.Container();
  237. protected ISystemEvents SystemEvents { get; set; }
  238. /// <summary>
  239. /// Gets the server configuration manager.
  240. /// </summary>
  241. /// <value>The server configuration manager.</value>
  242. public IServerConfigurationManager ServerConfigurationManager
  243. {
  244. get { return (IServerConfigurationManager)ConfigurationManager; }
  245. }
  246. /// <summary>
  247. /// Gets the configuration manager.
  248. /// </summary>
  249. /// <returns>IConfigurationManager.</returns>
  250. protected IConfigurationManager GetConfigurationManager()
  251. {
  252. return new ServerConfigurationManager(ApplicationPaths, LogManager, XmlSerializer, FileSystemManager);
  253. }
  254. protected virtual IResourceFileManager CreateResourceFileManager()
  255. {
  256. return new ResourceFileManager(HttpResultFactory, LogManager.GetLogger("ResourceManager"), FileSystemManager);
  257. }
  258. /// <summary>
  259. /// Gets or sets the user manager.
  260. /// </summary>
  261. /// <value>The user manager.</value>
  262. public IUserManager UserManager { get; set; }
  263. /// <summary>
  264. /// Gets or sets the library manager.
  265. /// </summary>
  266. /// <value>The library manager.</value>
  267. internal ILibraryManager LibraryManager { get; set; }
  268. /// <summary>
  269. /// Gets or sets the directory watchers.
  270. /// </summary>
  271. /// <value>The directory watchers.</value>
  272. private ILibraryMonitor LibraryMonitor { get; set; }
  273. /// <summary>
  274. /// Gets or sets the provider manager.
  275. /// </summary>
  276. /// <value>The provider manager.</value>
  277. private IProviderManager ProviderManager { get; set; }
  278. /// <summary>
  279. /// Gets or sets the HTTP server.
  280. /// </summary>
  281. /// <value>The HTTP server.</value>
  282. private IHttpServer HttpServer { get; set; }
  283. private IDtoService DtoService { get; set; }
  284. public IImageProcessor ImageProcessor { get; set; }
  285. /// <summary>
  286. /// Gets or sets the media encoder.
  287. /// </summary>
  288. /// <value>The media encoder.</value>
  289. private IMediaEncoder MediaEncoder { get; set; }
  290. private ISubtitleEncoder SubtitleEncoder { get; set; }
  291. private IConnectManager ConnectManager { get; set; }
  292. private ISessionManager SessionManager { get; set; }
  293. private ILiveTvManager LiveTvManager { get; set; }
  294. public ILocalizationManager LocalizationManager { get; set; }
  295. private IEncodingManager EncodingManager { get; set; }
  296. private IChannelManager ChannelManager { get; set; }
  297. protected ITextEncoding TextEncoding { get; private set; }
  298. /// <summary>
  299. /// Gets or sets the user data repository.
  300. /// </summary>
  301. /// <value>The user data repository.</value>
  302. private IUserDataManager UserDataManager { get; set; }
  303. private IUserRepository UserRepository { get; set; }
  304. internal IDisplayPreferencesRepository DisplayPreferencesRepository { get; set; }
  305. internal IItemRepository ItemRepository { get; set; }
  306. private INotificationManager NotificationManager { get; set; }
  307. private ISubtitleManager SubtitleManager { get; set; }
  308. private IChapterManager ChapterManager { get; set; }
  309. private IDeviceManager DeviceManager { get; set; }
  310. internal IUserViewManager UserViewManager { get; set; }
  311. private IAuthenticationRepository AuthenticationRepository { get; set; }
  312. private ITVSeriesManager TVSeriesManager { get; set; }
  313. private ICollectionManager CollectionManager { get; set; }
  314. private IMediaSourceManager MediaSourceManager { get; set; }
  315. private IPlaylistManager PlaylistManager { get; set; }
  316. /// <summary>
  317. /// Gets or sets the installation manager.
  318. /// </summary>
  319. /// <value>The installation manager.</value>
  320. protected IInstallationManager InstallationManager { get; private set; }
  321. /// <summary>
  322. /// Gets the security manager.
  323. /// </summary>
  324. /// <value>The security manager.</value>
  325. protected ISecurityManager SecurityManager { get; private set; }
  326. /// <summary>
  327. /// Gets or sets the zip client.
  328. /// </summary>
  329. /// <value>The zip client.</value>
  330. protected IZipClient ZipClient { get; private set; }
  331. protected IHttpResultFactory HttpResultFactory { get; private set; }
  332. protected IAuthService AuthService { get; private set; }
  333. public StartupOptions StartupOptions { get; private set; }
  334. protected readonly string ReleaseAssetFilename;
  335. internal IPowerManagement PowerManagement { get; private set; }
  336. internal IImageEncoder ImageEncoder { get; private set; }
  337. protected IProcessFactory ProcessFactory { get; private set; }
  338. protected ITimerFactory TimerFactory { get; private set; }
  339. protected ICryptoProvider CryptographyProvider = new CryptographyProvider();
  340. protected readonly IXmlSerializer XmlSerializer;
  341. protected ISocketFactory SocketFactory { get; private set; }
  342. protected ITaskManager TaskManager { get; private set; }
  343. public IHttpClient HttpClient { get; private set; }
  344. protected INetworkManager NetworkManager { get; set; }
  345. public IJsonSerializer JsonSerializer { get; private set; }
  346. protected IIsoManager IsoManager { get; private set; }
  347. /// <summary>
  348. /// Initializes a new instance of the <see cref="ApplicationHost" /> class.
  349. /// </summary>
  350. public ApplicationHost(ServerApplicationPaths applicationPaths,
  351. ILogManager logManager,
  352. StartupOptions options,
  353. IFileSystem fileSystem,
  354. IPowerManagement powerManagement,
  355. string releaseAssetFilename,
  356. IEnvironmentInfo environmentInfo,
  357. IImageEncoder imageEncoder,
  358. ISystemEvents systemEvents,
  359. INetworkManager networkManager)
  360. {
  361. // hack alert, until common can target .net core
  362. BaseExtensions.CryptographyProvider = CryptographyProvider;
  363. XmlSerializer = new MyXmlSerializer(fileSystem, logManager.GetLogger("XmlSerializer"));
  364. NetworkManager = networkManager;
  365. networkManager.LocalSubnetsFn = GetConfiguredLocalSubnets;
  366. EnvironmentInfo = environmentInfo;
  367. SystemEvents = systemEvents;
  368. ApplicationPaths = applicationPaths;
  369. LogManager = logManager;
  370. FileSystemManager = fileSystem;
  371. ConfigurationManager = GetConfigurationManager();
  372. // Initialize this early in case the -v command line option is used
  373. Logger = LogManager.GetLogger("App");
  374. StartupOptions = options;
  375. ReleaseAssetFilename = releaseAssetFilename;
  376. PowerManagement = powerManagement;
  377. ImageEncoder = imageEncoder;
  378. SetBaseExceptionMessage();
  379. fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem));
  380. NetworkManager.NetworkChanged += NetworkManager_NetworkChanged;
  381. }
  382. public string ExpandVirtualPath(string path)
  383. {
  384. var appPaths = ApplicationPaths;
  385. return path.Replace(appPaths.VirtualDataPath, appPaths.DataPath, StringComparison.OrdinalIgnoreCase)
  386. .Replace(appPaths.VirtualInternalMetadataPath, appPaths.InternalMetadataPath, StringComparison.OrdinalIgnoreCase);
  387. }
  388. public string ReverseVirtualPath(string path)
  389. {
  390. var appPaths = ApplicationPaths;
  391. return path.Replace(appPaths.DataPath, appPaths.VirtualDataPath, StringComparison.OrdinalIgnoreCase)
  392. .Replace(appPaths.InternalMetadataPath, appPaths.VirtualInternalMetadataPath, StringComparison.OrdinalIgnoreCase);
  393. }
  394. private string[] GetConfiguredLocalSubnets()
  395. {
  396. return ServerConfigurationManager.Configuration.LocalNetworkSubnets;
  397. }
  398. private void NetworkManager_NetworkChanged(object sender, EventArgs e)
  399. {
  400. _validAddressResults.Clear();
  401. }
  402. private Version _version;
  403. /// <summary>
  404. /// Gets the current application version
  405. /// </summary>
  406. /// <value>The application version.</value>
  407. public Version ApplicationVersion
  408. {
  409. get
  410. {
  411. return _version ?? (_version = GetType().GetTypeInfo().Assembly.GetName().Version);
  412. }
  413. }
  414. private DeviceId _deviceId;
  415. public string SystemId
  416. {
  417. get
  418. {
  419. if (_deviceId == null)
  420. {
  421. _deviceId = new DeviceId(ApplicationPaths, LogManager.GetLogger("SystemId"), FileSystemManager);
  422. }
  423. return _deviceId.Value;
  424. }
  425. }
  426. /// <summary>
  427. /// Gets the name.
  428. /// </summary>
  429. /// <value>The name.</value>
  430. public string Name
  431. {
  432. get
  433. {
  434. return "Emby Server";
  435. }
  436. }
  437. private Tuple<Assembly, string> GetAssembly(Type type)
  438. {
  439. var assembly = type.GetTypeInfo().Assembly;
  440. string path = null;
  441. return new Tuple<Assembly, string>(assembly, path);
  442. }
  443. public virtual IStreamHelper CreateStreamHelper()
  444. {
  445. return new StreamHelper();
  446. }
  447. public virtual bool SupportsAutoRunAtStartup
  448. {
  449. get
  450. {
  451. return EnvironmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.Windows;
  452. }
  453. }
  454. /// <summary>
  455. /// Creates an instance of type and resolves all constructor dependancies
  456. /// </summary>
  457. /// <param name="type">The type.</param>
  458. /// <returns>System.Object.</returns>
  459. public object CreateInstance(Type type)
  460. {
  461. return Container.GetInstance(type);
  462. }
  463. /// <summary>
  464. /// Creates the instance safe.
  465. /// </summary>
  466. /// <param name="type">The type.</param>
  467. /// <returns>System.Object.</returns>
  468. protected object CreateInstanceSafe(Tuple<Type, string> typeInfo)
  469. {
  470. var type = typeInfo.Item1;
  471. try
  472. {
  473. return Container.GetInstance(type);
  474. }
  475. catch (Exception ex)
  476. {
  477. Logger.ErrorException("Error creating {0}", ex, type.FullName);
  478. // Don't blow up in release mode
  479. return null;
  480. }
  481. }
  482. /// <summary>
  483. /// Registers the specified obj.
  484. /// </summary>
  485. /// <typeparam name="T"></typeparam>
  486. /// <param name="obj">The obj.</param>
  487. /// <param name="manageLifetime">if set to <c>true</c> [manage lifetime].</param>
  488. protected void RegisterSingleInstance<T>(T obj, bool manageLifetime = true)
  489. where T : class
  490. {
  491. Container.RegisterSingleton(obj);
  492. if (manageLifetime)
  493. {
  494. var disposable = obj as IDisposable;
  495. if (disposable != null)
  496. {
  497. DisposableParts.Add(disposable);
  498. }
  499. }
  500. }
  501. /// <summary>
  502. /// Registers the single instance.
  503. /// </summary>
  504. /// <typeparam name="T"></typeparam>
  505. /// <param name="func">The func.</param>
  506. protected void RegisterSingleInstance<T>(Func<T> func)
  507. where T : class
  508. {
  509. Container.RegisterSingleton(func);
  510. }
  511. /// <summary>
  512. /// Resolves this instance.
  513. /// </summary>
  514. /// <typeparam name="T"></typeparam>
  515. /// <returns>``0.</returns>
  516. public T Resolve<T>()
  517. {
  518. return (T)Container.GetRegistration(typeof(T), true).GetInstance();
  519. }
  520. /// <summary>
  521. /// Resolves this instance.
  522. /// </summary>
  523. /// <typeparam name="T"></typeparam>
  524. /// <returns>``0.</returns>
  525. public T TryResolve<T>()
  526. {
  527. var result = Container.GetRegistration(typeof(T), false);
  528. if (result == null)
  529. {
  530. return default(T);
  531. }
  532. return (T)result.GetInstance();
  533. }
  534. /// <summary>
  535. /// Loads the assembly.
  536. /// </summary>
  537. /// <param name="file">The file.</param>
  538. /// <returns>Assembly.</returns>
  539. protected Tuple<Assembly, string> LoadAssembly(string file)
  540. {
  541. try
  542. {
  543. var assembly = Assembly.Load(File.ReadAllBytes(file));
  544. return new Tuple<Assembly, string>(assembly, file);
  545. }
  546. catch (Exception ex)
  547. {
  548. Logger.ErrorException("Error loading assembly {0}", ex, file);
  549. return null;
  550. }
  551. }
  552. /// <summary>
  553. /// Gets the export types.
  554. /// </summary>
  555. /// <typeparam name="T"></typeparam>
  556. /// <returns>IEnumerable{Type}.</returns>
  557. public IEnumerable<Tuple<Type, string>> GetExportTypes<T>()
  558. {
  559. var currentType = typeof(T);
  560. return AllConcreteTypes.Where(i => currentType.IsAssignableFrom(i.Item1));
  561. }
  562. /// <summary>
  563. /// Gets the exports.
  564. /// </summary>
  565. /// <typeparam name="T"></typeparam>
  566. /// <param name="manageLiftime">if set to <c>true</c> [manage liftime].</param>
  567. /// <returns>IEnumerable{``0}.</returns>
  568. public IEnumerable<T> GetExports<T>(bool manageLiftime = true)
  569. {
  570. var parts = GetExportTypes<T>()
  571. .Select(CreateInstanceSafe)
  572. .Where(i => i != null)
  573. .Cast<T>()
  574. .ToList();
  575. if (manageLiftime)
  576. {
  577. lock (DisposableParts)
  578. {
  579. DisposableParts.AddRange(parts.OfType<IDisposable>());
  580. }
  581. }
  582. return parts;
  583. }
  584. public List<Tuple<T, string>> GetExportsWithInfo<T>(bool manageLiftime = true)
  585. {
  586. var parts = GetExportTypes<T>()
  587. .Select(i =>
  588. {
  589. var obj = CreateInstanceSafe(i);
  590. if (obj == null)
  591. {
  592. return null;
  593. }
  594. return new Tuple<T, string>((T)obj, i.Item2);
  595. })
  596. .Where(i => i != null)
  597. .ToList();
  598. if (manageLiftime)
  599. {
  600. lock (DisposableParts)
  601. {
  602. DisposableParts.AddRange(parts.Select(i => i.Item1).OfType<IDisposable>());
  603. }
  604. }
  605. return parts;
  606. }
  607. private void SetBaseExceptionMessage()
  608. {
  609. var builder = GetBaseExceptionMessage(ApplicationPaths);
  610. builder.Insert(0, string.Format("Version: {0}{1}", ApplicationVersion, Environment.NewLine));
  611. builder.Insert(0, "*** Error Report ***" + Environment.NewLine);
  612. LogManager.ExceptionMessagePrefix = builder.ToString();
  613. }
  614. /// <summary>
  615. /// Runs the startup tasks.
  616. /// </summary>
  617. public async Task RunStartupTasks()
  618. {
  619. Resolve<ITaskManager>().AddTasks(GetExports<IScheduledTask>(false));
  620. ConfigureAutorun();
  621. ConfigurationManager.ConfigurationUpdated += OnConfigurationUpdated;
  622. MediaEncoder.Init();
  623. //if (string.IsNullOrWhiteSpace(MediaEncoder.EncoderPath))
  624. //{
  625. // if (ServerConfigurationManager.Configuration.IsStartupWizardCompleted)
  626. // {
  627. // ServerConfigurationManager.Configuration.IsStartupWizardCompleted = false;
  628. // ServerConfigurationManager.SaveConfiguration();
  629. // }
  630. //}
  631. Logger.Info("ServerId: {0}", SystemId);
  632. var entryPoints = GetExports<IServerEntryPoint>().ToList();
  633. RunEntryPoints(entryPoints, true);
  634. Logger.Info("Core startup complete");
  635. HttpServer.GlobalResponse = null;
  636. Logger.Info("Post-init migrations complete");
  637. RunEntryPoints(entryPoints, false);
  638. Logger.Info("All entry points have started");
  639. LogManager.RemoveConsoleOutput();
  640. }
  641. private void RunEntryPoints(IEnumerable<IServerEntryPoint> entryPoints, bool isBeforeStartup)
  642. {
  643. foreach (var entryPoint in entryPoints)
  644. {
  645. if (isBeforeStartup != (entryPoint is IRunBeforeStartup))
  646. {
  647. continue;
  648. }
  649. var name = entryPoint.GetType().FullName;
  650. Logger.Info("Starting entry point {0}", name);
  651. var now = DateTime.UtcNow;
  652. try
  653. {
  654. entryPoint.Run();
  655. }
  656. catch (Exception ex)
  657. {
  658. Logger.ErrorException("Error in {0}", ex, name);
  659. }
  660. Logger.Info("Entry point completed: {0}. Duration: {1} seconds", name, (DateTime.UtcNow - now).TotalSeconds.ToString(CultureInfo.InvariantCulture), "ImageInfos");
  661. }
  662. }
  663. /// <summary>
  664. /// Configures the autorun.
  665. /// </summary>
  666. private void ConfigureAutorun()
  667. {
  668. try
  669. {
  670. ConfigureAutoRunAtStartup(ConfigurationManager.CommonConfiguration.RunAtStartup);
  671. }
  672. catch (Exception ex)
  673. {
  674. Logger.ErrorException("Error configuring autorun", ex);
  675. }
  676. }
  677. private IJsonSerializer CreateJsonSerializer()
  678. {
  679. return new JsonSerializer(FileSystemManager, LogManager.GetLogger("JsonSerializer"));
  680. }
  681. public void Init()
  682. {
  683. HttpPort = ServerConfigurationManager.Configuration.HttpServerPortNumber;
  684. HttpsPort = ServerConfigurationManager.Configuration.HttpsPortNumber;
  685. // Safeguard against invalid configuration
  686. if (HttpPort == HttpsPort)
  687. {
  688. HttpPort = ServerConfiguration.DefaultHttpPort;
  689. HttpsPort = ServerConfiguration.DefaultHttpsPort;
  690. }
  691. JsonSerializer = CreateJsonSerializer();
  692. OnLoggerLoaded(true);
  693. LogManager.LoggerLoaded += (s, e) => OnLoggerLoaded(false);
  694. LogManager.LogSeverity = ConfigurationManager.CommonConfiguration.EnableDebugLevelLogging
  695. ? LogSeverity.Debug
  696. : LogSeverity.Info;
  697. DiscoverTypes();
  698. SetHttpLimit();
  699. RegisterResources();
  700. FindParts();
  701. }
  702. protected virtual void OnLoggerLoaded(bool isFirstLoad)
  703. {
  704. Logger.Info("Application version: {0}", ApplicationVersion);
  705. if (!isFirstLoad)
  706. {
  707. LogEnvironmentInfo(Logger, ApplicationPaths, false);
  708. }
  709. if (Plugins != null)
  710. {
  711. var pluginBuilder = new StringBuilder();
  712. foreach (var plugin in Plugins)
  713. {
  714. pluginBuilder.AppendLine(string.Format("{0} {1}", plugin.Name, plugin.Version));
  715. }
  716. Logger.LogMultiline("Plugins:", LogSeverity.Info, pluginBuilder);
  717. }
  718. }
  719. protected abstract IConnectManager CreateConnectManager();
  720. protected virtual IHttpClient CreateHttpClient()
  721. {
  722. return new HttpClientManager.HttpClientManager(ApplicationPaths, LogManager.GetLogger("HttpClient"), FileSystemManager, GetDefaultUserAgent);
  723. }
  724. public static IStreamHelper StreamHelper { get; set; }
  725. /// <summary>
  726. /// Registers resources that classes will depend on
  727. /// </summary>
  728. protected void RegisterResources()
  729. {
  730. RegisterSingleInstance(ConfigurationManager);
  731. RegisterSingleInstance<IApplicationHost>(this);
  732. RegisterSingleInstance<IApplicationPaths>(ApplicationPaths);
  733. RegisterSingleInstance(JsonSerializer);
  734. RegisterSingleInstance(SystemEvents);
  735. RegisterSingleInstance(LogManager, false);
  736. RegisterSingleInstance(Logger);
  737. RegisterSingleInstance(EnvironmentInfo);
  738. RegisterSingleInstance(FileSystemManager);
  739. HttpClient = CreateHttpClient();
  740. RegisterSingleInstance(HttpClient);
  741. RegisterSingleInstance(NetworkManager);
  742. IsoManager = new IsoManager();
  743. RegisterSingleInstance(IsoManager);
  744. TaskManager = new TaskManager(ApplicationPaths, JsonSerializer, LogManager.GetLogger("TaskManager"), FileSystemManager, SystemEvents);
  745. RegisterSingleInstance(TaskManager);
  746. RegisterSingleInstance(XmlSerializer);
  747. ProcessFactory = new ProcessFactory();
  748. RegisterSingleInstance(ProcessFactory);
  749. TimerFactory = new TimerFactory();
  750. RegisterSingleInstance(TimerFactory);
  751. var streamHelper = CreateStreamHelper();
  752. ApplicationHost.StreamHelper = streamHelper;
  753. RegisterSingleInstance(streamHelper);
  754. RegisterSingleInstance(CryptographyProvider);
  755. SocketFactory = new SocketFactory(LogManager.GetLogger("SocketFactory"));
  756. RegisterSingleInstance(SocketFactory);
  757. RegisterSingleInstance(PowerManagement);
  758. SecurityManager = new PluginSecurityManager(this, HttpClient, JsonSerializer, ApplicationPaths, LogManager, FileSystemManager, CryptographyProvider);
  759. RegisterSingleInstance(SecurityManager);
  760. InstallationManager = new InstallationManager(LogManager.GetLogger("InstallationManager"), this, ApplicationPaths, HttpClient, JsonSerializer, SecurityManager, ServerConfigurationManager, FileSystemManager, CryptographyProvider, PackageRuntime);
  761. RegisterSingleInstance(InstallationManager);
  762. ZipClient = new ZipClient(FileSystemManager);
  763. RegisterSingleInstance(ZipClient);
  764. HttpResultFactory = new HttpResultFactory(LogManager, FileSystemManager, JsonSerializer, CreateBrotliCompressor());
  765. RegisterSingleInstance(HttpResultFactory);
  766. RegisterSingleInstance<IServerApplicationHost>(this);
  767. RegisterSingleInstance<IServerApplicationPaths>(ApplicationPaths);
  768. RegisterSingleInstance(ServerConfigurationManager);
  769. IAssemblyInfo assemblyInfo = new AssemblyInfo();
  770. RegisterSingleInstance<IAssemblyInfo>(assemblyInfo);
  771. LocalizationManager = new LocalizationManager(ServerConfigurationManager, FileSystemManager, JsonSerializer, LogManager.GetLogger("LocalizationManager"), assemblyInfo, new TextLocalizer());
  772. StringExtensions.LocalizationManager = LocalizationManager;
  773. RegisterSingleInstance(LocalizationManager);
  774. TextEncoding = new TextEncoding.TextEncoding(FileSystemManager, LogManager.GetLogger("TextEncoding"), JsonSerializer);
  775. RegisterSingleInstance(TextEncoding);
  776. BlurayExaminer = new BdInfoExaminer(FileSystemManager, TextEncoding);
  777. RegisterSingleInstance(BlurayExaminer);
  778. RegisterSingleInstance<IXmlReaderSettingsFactory>(new XmlReaderSettingsFactory());
  779. UserDataManager = new UserDataManager(LogManager, ServerConfigurationManager, () => UserManager);
  780. RegisterSingleInstance(UserDataManager);
  781. UserRepository = GetUserRepository();
  782. // This is only needed for disposal purposes. If removing this, make sure to have the manager handle disposing it
  783. RegisterSingleInstance(UserRepository);
  784. var displayPreferencesRepo = new SqliteDisplayPreferencesRepository(LogManager.GetLogger("SqliteDisplayPreferencesRepository"), JsonSerializer, ApplicationPaths, FileSystemManager);
  785. DisplayPreferencesRepository = displayPreferencesRepo;
  786. RegisterSingleInstance(DisplayPreferencesRepository);
  787. var itemRepo = new SqliteItemRepository(ServerConfigurationManager, this, JsonSerializer, LogManager.GetLogger("SqliteItemRepository"), assemblyInfo, FileSystemManager, EnvironmentInfo, TimerFactory);
  788. ItemRepository = itemRepo;
  789. RegisterSingleInstance(ItemRepository);
  790. AuthenticationRepository = GetAuthenticationRepository();
  791. RegisterSingleInstance(AuthenticationRepository);
  792. UserManager = new UserManager(LogManager.GetLogger("UserManager"), ServerConfigurationManager, UserRepository, XmlSerializer, NetworkManager, () => ImageProcessor, () => DtoService, () => ConnectManager, this, JsonSerializer, FileSystemManager, CryptographyProvider);
  793. RegisterSingleInstance(UserManager);
  794. LibraryManager = new LibraryManager(this, Logger, TaskManager, UserManager, ServerConfigurationManager, UserDataManager, () => LibraryMonitor, FileSystemManager, () => ProviderManager, () => UserViewManager);
  795. RegisterSingleInstance(LibraryManager);
  796. var musicManager = new MusicManager(LibraryManager);
  797. RegisterSingleInstance<IMusicManager>(new MusicManager(LibraryManager));
  798. LibraryMonitor = new LibraryMonitor(LogManager, TaskManager, LibraryManager, ServerConfigurationManager, FileSystemManager, TimerFactory, SystemEvents, EnvironmentInfo);
  799. RegisterSingleInstance(LibraryMonitor);
  800. RegisterSingleInstance<ISearchEngine>(() => new SearchEngine(LogManager, LibraryManager, UserManager));
  801. CertificateInfo = GetCertificateInfo(true);
  802. Certificate = GetCertificate(CertificateInfo);
  803. HttpServer = new HttpListenerHost(this,
  804. LogManager.GetLogger("HttpServer"),
  805. ServerConfigurationManager,
  806. "web/index.html",
  807. NetworkManager,
  808. TextEncoding,
  809. JsonSerializer,
  810. XmlSerializer,
  811. GetParseFn);
  812. HttpServer.GlobalResponse = LocalizationManager.GetLocalizedString("StartupEmbyServerIsLoading");
  813. RegisterSingleInstance(HttpServer);
  814. ImageProcessor = GetImageProcessor();
  815. RegisterSingleInstance(ImageProcessor);
  816. TVSeriesManager = new TVSeriesManager(UserManager, UserDataManager, LibraryManager, ServerConfigurationManager);
  817. RegisterSingleInstance(TVSeriesManager);
  818. var encryptionManager = new EncryptionManager();
  819. RegisterSingleInstance<IEncryptionManager>(encryptionManager);
  820. ConnectManager = CreateConnectManager();
  821. RegisterSingleInstance(ConnectManager);
  822. DeviceManager = new DeviceManager(AuthenticationRepository, JsonSerializer, LibraryManager, LocalizationManager, UserManager, FileSystemManager, LibraryMonitor, ServerConfigurationManager, LogManager.GetLogger("DeviceManager"), NetworkManager);
  823. RegisterSingleInstance(DeviceManager);
  824. var newsService = new Emby.Server.Implementations.News.NewsService(ApplicationPaths, JsonSerializer);
  825. RegisterSingleInstance<INewsService>(newsService);
  826. MediaSourceManager = new MediaSourceManager(ItemRepository, ApplicationPaths, LocalizationManager, UserManager, LibraryManager, LogManager.GetLogger("MediaSourceManager"), JsonSerializer, FileSystemManager, UserDataManager, TimerFactory, () => MediaEncoder);
  827. RegisterSingleInstance(MediaSourceManager);
  828. SubtitleManager = new SubtitleManager(LogManager.GetLogger("SubtitleManager"), FileSystemManager, LibraryMonitor, MediaSourceManager, ServerConfigurationManager, LocalizationManager);
  829. RegisterSingleInstance(SubtitleManager);
  830. ProviderManager = new ProviderManager(HttpClient, SubtitleManager, ServerConfigurationManager, LibraryMonitor, LogManager, FileSystemManager, ApplicationPaths, () => LibraryManager, JsonSerializer);
  831. RegisterSingleInstance(ProviderManager);
  832. DtoService = new DtoService(LogManager.GetLogger("DtoService"), LibraryManager, UserDataManager, ItemRepository, ImageProcessor, ServerConfigurationManager, FileSystemManager, ProviderManager, () => ChannelManager, this, () => DeviceManager, () => MediaSourceManager, () => LiveTvManager);
  833. RegisterSingleInstance(DtoService);
  834. ChannelManager = new ChannelManager(UserManager, DtoService, LibraryManager, LogManager.GetLogger("ChannelManager"), ServerConfigurationManager, FileSystemManager, UserDataManager, JsonSerializer, LocalizationManager, HttpClient, ProviderManager);
  835. RegisterSingleInstance(ChannelManager);
  836. SessionManager = new SessionManager(UserDataManager, LogManager.GetLogger("SessionManager"), LibraryManager, UserManager, musicManager, DtoService, ImageProcessor, JsonSerializer, this, HttpClient, AuthenticationRepository, DeviceManager, MediaSourceManager, TimerFactory);
  837. RegisterSingleInstance(SessionManager);
  838. var dlnaManager = new DlnaManager(XmlSerializer, FileSystemManager, ApplicationPaths, LogManager.GetLogger("Dlna"), JsonSerializer, this, assemblyInfo);
  839. RegisterSingleInstance<IDlnaManager>(dlnaManager);
  840. CollectionManager = new CollectionManager(LibraryManager, ApplicationPaths, LocalizationManager, FileSystemManager, LibraryMonitor, LogManager.GetLogger("CollectionManager"), ProviderManager);
  841. RegisterSingleInstance(CollectionManager);
  842. PlaylistManager = new PlaylistManager(LibraryManager, FileSystemManager, LibraryMonitor, LogManager.GetLogger("PlaylistManager"), UserManager, ProviderManager);
  843. RegisterSingleInstance<IPlaylistManager>(PlaylistManager);
  844. LiveTvManager = new LiveTvManager(this, HttpClient, ServerConfigurationManager, Logger, ItemRepository, ImageProcessor, UserDataManager, DtoService, UserManager, LibraryManager, TaskManager, LocalizationManager, JsonSerializer, ProviderManager, FileSystemManager, SecurityManager, () => ChannelManager);
  845. RegisterSingleInstance(LiveTvManager);
  846. UserViewManager = new UserViewManager(LibraryManager, LocalizationManager, UserManager, ChannelManager, LiveTvManager, ServerConfigurationManager);
  847. RegisterSingleInstance(UserViewManager);
  848. NotificationManager = new NotificationManager(LogManager, UserManager, ServerConfigurationManager);
  849. RegisterSingleInstance(NotificationManager);
  850. RegisterSingleInstance<IDeviceDiscovery>(new DeviceDiscovery(LogManager.GetLogger("IDeviceDiscovery"), ServerConfigurationManager, SocketFactory, TimerFactory));
  851. ChapterManager = new ChapterManager(LibraryManager, LogManager.GetLogger("ChapterManager"), ServerConfigurationManager, ItemRepository);
  852. RegisterSingleInstance(ChapterManager);
  853. RegisterMediaEncoder(assemblyInfo);
  854. EncodingManager = new EncodingManager(FileSystemManager, Logger, MediaEncoder, ChapterManager, LibraryManager);
  855. RegisterSingleInstance(EncodingManager);
  856. var activityLogRepo = GetActivityLogRepository();
  857. RegisterSingleInstance(activityLogRepo);
  858. RegisterSingleInstance<IActivityManager>(new ActivityManager(LogManager.GetLogger("ActivityManager"), activityLogRepo, UserManager));
  859. var authContext = new AuthorizationContext(AuthenticationRepository, ConnectManager, UserManager);
  860. RegisterSingleInstance<IAuthorizationContext>(authContext);
  861. RegisterSingleInstance<ISessionContext>(new SessionContext(UserManager, authContext, SessionManager));
  862. AuthService = new AuthService(UserManager, authContext, ServerConfigurationManager, ConnectManager, SessionManager, NetworkManager);
  863. RegisterSingleInstance<IAuthService>(AuthService);
  864. SubtitleEncoder = new SubtitleEncoder(LibraryManager, LogManager.GetLogger("SubtitleEncoder"), ApplicationPaths, FileSystemManager, MediaEncoder, JsonSerializer, HttpClient, MediaSourceManager, ProcessFactory, TextEncoding);
  865. RegisterSingleInstance(SubtitleEncoder);
  866. RegisterSingleInstance(CreateResourceFileManager());
  867. displayPreferencesRepo.Initialize();
  868. var userDataRepo = new SqliteUserDataRepository(LogManager.GetLogger("SqliteUserDataRepository"), ApplicationPaths, FileSystemManager);
  869. SetStaticProperties();
  870. ((UserManager)UserManager).Initialize();
  871. ((UserDataManager)UserDataManager).Repository = userDataRepo;
  872. itemRepo.Initialize(userDataRepo, UserManager);
  873. ((LibraryManager)LibraryManager).ItemRepository = ItemRepository;
  874. }
  875. protected virtual IBrotliCompressor CreateBrotliCompressor()
  876. {
  877. return null;
  878. }
  879. private static Func<string, object> GetParseFn(Type propertyType)
  880. {
  881. return s => JsvReader.GetParseFn(propertyType)(s);
  882. }
  883. public virtual string PackageRuntime
  884. {
  885. get
  886. {
  887. return "netframework";
  888. }
  889. }
  890. public static void LogEnvironmentInfo(ILogger logger, IApplicationPaths appPaths, bool isStartup)
  891. {
  892. logger.LogMultiline("Emby", LogSeverity.Info, GetBaseExceptionMessage(appPaths));
  893. }
  894. protected static StringBuilder GetBaseExceptionMessage(IApplicationPaths appPaths)
  895. {
  896. var builder = new StringBuilder();
  897. // Distinct these to prevent users from reporting problems that aren't actually problems
  898. var commandLineArgs = Environment
  899. .GetCommandLineArgs()
  900. .Distinct()
  901. .ToArray();
  902. builder.AppendLine(string.Format("Command line: {0}", string.Join(" ", commandLineArgs)));
  903. builder.AppendLine(string.Format("Operating system: {0}", Environment.OSVersion));
  904. builder.AppendLine(string.Format("64-Bit OS: {0}", Environment.Is64BitOperatingSystem));
  905. builder.AppendLine(string.Format("64-Bit Process: {0}", Environment.Is64BitProcess));
  906. builder.AppendLine(string.Format("User Interactive: {0}", Environment.UserInteractive));
  907. Type type = Type.GetType("Mono.Runtime");
  908. if (type != null)
  909. {
  910. MethodInfo displayName = type.GetMethod("GetDisplayName", BindingFlags.NonPublic | BindingFlags.Static);
  911. if (displayName != null)
  912. {
  913. builder.AppendLine("Mono: " + displayName.Invoke(null, null));
  914. }
  915. }
  916. builder.AppendLine(string.Format("Processor count: {0}", Environment.ProcessorCount));
  917. builder.AppendLine(string.Format("Program data path: {0}", appPaths.ProgramDataPath));
  918. builder.AppendLine(string.Format("Application directory: {0}", appPaths.ProgramSystemPath));
  919. return builder;
  920. }
  921. private void SetHttpLimit()
  922. {
  923. try
  924. {
  925. // Increase the max http request limit
  926. ServicePointManager.DefaultConnectionLimit = Math.Max(96, ServicePointManager.DefaultConnectionLimit);
  927. }
  928. catch (Exception ex)
  929. {
  930. Logger.ErrorException("Error setting http limit", ex);
  931. }
  932. }
  933. protected string GetDefaultUserAgent()
  934. {
  935. var name = FormatAttribute(Name);
  936. return name + "/" + ApplicationVersion;
  937. }
  938. private string FormatAttribute(string str)
  939. {
  940. var arr = str.ToCharArray();
  941. arr = Array.FindAll<char>(arr, (c => (char.IsLetterOrDigit(c)
  942. || char.IsWhiteSpace(c))));
  943. var result = new string(arr);
  944. if (string.IsNullOrWhiteSpace(result))
  945. {
  946. result = "Emby";
  947. }
  948. return result;
  949. }
  950. protected virtual bool SupportsDualModeSockets
  951. {
  952. get
  953. {
  954. return true;
  955. }
  956. }
  957. private X509Certificate GetCertificate(CertificateInfo info)
  958. {
  959. var certificateLocation = info == null ? null : info.Path;
  960. if (string.IsNullOrWhiteSpace(certificateLocation))
  961. {
  962. return null;
  963. }
  964. try
  965. {
  966. if (!FileSystemManager.FileExists(certificateLocation))
  967. {
  968. return null;
  969. }
  970. // Don't use an empty string password
  971. var password = string.IsNullOrWhiteSpace(info.Password) ? null : info.Password;
  972. X509Certificate2 localCert = new X509Certificate2(certificateLocation, password);
  973. //localCert.PrivateKey = PrivateKey.CreateFromFile(pvk_file).RSA;
  974. if (!localCert.HasPrivateKey)
  975. {
  976. Logger.Error("No private key included in SSL cert {0}.", certificateLocation);
  977. return null;
  978. }
  979. return localCert;
  980. }
  981. catch (Exception ex)
  982. {
  983. Logger.ErrorException("Error loading cert from {0}", ex, certificateLocation);
  984. return null;
  985. }
  986. }
  987. private IImageProcessor GetImageProcessor()
  988. {
  989. return new ImageProcessor(LogManager.GetLogger("ImageProcessor"), ServerConfigurationManager.ApplicationPaths, FileSystemManager, JsonSerializer, ImageEncoder, () => LibraryManager, TimerFactory, () => MediaEncoder);
  990. }
  991. protected virtual FFMpegInstallInfo GetFfmpegInstallInfo()
  992. {
  993. var info = new FFMpegInstallInfo();
  994. // Windows builds: http://ffmpeg.zeranoe.com/builds/
  995. // Linux builds: http://johnvansickle.com/ffmpeg/
  996. // OS X builds: http://ffmpegmac.net/
  997. // OS X x64: http://www.evermeet.cx/ffmpeg/
  998. if (EnvironmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.Linux)
  999. {
  1000. info.FFMpegFilename = "ffmpeg";
  1001. info.FFProbeFilename = "ffprobe";
  1002. info.ArchiveType = "7z";
  1003. info.Version = "20170308";
  1004. }
  1005. else if (EnvironmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.Windows)
  1006. {
  1007. info.FFMpegFilename = "ffmpeg.exe";
  1008. info.FFProbeFilename = "ffprobe.exe";
  1009. info.Version = "20170308";
  1010. info.ArchiveType = "7z";
  1011. }
  1012. else if (EnvironmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.OSX)
  1013. {
  1014. info.FFMpegFilename = "ffmpeg";
  1015. info.FFProbeFilename = "ffprobe";
  1016. info.ArchiveType = "7z";
  1017. info.Version = "20170308";
  1018. }
  1019. return info;
  1020. }
  1021. protected virtual FFMpegInfo GetFFMpegInfo()
  1022. {
  1023. return new FFMpegLoader(Logger, ApplicationPaths, HttpClient, ZipClient, FileSystemManager, GetFfmpegInstallInfo())
  1024. .GetFFMpegInfo(StartupOptions);
  1025. }
  1026. /// <summary>
  1027. /// Registers the media encoder.
  1028. /// </summary>
  1029. /// <returns>Task.</returns>
  1030. private void RegisterMediaEncoder(IAssemblyInfo assemblyInfo)
  1031. {
  1032. string encoderPath = null;
  1033. string probePath = null;
  1034. var info = GetFFMpegInfo();
  1035. encoderPath = info.EncoderPath;
  1036. probePath = info.ProbePath;
  1037. var hasExternalEncoder = string.Equals(info.Version, "external", StringComparison.OrdinalIgnoreCase);
  1038. var mediaEncoder = new MediaEncoding.Encoder.MediaEncoder(LogManager.GetLogger("MediaEncoder"),
  1039. JsonSerializer,
  1040. encoderPath,
  1041. probePath,
  1042. hasExternalEncoder,
  1043. ServerConfigurationManager,
  1044. FileSystemManager,
  1045. LiveTvManager,
  1046. IsoManager,
  1047. LibraryManager,
  1048. ChannelManager,
  1049. SessionManager,
  1050. () => SubtitleEncoder,
  1051. () => MediaSourceManager,
  1052. HttpClient,
  1053. ZipClient,
  1054. ProcessFactory,
  1055. EnvironmentInfo,
  1056. BlurayExaminer,
  1057. assemblyInfo,
  1058. this);
  1059. MediaEncoder = mediaEncoder;
  1060. RegisterSingleInstance(MediaEncoder);
  1061. }
  1062. /// <summary>
  1063. /// Gets the user repository.
  1064. /// </summary>
  1065. /// <returns>Task{IUserRepository}.</returns>
  1066. private IUserRepository GetUserRepository()
  1067. {
  1068. var repo = new SqliteUserRepository(LogManager.GetLogger("SqliteUserRepository"), ApplicationPaths, JsonSerializer);
  1069. repo.Initialize();
  1070. return repo;
  1071. }
  1072. private IAuthenticationRepository GetAuthenticationRepository()
  1073. {
  1074. var repo = new AuthenticationRepository(LogManager.GetLogger("AuthenticationRepository"), ServerConfigurationManager);
  1075. repo.Initialize();
  1076. return repo;
  1077. }
  1078. private IActivityRepository GetActivityLogRepository()
  1079. {
  1080. var repo = new ActivityRepository(LogManager.GetLogger("ActivityRepository"), ServerConfigurationManager.ApplicationPaths, FileSystemManager);
  1081. repo.Initialize();
  1082. return repo;
  1083. }
  1084. /// <summary>
  1085. /// Dirty hacks
  1086. /// </summary>
  1087. private void SetStaticProperties()
  1088. {
  1089. ((SqliteItemRepository)ItemRepository).ImageProcessor = ImageProcessor;
  1090. // For now there's no real way to inject these properly
  1091. BaseItem.Logger = LogManager.GetLogger("BaseItem");
  1092. BaseItem.ConfigurationManager = ServerConfigurationManager;
  1093. BaseItem.LibraryManager = LibraryManager;
  1094. BaseItem.ProviderManager = ProviderManager;
  1095. BaseItem.LocalizationManager = LocalizationManager;
  1096. BaseItem.ItemRepository = ItemRepository;
  1097. User.UserManager = UserManager;
  1098. BaseItem.FileSystem = FileSystemManager;
  1099. BaseItem.UserDataManager = UserDataManager;
  1100. BaseItem.ChannelManager = ChannelManager;
  1101. Video.LiveTvManager = LiveTvManager;
  1102. Folder.UserViewManager = UserViewManager;
  1103. UserView.TVSeriesManager = TVSeriesManager;
  1104. UserView.PlaylistManager = PlaylistManager;
  1105. UserView.CollectionManager = CollectionManager;
  1106. BaseItem.MediaSourceManager = MediaSourceManager;
  1107. CollectionFolder.XmlSerializer = XmlSerializer;
  1108. CollectionFolder.JsonSerializer = JsonSerializer;
  1109. CollectionFolder.ApplicationHost = this;
  1110. AuthenticatedAttribute.AuthService = AuthService;
  1111. }
  1112. /// <summary>
  1113. /// Finds the parts.
  1114. /// </summary>
  1115. protected void FindParts()
  1116. {
  1117. if (!ServerConfigurationManager.Configuration.IsPortAuthorized)
  1118. {
  1119. RegisterServerWithAdministratorAccess();
  1120. ServerConfigurationManager.Configuration.IsPortAuthorized = true;
  1121. ConfigurationManager.SaveConfiguration();
  1122. }
  1123. ConfigurationManager.AddParts(GetExports<IConfigurationFactory>());
  1124. Plugins = GetExportsWithInfo<IPlugin>().Select(LoadPlugin).Where(i => i != null).ToArray();
  1125. HttpServer.Init(GetExports<IService>(false), GetExports<IWebSocketListener>());
  1126. StartServer();
  1127. LibraryManager.AddParts(GetExports<IResolverIgnoreRule>(),
  1128. GetExports<IItemResolver>(),
  1129. GetExports<IIntroProvider>(),
  1130. GetExports<IBaseItemComparer>(),
  1131. GetExports<ILibraryPostScanTask>());
  1132. ProviderManager.AddParts(GetExports<IImageProvider>(),
  1133. GetExports<IMetadataService>(),
  1134. GetExports<IMetadataProvider>(),
  1135. GetExports<IMetadataSaver>(),
  1136. GetExports<IExternalId>());
  1137. ImageProcessor.AddParts(GetExports<IImageEnhancer>());
  1138. LiveTvManager.AddParts(GetExports<ILiveTvService>(), GetExports<ITunerHost>(), GetExports<IListingsProvider>());
  1139. SubtitleManager.AddParts(GetExports<ISubtitleProvider>());
  1140. ChannelManager.AddParts(GetExports<IChannel>());
  1141. MediaSourceManager.AddParts(GetExports<IMediaSourceProvider>());
  1142. NotificationManager.AddParts(GetExports<INotificationService>(), GetExports<INotificationTypeFactory>());
  1143. UserManager.AddParts(GetExports<IAuthenticationProvider>());
  1144. IsoManager.AddParts(GetExports<IIsoMounter>());
  1145. }
  1146. private IPlugin LoadPlugin(Tuple<IPlugin, string> info)
  1147. {
  1148. var plugin = info.Item1;
  1149. var assemblyFilePath = info.Item2;
  1150. try
  1151. {
  1152. var assemblyPlugin = plugin as IPluginAssembly;
  1153. if (assemblyPlugin != null)
  1154. {
  1155. var assembly = plugin.GetType().Assembly;
  1156. var assemblyName = assembly.GetName();
  1157. var dataFolderPath = Path.Combine(ApplicationPaths.PluginsPath, Path.GetFileNameWithoutExtension(assemblyFilePath));
  1158. assemblyPlugin.SetAttributes(assemblyFilePath, dataFolderPath, assemblyName.Version);
  1159. try
  1160. {
  1161. var idAttributes = assembly.GetCustomAttributes(typeof(GuidAttribute), true);
  1162. if (idAttributes.Length > 0)
  1163. {
  1164. var attribute = (GuidAttribute)idAttributes[0];
  1165. var assemblyId = new Guid(attribute.Value);
  1166. assemblyPlugin.SetId(assemblyId);
  1167. }
  1168. }
  1169. catch (Exception ex)
  1170. {
  1171. Logger.ErrorException("Error getting plugin Id from {0}.", ex, plugin.GetType().FullName);
  1172. }
  1173. }
  1174. var hasPluginConfiguration = plugin as IHasPluginConfiguration;
  1175. if (hasPluginConfiguration != null)
  1176. {
  1177. hasPluginConfiguration.SetStartupInfo(s => Directory.CreateDirectory(s));
  1178. }
  1179. }
  1180. catch (Exception ex)
  1181. {
  1182. Logger.ErrorException("Error loading plugin {0}", ex, plugin.GetType().FullName);
  1183. return null;
  1184. }
  1185. return plugin;
  1186. }
  1187. /// <summary>
  1188. /// Discovers the types.
  1189. /// </summary>
  1190. protected void DiscoverTypes()
  1191. {
  1192. Logger.Info("Loading assemblies");
  1193. var assemblyInfos = GetComposablePartAssemblies();
  1194. foreach (var assemblyInfo in assemblyInfos)
  1195. {
  1196. var assembly = assemblyInfo.Item1;
  1197. var path = assemblyInfo.Item2;
  1198. if (path == null)
  1199. {
  1200. Logger.Info("Loading {0}", assembly.FullName);
  1201. }
  1202. else
  1203. {
  1204. Logger.Info("Loading {0} from {1}", assembly.FullName, path);
  1205. }
  1206. }
  1207. AllConcreteTypes = assemblyInfos
  1208. .SelectMany(GetTypes)
  1209. .Where(info =>
  1210. {
  1211. var t = info.Item1;
  1212. return t.IsClass && !t.IsAbstract && !t.IsInterface && !t.IsGenericType;
  1213. })
  1214. .ToArray();
  1215. }
  1216. /// <summary>
  1217. /// Gets a list of types within an assembly
  1218. /// This will handle situations that would normally throw an exception - such as a type within the assembly that depends on some other non-existant reference
  1219. /// </summary>
  1220. protected List<Tuple<Type, string>> GetTypes(Tuple<Assembly, string> assemblyInfo)
  1221. {
  1222. if (assemblyInfo == null)
  1223. {
  1224. return new List<Tuple<Type, string>>();
  1225. }
  1226. var assembly = assemblyInfo.Item1;
  1227. try
  1228. {
  1229. // This null checking really shouldn't be needed but adding it due to some
  1230. // unhandled exceptions in mono 5.0 that are a little hard to hunt down
  1231. var types = assembly.GetTypes() ?? new Type[] { };
  1232. return types.Where(t => t != null).Select(i => new Tuple<Type, string>(i, assemblyInfo.Item2)).ToList();
  1233. }
  1234. catch (ReflectionTypeLoadException ex)
  1235. {
  1236. if (ex.LoaderExceptions != null)
  1237. {
  1238. foreach (var loaderException in ex.LoaderExceptions)
  1239. {
  1240. if (loaderException != null)
  1241. {
  1242. Logger.Error("LoaderException: " + loaderException.Message);
  1243. }
  1244. }
  1245. }
  1246. // If it fails we can still get a list of the Types it was able to resolve
  1247. var types = ex.Types ?? new Type[] { };
  1248. return types.Where(t => t != null).Select(i => new Tuple<Type, string>(i, assemblyInfo.Item2)).ToList();
  1249. }
  1250. catch (Exception ex)
  1251. {
  1252. Logger.ErrorException("Error loading types from assembly", ex);
  1253. return new List<Tuple<Type, string>>();
  1254. }
  1255. }
  1256. private CertificateInfo CertificateInfo { get; set; }
  1257. protected X509Certificate Certificate { get; private set; }
  1258. private IEnumerable<string> GetUrlPrefixes()
  1259. {
  1260. var hosts = new[] { "+" };
  1261. return hosts.SelectMany(i =>
  1262. {
  1263. var prefixes = new List<string>
  1264. {
  1265. "http://"+i+":" + HttpPort + "/"
  1266. };
  1267. if (CertificateInfo != null)
  1268. {
  1269. prefixes.Add("https://" + i + ":" + HttpsPort + "/");
  1270. }
  1271. return prefixes;
  1272. });
  1273. }
  1274. protected abstract IHttpListener CreateHttpListener();
  1275. /// <summary>
  1276. /// Starts the server.
  1277. /// </summary>
  1278. private void StartServer()
  1279. {
  1280. try
  1281. {
  1282. ((HttpListenerHost)HttpServer).StartServer(GetUrlPrefixes().ToArray(), CreateHttpListener());
  1283. return;
  1284. }
  1285. catch (Exception ex)
  1286. {
  1287. var msg = string.Equals(ex.GetType().Name, "SocketException", StringComparison.OrdinalIgnoreCase)
  1288. ? "The http server is unable to start due to a Socket error. This can occasionally happen when the operating system takes longer than usual to release the IP bindings from the previous session. This can take up to five minutes. Please try waiting or rebooting the system."
  1289. : "Error starting Http Server";
  1290. Logger.ErrorException(msg, ex);
  1291. if (HttpPort == ServerConfiguration.DefaultHttpPort)
  1292. {
  1293. throw;
  1294. }
  1295. }
  1296. HttpPort = ServerConfiguration.DefaultHttpPort;
  1297. try
  1298. {
  1299. ((HttpListenerHost)HttpServer).StartServer(GetUrlPrefixes().ToArray(), CreateHttpListener());
  1300. }
  1301. catch (Exception ex)
  1302. {
  1303. Logger.ErrorException("Error starting http server", ex);
  1304. throw;
  1305. }
  1306. }
  1307. private CertificateInfo GetCertificateInfo(bool generateCertificate)
  1308. {
  1309. if (!string.IsNullOrWhiteSpace(ServerConfigurationManager.Configuration.CertificatePath))
  1310. {
  1311. // Custom cert
  1312. return new CertificateInfo
  1313. {
  1314. Path = ServerConfigurationManager.Configuration.CertificatePath,
  1315. Password = ServerConfigurationManager.Configuration.CertificatePassword
  1316. };
  1317. }
  1318. // Generate self-signed cert
  1319. var certHost = GetHostnameFromExternalDns(ServerConfigurationManager.Configuration.WanDdns);
  1320. var certPath = Path.Combine(ServerConfigurationManager.ApplicationPaths.ProgramDataPath, "ssl", "cert_" + (certHost + "2").GetMD5().ToString("N") + ".pfx");
  1321. var password = "embycert";
  1322. //if (generateCertificate)
  1323. //{
  1324. // if (!FileSystemManager.FileExists(certPath))
  1325. // {
  1326. // FileSystemManager.CreateDirectory(FileSystemManager.GetDirectoryName(certPath));
  1327. // try
  1328. // {
  1329. // CertificateGenerator.CreateSelfSignCertificatePfx(certPath, certHost, password, Logger);
  1330. // }
  1331. // catch (Exception ex)
  1332. // {
  1333. // Logger.ErrorException("Error creating ssl cert", ex);
  1334. // return null;
  1335. // }
  1336. // }
  1337. //}
  1338. return new CertificateInfo
  1339. {
  1340. Path = certPath,
  1341. Password = password
  1342. };
  1343. }
  1344. /// <summary>
  1345. /// Called when [configuration updated].
  1346. /// </summary>
  1347. /// <param name="sender">The sender.</param>
  1348. /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
  1349. protected void OnConfigurationUpdated(object sender, EventArgs e)
  1350. {
  1351. ConfigureAutorun();
  1352. var requiresRestart = false;
  1353. // Don't do anything if these haven't been set yet
  1354. if (HttpPort != 0 && HttpsPort != 0)
  1355. {
  1356. // Need to restart if ports have changed
  1357. if (ServerConfigurationManager.Configuration.HttpServerPortNumber != HttpPort ||
  1358. ServerConfigurationManager.Configuration.HttpsPortNumber != HttpsPort)
  1359. {
  1360. if (ServerConfigurationManager.Configuration.IsPortAuthorized)
  1361. {
  1362. ServerConfigurationManager.Configuration.IsPortAuthorized = false;
  1363. ServerConfigurationManager.SaveConfiguration();
  1364. requiresRestart = true;
  1365. }
  1366. }
  1367. }
  1368. if (!HttpServer.UrlPrefixes.SequenceEqual(GetUrlPrefixes(), StringComparer.OrdinalIgnoreCase))
  1369. {
  1370. requiresRestart = true;
  1371. }
  1372. var currentCertPath = CertificateInfo == null ? null : CertificateInfo.Path;
  1373. var newCertInfo = GetCertificateInfo(false);
  1374. var newCertPath = newCertInfo == null ? null : newCertInfo.Path;
  1375. if (!string.Equals(currentCertPath, newCertPath, StringComparison.OrdinalIgnoreCase))
  1376. {
  1377. requiresRestart = true;
  1378. }
  1379. if (requiresRestart)
  1380. {
  1381. Logger.Info("App needs to be restarted due to configuration change.");
  1382. NotifyPendingRestart();
  1383. }
  1384. }
  1385. /// <summary>
  1386. /// Notifies that the kernel that a change has been made that requires a restart
  1387. /// </summary>
  1388. public void NotifyPendingRestart()
  1389. {
  1390. Logger.Info("App needs to be restarted.");
  1391. var changed = !HasPendingRestart;
  1392. HasPendingRestart = true;
  1393. if (changed)
  1394. {
  1395. EventHelper.QueueEventIfNotNull(HasPendingRestartChanged, this, EventArgs.Empty, Logger);
  1396. }
  1397. }
  1398. /// <summary>
  1399. /// Restarts this instance.
  1400. /// </summary>
  1401. public void Restart()
  1402. {
  1403. if (!CanSelfRestart)
  1404. {
  1405. throw new PlatformNotSupportedException("The server is unable to self-restart. Please restart manually.");
  1406. }
  1407. if (IsShuttingDown)
  1408. {
  1409. return;
  1410. }
  1411. IsShuttingDown = true;
  1412. Task.Run(async () =>
  1413. {
  1414. try
  1415. {
  1416. await SessionManager.SendServerRestartNotification(CancellationToken.None).ConfigureAwait(false);
  1417. }
  1418. catch (Exception ex)
  1419. {
  1420. Logger.ErrorException("Error sending server restart notification", ex);
  1421. }
  1422. Logger.Info("Calling RestartInternal");
  1423. RestartInternal();
  1424. });
  1425. }
  1426. protected abstract void RestartInternal();
  1427. /// <summary>
  1428. /// Gets the composable part assemblies.
  1429. /// </summary>
  1430. /// <returns>IEnumerable{Assembly}.</returns>
  1431. protected List<Tuple<Assembly, string>> GetComposablePartAssemblies()
  1432. {
  1433. var list = GetPluginAssemblies();
  1434. // Gets all plugin assemblies by first reading all bytes of the .dll and calling Assembly.Load against that
  1435. // This will prevent the .dll file from getting locked, and allow us to replace it when needed
  1436. // Include composable parts in the Api assembly
  1437. list.Add(GetAssembly(typeof(ApiEntryPoint)));
  1438. // Include composable parts in the Dashboard assembly
  1439. list.Add(GetAssembly(typeof(DashboardService)));
  1440. // Include composable parts in the Model assembly
  1441. list.Add(GetAssembly(typeof(SystemInfo)));
  1442. // Include composable parts in the Common assembly
  1443. list.Add(GetAssembly(typeof(IApplicationHost)));
  1444. // Include composable parts in the Controller assembly
  1445. list.Add(GetAssembly(typeof(IServerApplicationHost)));
  1446. // Include composable parts in the Providers assembly
  1447. list.Add(GetAssembly(typeof(ProviderUtils)));
  1448. // Include composable parts in the Photos assembly
  1449. list.Add(GetAssembly(typeof(PhotoProvider)));
  1450. // Emby.Server implementations
  1451. list.Add(GetAssembly(typeof(InstallationManager)));
  1452. // MediaEncoding
  1453. list.Add(GetAssembly(typeof(MediaEncoding.Encoder.MediaEncoder)));
  1454. // Dlna
  1455. list.Add(GetAssembly(typeof(DlnaEntryPoint)));
  1456. // Local metadata
  1457. list.Add(GetAssembly(typeof(BoxSetXmlSaver)));
  1458. // Notifications
  1459. list.Add(GetAssembly(typeof(NotificationManager)));
  1460. // Xbmc
  1461. list.Add(GetAssembly(typeof(ArtistNfoProvider)));
  1462. list.AddRange(GetAssembliesWithPartsInternal().Select(i => new Tuple<Assembly, string>(i, null)));
  1463. return list.ToList();
  1464. }
  1465. protected abstract List<Assembly> GetAssembliesWithPartsInternal();
  1466. /// <summary>
  1467. /// Gets the plugin assemblies.
  1468. /// </summary>
  1469. /// <returns>IEnumerable{Assembly}.</returns>
  1470. private List<Tuple<Assembly, string>> GetPluginAssemblies()
  1471. {
  1472. // Copy pre-installed plugins
  1473. var sourcePath = Path.Combine(ApplicationPaths.ApplicationResourcesPath, "plugins");
  1474. CopyPlugins(sourcePath, ApplicationPaths.PluginsPath);
  1475. return GetPluginAssemblies(ApplicationPaths.PluginsPath);
  1476. }
  1477. private void CopyPlugins(string source, string target)
  1478. {
  1479. List<string> files;
  1480. try
  1481. {
  1482. files = Directory.EnumerateFiles(source, "*.dll", SearchOption.TopDirectoryOnly)
  1483. .ToList();
  1484. }
  1485. catch (DirectoryNotFoundException)
  1486. {
  1487. return;
  1488. }
  1489. if (files.Count == 0)
  1490. {
  1491. return;
  1492. }
  1493. foreach (var sourceFile in files)
  1494. {
  1495. var filename = Path.GetFileName(sourceFile);
  1496. var targetFile = Path.Combine(target, filename);
  1497. var targetFileExists = File.Exists(targetFile);
  1498. if (!targetFileExists && ServerConfigurationManager.Configuration.UninstalledPlugins.Contains(filename, StringComparer.OrdinalIgnoreCase))
  1499. {
  1500. continue;
  1501. }
  1502. if (targetFileExists && GetDllVersion(targetFile) >= GetDllVersion(sourceFile))
  1503. {
  1504. continue;
  1505. }
  1506. Directory.CreateDirectory(target);
  1507. File.Copy(sourceFile, targetFile, true);
  1508. }
  1509. }
  1510. private Version GetDllVersion(string path)
  1511. {
  1512. try
  1513. {
  1514. var result = Version.Parse(FileVersionInfo.GetVersionInfo(path).FileVersion);
  1515. Logger.Info("File {0} has version {1}", path, result);
  1516. return result;
  1517. }
  1518. catch (Exception ex)
  1519. {
  1520. Logger.ErrorException("Error getting version number from {0}", ex, path);
  1521. return new Version(1, 0);
  1522. }
  1523. }
  1524. private List<Tuple<Assembly, string>> GetPluginAssemblies(string path)
  1525. {
  1526. try
  1527. {
  1528. return FilterAssembliesToLoad(Directory.EnumerateFiles(path, "*.dll", SearchOption.TopDirectoryOnly))
  1529. .Select(LoadAssembly)
  1530. .Where(a => a != null)
  1531. .ToList();
  1532. }
  1533. catch (DirectoryNotFoundException)
  1534. {
  1535. return new List<Tuple<Assembly, string>>();
  1536. }
  1537. }
  1538. private IEnumerable<string> FilterAssembliesToLoad(IEnumerable<string> paths)
  1539. {
  1540. var exclude = new[]
  1541. {
  1542. "mbplus.dll",
  1543. "mbintros.dll",
  1544. "embytv.dll",
  1545. "Messenger.dll",
  1546. "Messages.dll",
  1547. "MediaBrowser.Plugins.TvMazeProvider.dll",
  1548. "MBBookshelf.dll",
  1549. "MediaBrowser.Channels.Adult.YouJizz.dll",
  1550. "MediaBrowser.Channels.Vine-co.dll",
  1551. "MediaBrowser.Plugins.Vimeo.dll",
  1552. "MediaBrowser.Channels.Vevo.dll",
  1553. "MediaBrowser.Plugins.Twitch.dll",
  1554. "MediaBrowser.Channels.SvtPlay.dll",
  1555. "MediaBrowser.Plugins.SoundCloud.dll",
  1556. "MediaBrowser.Plugins.SnesBox.dll",
  1557. "MediaBrowser.Plugins.RottenTomatoes.dll",
  1558. "MediaBrowser.Plugins.Revision3.dll",
  1559. "MediaBrowser.Plugins.NesBox.dll",
  1560. "MBChapters.dll",
  1561. "MediaBrowser.Channels.LeagueOfLegends.dll",
  1562. "MediaBrowser.Plugins.ADEProvider.dll",
  1563. "MediaBrowser.Channels.BallStreams.dll",
  1564. "MediaBrowser.Channels.Adult.Beeg.dll",
  1565. "ChannelDownloader.dll",
  1566. "Hamstercat.Emby.EmbyBands.dll",
  1567. "EmbyTV.dll",
  1568. "MediaBrowser.Channels.HitboxTV.dll",
  1569. "MediaBrowser.Channels.HockeyStreams.dll",
  1570. "MediaBrowser.Plugins.ITV.dll",
  1571. "MediaBrowser.Plugins.Lastfm.dll",
  1572. "ServerRestart.dll",
  1573. "MediaBrowser.Plugins.NotifyMyAndroidNotifications.dll",
  1574. "MetadataViewer.dll"
  1575. };
  1576. var minRequiredVersions = new Dictionary<string, Version>(StringComparer.OrdinalIgnoreCase)
  1577. {
  1578. { "GameBrowser.dll", new Version(3, 1) },
  1579. { "moviethemesongs.dll", new Version(1, 6) },
  1580. { "themesongs.dll", new Version(1, 2) }
  1581. };
  1582. return paths.Where(path =>
  1583. {
  1584. var filename = Path.GetFileName(path);
  1585. if (exclude.Contains(filename ?? string.Empty, StringComparer.OrdinalIgnoreCase))
  1586. {
  1587. return false;
  1588. }
  1589. Version minRequiredVersion;
  1590. if (minRequiredVersions.TryGetValue(filename, out minRequiredVersion))
  1591. {
  1592. try
  1593. {
  1594. var version = Version.Parse(FileVersionInfo.GetVersionInfo(path).FileVersion);
  1595. if (version < minRequiredVersion)
  1596. {
  1597. Logger.Info("Not loading {0} {1} because the minimum supported version is {2}. Please update to the newer version", filename, version, minRequiredVersion);
  1598. return false;
  1599. }
  1600. }
  1601. catch (Exception ex)
  1602. {
  1603. Logger.ErrorException("Error getting version number from {0}", ex, path);
  1604. return false;
  1605. }
  1606. }
  1607. return true;
  1608. });
  1609. }
  1610. /// <summary>
  1611. /// Gets the system status.
  1612. /// </summary>
  1613. /// <returns>SystemInfo.</returns>
  1614. public async Task<SystemInfo> GetSystemInfo(CancellationToken cancellationToken)
  1615. {
  1616. var localAddress = await GetLocalApiUrl(cancellationToken).ConfigureAwait(false);
  1617. return new SystemInfo
  1618. {
  1619. HasPendingRestart = HasPendingRestart,
  1620. IsShuttingDown = IsShuttingDown,
  1621. Version = ApplicationVersion.ToString(),
  1622. WebSocketPortNumber = HttpPort,
  1623. CompletedInstallations = InstallationManager.CompletedInstallations.ToArray(),
  1624. Id = SystemId,
  1625. ProgramDataPath = ApplicationPaths.ProgramDataPath,
  1626. LogPath = ApplicationPaths.LogDirectoryPath,
  1627. ItemsByNamePath = ApplicationPaths.InternalMetadataPath,
  1628. InternalMetadataPath = ApplicationPaths.InternalMetadataPath,
  1629. CachePath = ApplicationPaths.CachePath,
  1630. HttpServerPortNumber = HttpPort,
  1631. SupportsHttps = SupportsHttps,
  1632. HttpsPortNumber = HttpsPort,
  1633. OperatingSystem = EnvironmentInfo.OperatingSystem.ToString(),
  1634. OperatingSystemDisplayName = OperatingSystemDisplayName,
  1635. CanSelfRestart = CanSelfRestart,
  1636. CanSelfUpdate = CanSelfUpdate,
  1637. CanLaunchWebBrowser = CanLaunchWebBrowser,
  1638. WanAddress = ConnectManager.WanApiAddress,
  1639. HasUpdateAvailable = HasUpdateAvailable,
  1640. SupportsAutoRunAtStartup = SupportsAutoRunAtStartup,
  1641. TranscodingTempPath = ApplicationPaths.TranscodingTempPath,
  1642. ServerName = FriendlyName,
  1643. LocalAddress = localAddress,
  1644. SupportsLibraryMonitor = true,
  1645. EncoderLocationType = MediaEncoder.EncoderLocationType,
  1646. SystemArchitecture = EnvironmentInfo.SystemArchitecture,
  1647. SystemUpdateLevel = SystemUpdateLevel,
  1648. PackageName = StartupOptions.GetOption("-package")
  1649. };
  1650. }
  1651. public WakeOnLanInfo[] GetWakeOnLanInfo()
  1652. {
  1653. return NetworkManager.GetMacAddresses()
  1654. .Select(i => new WakeOnLanInfo
  1655. {
  1656. MacAddress = i
  1657. })
  1658. .ToArray();
  1659. }
  1660. public async Task<PublicSystemInfo> GetPublicSystemInfo(CancellationToken cancellationToken)
  1661. {
  1662. var localAddress = await GetLocalApiUrl(cancellationToken).ConfigureAwait(false);
  1663. return new PublicSystemInfo
  1664. {
  1665. Version = ApplicationVersion.ToString(),
  1666. Id = SystemId,
  1667. OperatingSystem = EnvironmentInfo.OperatingSystem.ToString(),
  1668. WanAddress = ConnectManager.WanApiAddress,
  1669. ServerName = FriendlyName,
  1670. LocalAddress = localAddress
  1671. };
  1672. }
  1673. public bool EnableHttps
  1674. {
  1675. get
  1676. {
  1677. return SupportsHttps && ServerConfigurationManager.Configuration.EnableHttps;
  1678. }
  1679. }
  1680. public bool SupportsHttps
  1681. {
  1682. get { return Certificate != null || ServerConfigurationManager.Configuration.IsBehindProxy; }
  1683. }
  1684. public async Task<string> GetLocalApiUrl(CancellationToken cancellationToken)
  1685. {
  1686. try
  1687. {
  1688. // Return the first matched address, if found, or the first known local address
  1689. var addresses = await GetLocalIpAddressesInternal(false, 1, cancellationToken).ConfigureAwait(false);
  1690. foreach (var address in addresses)
  1691. {
  1692. return GetLocalApiUrl(address);
  1693. }
  1694. return null;
  1695. }
  1696. catch (Exception ex)
  1697. {
  1698. Logger.ErrorException("Error getting local Ip address information", ex);
  1699. }
  1700. return null;
  1701. }
  1702. public string GetLocalApiUrl(IpAddressInfo ipAddress)
  1703. {
  1704. if (ipAddress.AddressFamily == IpAddressFamily.InterNetworkV6)
  1705. {
  1706. return GetLocalApiUrl("[" + ipAddress.Address + "]");
  1707. }
  1708. return GetLocalApiUrl(ipAddress.Address);
  1709. }
  1710. public string GetLocalApiUrl(string host)
  1711. {
  1712. return string.Format("http://{0}:{1}",
  1713. host,
  1714. HttpPort.ToString(CultureInfo.InvariantCulture));
  1715. }
  1716. public Task<List<IpAddressInfo>> GetLocalIpAddresses(CancellationToken cancellationToken)
  1717. {
  1718. return GetLocalIpAddressesInternal(true, 0, cancellationToken);
  1719. }
  1720. private async Task<List<IpAddressInfo>> GetLocalIpAddressesInternal(bool allowLoopback, int limit, CancellationToken cancellationToken)
  1721. {
  1722. var addresses = ServerConfigurationManager
  1723. .Configuration
  1724. .LocalNetworkAddresses
  1725. .Select(NormalizeConfiguredLocalAddress)
  1726. .Where(i => i != null)
  1727. .ToList();
  1728. if (addresses.Count == 0)
  1729. {
  1730. addresses.AddRange(NetworkManager.GetLocalIpAddresses());
  1731. }
  1732. var resultList = new List<IpAddressInfo>();
  1733. foreach (var address in addresses)
  1734. {
  1735. if (!allowLoopback)
  1736. {
  1737. if (address.Equals(IpAddressInfo.Loopback) || address.Equals(IpAddressInfo.IPv6Loopback))
  1738. {
  1739. continue;
  1740. }
  1741. }
  1742. var valid = await IsIpAddressValidAsync(address, cancellationToken).ConfigureAwait(false);
  1743. if (valid)
  1744. {
  1745. resultList.Add(address);
  1746. if (limit > 0 && resultList.Count >= limit)
  1747. {
  1748. return resultList;
  1749. }
  1750. }
  1751. }
  1752. return resultList;
  1753. }
  1754. private IpAddressInfo NormalizeConfiguredLocalAddress(string address)
  1755. {
  1756. var index = address.Trim('/').IndexOf('/');
  1757. if (index != -1)
  1758. {
  1759. address = address.Substring(index + 1);
  1760. }
  1761. IpAddressInfo result;
  1762. if (NetworkManager.TryParseIpAddress(address.Trim('/'), out result))
  1763. {
  1764. return result;
  1765. }
  1766. return null;
  1767. }
  1768. private readonly ConcurrentDictionary<string, bool> _validAddressResults = new ConcurrentDictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
  1769. private async Task<bool> IsIpAddressValidAsync(IpAddressInfo address, CancellationToken cancellationToken)
  1770. {
  1771. if (address.Equals(IpAddressInfo.Loopback) ||
  1772. address.Equals(IpAddressInfo.IPv6Loopback))
  1773. {
  1774. return true;
  1775. }
  1776. var apiUrl = GetLocalApiUrl(address);
  1777. apiUrl += "/system/ping";
  1778. bool cachedResult;
  1779. if (_validAddressResults.TryGetValue(apiUrl, out cachedResult))
  1780. {
  1781. return cachedResult;
  1782. }
  1783. var logPing = false;
  1784. #if DEBUG
  1785. logPing = true;
  1786. #endif
  1787. try
  1788. {
  1789. using (var response = await HttpClient.SendAsync(new HttpRequestOptions
  1790. {
  1791. Url = apiUrl,
  1792. LogErrorResponseBody = false,
  1793. LogErrors = logPing,
  1794. LogRequest = logPing,
  1795. TimeoutMs = 30000,
  1796. BufferContent = false,
  1797. CancellationToken = cancellationToken
  1798. }, "POST").ConfigureAwait(false))
  1799. {
  1800. using (var reader = new StreamReader(response.Content))
  1801. {
  1802. var result = reader.ReadToEnd();
  1803. var valid = string.Equals(Name, result, StringComparison.OrdinalIgnoreCase);
  1804. _validAddressResults.AddOrUpdate(apiUrl, valid, (k, v) => valid);
  1805. Logger.Debug("Ping test result to {0}. Success: {1}", apiUrl, valid);
  1806. return valid;
  1807. }
  1808. }
  1809. }
  1810. catch (OperationCanceledException)
  1811. {
  1812. Logger.Debug("Ping test result to {0}. Success: {1}", apiUrl, "Cancelled");
  1813. throw;
  1814. }
  1815. catch (Exception ex)
  1816. {
  1817. Logger.Debug("Ping test result to {0}. Success: {1} {2}", apiUrl, false, ex.Message);
  1818. _validAddressResults.AddOrUpdate(apiUrl, false, (k, v) => false);
  1819. return false;
  1820. }
  1821. }
  1822. public string FriendlyName
  1823. {
  1824. get
  1825. {
  1826. return string.IsNullOrEmpty(ServerConfigurationManager.Configuration.ServerName)
  1827. ? Environment.MachineName
  1828. : ServerConfigurationManager.Configuration.ServerName;
  1829. }
  1830. }
  1831. public int HttpPort { get; private set; }
  1832. public int HttpsPort { get; private set; }
  1833. /// <summary>
  1834. /// Shuts down.
  1835. /// </summary>
  1836. public async Task Shutdown()
  1837. {
  1838. if (IsShuttingDown)
  1839. {
  1840. return;
  1841. }
  1842. IsShuttingDown = true;
  1843. try
  1844. {
  1845. await SessionManager.SendServerShutdownNotification(CancellationToken.None).ConfigureAwait(false);
  1846. }
  1847. catch (Exception ex)
  1848. {
  1849. Logger.ErrorException("Error sending server shutdown notification", ex);
  1850. }
  1851. ShutdownInternal();
  1852. }
  1853. protected abstract void ShutdownInternal();
  1854. /// <summary>
  1855. /// Registers the server with administrator access.
  1856. /// </summary>
  1857. private void RegisterServerWithAdministratorAccess()
  1858. {
  1859. Logger.Info("Requesting administrative access to authorize http server");
  1860. try
  1861. {
  1862. AuthorizeServer();
  1863. }
  1864. catch (NotImplementedException)
  1865. {
  1866. }
  1867. catch (Exception ex)
  1868. {
  1869. Logger.ErrorException("Error authorizing server", ex);
  1870. }
  1871. }
  1872. protected virtual void AuthorizeServer()
  1873. {
  1874. throw new NotImplementedException();
  1875. }
  1876. public event EventHandler HasUpdateAvailableChanged;
  1877. private bool _hasUpdateAvailable;
  1878. public bool HasUpdateAvailable
  1879. {
  1880. get { return _hasUpdateAvailable; }
  1881. set
  1882. {
  1883. var fireEvent = value && !_hasUpdateAvailable;
  1884. _hasUpdateAvailable = value;
  1885. if (fireEvent)
  1886. {
  1887. EventHelper.FireEventIfNotNull(HasUpdateAvailableChanged, this, EventArgs.Empty, Logger);
  1888. }
  1889. }
  1890. }
  1891. /// <summary>
  1892. /// Removes the plugin.
  1893. /// </summary>
  1894. /// <param name="plugin">The plugin.</param>
  1895. public void RemovePlugin(IPlugin plugin)
  1896. {
  1897. var list = Plugins.ToList();
  1898. list.Remove(plugin);
  1899. Plugins = list.ToArray();
  1900. }
  1901. /// <summary>
  1902. /// Checks for update.
  1903. /// </summary>
  1904. /// <param name="cancellationToken">The cancellation token.</param>
  1905. /// <param name="progress">The progress.</param>
  1906. /// <returns>Task{CheckForUpdateResult}.</returns>
  1907. public async Task<CheckForUpdateResult> CheckForApplicationUpdate(CancellationToken cancellationToken, IProgress<double> progress)
  1908. {
  1909. var updateLevel = SystemUpdateLevel;
  1910. var cacheLength = updateLevel == PackageVersionClass.Release ?
  1911. TimeSpan.FromHours(12) :
  1912. TimeSpan.FromMinutes(5);
  1913. try
  1914. {
  1915. var result = await new GithubUpdater(HttpClient, JsonSerializer).CheckForUpdateResult("MediaBrowser",
  1916. "Emby.Releases",
  1917. ApplicationVersion,
  1918. updateLevel,
  1919. ReleaseAssetFilename,
  1920. "MBServer",
  1921. UpdateTargetFileName,
  1922. cacheLength,
  1923. cancellationToken).ConfigureAwait(false);
  1924. HasUpdateAvailable = result.IsUpdateAvailable;
  1925. return result;
  1926. }
  1927. catch (HttpException ex)
  1928. {
  1929. // users are overreacting to this occasionally failing
  1930. if (ex.StatusCode.HasValue && ex.StatusCode.Value == HttpStatusCode.Forbidden)
  1931. {
  1932. HasUpdateAvailable = false;
  1933. return new CheckForUpdateResult
  1934. {
  1935. IsUpdateAvailable = false
  1936. };
  1937. }
  1938. throw;
  1939. }
  1940. }
  1941. protected virtual string UpdateTargetFileName
  1942. {
  1943. get { return "Mbserver.zip"; }
  1944. }
  1945. /// <summary>
  1946. /// Updates the application.
  1947. /// </summary>
  1948. /// <param name="package">The package that contains the update</param>
  1949. /// <param name="cancellationToken">The cancellation token.</param>
  1950. /// <param name="progress">The progress.</param>
  1951. public async Task UpdateApplication(PackageVersionInfo package, CancellationToken cancellationToken, IProgress<double> progress)
  1952. {
  1953. await InstallationManager.InstallPackage(package, false, progress, cancellationToken).ConfigureAwait(false);
  1954. HasUpdateAvailable = false;
  1955. OnApplicationUpdated(package);
  1956. }
  1957. /// <summary>
  1958. /// Configures the automatic run at startup.
  1959. /// </summary>
  1960. /// <param name="autorun">if set to <c>true</c> [autorun].</param>
  1961. protected void ConfigureAutoRunAtStartup(bool autorun)
  1962. {
  1963. if (SupportsAutoRunAtStartup)
  1964. {
  1965. ConfigureAutoRunInternal(autorun);
  1966. }
  1967. }
  1968. protected virtual void ConfigureAutoRunInternal(bool autorun)
  1969. {
  1970. throw new NotImplementedException();
  1971. }
  1972. /// <summary>
  1973. /// This returns localhost in the case of no external dns, and the hostname if the
  1974. /// dns is prefixed with a valid Uri prefix.
  1975. /// </summary>
  1976. /// <param name="externalDns">The external dns prefix to get the hostname of.</param>
  1977. /// <returns>The hostname in <paramref name="externalDns"/></returns>
  1978. private static string GetHostnameFromExternalDns(string externalDns)
  1979. {
  1980. if (string.IsNullOrEmpty(externalDns))
  1981. {
  1982. return "localhost";
  1983. }
  1984. try
  1985. {
  1986. return new Uri(externalDns).Host;
  1987. }
  1988. catch
  1989. {
  1990. return externalDns;
  1991. }
  1992. }
  1993. public virtual void LaunchUrl(string url)
  1994. {
  1995. if (!CanLaunchWebBrowser)
  1996. {
  1997. throw new NotSupportedException();
  1998. }
  1999. var process = ProcessFactory.Create(new ProcessOptions
  2000. {
  2001. FileName = url,
  2002. //EnableRaisingEvents = true,
  2003. UseShellExecute = true,
  2004. ErrorDialog = false
  2005. });
  2006. process.Exited += ProcessExited;
  2007. try
  2008. {
  2009. process.Start();
  2010. }
  2011. catch (Exception ex)
  2012. {
  2013. Console.WriteLine("Error launching url: {0}", url);
  2014. Logger.ErrorException("Error launching url: {0}", ex, url);
  2015. throw;
  2016. }
  2017. }
  2018. private static void ProcessExited(object sender, EventArgs e)
  2019. {
  2020. ((IProcess)sender).Dispose();
  2021. }
  2022. public virtual void EnableLoopback(string appName)
  2023. {
  2024. }
  2025. /// <summary>
  2026. /// Called when [application updated].
  2027. /// </summary>
  2028. /// <param name="package">The package.</param>
  2029. protected void OnApplicationUpdated(PackageVersionInfo package)
  2030. {
  2031. Logger.Info("Application has been updated to version {0}", package.versionStr);
  2032. EventHelper.FireEventIfNotNull(ApplicationUpdated, this, new GenericEventArgs<PackageVersionInfo>
  2033. {
  2034. Argument = package
  2035. }, Logger);
  2036. NotifyPendingRestart();
  2037. }
  2038. private bool _disposed;
  2039. /// <summary>
  2040. /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
  2041. /// </summary>
  2042. public void Dispose()
  2043. {
  2044. if (!_disposed)
  2045. {
  2046. _disposed = true;
  2047. Dispose(true);
  2048. }
  2049. }
  2050. /// <summary>
  2051. /// Releases unmanaged and - optionally - managed resources.
  2052. /// </summary>
  2053. /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
  2054. protected virtual void Dispose(bool dispose)
  2055. {
  2056. if (dispose)
  2057. {
  2058. var type = GetType();
  2059. LogManager.AddConsoleOutput();
  2060. Logger.Info("Disposing " + type.Name);
  2061. var parts = DisposableParts.Distinct().Where(i => i.GetType() != type).ToList();
  2062. DisposableParts.Clear();
  2063. foreach (var part in parts)
  2064. {
  2065. Logger.Info("Disposing " + part.GetType().Name);
  2066. try
  2067. {
  2068. part.Dispose();
  2069. }
  2070. catch (Exception ex)
  2071. {
  2072. Logger.ErrorException("Error disposing {0}", ex, part.GetType().Name);
  2073. }
  2074. }
  2075. }
  2076. }
  2077. private Dictionary<string, string> _values;
  2078. public string GetValue(string name)
  2079. {
  2080. if (_values == null)
  2081. {
  2082. _values = LoadValues();
  2083. }
  2084. string value;
  2085. if (_values.TryGetValue(name, out value))
  2086. {
  2087. return value;
  2088. }
  2089. return null;
  2090. }
  2091. private Dictionary<string, string> LoadValues()
  2092. {
  2093. Dictionary<string, string> values = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
  2094. using (var stream = typeof(ApplicationHost).Assembly.GetManifestResourceStream(typeof(ApplicationHost).Namespace + ".values.txt"))
  2095. {
  2096. using (var reader = new StreamReader(stream))
  2097. {
  2098. while (!reader.EndOfStream)
  2099. {
  2100. var line = reader.ReadLine();
  2101. if (string.IsNullOrEmpty(line))
  2102. {
  2103. continue;
  2104. }
  2105. var index = line.IndexOf('=');
  2106. if (index != -1)
  2107. {
  2108. values[line.Substring(0, index)] = line.Substring(index + 1);
  2109. }
  2110. }
  2111. }
  2112. }
  2113. return values;
  2114. }
  2115. }
  2116. internal class CertificateInfo
  2117. {
  2118. public string Path { get; set; }
  2119. public string Password { get; set; }
  2120. }
  2121. }