Compare commits

...

590 Commits

Author SHA1 Message Date
Joshua Boniface
46c37c0ae8 Bump version to 10.3.0 (release) 2019-04-19 14:25:29 -04:00
Joshua Boniface
4ad71766fc Merge branch 'translations' into release-10.3.z 2019-04-19 14:19:22 -04:00
Weblate
9d60cc8c66 Rename Chinese (Traditional) file 2019-04-19 13:59:04 -04:00
Libor Filípek
4a6243096a Translated using Weblate (Czech)
Currently translated at 100.0% (94 of 94 strings)

Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/cs/
2019-04-19 13:38:32 -04:00
Heldenkrieger01
10cbdc8e8e Translated using Weblate (Swiss German)
Currently translated at 100.0% (94 of 94 strings)

Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/gsw/
2019-04-19 12:09:39 -04:00
SaddFox
4886fc467c Translated using Weblate (Slovenian)
Currently translated at 100.0% (94 of 94 strings)

Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/sl/
2019-04-19 12:09:38 -04:00
WWWesten
8e2827cc39 Translated using Weblate (Kazakh)
Currently translated at 100.0% (94 of 94 strings)

Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/kk/
2019-04-19 12:09:37 -04:00
Βασίλης Μουρατίδης
395d2e4917 Translated using Weblate (Greek)
Currently translated at 100.0% (94 of 94 strings)

Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/el/
2019-04-19 12:09:37 -04:00
Dan Johansen
d31f5229da Translated using Weblate (Danish)
Currently translated at 100.0% (94 of 94 strings)

Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/da/
2019-04-19 12:09:37 -04:00
Libor Filípek
d6622818dc Translated using Weblate (Czech)
Currently translated at 100.0% (94 of 94 strings)

Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/cs/
2019-04-19 12:09:37 -04:00
tinganhsu
ba684d6d3a Translated using Weblate (Chinese (Traditional))
Currently translated at 96.8% (91 of 94 strings)

Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/zh_Hant/
2019-04-19 12:09:36 -04:00
tinganhsu
90c04a4640 Added translation using Weblate (Chinese (Traditional)) 2019-04-19 00:32:52 -04:00
Joshua M. Boniface
06a1e1f166 Merge pull request #1244 from joshuaboniface/hotfix-authapi
Hotfix authapi
2019-04-18 17:58:54 -04:00
Joshua Boniface
31ad366aa9 Implemented suggested conditional 2019-04-18 10:24:08 -04:00
Joshua Boniface
10f33b0273 Update conditional to be correct 2019-04-18 09:31:30 -04:00
Joshua Boniface
eaa1ac8013 Apparently strings can't be !'d 2019-04-17 22:49:17 -04:00
Joshua Boniface
ca3bb308b3 Add the proper Class too 2019-04-17 22:46:26 -04:00
Joshua Boniface
e790f024c2 Return MethodNotAllowedException if Pw is not set
Don't accept pre-hashed (not-plaintext) passwords as the auth
provider no longer supports this due to sha1+salting the passwords
in the database.
2019-04-17 22:33:00 -04:00
Joshua Boniface
250e0c75df Add MethodNotAllowedException with code 405 2019-04-17 22:31:06 -04:00
Joshua M. Boniface
cde7375049 Merge pull request #1242 from Bond-009/metadata
Fix metadata path save
2019-04-17 09:26:04 -04:00
Bond_009
c7fedfbca3 Fix metadata path save 2019-04-17 15:09:31 +02:00
Bond-009
f520831025 Merge pull request #1239 from anthonylavado/fix-ident
Clean up UDP responders, and move ProductName to Public endpoint
2019-04-16 11:56:38 +02:00
Anthony Lavado
2f0719a883 Move the definition of ProductName to the correct class
Missed moving this from one class to the other.
2019-04-16 01:38:00 -04:00
Anthony Lavado
34ab99caf1 Move the ProductName to the public endpoint
Moves the ProductName field over from the private system/info point to
the public one, for easier identification
2019-04-16 01:16:02 -04:00
Anthony Lavado
b2f94c0e40 Remove the old message responders
Leaves only an answer to "Who is Jellyfin", removing older ones for
EmbyServer and MediaBrowser_v2.
2019-04-15 00:21:14 -04:00
Joshua Boniface
65bff1181a Bump version to 10.3.0-rc2 and update submodule 2019-04-10 00:51:21 -04:00
Joshua Boniface
efb14f0b58 Bump dockerfile web versions too 2019-04-10 00:49:33 -04:00
Joshua M. Boniface
75a4f04cce Merge pull request #1209 from joshuaboniface/hotfix-authprovider-create
Override username with AuthenticationProvider
2019-04-10 00:18:08 -04:00
Joshua M. Boniface
007fe34363 Merge pull request #1221 from LogicalPhallacy/ffmpegdetection
Make Jellyfin search its base dir for ffmpeg
2019-04-09 23:57:20 -04:00
Phallacy
a7e31ef31f applied changes to just also search jellyfin base dir 2019-04-09 00:27:41 -07:00
Joshua M. Boniface
eae0c28e6d Merge pull request #1178 from jellyfin/LogicalPhallacy-patch-1
Updates windows installer default lib location
2019-04-08 18:44:43 -04:00
Joshua M. Boniface
21950382b9 Merge pull request #1188 from joshuaboniface/hotfix-pluginload
Fix problems with plugin installation
2019-04-08 11:24:53 -04:00
Joshua Boniface
1af9c047fb Override username with AuthenticationProvider
Pass back the Username directive returned by an AuthenticationProvider
to the calling code, so we may override the user-provided Username
value if the authentication provider passes this back. Useful for
instance in an LDAP scenario where what the user types may not
necessarily be the "username" that is mapped in the system, e.g.
the user providing 'mail' while 'uid' is the "username" value.
Could also then be extensible to other authentication providers
as well, should they wish to do a similar thing.
2019-04-07 19:51:45 -04:00
Joshua M. Boniface
2d19bfa7fb Merge pull request #1199 from jftuga/use_tls12_for_nssm
Use TLS 1.2 to download NSSM
2019-04-07 02:48:59 -04:00
John Taylor
f5f7de64de Use TLS 1.2 to download NSSM 2019-04-06 13:40:19 -04:00
Joshua Boniface
754e76a61b Add TODO to remove string target 2019-04-04 02:34:23 -04:00
Joshua Boniface
09505e0988 Apply review feedback
Remove a few superfluous/testing log statements, and print the
deletion debug messages when it occurs rather than earlier. Use
a nicer name for the isDirectory variable.
2019-04-04 01:54:31 -04:00
Anthony Lavado
67e206fa0f Merge pull request #1195 from nvllsvm/optimize
Optimize images with image_optim
2019-04-04 01:16:49 -04:00
Andrew Rabert
608fd873de Optimize images with image_optim 2019-04-03 22:58:52 -04:00
Joshua Boniface
05a4161fd3 Correct the installation and removal of plugins
Upgrading plugins was broken for various reasons. There are four
fixes and a minor one:

1. Use a directory name based only on the `Name` of the plugin, not
   the source filename, which contains the version. Avoids strange
   duplication of the plugin.
2. Use the new directory name for the deletes if it's present, so
   that installation and removal happen at that directory level
   and we don't leave empty folders laying around. Ensures we
   properly remove additional resources in plugins too, not just
   the main `.dll` file.
3. Ignore the incoming `target` when installing, and always set
   it ourself to the proper directory, which would matter when
   reinstalling.
4. Deletes an existing target directory before installing if it
   exists. Note that not calling any of the plugin removal code
   is intentional; I suspect that would delete configurations
   unexpectedly when upgrading which would be annoying. This way,
   it just replaces the files and then reloads.
5. (Minor) Added some actual debug messages around the plugin
   download section so failures can be more accurately seen.
2019-04-03 20:05:14 -04:00
Vasily
05040351dc Merge pull request #1190 from jellyfin/updates
Update Dockerfiles
2019-04-03 18:05:59 +03:00
Andrew Rabert
d75324afc9 Update Dockerfiles
* Use new dotnet image paths
* Update jellyfin-web to 10.3.0-rc1
2019-04-03 01:21:28 -04:00
Joshua Boniface
38fcd31917 Search all subdirectories for Plugins
This was added in #801 which broke the previous plugin install
behaviour. Previously plugins could be loaded from subdirectories
but this search was only for the highest level. Change it to search
all subdirectories instead to restore the previous behaviour.

Also modifies the same option from #934, though I'm not 100% sure
if this is needed here.
2019-04-02 18:29:14 -04:00
LogicalPhallacy
816d8a0216 Update install-jellyfin.ps1 2019-03-31 10:34:49 -07:00
LogicalPhallacy
e37ccd6ec0 Updates windows installer default lib location
You can use the emby import to move an existing library this way.
2019-03-31 10:32:56 -07:00
Joshua Boniface
f27477da26 Bump version to 10.3.0 and update submodule 2019-03-30 15:47:34 -04:00
Andrew Rabert
c032a015a4 Merge pull request #1172 from joshuaboniface/build-improvements
Minor improvements to release build setup
2019-03-30 15:45:11 -04:00
Anthony Lavado
11e81b035a Merge pull request #1171 from joshuaboniface/ubuntu-armhf
Add Ubuntu armhf build
2019-03-30 13:23:10 -04:00
Joshua Boniface
891a03c038 Remove superfluous variable declaration 2019-03-30 12:58:39 -04:00
Joshua Boniface
31aa6c486c Get the version string from build.yaml
For the purposes of packaging, this makes more sense, since we can
include additional appends to this version (e.g. `-rcX`) when we
can't in the SharedVersion file. The previous commit to the
bump_version script sets this as well.
2019-03-30 12:42:33 -04:00
Joshua Boniface
1d9133a5e8 Simplify bump_version and remove changelogs
Make this a lot simpler, use a reference to the release page
in the package changelogs instead of a full list.
2019-03-30 12:42:16 -04:00
Joshua Boniface
3375ca5a8c Split lists echoes into separate lines 2019-03-30 12:19:49 -04:00
Joshua Boniface
1596e93cc1 Fix up the Ubuntu repository definitions 2019-03-30 11:58:56 -04:00
Joshua Boniface
1a540f1cf7 Add Ubuntu armhf (Raspberry Pi) build
A pretty-much direct copy of the Debian armhf build infrastructure.
2019-03-30 11:50:46 -04:00
Joshua M. Boniface
05f5cd1bde Merge pull request #1170 from joshuaboniface/fix-build-typo
Correct bad quote characters
2019-03-29 19:17:32 -04:00
Joshua Boniface
f0fbd0232c Correct bad quote characters 2019-03-29 19:13:01 -04:00
Joshua M. Boniface
72dd609109 Merge pull request #1149 from LogicalPhallacy/ImprovedPasswordReset
Adds per user password reset
2019-03-29 18:26:30 -04:00
LogicalPhallacy
13e94a8b1b Remove dashes from pins 2019-03-29 12:48:07 -07:00
Vasily
d9e7883fb5 Merge pull request #1169 from joshuaboniface/ffmpeg-location
Use new libexecdir location for jellyfin-ffmpeg
2019-03-29 18:16:36 +03:00
Phallacy
2d396cb589 adds readonly to properties 2019-03-29 07:10:49 -07:00
Phallacy
b56031b9f3 fix byte string 2019-03-28 20:49:11 -07:00
Joshua M. Boniface
fd86b141e2 Merge pull request #1166 from Bond-009/#1162
Fix exception on startup
2019-03-28 22:45:34 -04:00
Joshua Boniface
427a3e9b08 Use new libexecdir location for jellyfin-ffmpeg
From commit d6bb1f3c in jellyfin-ffmpeg, which moves the installed
binaries from /usr/share to /usr/lib on the next release.
2019-03-28 18:21:25 -04:00
Bond_009
3001f21f8d Hacky fix for a hacky issue 2019-03-28 19:11:05 +01:00
Phallacy
48b50a22a4 switched to a hexa string with crypto random backing 2019-03-28 08:15:53 -07:00
Phallacy
5e8496bc59 minor fixes and usings 2019-03-27 22:46:25 -07:00
Joshua M. Boniface
2dbc1153e8 Merge pull request #934 from Bond-009/plugin
WIP - Don't require a restart for 75% of plugins
2019-03-27 21:35:09 -04:00
Bond-009
b07c146fd9 Update Emby.Server.Implementations/Library/DefaultPasswordResetProvider.cs
Co-Authored-By: LogicalPhallacy <44458166+LogicalPhallacy@users.noreply.github.com>
2019-03-27 16:17:18 -07:00
Joshua M. Boniface
cc2edc4d66 Merge pull request #1151 from Phlogi/patch-1
Use public ports and advertise DNS if available for WAN address
2019-03-27 13:54:14 -04:00
Anthony Lavado
524357bfa8 Merge pull request #1157 from Bond-009/smallfix
Simplify/remove/clean code
2019-03-27 09:53:45 -04:00
Bond-009
7343e07fe5 Fix build error 2019-03-26 19:31:06 +01:00
Phallacy
6be8624373 async improvements and post reset cleanups 2019-03-25 22:17:23 -07:00
LogicalPhallacy
740c95d557 Apply minor suggestions from code review
Co-Authored-By: LogicalPhallacy <44458166+LogicalPhallacy@users.noreply.github.com>
2019-03-25 21:40:10 -07:00
Joshua M. Boniface
31607fbb37 Merge pull request #1153 from Bond-009/dlna
Check if disposed first
2019-03-25 20:08:11 -04:00
Phlogi
122cba2aa7 Correct use of local variable wanAddress. 2019-03-25 22:26:05 +01:00
Bond-009
b44a70ff36 Simplify/remove/clean code
* Remove useless runtime check (we only support one)
* Remove unused args
* Remove a global constant

And ofc fix some warnings ;)
2019-03-25 22:25:32 +01:00
Phlogi
1b03f078b9 No need to assign empty string. 2019-03-25 21:43:50 +01:00
Phlogi
4c8f8cf64c Removed trailing spaces, renamed get wan IP function. 2019-03-25 21:34:55 +01:00
Bond-009
d623f616fa Improved dispose method 2019-03-25 17:32:27 +01:00
Bond-009
fc8de8aead Check if disposed first 2019-03-25 17:27:24 +01:00
Claus Vium
6480cfcc87 Formatting update Emby.Server.Implementations/ApplicationHost.cs
Co-Authored-By: Phlogi <Phlogi@users.noreply.github.com>
2019-03-25 10:19:08 +01:00
Claus Vium
e36d424b5f Formatting update Emby.Server.Implementations/ApplicationHost.cs
Co-Authored-By: Phlogi <Phlogi@users.noreply.github.com>
2019-03-25 10:18:47 +01:00
Claus Vium
f7e7d72688 Formatting update Emby.Server.Implementations/ApplicationHost.cs
Co-Authored-By: Phlogi <Phlogi@users.noreply.github.com>
2019-03-25 10:18:18 +01:00
Claus Vium
3474568ce2 Update Emby.Server.Implementations/ApplicationHost.cs
Co-Authored-By: Phlogi <Phlogi@users.noreply.github.com>
2019-03-25 10:18:04 +01:00
Claus Vium
89f2dfd78a Update Emby.Server.Implementations/ApplicationHost.cs
Co-Authored-By: Phlogi <Phlogi@users.noreply.github.com>
2019-03-25 10:17:53 +01:00
Claus Vium
2c4c56d6d6 Formatting update Emby.Server.Implementations/ApplicationHost.cs
Co-Authored-By: Phlogi <Phlogi@users.noreply.github.com>
2019-03-25 10:17:40 +01:00
Phlogi
087d4153ae Fix check for available WAN address. 2019-03-24 21:47:18 +01:00
Phallacy
86772bd7bd removes needless dictionary 2019-03-24 12:17:32 -07:00
Claus Vium
4e2841f0d7 Update Emby.Server.Implementations/Library/UserManager.cs
Co-Authored-By: LogicalPhallacy <44458166+LogicalPhallacy@users.noreply.github.com>
2019-03-24 11:41:03 -07:00
Phallacy
26fe4040bf fixes some usings 2019-03-24 11:40:00 -07:00
Phlogi
fb7f29de18 Format the WAN API Url correctly with https and Port. 2019-03-24 18:33:21 +01:00
Phlogi
d18252542d Also add the WAN switch to the public system info. 2019-03-24 17:11:21 +01:00
Phlogi
030fcaac15 Proper access to configuration objects 2019-03-24 17:02:03 +01:00
Phlogi
7ebb043249 Removed comment, renamed methods consistently. 2019-03-24 16:50:39 +01:00
Claus Vium
598b1c9966 Update Emby.Server.Implementations/ApplicationHost.cs
Co-Authored-By: Phlogi <Phlogi@users.noreply.github.com>
2019-03-24 16:47:59 +01:00
Claus Vium
cf36aaef2b Update Emby.Server.Implementations/ApplicationHost.cs
Co-Authored-By: Phlogi <Phlogi@users.noreply.github.com>
2019-03-24 16:47:48 +01:00
Claus Vium
f30af9cd5f Update Emby.Server.Implementations/ApplicationHost.cs
Co-Authored-By: Phlogi <Phlogi@users.noreply.github.com>
2019-03-24 16:47:42 +01:00
Bond-009
5024c52c60 Merge pull request #1140 from oddstr13/pr-doxygen-1
Add Doxygen config
2019-03-24 13:26:56 +01:00
Bond-009
e971b62dab Merge pull request #1137 from thornbill/fix-expires-header
Fix default value for Expires header
2019-03-24 13:25:41 +01:00
Phlogi
4ffec8ad26 Fix build, missing changes. 2019-03-24 12:19:10 +01:00
Phlogi
69cc5814d8 Change WAN IP behaviour: Use ServerConfiguration.WanDdns if set in configuration. 2019-03-24 12:11:46 +01:00
Phlogi
414a318a0d WAN Address should use public ports instead of local ports.
https://github.com/jellyfin/jellyfin/issues/601#issuecomment-475941080
2019-03-24 11:59:40 +01:00
Phallacy
758e35baba greaterthen/lessthen reversal fix 2019-03-24 00:30:16 -07:00
Phallacy
09921a00aa made password resets an interface and per user 2019-03-22 00:01:23 -07:00
Odd Stråbø
16a3bb2df4 Implemented some requested changes to the Doxyfile 2019-03-21 18:21:07 +01:00
Odd Stråbø
2c684c0231 Customize Doxygen config. 2019-03-21 13:42:29 +01:00
Odd Stråbø
949a1cce21 Generate doxygen template config doxygen -g 2019-03-21 13:16:33 +01:00
Vasily
0e787f4e9f Merge pull request #1139 from Liggy/debian-init
Update init scripts for compatibility with Devuan
2019-03-20 23:27:24 +03:00
Torsten
bd31091648 Update init scripts for compatibility with Devuan
Include start, stop, restart and status option for /etc/init.d/jellyfin
Use start-stop-daemon to make the script refer to systemctl mechanism
on systems that have systemd installed
2019-03-20 20:16:24 +01:00
Bill Thornton
4cd8903abc Fix default value for Expires header 2019-03-19 23:13:02 -04:00
Joshua M. Boniface
7b01de8db1 Merge pull request #1136 from jellyfin/add-access-to-template
Require access type to be included in bug report
2019-03-19 10:52:49 -04:00
Vasily
f73d8a44df Improve the wording per @joshuaboniface suggestion 2019-03-19 17:37:56 +03:00
Vasily
752d65d020 Require access type to be included in bug report
Inspired by https://github.com/jellyfin/jellyfin/issues/1085#issuecomment-473833591

It seems that the issue with "setup wizard" described there is only prominent when reverse-proxied, not when accessed directly. So this type of information should be gathered in the bug report as well.
2019-03-19 17:13:27 +03:00
LogicalPhallacy
c2667f99f4 Merge pull request #4 from jellyfin/master
updating local master
2019-03-18 22:58:37 -07:00
Joshua M. Boniface
c7e7aa0a61 Merge pull request #1117 from Bond-009/ffmpeg
Check before flushing ffmpeg log
2019-03-18 23:59:12 -04:00
Joshua M. Boniface
fc79659549 Merge pull request #1127 from LogicalPhallacy/lockoutfix
Add configurable user lockout
2019-03-18 21:13:51 -04:00
Vasily
e81a6adb95 Merge pull request #1090 from redSpoutnik/subtitle-display-title
Set DisplayTitle for subtitles
2019-03-17 09:36:35 +03:00
Phallacy
80aedcd7e2 really fixed line endings 2019-03-16 21:36:45 -07:00
Phallacy
fc28c9237c fixed line endings 2019-03-16 21:34:26 -07:00
Phallacy
b04200ca68 adding regex fix 2019-03-16 21:21:14 -07:00
Joshua M. Boniface
67fbbcfd12 Merge pull request #1121 from LogicalPhallacy/master
Update username regex to string literal with escaped -
2019-03-17 00:12:15 -04:00
Joshua M. Boniface
e3dbed1c1a Update Emby.Server.Implementations/Library/UserManager.cs
Co-Authored-By: LogicalPhallacy <44458166+LogicalPhallacy@users.noreply.github.com>
2019-03-16 10:16:23 -07:00
redSpoutnik
480a6607e2 Merge branch 'master' into subtitle-display-title 2019-03-16 17:54:57 +01:00
redSpoutnik
4a30fee40d Remove some dead code 2019-03-16 17:28:45 +01:00
Phallacy
7f0fa74467 updated regex to string literal with escaped - 2019-03-16 00:38:31 -07:00
Vasily
3d1d27230d Merge pull request #1120 from LogicalPhallacy/master
quick fix for auth bug
2019-03-16 10:32:51 +03:00
LogicalPhallacy
9df1506794 Merge pull request #2 from LogicalPhallacy/master
update lockoutfix to latest for testing
2019-03-16 00:26:12 -07:00
LogicalPhallacy
2d0844b5db Merge pull request #1 from jellyfin/master
merging myself to latest
2019-03-16 00:25:16 -07:00
Phallacy
1ee016c997 configurable user lockout 2019-03-16 00:18:52 -07:00
Phallacy
221389089c quick fix for auth bug 2019-03-15 21:25:19 -07:00
Joshua M. Boniface
59031ee3b8 Merge pull request #1119 from ploughpuff/503retry
MusicBrainz 503 Retry Strategy
2019-03-15 16:47:03 -04:00
PloughPuff
d2e408539e MusicBrainz 503 Retry Strategy
Upon receiving back a 503 Service Unavailable from MusicBrainz (indicating throttling), retry the same request a number of times before giving up.
2019-03-15 19:33:26 +00:00
Bond_009
a8140cc74b Merge branch 'master' of github.com:jellyfin/jellyfin into ffmpeg 2019-03-15 18:08:51 +01:00
Bond_009
d5f080fefb Check before flushing ffmpeg log
The stream could have been diposed while writing.
2019-03-15 17:58:34 +01:00
Joshua M. Boniface
35ff8ec713 Merge pull request #1116 from Bond-009/sub
Fix exception caused by #1096
2019-03-15 12:48:15 -04:00
Bond_009
764c901cd7 Fix exception caused by #1096
```cs
MediaBrowser.Common.Extensions.ResourceNotFoundException: Configuration
with key subtitles not found.
   at
   Emby.Server.Implementations.AppBase.BaseConfigurationManager.<>c__DisplayClass42_0.<GetConfiguration>b__0(String
   k) in
   /home/pi/dev/jellyfin/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs:line
   247
      at
      System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey
      key, Func`2 valueFactory)
         at
	 Emby.Server.Implementations.AppBase.BaseConfigurationManager.GetConfiguration(String
	 key) in
	 /home/pi/dev/jellyfin/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs:line
	 238
	    at
	    MediaBrowser.Providers.MediaInfo.FFProbeVideoInfo.AddExternalSubtitles(Video
	    video, List`1 currentStreams, MetadataRefreshOptions
	    options, CancellationToken cancellationToken) in
	    /home/pi/dev/jellyfin/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs:line
	    486
	       at
	       MediaBrowser.Providers.MediaInfo.FFProbeVideoInfo.Fetch(Video
	       video, CancellationToken cancellationToken, MediaInfo
	       mediaInfo, BlurayDiscInfo blurayInfo,
	       MetadataRefreshOptions options) in
	       /home/pi/dev/jellyfin/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs:line
	       204
	          at
		  MediaBrowser.Providers.MediaInfo.FFProbeVideoInfo.ProbeVideo[T](T
		  item, MetadataRefreshOptions options,
		  CancellationToken cancellationToken) in
		  /home/pi/dev/jellyfin/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs:line
		  119
		     at
		     MediaBrowser.Providers.Manager.MetadataService`2.RunCustomProvider(ICustomMetadataProvider`1
		     provider, TItemType item, String logName,
		     MetadataRefreshOptions options, RefreshResult
		     refreshResult, CancellationToken cancellationToken)
		     in
		     /home/pi/dev/jellyfin/MediaBrowser.Providers/Manager/MetadataService.cs:line
		     806

```
2019-03-15 17:34:15 +01:00
Andrew Rabert
f85d45d17f Merge pull request #1115 from SuperSandro2000/patch-2
Clean apt lists in arm Dockerfiles
2019-03-15 10:53:10 -04:00
Andrew Rabert
022bd1b8b4 Merge pull request #1114 from SuperSandro2000/patch-1
Only remove /var/lib/apt/lists/* in Dockerfile
2019-03-15 10:53:00 -04:00
Sandro Jäckel
31305af7ff Clean apt lists in arm Dockerfiles 2019-03-15 14:39:23 +01:00
Sandro Jäckel
dd929d796f Only remove /var/lib/apt/lists/* 2019-03-15 14:30:15 +01:00
Vasily
11fde02035 Merge pull request #1105 from ploughpuff/ratelimit
Only delay making MusicBrainz request if necessary
2019-03-15 16:01:55 +03:00
Joshua M. Boniface
3d85014edc Merge pull request #1110 from EraYaN/productname-and-ua
Adjusted the Product Name so the User Agent is correct/better.
2019-03-15 00:25:38 -04:00
PloughPuff
d125fbc43d Added contact email to user agent
MusicBrainz request a contact email address is supplied in comment section of user agent field.
2019-03-14 21:34:09 +00:00
redSpoutnik
427688a0a0 Change subtitles DisplayTitle behavior 2019-03-14 22:31:51 +01:00
Erwin de Haan
21cc38fcf4 Adjusted AssemblyCopyright attribute values. 2019-03-14 22:17:56 +01:00
Erwin de Haan
ee7bf86e0f Adjusted the Product Name so the User Agent is correct/better. 2019-03-14 22:11:47 +01:00
PloughPuff
f8bb7a7ff4 Increased interval to 1050ms and moved to class scope
Review comments from JustAMan.
2019-03-14 19:01:17 +00:00
PloughPuff
6d3e6d800f Only delay making request if necessary
When requesting data from MusicBrainz, only delay the request if previous request was less than rate limit ago, instead of always delaying for one second at start.
2019-03-14 19:01:17 +00:00
Vasily
208585d3f6 Merge pull request #1106 from Bond-009/warn2
More warning fixes
2019-03-14 19:54:44 +03:00
Vasily
bf00dedc7f Merge pull request #1103 from Bond-009/stream
Improvements around streams
2019-03-14 19:53:50 +03:00
Bond-009
bf43dc00bb More warning fixes 2019-03-13 22:32:52 +01:00
Bond-009
e64aaebbac Improvements around streams
* Use ArrayPool instead of allocating new buffers each time
* Remove NetworkStream copy
* Remove some dead code
2019-03-13 21:11:01 +01:00
Erwin de Haan
1d443d2ff5 Do not use the nuget packages for comparison, but the last master build (#1091)
* Do not use the nuget packages for comparison, but the last master build.
* Only allow passing builds.
2019-03-13 21:09:08 +01:00
Bond-009
6507a9b2ee Merge pull request #1104 from EraYaN/disable-abi-check-on-drone
Disable the Drone CI ABI check
2019-03-13 20:46:59 +01:00
Erwin de Haan
4cc4d57a78 Disable the Drone CI ABI check 2019-03-13 20:37:08 +01:00
Vasily
605bf0e8c3 Merge pull request #1100 from ploughpuff/rmprobeswitch
Finalise removal of --ffprobe switch
2019-03-13 01:42:07 +03:00
Vasily
89e2af6b57 Merge pull request #1096 from dkanada/opensubs
Remove open subtitles from the server
2019-03-13 01:22:55 +03:00
PloughPuff
b864e9da2a Finalise removal of --ffprobe switch
Removed --ffprobe from src files and server/docker scripts.
2019-03-12 22:09:18 +00:00
Vasily
f10382a696 Merge pull request #1098 from jellyfin/Bond-009-patch-2
Fix build by removing non existent namespace
2019-03-13 00:02:24 +03:00
Vasily
297f25cfc2 Merge pull request #1059 from Bond-009/os
Remove EnvironmentInfo
2019-03-13 00:01:00 +03:00
Bond-009
afdef163ea Fix build by removing non existent namespace
Looks like a wrong auto merge. (We really should fix CI)
2019-03-12 20:49:29 +01:00
Joshua M. Boniface
6751560228 Merge pull request #1092 from joshuaboniface/configurable-webdir
Add configurable webdir option
2019-03-12 12:51:11 -04:00
Joshua M. Boniface
2012eb5e11 Merge pull request #785 from Bond-009/xml
Remove useless abstraction around XmlReaderSettings
2019-03-12 11:49:39 -04:00
Bond-009
58068e249a Merge pull request #1094 from cvium/imageprocessor_exception
Skip processing of images that don't exist
2019-03-12 16:40:20 +01:00
Bond-009
3ddbda9aca Merge branch 'master' into xml 2019-03-12 16:37:18 +01:00
Vasily
1fef8bf266 Merge pull request #1060 from Bond-009/assinfo
Remove redundant class AssemblyInfo
2019-03-12 16:34:21 +03:00
Joshua Boniface
3c4043199a Implement review feedback 2019-03-12 09:18:45 -04:00
Vasily
0220309ea7 Merge pull request #1095 from Bond-009/fix1077
Add AppConfig to the DI service collection
2019-03-12 12:56:39 +03:00
Vasily
497b4f834f Merge pull request #1021 from Bond-009/failonwarn
Fail on warnings for Jellyfin.Server
2019-03-12 11:31:22 +03:00
dkanada
715ddbb3b0 remove open subtitles from the server 2019-03-11 18:10:31 -07:00
Bond-009
0ff038f0a2 Fix nullref 2019-03-11 23:13:01 +01:00
Claus Vium
7322485a6d Skip processing of images that don't exist 2019-03-11 20:44:12 +01:00
Vasily
f77af5f6e4 Merge pull request #1093 from joshuaboniface/saner-paths
Use better path configuration for packages
2019-03-11 15:32:36 +03:00
Vasily
2324c408ba Merge pull request #1089 from jellyfin/translations
Update translations
2019-03-11 15:30:50 +03:00
Joshua Boniface
037cf9e1ee Move CreateDirectory for dataDir to try block 2019-03-10 18:30:10 -04:00
Joshua Boniface
5268553e7f Have datadir envvar match the others 2019-03-10 18:24:11 -04:00
Joshua Boniface
5f7524aca2 Remove unneccessary string 2019-03-10 17:21:10 -04:00
Joshua Boniface
86f5221f96 Use environment variables instead of opts for RPM 2019-03-10 17:11:16 -04:00
Joshua Boniface
ecf85a73ec Use environment variables instead of opts for Deb 2019-03-10 17:09:51 -04:00
Joshua Boniface
132ce3ece1 Add further resources to complete WebPath 2019-03-10 17:04:18 -04:00
Joshua Boniface
25deca9579 Make use of WebPath 2019-03-10 16:20:46 -04:00
Joshua Boniface
93d15cd969 Add configuration flag for Web directory 2019-03-10 16:17:48 -04:00
Anthony Lavado
4b91c9bf66 Merge pull request #1075 from dkanada/thumbnail
Remove mirror images from library thumbnail
2019-03-10 10:52:50 -04:00
WWWesten
16adaa64c9 Translated using Weblate (Kazakh)
Currently translated at 100.0% (94 of 94 strings)

Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/kk/
2019-03-10 03:06:01 -04:00
Matsuri
93fe7957fb Translated using Weblate (Chinese (Simplified))
Currently translated at 97.8% (92 of 94 strings)

Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/zh_Hans/
2019-03-10 03:06:00 -04:00
Joshua M. Boniface
fb96763f65 Merge pull request #1077 from Bond-009/musicbrainz
Make MusicBrainz base url configurable
2019-03-09 23:19:32 -05:00
Anthony Lavado
63342f89d4 Merge pull request #1081 from cvium/certificate_not_null
Disable HTTPS in Kestrel if Certificate is null
2019-03-09 02:11:02 -05:00
dkanada
47095e6cf8 move a variable out of for loop 2019-03-09 11:17:02 +09:00
Claus Vium
f2062ba19b Disable HTTPS in Kestrel if Certificate is null 2019-03-08 22:25:45 +01:00
Bond-009
58061a7295 Make MusicBrainz base url configurable 2019-03-08 17:15:52 +01:00
Anthony Lavado
c6c398179a Merge pull request #1072 from anthonylavado/remove-header
Remove New File Header
2019-03-08 10:23:13 -05:00
dkanada
e498e47109 remove mirror images from library thumbnail 2019-03-08 18:39:41 +09:00
Anthony Lavado
40089e2fd9 Merge pull request #1071 from jellyfin/Bond-009-patch-1
Fix error from #1069
2019-03-08 02:36:54 -05:00
Anthony Lavado
045a0419f6 remove new file header text, and remove it from solution
This removes the new file header text file from the repository, and also removes the include that was in the project solution.
2019-03-08 02:33:08 -05:00
Bond-009
80fb3dc2cb Fix error 2019-03-08 06:36:00 +01:00
Vasily
fcee64df09 Merge pull request #1069 from Bond-009/fix
Quick nullref fix
2019-03-08 00:58:52 +03:00
Bond-009
757e0194b9 Merge pull request #1067 from cvium/add_urlprefixes
Add urlprefixes during init
2019-03-07 22:54:02 +01:00
Bond-009
4625592a83 Quick nullref fix 2019-03-07 22:52:41 +01:00
Claus Vium
e3b844b5aa Add urlprefixes during init 2019-03-07 22:49:41 +01:00
Bond-009
decaffed86 Remove EnvironmentInfo
This moved the last bit of usefulness of EnvironmentInfo into a static
class.
2019-03-07 22:41:41 +01:00
Bond-009
669c48cc8b Merge pull request #1065 from cvium/closed_response
Don't set status code if response is closed
2019-03-07 22:32:01 +01:00
Vasily
d1fe24ac92 Merge pull request #1064 from Bond-009/fix2
Remove file added in #996
2019-03-08 00:29:33 +03:00
Claus Vium
3fa43a1e08 Don't set status code if response is closed 2019-03-07 22:26:23 +01:00
Vasily
028a98d2c1 Merge pull request #1058 from Bond-009/clean
Cleanup/simplification
2019-03-08 00:23:00 +03:00
Vasily
0f70a81db3 Merge pull request #1063 from EraYaN/azure-pipelines-upstream-change-fix
Update to renamed DownloadGitHubRelease task (Microsoft/azure-pipelines-tasks#9481)
2019-03-08 00:21:32 +03:00
Bond-009
d014a1dc1d Remove file added in #996 2019-03-07 22:16:27 +01:00
Vasily
e04a152ed0 Merge pull request #996 from Bond-009/libscan
Reduce the amount of exceptions thrown
2019-03-08 00:11:53 +03:00
Erwin de Haan
8a680ae324 Update to renamed DownloadGitHubRelease task (Microsoft/azure-pipelines-tasks#9481) 2019-03-07 22:00:28 +01:00
Vasily
75996476a7 Merge pull request #1061 from Bond-009/dead
Remove dead code
2019-03-07 23:57:51 +03:00
Bond-009
620d7b560d Fail on warnings for Jellyfin.Server 2019-03-07 21:52:16 +01:00
Bond-009
ab9859ecef Address comment 2019-03-07 21:42:56 +01:00
Bond_009
37ea50a572 Reduce the amount of exceptions thrown 2019-03-07 21:42:56 +01:00
Joshua M. Boniface
5cb3f04389 Merge pull request #1062 from Bond-009/warnfix
Fix the 2 new warnings
2019-03-07 15:34:51 -05:00
Bond-009
cedf50eeec Fix the 2 new warnings 2019-03-07 21:29:17 +01:00
Bond-009
c5fce647de Cleanup/simplification
* Removed useless copies/allocations
* Reduced unneeded complexity
2019-03-07 21:13:13 +01:00
Bond-009
10a0d6bdba Merge pull request #1010 from cvium/kestrel_poc
Remove System.Net and port to Kestrel
2019-03-07 21:08:57 +01:00
Claus Vium
0abe57e930 Merge remote-tracking branch 'remotes/upstream/master' into kestrel_poc 2019-03-07 20:16:51 +01:00
Bond-009
65c0b486aa Remove dead code
What it says on the tin
2019-03-07 19:27:43 +01:00
Bond-009
ae0ecc1b10 Merge pull request #870 from LogicalPhallacy/betterauth
Better default authentication
2019-03-07 19:11:36 +01:00
Claus Vium
dfff68b2f4 Make SkipLogExtensions static 2019-03-07 19:05:53 +01:00
Bond-009
e4c5d51860 Update MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
Co-Authored-By: cvium <cvium@users.noreply.github.com>
2019-03-07 19:04:50 +01:00
Claus Vium
8c609bc9ce Reduce aspnet imports 2019-03-07 19:04:09 +01:00
Bond-009
f486f5966f Update Emby.Server.Implementations/Library/DefaultAuthenticationProvider.cs
Co-Authored-By: LogicalPhallacy <44458166+LogicalPhallacy@users.noreply.github.com>
2019-03-07 09:56:03 -08:00
Bond-009
e91dd14b31 Remove redundent class AssemblyInfo 2019-03-07 18:10:55 +01:00
Joshua M. Boniface
8a53b60912 Merge pull request #947 from EraYaN/azure-pipelines
Add Azure Pipelines YAML
2019-03-07 09:57:14 -05:00
Vasily
a4b52b7264 Merge pull request #844 from ploughpuff/ffmpeg
Reworked FFmpeg path discovery and always display to user
2019-03-07 17:23:06 +03:00
Vasily
5ae0ef0527 Merge pull request #1028 from Bond-009/ratings
Simplify rating loading
2019-03-07 17:22:26 +03:00
Phallacy
dfb1d704ed made hashset static and readonly 2019-03-07 03:32:05 -08:00
Bond_009
ffd6dac03a Remove useless comments 2019-03-07 12:24:44 +01:00
Phallacy
8f4895e8a5 more fixes for perf and style 2019-03-07 03:11:41 -08:00
Bond_009
a9302b8b53 Remove useless abstraction around XmlReaderSettings
This removes the amount of stuff that needs to be passed around
Also removes some unneeded `ManagedFileSystem` usage
2019-03-07 12:04:14 +01:00
Bond-009
c31b0b311b Apply suggestions from code review
more minor fixes before I do larger fixes

Co-Authored-By: LogicalPhallacy <44458166+LogicalPhallacy@users.noreply.github.com>
2019-03-07 02:41:44 -08:00
Claus Vium
bba049c987 Make FileSystem readonly 2019-03-06 19:29:25 +01:00
Claus Vium
21c2acc520 Remove public Host property 2019-03-06 19:27:05 +01:00
Claus Vium
394d23a73a Review comments 2019-03-06 19:14:03 +01:00
Joshua M. Boniface
276428878e Merge pull request #1051 from joshuaboniface/build-improvements
Build improvements for wrapping infrastructure
2019-03-06 13:12:51 -05:00
Bond-009
04db0369d4 Update LocalizationManager.cs 2019-03-06 17:31:52 +01:00
Joshua Boniface
4ef7eda593 Copy install script from new location 2019-03-06 09:22:38 -05:00
Vasily
2242c8d793 Merge pull request #915 from cvium/remove_encryptionmanager
Remove IEncryptionManager
2019-03-06 15:56:15 +03:00
Phallacy
bef665be36 Minor fixes to address style issues 2019-03-05 23:45:05 -08:00
Joshua Boniface
bf9f342c13 Add build.yaml for parent build infrastructure 2019-03-05 23:53:07 -05:00
Joshua Boniface
a994edda04 Allow complete ignoring of submodule
Used by the parent build infrastructure
2019-03-05 23:52:58 -05:00
Joshua Boniface
9f6bca3658 Put output into bin instead of jellyfin-build 2019-03-05 23:22:07 -05:00
PloughPuff
2617a49b78 Renamed Init() to SetFFmpegPath() 2019-03-05 21:29:15 +00:00
PloughPuff
656bffbbb2 Remove --ffprobe logic 2019-03-05 21:29:15 +00:00
PloughPuff
8104e739d5 Address review comments from Bond 2019-03-05 21:29:15 +00:00
PloughPuff
632968dc81 Added self to contributors 2019-03-05 21:29:15 +00:00
PloughPuff
ed69e690b8 Review comments
Address review comments from JustAMan, Bond-009 and cvium.
2019-03-05 21:29:15 +00:00
PloughPuff
20775116f7 Reworked FFmpeg path discovery and always display to user
1) Reworked FFmpeg and FFprobe path discovery (CLI switch, Custom xml, system $PATH, UI update trigger).  Removed FFMpeg folder from Emby.Server.Implementations.  All path discovery now in MediaEncoder.

2) Always display FFmpeg path to user in Transcode page.

3) Allow user to remove a Custome FFmpeg path and return to using system $PATH (or --ffmpeg if available).

4) Remove unused code associated with 'prebuilt' FFmpeg.

5) Much improved logging during path discovery.
2019-03-05 21:24:54 +00:00
Claus Vium
446f9bf81f Remove more Content-Length references 2019-03-05 20:48:04 +01:00
Claus Vium
913e80fd55 Add ProcessWebSocketRequest to IHttpListener 2019-03-05 20:35:07 +01:00
Claus Vium
9a4a01fb0e Fix DI in FileWriter.TransmitFile 2019-03-05 19:32:22 +01:00
Claus Vium
df92df7bd6 Remove BOM 2019-03-05 19:22:41 +01:00
Claus Vium
78742b8e4c Switch to HeaderNames instead of hardcoded strings (and other header related fixes) 2019-03-05 19:20:28 +01:00
Erwin de Haan
942c400c19 Update README with Azure Pipelines status badge 2019-03-05 17:12:56 +01:00
Joshua M. Boniface
5587dd8bfb Merge pull request #900 from ploughpuff/validator
Implement proper FFmpeg version checking
2019-03-05 11:07:49 -05:00
Bond-009
8d1fc3f984 Merge pull request #1043 from thornbill/update-colors
Update image overlays to use Jellyfin blue
2019-03-05 12:06:48 +01:00
Claus Vium
318e0d4a24 Add GetValueOrDefault dictionary extension 2019-03-05 10:27:25 +01:00
Claus Vium
bc00617df7 Remove unused Brotli compressor 2019-03-05 10:26:43 +01:00
Phallacy
2c26517172 minor style fixes 2019-03-04 23:58:25 -08:00
Claus Vium
51648a2a21 Remove unused _listener 2019-03-05 08:05:42 +01:00
Claus Vium
12df381495 Grab content root from config and fix kestrel port bindings 2019-03-05 07:55:29 +01:00
Claus Vium
17ca23d73b Don't dispose the connection 2019-03-05 07:41:41 +01:00
Bill Thornton
41df94115f Update image overlays to use Jellyfin blue 2019-03-04 22:36:23 -05:00
Claus Vium
0250204f14 Expand todo 2019-03-04 22:26:57 +01:00
Bond-009
0419deeec4 Update LocalizationManager.cs 2019-03-04 20:18:35 +01:00
Claus Vium
9020f68ce1 Use QueryHelpers.AddQueryString 2019-03-04 20:08:54 +01:00
Claus Vium
557c4d065d Review comments 2019-03-04 19:55:59 +01:00
Claus Vium
6cc1bd544a Fix a logging statement 2019-03-04 19:31:26 +01:00
Joshua M. Boniface
aba22b92bc Merge pull request #735 from Bond-009/loop
Readability changes
2019-03-04 00:27:48 -05:00
Claus Vium
040871459b Remove some unused references 2019-03-03 14:35:54 +01:00
Claus Vium
6263b73d9c Await host startup 2019-03-03 14:30:41 +01:00
Claus Vium
1cc433eabc Start the webhost before RunStartupTasks and fix ContentEncoding 2019-03-03 13:54:14 +01:00
Daniel Widrick
5982cdad90 Implement SxxExx EpisodeNum Processing (#1009)
**Changes**
Implement and use SxxExx Episode numbering system from guide data if available.

**Issues**
Fixes #1008
2019-03-03 12:46:03 +01:00
Claus Vium
d450169964 Use EnableHttps instead of CertificateInfo 2019-03-03 08:46:17 +01:00
Claus Vium
e823c11b46 Add certificate to https and minor cleanup 2019-03-03 08:29:23 +01:00
Bond-009
c328417d29 Merge pull request #1030 from jellyfin/release-10.2.z
Backmerge for 10.2.2
2019-03-02 18:12:24 +01:00
Bond-009
c4192f9f8b Merge pull request #1032 from Lynxy/master
Correct the list of series types
2019-03-02 18:11:53 +01:00
Lynxy
5368112d90 Correct the list of series types 2019-03-01 22:28:25 -05:00
Bond-009
ed07ed44ae Simplify rating loading 2019-03-01 19:30:48 +01:00
Bond-009
9993dafe54 Don't mix LINQ and roreach loops for readability 2019-03-01 17:12:22 +01:00
Claus Vium
6bdb5debd2 Add some websocket manager boilerplate 2019-03-01 14:08:51 +01:00
Andrew Rabert
65403747df Merge pull request #1025 from jellyfin/justadep
Treat jellyfin-web as just another dependency for Docker builds
2019-03-01 07:52:29 -05:00
Bond-009
594b271383 Merge pull request #1024 from jellyfin/release-10.2.z
Backmerge for 10.2.2
2019-03-01 07:49:07 +01:00
Andrew Rabert
27f9981142 Treat jellyfin-web as just another dependency for Docker builds 2019-03-01 00:17:46 -05:00
Deniz
3d3d879b99 Translated using Weblate (Turkish)
Currently translated at 100.0% (94 of 94 strings)

Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/tr/
2019-02-28 23:13:39 -05:00
ElFantasma
53ed6e5e6e Translated using Weblate (Spanish (Argentina))
Currently translated at 100.0% (94 of 94 strings)

Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/es_AR/
2019-02-28 23:13:38 -05:00
SaddFox
d0e4e0f600 Translated using Weblate (Slovenian)
Currently translated at 87.2% (82 of 94 strings)

Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/sl/
2019-02-28 23:13:36 -05:00
v1tin
311caf3fc3 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (94 of 94 strings)

Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/pt_BR/
2019-02-28 23:13:35 -05:00
EffeF
7c13021def Translated using Weblate (Italian)
Currently translated at 100.0% (94 of 94 strings)

Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/it/
2019-02-28 23:13:35 -05:00
TheBird956
c8788d83fb Translated using Weblate (French (Canada))
Currently translated at 100.0% (94 of 94 strings)

Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/fr_CA/
2019-02-28 23:13:35 -05:00
TheBird956
331260cf80 Translated using Weblate (French)
Currently translated at 100.0% (94 of 94 strings)

Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/fr/
2019-02-28 23:13:34 -05:00
Joshua Boniface
58e5931a32 Bump version to 10.2.2 2019-02-28 22:03:08 -05:00
Bond-009
02041fa6f4 Merge pull request #1020 from Lynxy/master
Do not allow new users to delete content by default
2019-02-28 21:17:11 +01:00
Anthony Lavado
fcd299965d Merge pull request #992 from joshuaboniface/armhf-debian
Add Debian armhf (Rasberry Pi) build plus crossbuild
2019-02-28 12:55:59 -05:00
Vasily
79d5a53aea Merge pull request #1018 from fasheng/fix-dlna-rmvb
Fix rmvb video can not play under DLNA
2019-02-28 19:41:53 +03:00
Vasily
f1086a72bf Improve logic when determining return value
Co-Authored-By: ploughpuff <33969763+ploughpuff@users.noreply.github.com>
2019-02-28 15:58:41 +00:00
Xu Fasheng
95d001a053 Update CONTRIBUTORS.md 2019-02-28 22:15:59 +08:00
Vasily
b7fd68d366 Merge pull request #1017 from nvllsvm/dockerffmpeg
Set ffmpeg+ffprobe paths in Docker container
2019-02-28 16:43:35 +03:00
The Lynxy
c84729a4f4 Do not allow new users to delete content by default 2019-02-28 07:50:32 -05:00
Xu Fasheng
4951ec9814 Fix rmvb video can not play under DLNA
Or will report "Could not find handler for /videos/xxx/stream.rm" error
in server side.

Test OK with Kodi and gupnp-tools.
2019-02-28 18:00:25 +08:00
Phallacy
edba82db37 fixed logic flip in auth empty check and fixed crypto algo choice 2019-02-27 23:05:12 -08:00
Andrew Rabert
1d1e6dede9 Set ffmpeg+ffprobe paths in Docker container
Will always ensure containers use correct path.

Yes - the arm images have a different path than the amd64 one. This is
caused by the amd64 image using ffmpeg from jellyfin/ffmpeg while the
others use ffmpeg from their distro's repos.
2019-02-27 21:04:37 -05:00
Andrew Rabert
f384822aa5 Merge pull request #991 from joshuaboniface/ffmpeg-compat
Fix the ffmpeg compatibility
2019-02-27 20:45:43 -05:00
Claus Vium
1ac282b12e Call SharpWebSocket's Closed event handler before disposing 2019-02-27 23:39:20 +01:00
Claus Vium
588a13377c Remove a file that shouldn't have been added 2019-02-27 23:24:43 +01:00
Claus Vium
fb1de5a921 Remove more cruft and add the beginnings of a socket middleware 2019-02-27 23:22:55 +01:00
Claus Vium
71ed840944 Simplify websocket listeners 2019-02-27 22:09:22 +01:00
Claus Vium
dab8e15052 Check websocket state before closing 2019-02-27 21:48:28 +01:00
Claus Vium
e47d121985 Fix websockets 2019-02-27 21:40:47 +01:00
Claus Vium
c0b95dbc79 Fix query log for real 2019-02-27 20:11:40 +01:00
Claus Vium
647adc51c8 Fix query log 2019-02-27 19:55:25 +01:00
PloughPuff
7668ecf9c9 Use Version Class to ease comparisons 2019-02-27 18:20:48 +00:00
Vasily
3769453541 Merge pull request #978 from fasheng/fix-dlna-multiple-interfaces
Fix DLNA for multiple interfaces on linux
2019-02-27 19:23:31 +03:00
Vasily
8c2af50170 Merge pull request #1011 from Bond-009/order
Don't try to order the response the same as the request
2019-02-27 17:29:12 +03:00
Claus Vium
1e97e4d462 Remove IHttpResponse 2019-02-27 14:29:44 +01:00
Claus Vium
27e7e792b3 Replace some usage of QueryParamCollection 2019-02-27 14:23:39 +01:00
Xu Fasheng
7429c07c05 Remove redundant parenthesis 2019-02-27 20:16:54 +08:00
Claus Vium
91afaaf8fe Cleanup in QueryParamCollection 2019-02-27 12:45:06 +01:00
Claus Vium
333bd2107a Remove HttpUtility 2019-02-27 12:40:18 +01:00
Claus Vium
25d3d0b731 Remove some unused stuff 2019-02-27 08:02:32 +01:00
Claus Vium
77addb2283 Remove SocketHttpListener 2019-02-27 07:32:36 +01:00
Joshua M. Boniface
9651a78b0c Merge pull request #977 from Lynxy/genpts
Always set ffmpeg flag +genpts when video stream is being copied
2019-02-27 00:52:51 -05:00
Joshua M. Boniface
9eba31185a Merge pull request #959 from Bond-009/string
Reduce string allocations at startup
2019-02-27 00:37:31 -05:00
Joshua M. Boniface
aea7edf0fa Merge pull request #891 from Bond-009/postsan
Reduce the amount of db calls during the post scan event
2019-02-27 00:31:48 -05:00
Joshua M. Boniface
42d4834f63 Merge pull request #849 from Bond-009/span
Less string allocations
2019-02-27 00:30:31 -05:00
Joshua M. Boniface
ba78f6a0ff Merge pull request #999 from cvium/dont_write_disposed_log
Check that ffmpeg log target isn't disposed before writing to it
2019-02-27 00:27:25 -05:00
Erwin de Haan
feb5b62ad4 Enabled clean and updated the Github Connection Name 2019-02-27 00:53:16 +01:00
Erwin de Haan
5ccba7cf8a Move .azure to .ci 2019-02-27 00:20:04 +01:00
Claus Vium
848cfc32cc More cleanup 2019-02-26 22:57:59 +01:00
Claus Vium
5510e8ebee Remove unused Cookies 2019-02-26 22:53:59 +01:00
Claus Vium
9c02e99e35 Undo some of the span abuse 2019-02-26 22:40:25 +01:00
Claus Vium
148db8b81a Remove unused SharpSocket stuff 2019-02-26 22:11:21 +01:00
Claus Vium
e342b7bc71 Extend the IHttpServer interface to avoid the typecasting 2019-02-26 22:11:21 +01:00
Claus Vium
f1c93ae618 Remove SetContentLength and company 2019-02-26 22:11:21 +01:00
Claus Vium
4e229ad86b Fix PathInfo 2019-02-26 22:11:21 +01:00
Claus Vium
e88f079da6 Remove websocket options and configure kestrel listen ports 2019-02-26 22:11:21 +01:00
Claus Vium
4e8de67aca Remove SocketSharp from Jellyfin.Server and some other cleanup 2019-02-26 22:11:21 +01:00
Claus Vium
a85488cd20 Fix websockets array index out of bounds and some cleanup 2019-02-26 22:11:21 +01:00
Claus Vium
5a7cca9d1b Fix websockets and RawUrl 2019-02-26 22:11:21 +01:00
Claus Vium
d6c6f3c10c Still broken 2019-02-26 22:11:21 +01:00
Claus Vium
38f52a139e Add response compression middleware 2019-02-26 22:11:21 +01:00
Claus Vium
194da8416b Use middlewares instead of Routing 2019-02-26 22:11:21 +01:00
Claus Vium
f3e7bc0573 Replace some todos with http extensions and prepare some socket work 2019-02-26 22:11:21 +01:00
Claus Vium
c3fa299acc Remove hardcoded path and fix url bug in Windows 2019-02-26 22:11:21 +01:00
Claus Vium
852460b991 kestrel init 2019-02-26 22:11:21 +01:00
Claus Vium
33b67a357f Remove unused deps 2019-02-26 22:11:21 +01:00
Claus Vium
4db31acff9 Begin removing System.Net sources 2019-02-26 22:11:21 +01:00
Joshua M. Boniface
968e282c90 Merge pull request #1007 from Bond-009/time
Log time in a standardized way
2019-02-26 16:05:59 -05:00
Bond-009
1731bf7372 Remove ordering items 2019-02-26 20:47:23 +01:00
Bond-009
0804bed66d Log time in a standardized way 2019-02-26 19:40:23 +01:00
Bond-009
a0606b5730 Don't change submodule 2019-02-26 17:11:27 +01:00
Bond-009
9ba6227db4 Less string allocations 2019-02-26 17:11:04 +01:00
Vasily
9bab93262e Merge pull request #1003 from Bond-009/stopwatch
Use stopwatch for more accurate measurements and reduce log spam
2019-02-26 01:27:42 +03:00
Bond_009
0f9006c81f Use stopwatch for more accurate measurements and reduce log spam
DateTime.Now is suitible for small timespans
Replaced the needlessly complex and verbose logging for the httpserver
2019-02-25 18:26:17 +01:00
Vasily
b3438559cc Merge pull request #1000 from cvium/fix_object_disposed
Don't close the socket response multiple times
2019-02-25 16:52:31 +03:00
Vasily
8e5cccb22c Merge pull request #998 from cvium/enableraisingevents_default_true
Set EnableRaisingEvents to true for processes that require it
2019-02-25 16:42:27 +03:00
Vasily
500c0b9cba Merge pull request #979 from Wuerfelbecher/release-disable-debug
Build Package releases without debug turned on
2019-02-25 16:35:06 +03:00
Joshua Boniface
5054a77dcf Fix the ffmpeg compatibility
Doing this the other way was just complex. No longer try to override
the system ffmpeg, just put ours somewhere else and depend on that
package.
2019-02-25 00:41:34 -05:00
Joshua Boniface
dac2c98d8a Disable documentation and debug in build 2019-02-24 23:20:04 -05:00
Claus Vium
4df3333b71 Remove the unused status code 2019-02-24 22:31:46 +01:00
Claus Vium
5262e50fee Try another fix 2019-02-24 22:28:46 +01:00
Claus Vium
547d0ecf58 Move the check further down 2019-02-24 22:04:30 +01:00
Claus Vium
6e07eab247 Don't close the socket response multiple times 2019-02-24 21:45:03 +01:00
Claus Vium
96b3d37caf Check that ffmpeg log target isn't disposed before writing to it 2019-02-24 21:25:24 +01:00
Claus Vium
aafed63c3f Set EnableRaisingEvents to true for processes that require it 2019-02-24 16:33:05 +01:00
Claus Vium
2e9a3d45c2 Fix slow local image validation (#990)
* Check for local image directory existence to avoid tons of exceptions
2019-02-24 10:16:53 -05:00
Bond-009
e281c79d6f Merge pull request #968 from brianjmurrell/release-10.2.z-copr-autobuild
Release 10.2.z copr autobuild
2019-02-24 10:10:19 -05:00
Thomas Büttner
38ec68c488 use common.build.sh for docker image builds
Signed-off-by: Thomas Büttner <thomas@vergesslicher.tech>
2019-02-24 11:17:39 +01:00
Thomas Büttner
da61998ad6 Build releases without debug
Signed-off-by: Thomas Büttner <thomas@vergesslicher.tech>
2019-02-24 11:00:15 +01:00
Joshua M. Boniface
f28dd79fb1 Merge pull request #964 from jellyfin/fedora-runtime
Install the dotnet runtime package in Fedora build
2019-02-23 21:31:38 -05:00
Joshua Boniface
c2e57aba27 Add Debian armhf (Rasberry Pi) build plus crossbuild 2019-02-23 20:07:05 -05:00
Bond-009
4a3e42e779 Merge pull request #986 from JustAMan/submodule-update
Backmerge submodule updating strategy
2019-02-23 10:13:02 -05:00
The Lynxy
67f399dccf Leave +genpts untouched in GetProgressiveVideoArguments() 2019-02-23 10:01:41 -05:00
Lynxy
eb95b025d4 Add to contributors 2019-02-22 23:28:19 -05:00
Anthony Lavado
de45cfdd8c Merge pull request #984 from WWWesten/patch-1
Update kz.csv
2019-02-22 22:05:36 -05:00
Xu Fasheng
47966793c0 Remove useless if..else in SsdpDevicePublisher 2019-02-23 10:15:38 +08:00
Xu Fasheng
0c49079c16 Update comments for DLNA IPv6 2019-02-23 09:56:55 +08:00
Vasily
d82d6b6aef Merge pull request #981 from cvium/close_response_stream
Close the response stream after fetching temp files
2019-02-23 02:01:20 +03:00
Vasily
7ae526da8b Merging #975 to master 2019-02-23 01:52:51 +03:00
WWWesten
e79d44d9f1 Update kz.csv
The new ratings system
2019-02-23 01:51:35 +05:00
Claus Vium
fb7de2f966 Remove duplicate code and use using to properly dispose the response stream 2019-02-22 20:24:42 +01:00
Bond-009
db54fe4c70 Merge pull request #975 from cvium/release-10.2.z
Update submodule
2019-02-22 12:57:20 -05:00
Xu Fasheng
1eb26bdf08 Ignore IPv6 DLNA devices
DLNA is not ready for IPv6 now, uncomment the code will be fine.
2019-02-22 20:18:34 +08:00
Xu Fasheng
cbd0e71c07 Send DLNA devices message to only the matched interface
This will be the right way for multiple interfaces, or the client will
receive all devices message with different IP addresses and could not
detect which one could access.

And provide one option DlnaOptions.SendOnlyMatchedHost to fallback to old
behaviour if this commit missed something.
2019-02-22 20:18:34 +08:00
Xu Fasheng
2db1826ed8 Enable DLNA multi socket binding for linux
If not, DLNA on multiple interfaces not works for linux, for
example ZerotierOne VPN.
2019-02-22 20:13:17 +08:00
Xu Fasheng
cf4e64f430 Add option to toggle if ignore virtual interfaces
Some VPN like ZerotierOne owns IP address but no gateway, and there is no
good idea in NetworkManager.GetIPsDefault() to filter such virtual interfaces,
so just provide one option to let user decide it.
2019-02-22 20:13:17 +08:00
Lynxy
9b39404b9a Always set ffmpeg flag +genpts when video stream is being copied 2019-02-21 19:50:57 -05:00
Claus Vium
00fe66a38c Update submodule 2019-02-21 20:59:10 +01:00
Vasily
406af5f086 Merge pull request #967 from brianjmurrell/dotnet-runtime
dotnet-runtime is needed on Fedora now
2019-02-21 15:25:51 +03:00
Vasily
e7e7d96f51 Merge pull request #776 from cvium/update_tvdb
Update tvdb provider to v2 api
2019-02-21 15:09:54 +03:00
Vasily
785fa76ac6 Merge pull request #955 from ploughpuff/avoid
Avoid exceptions due to folder and file not found
2019-02-21 15:05:31 +03:00
Vasily
6c967c5982 Merge pull request #952 from Liggy/populate-extras
Populate video extras again
2019-02-21 15:02:36 +03:00
Brian J. Murrell
f03e279382 COPR auto building
This adds enhancements so that Fedora/EL packages can be automatically
built in COPR when a webhook is received.  A typical webhook could be
for tagging events for example or even a "Release" webhook to only
build releases.
2019-02-21 02:12:16 -05:00
Brian J. Murrell
1bc2b12ee3 dotnet-runtime is needed in Fedora RPM build also 2019-02-21 02:11:46 -05:00
Joshua Boniface
469a17b3ca Install the dotnet runtime too
This is needed since /usr/bin/dotnet doesn't exist in the SDK package
for whatever reason as of Feb 18 2019.
2019-02-20 20:36:49 -05:00
Bond-009
affb8c8673 Merge pull request #962 from scheidleon/fix-windows-build
Fix Path
2019-02-20 15:38:43 -05:00
scheidleon
74aa38acd7 Fix Path 2019-02-20 21:04:52 +01:00
Joshua M. Boniface
d4ded281aa Merge pull request #961 from jellyfin/release-10.2.z
Release 10.2.1
2019-02-20 14:24:22 -05:00
Claus Vium
c597f0de35 Make Tvdb strings const 2019-02-20 19:55:06 +01:00
Bond-009
3965f90236 Update MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesImageProvider.cs
Co-Authored-By: cvium <cvium@users.noreply.github.com>
2019-02-20 19:36:33 +01:00
Claus Vium
8af4417f8f Add ConfigureAwait to awaited calls 2019-02-20 19:35:47 +01:00
Claus Vium
4a5c526ccc Fix logging args and add ilogger with categoryname 2019-02-20 19:08:47 +01:00
Bond_009
320707d44c Reduce string allocations at startup 2019-02-20 16:49:03 +01:00
Torsten
2690ac299b Only refresh metadata if extras changed 2019-02-20 16:39:49 +01:00
Torsten
268b099ca8 Merge branch 'populate-extras' of github.com:Liggy/jellyfin into populate-extras 2019-02-20 16:38:30 +01:00
Liggy
33171a58b5 Merge branch 'master' into populate-extras 2019-02-20 16:37:57 +01:00
PloughPuff
73c1cdb32a Avoid exceptions due to folder and file not found
1) Use function to return path to temp transcode path which has benefit of creating temp folder if not exists, thereby avoiding the exception when GetFilePaths is used.
2) Check json files exists before attempting to read from it.  Avoids having to mask FileNotFound exceptions when debugging.
2019-02-20 13:30:06 +00:00
Liggy
13bfe5093e Merge branch 'master' into populate-extras 2019-02-20 14:24:23 +01:00
Bond-009
99bed9a9c3 Merge pull request #939 from joshuaboniface/cleanup-builds
Clean up and rename obsolete deployment platforms
2019-02-20 07:28:20 -05:00
Vasily
8ef41020d9 Merge pull request #847 from Bond-009/async
Make websockets code async
2019-02-20 15:03:42 +03:00
Bond-009
fca226bdfd Add comment 2019-02-20 12:53:35 +01:00
Vasily
bca7a26ffd Merge branch 'master' into update_tvdb 2019-02-20 14:46:07 +03:00
Vasily
60df855b26 Merge pull request #930 from fruhnow/AuthorizationCheck
checking user-permission in GetQueryResult
2019-02-20 14:42:35 +03:00
Vasily
44ed037e73 Merge pull request #950 from cvium/replace_priority_queue
Replace OptimizedPriorityQueue source with NuGet reference
2019-02-20 14:39:52 +03:00
Vasily
50ce7572b4 Merge pull request #851 from Bond-009/appdata
Simplify code to get data dir
2019-02-20 14:31:01 +03:00
Vasily
74695428fe Merge pull request #914 from Bond-009/httppostedfile
Separate HttpPostedFile into it's own file
2019-02-20 13:33:42 +03:00
Claus Vium
139807719c Add missing base64 conversion 2019-02-20 11:09:10 +01:00
Claus Vium
1e2050f106 Rename functions to match functionality 2019-02-20 11:09:10 +01:00
Claus Vium
a23f04623e Remove IEncryptionManager 2019-02-20 11:09:06 +01:00
Claus Vium
1f30a50f4a Address review comments 2019-02-20 11:03:04 +01:00
Phallacy
098de6b050 made newlines into linux newlines 2019-02-20 01:17:30 -08:00
Phallacy
a0d31a49a0 merging with master to clear merge conflict 2019-02-20 00:46:13 -08:00
Phallacy
6bbb968b57 minor changes and return to netstandard 2019-02-20 00:00:26 -08:00
Joshua M. Boniface
6c6e9ca9f2 Merge pull request #889 from Bond-009/xmlex
Fix uncaught xml error
2019-02-19 21:31:16 -05:00
Joshua M. Boniface
89d4ce309d Merge pull request #848 from Bond-009/perf
Minor changes to reduce allocations
2019-02-19 21:24:51 -05:00
Joshua M. Boniface
b43317c5e1 Merge pull request #830 from Bond-009/update
Removed remaining self-update code
2019-02-19 21:21:36 -05:00
Torsten
5917e91447 Merge https://github.com/jellyfin/jellyfin into populate-extras 2019-02-19 23:21:40 +01:00
Torsten
9753a76905 Populate video extras again 2019-02-19 22:41:25 +01:00
Vasily
24b76dbed8 Merge pull request #936 from EraYaN/fix-drone-abi-tests
Fixed the assemblynames for compatibility check in drone.
2019-02-20 00:22:09 +03:00
Claus Vium
dab25a0eeb Remove OptimizedPriorityQueue source and grab it from nuget 2019-02-19 21:17:30 +01:00
Felix Ruhnow
53beebc774 switching logging to serilog convention according to pr comments 2019-02-19 12:17:28 +01:00
Felix Ruhnow
ba003e06ef adressing pr comments 2019-02-19 12:09:39 +01:00
Felix Ruhnow
1d631540ac adressing pr comments 2019-02-19 12:06:50 +01:00
Joshua Boniface
3ed9d32f68 Rename Windows scripts folder 2019-02-18 22:07:53 -05:00
Joshua Boniface
3ecfd1fdd1 Rename framework to portable 2019-02-18 22:07:12 -05:00
Joshua Boniface
24574d4964 Rename MacOS build 2019-02-18 22:06:44 -05:00
Joshua Boniface
512ab8c6aa Remove unneeded Linux builds 2019-02-18 22:06:06 -05:00
Erwin de Haan
029bafdf9c Changed build name template and limited number of parallel jobs. 2019-02-19 03:16:17 +01:00
Erwin de Haan
0849c4a447 Switched to dotnet based execution again because of permissions. 2019-02-19 03:12:53 +01:00
Erwin de Haan
5238ba5d8f Fix tool extraction search pattern. 2019-02-19 03:07:44 +01:00
Erwin de Haan
6b1a64652f Fix path for naming, and add extra CopyFIle Task. 2019-02-19 02:59:56 +01:00
Erwin de Haan
9961c8c459 No full publish of artifacts. 2019-02-19 02:55:10 +01:00
Erwin de Haan
18418b6892 Fixed secondary Artifact paths and Debug config. 2019-02-19 02:50:25 +01:00
Erwin de Haan
d4bc7b5a5a Fix NuGet task name. 2019-02-19 02:42:42 +01:00
Erwin de Haan
e2d0f67077 Fix the conditions. 2019-02-19 02:32:36 +01:00
Erwin de Haan
5ef63e738d Added final stage and removed triggers. 2019-02-19 02:28:16 +01:00
Erwin de Haan
7bbcb455c0 Added compat checking to YAML 2019-02-19 02:17:57 +01:00
Erwin de Haan
2ad54cd09d Fixed the assemblynames from drone since, the namespaces do not line up (yet). 2019-02-19 01:18:49 +01:00
Erwin de Haan
7c9803e135 Update azure-pipelines.yml for Azure Pipelines 2019-02-18 23:47:31 +01:00
Erwin de Haan
480999e8e6 Update azure-pipelines.yml for Azure Pipelines 2019-02-18 23:42:24 +01:00
Erwin de Haan
ef17ec700b Update azure-pipelines.yml 2019-02-18 23:24:39 +01:00
Erwin de Haan
4b34b0cfea Merge branch 'azure-pipelines' of https://github.com/EraYaN/jellyfin into azure-pipelines 2019-02-18 23:03:14 +01:00
Erwin de Haan
60fc53306d Fixed vmImage 2019-02-18 22:53:32 +01:00
Bond-009
c6188e26af Got to start somewhere 2019-02-18 22:47:02 +01:00
Erwin de Haan
18717d103a Update azure-pipelines.yml for Azure Pipelines 2019-02-18 22:36:24 +01:00
Erwin de Haan
6834b64922 Add first Azure Pipeline (Build) 2019-02-18 22:26:40 +01:00
Phallacy
56e3063342 little fixes for JustAMan 2019-02-18 10:56:01 -08:00
Joshua M. Boniface
781cca0c82 Merge pull request #902 from brianjmurrell/copr-autobuild
COPR auto building
2019-02-18 13:53:59 -05:00
Andrew Rabert
eab35890dc Merge pull request #862 from EraYaN/abi-check-drone
Add dotnet-compat ABI testing and Debug configuration building to drone-CI
2019-02-18 13:11:06 -05:00
Felix Ruhnow
967d5deeb7 checking user-permission in GetQueryResult to prevent accessing the library without permission but having a link. (+added myself as contributor. forgot last time bout that) 2019-02-18 18:29:58 +01:00
Bond-009
51ba28bd65 Remove useless check 2019-02-18 17:37:10 +01:00
Bond_009
a94aeb5c87 Simplify code to get data dir 2019-02-18 17:35:09 +01:00
Vasily
13f2783a8e Merge pull request #887 from wtayl0r/replace-primitives-with-iconfiguration
Replace primitive injection with IConfiguration
2019-02-18 19:30:11 +03:00
Bond_009
7554f63551 Remove more self-update code 2019-02-18 16:57:08 +01:00
Bond_009
25253cf961 Fix style issues in changed files 2019-02-18 16:57:08 +01:00
Bond_009
77a5617774 Removed remaining self-update code 2019-02-18 16:57:08 +01:00
Vasily
395072239d Merge pull request #913 from Bond-009/log
Reduce log spam
2019-02-18 14:50:53 +03:00
Vasily
e2f6ecaef6 Merge pull request #829 from Bond-009/fields
Removed some unused fields
2019-02-18 14:47:02 +03:00
Phallacy
48e7274d37 added justaman notes, fixed new bug from emty has removals 2019-02-18 01:26:01 -08:00
LogicalPhallacy
9f3aa2cead Apply suggestions from code review
Adding minor stylistic suggestions from Bond-009

Co-Authored-By: LogicalPhallacy <44458166+LogicalPhallacy@users.noreply.github.com>
2019-02-18 00:31:03 -08:00
bobberb
bb50363812 Translated using Weblate (Hebrew)
Currently translated at 97.8% (92 of 94 strings)

Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/he/
2019-02-17 15:59:36 -05:00
Joshua M. Boniface
9a38e4dc8a Merge pull request #925 from Bond-009/newmaser
Merge 10.2.0 release branch back into master
2019-02-17 13:05:12 -05:00
William Taylor
c607c95e64 Removed async from non-async method 2019-02-17 14:33:20 +00:00
William Taylor
18ae107ce4 Removed unnecessary configuration options and reduced primitive dependencies 2019-02-17 14:09:52 +00:00
William Taylor
3f80b16ffa Removed Reference and replaced with package reference 2019-02-17 14:09:52 +00:00
William Taylor
72aa364aa5 Removed extra using 2019-02-17 14:08:52 +00:00
William Taylor
0d5fbcb031 Removed primitives from services in Program.cs
This will make it easier to move dependency registration
to a system without having to new up all the services first.
Moved the primitives to an IConfiguration which is much easier to inject.
2019-02-17 14:08:52 +00:00
Bond-009
a35ea49c99 Merge remote-tracking branch 'upstream/release-10.2.z' into newmaser 2019-02-17 10:38:44 +01:00
Bond-009
4811e76860 Merge branch 'master' into perf 2019-02-16 17:05:44 +01:00
Bond-009
64a4f259a2 Merge branch 'master' into async 2019-02-16 17:05:05 +01:00
Bond-009
bdfd042d70 Merge branch 'master' into fields 2019-02-16 17:03:15 +01:00
Bond-009
a993420676 Reduce log spam 2019-02-16 16:42:24 +01:00
Bond-009
fb6a901374 Separate HttpPostedFile 2019-02-16 11:46:58 +01:00
Bond-009
25c2267a89 Merge pull request #907 from cvium/fix_assembly_visibility
Fix assembly visibility
2019-02-16 10:38:10 +01:00
PloughPuff
69ea15f73a Use string interpolation
Two further review comments from JustAMan.
2019-02-16 00:47:38 +00:00
Vasily
b7ae044e65 Merge pull request #885 from Bond-009/warn
More warning fixes
2019-02-16 03:22:12 +03:00
PloughPuff
d8d237f6f2 Review comments
Addressed review comments from JustAMan.  Removed code to determine experimental version.  Store major and minor as two ints.  Allow control of a min and max recommended version.
2019-02-15 23:51:22 +00:00
Bond-009
18e1d03a89 Comments 2019-02-16 00:44:10 +01:00
Vasily
3947f2315d Update Jellyfin.Server/Jellyfin.Server.csproj
Co-Authored-By: Bond-009 <bond.009@outlook.com>
2019-02-16 00:43:56 +01:00
Bond-009
cb9e50b2ea Reorder elements 2019-02-16 00:43:56 +01:00
Bond-009
e620bb9512 Remove more doc warnings 2019-02-16 00:43:56 +01:00
Bond-009
8b04fe7633 More fixes 2019-02-16 00:43:56 +01:00
Bond-009
2cb747651b Correctly dispose WebSocketSharpListener 2019-02-16 00:43:56 +01:00
Bond-009
46897aab4f More warnings 2019-02-16 00:43:56 +01:00
Bond-009
892787cb1a Disable SA1130 2019-02-16 00:43:56 +01:00
Bond-009
be77e14db9 Warnings for docs 2019-02-16 00:43:56 +01:00
Bond-009
34af7501fa Fix up CoreAppHost.cs 2019-02-16 00:43:56 +01:00
Bond-009
183ef34422 Do not declare visible instance fields 2019-02-16 00:43:56 +01:00
Bond-009
637936cb9f Closing braces should be followed by an empty line 2019-02-16 00:43:56 +01:00
Bond-009
fc59b0ab77 Disable SA1512 2019-02-16 00:43:56 +01:00
Bond-009
d8b312674d No multiple empty lines 2019-02-16 00:43:56 +01:00
Bond-009
ebae7229c1 Single line comments should start with a space 2019-02-16 00:43:56 +01:00
Bond-009
3df8cda110 ConfigureAwait 2019-02-16 00:43:56 +01:00
Bond-009
43cf11aa35 Change discards 2019-02-16 00:42:56 +01:00
Claus Vium
21f0a7e020 Make all class implementing dynamically loaded interfaces public 2019-02-15 23:05:14 +01:00
Claus Vium
cb6d2cbd2d Remove SizeLimit 2019-02-15 22:02:17 +01:00
Claus Vium
ce51025e7c Use DI for TvDbClientManager 2019-02-15 20:11:27 +01:00
Claus Vium
5a054e5150 Remove useless doc 2019-02-15 19:33:10 +01:00
Claus Vium
98f003f71a Review comments 2019-02-15 19:33:10 +01:00
Claus Vium
b9efcace79 Extract imagetype-to-keytype statements into a utility function and move tvdb specific utils to separate class 2019-02-15 19:33:10 +01:00
Claus Vium
1aaa8de1f9 Use Task.WhenAll properly 2019-02-15 19:33:10 +01:00
Claus Vium
5e2e190f3e Add key delimiter to avoid potential clashes 2019-02-15 19:33:10 +01:00
Claus Vium
828434058f Use language supplied as argument instead of reading from TvDbClient 2019-02-15 19:33:10 +01:00
Claus Vium
dfbf5fc9fa Add generic key generation function 2019-02-15 19:33:10 +01:00
Claus Vium
8029cd3ebb Add better language support 2019-02-15 19:33:10 +01:00
Vasily
e970d7a6aa Update MediaBrowser.Providers/TV/MissingEpisodeProvider.cs
Co-Authored-By: cvium <cvium@users.noreply.github.com>
2019-02-15 19:33:10 +01:00
Claus Vium
350e795640 Fix namespace in tvdbclientmanager 2019-02-15 19:33:10 +01:00
Claus Vium
f5bda652c4 Add support for searching for episodes by premiere date and fixed timezones 2019-02-15 19:33:10 +01:00
Claus Vium
e8189cd0f6 Fix namespaces 2019-02-15 19:33:10 +01:00
Claus Vium
18231fedef Add braces to if's and other minor style changes 2019-02-15 19:33:10 +01:00
Claus Vium
935c7231eb Review comments 2019-02-15 19:33:10 +01:00
Vasily
da2c7db0df Apply suggestions from code review
Co-Authored-By: cvium <cvium@users.noreply.github.com>
2019-02-15 19:33:10 +01:00
Claus Vium
83d98ac92d Fix episode provider 2019-02-15 19:33:10 +01:00
Claus Vium
b997b12d27 Add names to tuple items and reduce list iterations 2019-02-15 19:33:10 +01:00
Claus Vium
6887e790c8 Minor fixes in MissingEpisodeProvider 2019-02-15 19:33:10 +01:00
Claus Vium
373a1f72bf Fix actor image provider 2019-02-15 19:33:10 +01:00
Claus Vium
0d43b06042 Fix MissingEpisodeProvider (almost) 2019-02-15 19:33:10 +01:00
Claus Vium
ced9868357 Fix a copy paste mistake and add series end date 2019-02-15 19:33:10 +01:00
Claus Vium
23c867f946 Remove TvdbPrescanTask as it looks like it was used for pre-fetching data, which is no longer relevant 2019-02-15 19:33:10 +01:00
Claus Vium
42c233c74e Add much needed exception handling and logging 2019-02-15 19:33:10 +01:00
Claus Vium
1f8e74f3a8 Add caching for all tvdb requests 2019-02-15 19:33:10 +01:00
Claus Vium
d6835f8dd6 Use the locking properly, this is not Python... 2019-02-15 19:33:10 +01:00
Claus Vium
86940e96d5 More MemoryCache PoC 2019-02-15 19:33:10 +01:00
Claus Vium
75d90c8e4c Add caching PoC 2019-02-15 19:33:10 +01:00
Claus Vium
ecbc0538f6 Add some error handling, grab imdb id and other minor fixes 2019-02-15 19:33:10 +01:00
Claus Vium
2a26760911 Episode provider is somewhat broken 2019-02-15 19:33:10 +01:00
Claus Vium
19b6808602 Remove some junk from series provider 2019-02-15 19:33:10 +01:00
Claus Vium
c2202be0f8 Some of it works??? 2019-02-15 19:33:10 +01:00
Claus Vium
9729ae52a3 initial commit 2019-02-15 19:33:10 +01:00
Vasily
7cc69f30c4 Merge pull request #801 from Bond-009/di
Move to Microsoft.Extensions.DependencyInjection
2019-02-15 21:21:58 +03:00
Brian J. Murrell
e33706ab25 Code review updates
Also fix a bug in the tarball creation that existed even prior
to moving it into create_tarball.sh
2019-02-15 10:22:52 -05:00
Brian J. Murrell
4018b7e2d5 COPR auto building
This adds enhancements so that Fedora/EL packages can be automatically
built in COPR when a webhook is received.  A typical webhook could be
for tagging events for example or even a "Release" webhook to only
build releases.
2019-02-15 08:21:55 -05:00
Vasily
8425d76198 Merge pull request #875 from Bond-009/error
Treat warnings as errors for release builds
2019-02-15 13:58:49 +03:00
Vasily
9bf009c4f8 Merge pull request #898 from EraYaN/namingrules-editorconfig
Switch to Roslyn naming rules in EditorConfig
2019-02-15 13:40:10 +03:00
PloughPuff
a6bde0943e Implement proper FFmpeg version checking
Three routes to determine FFmpeg version:
1) Grab the 'ffmpeg version x.y' from from the -version output.  This should work for all pre-built binaries.
2) Compare the library versions against known contents of FFmpeg versions.  This is fallback aimed at custom builds.
3) Compare libavcodec version to determine if newer than latest known release.  This suggests user is running within latest/HEAD/master build.
2019-02-14 22:08:48 +00:00
Erwin de Haan
db1ebe2559 Static fields prefix 's_' -> '_' 2019-02-14 20:14:29 +01:00
Erwin de Haan
dbebc4774f Switched to Roslyn naming rules 2019-02-14 20:06:20 +01:00
Bond-009
0fbc4545d1 Address comments 2019-02-14 17:02:46 +01:00
Vasily
5d4bef5478 Update jellyfin-web submodule to master as of 14.02.2019 2019-02-14 09:14:04 -05:00
Vasily
cac3a3e945 Merge pull request #863 from fruhnow/tvg-chno
Adding support for "tvg-chno"-Tag in M3U Channel Lists
2019-02-14 12:46:31 +03:00
Bond-009
bca569da42 Reduce the amount of db calls during the post scan event 2019-02-13 22:10:37 +01:00
Bond-009
a82303ccd1 Fix uncaught xml error 2019-02-13 21:41:24 +01:00
ploughpuff
a2dd2ddd55 Rewrite rules for determining app paths and use XDG_CONFIG_HOME for configDir (#781)
Re-write rules for determining dataDir, configDir and logDir.  Generally, arguments from command line take precedence, then JELLYFIN env vars, before using XDG names.

Co-Authored-By: ploughpuff <33969763+ploughpuff@users.noreply.github.com>
2019-02-13 16:35:14 +01:00
Bond-009
5835c4b21d Remove comment 2019-02-13 12:58:46 +01:00
Claus Vium
d8e6808d77 Update Emby.Server.Implementations/Library/DefaultAuthenticationProvider.cs
fix to styling

Co-Authored-By: LogicalPhallacy <44458166+LogicalPhallacy@users.noreply.github.com>
2019-02-13 00:44:07 -08:00
Claus Vium
9e58e31de0 Update Emby.Server.Implementations/Library/DefaultAuthenticationProvider.cs
fix to styling

Co-Authored-By: LogicalPhallacy <44458166+LogicalPhallacy@users.noreply.github.com>
2019-02-13 00:43:48 -08:00
Phallacy
77602aff88 Minor fixes re:PR870, added null checks from PR876 2019-02-13 00:33:00 -08:00
Phallacy
1ffd443d5a fixed nul user check to be first per justaman 2019-02-12 22:30:26 -08:00
Phallacy
1dc5a624a7 fixed gitignore fail 2019-02-12 22:24:05 -08:00
Erwin de Haan
3f878d63a5 Added Debug build and seperate the check-abi pipeline. 2019-02-12 22:44:01 +01:00
Bond-009
a5882ae162 Treat warnings as errors for release builds 2019-02-12 22:15:11 +01:00
Bond-009
c74028d08d Address comments 2019-02-12 21:59:56 +01:00
Bond-009
3f13851be5 Address comments 2019-02-12 21:06:47 +01:00
Bond_009
ea446fd4a3 Revert back to netcoreapp2.1 2019-02-12 21:06:47 +01:00
Bond_009
585b5201f1 Last bits 2019-02-12 21:06:47 +01:00
Bond_009
8d98885cda Less string allocations 2019-02-12 21:06:47 +01:00
Bond_009
da9418c1b2 Useless copy 2019-02-12 21:06:47 +01:00
Bond_009
9dba930a85 Warn faster for slow requests 2019-02-12 21:06:47 +01:00
Bond_009
7722cb3ffa Some Lists -> IEnumerable 2019-02-12 21:06:47 +01:00
Bond_009
3e6819c718 Don't clone lists 2019-02-12 21:06:47 +01:00
Bond_009
41fb1e5106 Tuple -> ValueTuple 2019-02-12 21:06:47 +01:00
Bond_009
64d5ec12e2 Use HashSets for increased perf 2019-02-12 21:06:47 +01:00
Bond_009
d409623086 Don't create multiple instances of the same type 2019-02-12 20:52:23 +01:00
Bond_009
9af28607c9 Simplify plugin loading 2019-02-12 20:52:23 +01:00
Bond_009
81a8ebde22 Move to Microsoft.Extensions.DependencyInjection
This PR replaces SimpleInjector with
Microsoft.Extensions.DependencyInjection.
2019-02-12 20:52:23 +01:00
Erwin de Haan
8055b70ab1 Fixed full pipeline, runs correctly now with drone exec 2019-02-12 16:21:46 +01:00
Phallacy
05bbf71b6d sha256 with salt auth and sha1 interop 2019-02-12 02:16:03 -08:00
LogicalPhallacy
8bf88f4cb2 Merge pull request #9 from jellyfin/master
Yanking in latest changes
2019-02-11 22:48:50 -08:00
Felix Ruhnow
edf5ee0cc4 combining some of the if's and adressing #820 2019-02-11 10:11:07 +01:00
Felix Ruhnow
86089ec03a Adding support for "tvg-chno"-Tag in M3U Channel Lists 2019-02-10 22:23:47 +01:00
Erwin de Haan
29d6783471 Switched to debian for the compat runners. 2019-02-10 21:10:03 +01:00
Erwin de Haan
236e21efcb Fixed extension of compat checker and added err_ignore flag. 2019-02-10 21:04:39 +01:00
Erwin de Haan
30ec203eff Added first test for dotnet-compat ABI testing to drone. 2019-02-10 20:57:31 +01:00
Bond_009
a6a4cd5667 Removed some unused fields 2019-02-09 15:57:42 +01:00
Bond_009
3a5bbcf2a8 Style fixes 2019-02-09 15:45:36 +01:00
Bond_009
449074e73f Make more things async 2019-02-09 15:39:17 +01:00
Bond_009
2fc97212a7 Make some methods async 2019-02-09 13:41:09 +01:00
Phallacy
4519ce26e2 Upgrade crypto provider, retarget better framework 2019-01-31 00:24:53 -08:00
Phallacy
49d9649b8e added submodule dir to gitignore 2019-01-30 23:35:17 -08:00
568 changed files with 10764 additions and 29445 deletions

192
.ci/azure-pipelines.yml Normal file
View File

@@ -0,0 +1,192 @@
name: $(Date:yyyyMMdd)$(Rev:.r)
variables:
- name: TestProjects
value: 'Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj'
- name: RestoreBuildProjects
value: 'Jellyfin.Server/Jellyfin.Server.csproj'
pr:
autoCancel: true
trigger:
batch: true
jobs:
- job: main_build
displayName: Main Build
pool:
vmImage: ubuntu-16.04
strategy:
matrix:
release:
BuildConfiguration: Release
debug:
BuildConfiguration: Debug
maxParallel: 2
steps:
- checkout: self
clean: true
submodules: true
persistCredentials: false
- task: DotNetCoreCLI@2
displayName: Restore
inputs:
command: restore
projects: '$(RestoreBuildProjects)'
- task: DotNetCoreCLI@2
displayName: Build
inputs:
projects: '$(RestoreBuildProjects)'
arguments: '--configuration $(BuildConfiguration)'
- task: DotNetCoreCLI@2
displayName: Test
inputs:
command: test
projects: '$(RestoreBuildProjects)'
arguments: '--configuration $(BuildConfiguration)'
enabled: false
- task: DotNetCoreCLI@2
displayName: Publish
inputs:
command: publish
publishWebProjects: false
projects: '$(RestoreBuildProjects)'
arguments: '--configuration $(BuildConfiguration) --output $(build.artifactstagingdirectory)'
zipAfterPublish: false
# - task: PublishBuildArtifacts@1
# displayName: 'Publish Artifact'
# inputs:
# PathtoPublish: '$(build.artifactstagingdirectory)'
# artifactName: 'jellyfin-build-$(BuildConfiguration)'
# zipAfterPublish: true
- task: PublishBuildArtifacts@1
displayName: 'Publish Artifact Naming'
condition: and(eq(variables['BuildConfiguration'], 'Release'), succeeded())
inputs:
PathtoPublish: '$(build.artifactstagingdirectory)/Jellyfin.Server/Emby.Naming.dll'
artifactName: 'Jellyfin.Naming'
- task: PublishBuildArtifacts@1
displayName: 'Publish Artifact Controller'
condition: and(eq(variables['BuildConfiguration'], 'Release'), succeeded())
inputs:
PathtoPublish: '$(build.artifactstagingdirectory)/Jellyfin.Server/MediaBrowser.Controller.dll'
artifactName: 'Jellyfin.Controller'
- task: PublishBuildArtifacts@1
displayName: 'Publish Artifact Model'
condition: and(eq(variables['BuildConfiguration'], 'Release'), succeeded())
inputs:
PathtoPublish: '$(build.artifactstagingdirectory)/Jellyfin.Server/MediaBrowser.Model.dll'
artifactName: 'Jellyfin.Model'
- task: PublishBuildArtifacts@1
displayName: 'Publish Artifact Common'
condition: and(eq(variables['BuildConfiguration'], 'Release'), succeeded())
inputs:
PathtoPublish: '$(build.artifactstagingdirectory)/Jellyfin.Server/MediaBrowser.Common.dll'
artifactName: 'Jellyfin.Common'
- job: dotnet_compat
displayName: Compatibility Check
pool:
vmImage: ubuntu-16.04
dependsOn: main_build
condition: and(succeeded(), variables['System.PullRequest.PullRequestNumber']) # Only execute if the pullrequest numer is defined. (So not for normal CI builds)
strategy:
matrix:
Naming:
NugetPackageName: Jellyfin.Naming
AssemblyFileName: Emby.Naming.dll
Controller:
NugetPackageName: Jellyfin.Controller
AssemblyFileName: MediaBrowser.Controller.dll
Model:
NugetPackageName: Jellyfin.Model
AssemblyFileName: MediaBrowser.Model.dll
Common:
NugetPackageName: Jellyfin.Common
AssemblyFileName: MediaBrowser.Common.dll
maxParallel: 2
steps:
- checkout: none
- task: DownloadBuildArtifacts@0
displayName: Download the Reference Assembly Build Artifact
inputs:
buildType: 'specific' # Options: current, specific
project: $(System.TeamProjectId) # Required when buildType == Specific
pipeline: $(System.DefinitionId) # Required when buildType == Specific, not sure if this will take a name too
#specificBuildWithTriggering: false # Optional
buildVersionToDownload: 'latestFromBranch' # Required when buildType == Specific# Options: latest, latestFromBranch, specific
allowPartiallySucceededBuilds: false # Optional
branchName: '$(System.PullRequest.TargetBranch)' # Required when buildType == Specific && BuildVersionToDownload == LatestFromBranch
#buildId: # Required when buildType == Specific && BuildVersionToDownload == Specific
#tags: # Optional
downloadType: 'single' # Options: single, specific
artifactName: '$(NugetPackageName)'# Required when downloadType == Single
#itemPattern: '**' # Optional
downloadPath: '$(System.ArtifactsDirectory)/current-artifacts'
#parallelizationLimit: '8' # Optional
- task: CopyFiles@2
displayName: Copy Nuget Assembly to current-release folder
inputs:
sourceFolder: $(System.ArtifactsDirectory)/current-artifacts # Optional
contents: '**/*.dll'
targetFolder: $(System.ArtifactsDirectory)/current-release
cleanTargetFolder: true # Optional
overWrite: true # Optional
flattenFolders: true # Optional
- task: DownloadBuildArtifacts@0
displayName: Download the New Assembly Build Artifact
inputs:
buildType: 'current' # Options: current, specific
allowPartiallySucceededBuilds: false # Optional
downloadType: 'single' # Options: single, specific
artifactName: '$(NugetPackageName)' # Required when downloadType == Single
downloadPath: '$(System.ArtifactsDirectory)/new-artifacts'
- task: CopyFiles@2
displayName: Copy Artifact Assembly to new-release folder
inputs:
sourceFolder: $(System.ArtifactsDirectory)/new-artifacts # Optional
contents: '**/*.dll'
targetFolder: $(System.ArtifactsDirectory)/new-release
cleanTargetFolder: true # Optional
overWrite: true # Optional
flattenFolders: true # Optional
- task: DownloadGitHubRelease@0
displayName: Download ABI compatibility check tool from GitHub
inputs:
connection: Jellyfin GitHub
userRepository: EraYaN/dotnet-compatibility
defaultVersionType: 'latest' # Options: latest, specificVersion, specificTag
#version: # Required when defaultVersionType != Latest
itemPattern: '**-ci.zip' # Optional
downloadPath: '$(System.ArtifactsDirectory)'
- task: ExtractFiles@1
displayName: Extract ABI compatibility check tool
inputs:
archiveFilePatterns: '$(System.ArtifactsDirectory)/*-ci.zip'
destinationFolder: $(System.ArtifactsDirectory)/tools
cleanDestinationFolder: true
- task: CmdLine@2
displayName: Execute ABI compatibility check tool
inputs:
script: 'dotnet tools/CompatibilityCheckerCoreCLI.dll current-release/$(AssemblyFileName) new-release/$(AssemblyFileName)'
workingDirectory: $(System.ArtifactsDirectory) # Optional
#failOnStderr: false # Optional

8
.copr/Makefile Normal file
View File

@@ -0,0 +1,8 @@
srpm:
dnf -y install git
git submodule update --init --recursive
cd deployment/fedora-package-x64; \
./create_tarball.sh; \
rpmbuild -bs pkg-src/jellyfin.spec \
--define "_sourcedir $$PWD/pkg-src/" \
--define "_srcrpmdir $(outdir)"

View File

@@ -8,3 +8,4 @@ README.md
deployment/*/dist
deployment/*/pkg-dist
deployment/collect-dist/
ci/

View File

@@ -1,12 +1,30 @@
---
kind: pipeline
name: build
name: build-debug
steps:
- name: submodules
image: docker:git
commands:
- git submodule update --init --recursive
- name: build
image: microsoft/dotnet:2-sdk
commands:
- dotnet publish --configuration release --output /release Jellyfin.Server
- dotnet publish "Jellyfin.Server" --configuration Debug --output "../ci/ci-debug"
---
kind: pipeline
name: build-release
steps:
- name: submodules
image: docker:git
commands:
- git submodule update --init --recursive
- name: build
image: microsoft/dotnet:2-sdk
commands:
- dotnet publish "Jellyfin.Server" --configuration Release --output "../ci/ci-release"

View File

@@ -15,6 +15,10 @@ insert_final_newline = true
end_of_line = lf
max_line_length = null
# YAML indentation
[*.{yml,yaml}]
indent_size = 2
# XML indentation
[*.{csproj,xml}]
indent_size = 2
@@ -55,15 +59,77 @@ dotnet_style_prefer_conditional_expression_over_return = true:silent
###############################
# Naming Conventions #
###############################
# Style Definitions
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
# Use PascalCase for constant fields
dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
dotnet_naming_symbols.constant_fields.applicable_kinds = field
dotnet_naming_symbols.constant_fields.applicable_accessibilities = *
dotnet_naming_symbols.constant_fields.required_modifiers = const
# Style Definitions (From Roslyn)
# Non-private static fields are PascalCase
dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.symbols = non_private_static_fields
dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.style = non_private_static_field_style
dotnet_naming_symbols.non_private_static_fields.applicable_kinds = field
dotnet_naming_symbols.non_private_static_fields.applicable_accessibilities = public, protected, internal, protected internal, private protected
dotnet_naming_symbols.non_private_static_fields.required_modifiers = static
dotnet_naming_style.non_private_static_field_style.capitalization = pascal_case
# Constants are PascalCase
dotnet_naming_rule.constants_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.constants_should_be_pascal_case.symbols = constants
dotnet_naming_rule.constants_should_be_pascal_case.style = constant_style
dotnet_naming_symbols.constants.applicable_kinds = field, local
dotnet_naming_symbols.constants.required_modifiers = const
dotnet_naming_style.constant_style.capitalization = pascal_case
# Static fields are camelCase and start with s_
dotnet_naming_rule.static_fields_should_be_camel_case.severity = suggestion
dotnet_naming_rule.static_fields_should_be_camel_case.symbols = static_fields
dotnet_naming_rule.static_fields_should_be_camel_case.style = static_field_style
dotnet_naming_symbols.static_fields.applicable_kinds = field
dotnet_naming_symbols.static_fields.required_modifiers = static
dotnet_naming_style.static_field_style.capitalization = camel_case
dotnet_naming_style.static_field_style.required_prefix = _
# Instance fields are camelCase and start with _
dotnet_naming_rule.instance_fields_should_be_camel_case.severity = suggestion
dotnet_naming_rule.instance_fields_should_be_camel_case.symbols = instance_fields
dotnet_naming_rule.instance_fields_should_be_camel_case.style = instance_field_style
dotnet_naming_symbols.instance_fields.applicable_kinds = field
dotnet_naming_style.instance_field_style.capitalization = camel_case
dotnet_naming_style.instance_field_style.required_prefix = _
# Locals and parameters are camelCase
dotnet_naming_rule.locals_should_be_camel_case.severity = suggestion
dotnet_naming_rule.locals_should_be_camel_case.symbols = locals_and_parameters
dotnet_naming_rule.locals_should_be_camel_case.style = camel_case_style
dotnet_naming_symbols.locals_and_parameters.applicable_kinds = parameter, local
dotnet_naming_style.camel_case_style.capitalization = camel_case
# Local functions are PascalCase
dotnet_naming_rule.local_functions_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.local_functions_should_be_pascal_case.symbols = local_functions
dotnet_naming_rule.local_functions_should_be_pascal_case.style = local_function_style
dotnet_naming_symbols.local_functions.applicable_kinds = local_function
dotnet_naming_style.local_function_style.capitalization = pascal_case
# By default, name items with PascalCase
dotnet_naming_rule.members_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.members_should_be_pascal_case.symbols = all_members
dotnet_naming_rule.members_should_be_pascal_case.style = pascal_case_style
dotnet_naming_symbols.all_members.applicable_kinds = *
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
###############################
# C# Coding Conventions #
###############################

View File

@@ -30,6 +30,7 @@ assignees: ''
- OS: [e.g. Docker, Debian, Windows]
- Browser: [e.g. Firefox, Chrome, Safari]
- Jellyfin Version: [e.g. 10.0.1]
- Reverse proxy: [e.g. no, nginx, apache, etc.]
**Additional context**
<!-- Add any other context about the problem here. -->

5
.gitignore vendored
View File

@@ -264,3 +264,8 @@ deployment/**/pkg-dist-tmp/
deployment/collect-dist/
jellyfin_version.ini
ci/
# Doxygen
doc/

1
.gitmodules vendored
View File

@@ -1,3 +1,4 @@
[submodule "MediaBrowser.WebDashboard/jellyfin-web"]
path = MediaBrowser.WebDashboard/jellyfin-web
url = https://github.com/jellyfin/jellyfin-web.git
branch = .

View File

@@ -165,7 +165,7 @@ namespace BDInfo
foreach (var file in files)
{
PlaylistFiles.Add(
file.Name.ToUpper(), new TSPlaylistFile(this, file, _fileSystem));
file.Name.ToUpper(), new TSPlaylistFile(this, file));
}
}
@@ -185,7 +185,7 @@ namespace BDInfo
foreach (var file in files)
{
StreamClipFiles.Add(
file.Name.ToUpper(), new TSStreamClipFile(file, _fileSystem));
file.Name.ToUpper(), new TSStreamClipFile(file));
}
}

View File

@@ -9,8 +9,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Jellyfin Project")]
[assembly: AssemblyProduct("Jellyfin: The Free Software Media System")]
[assembly: AssemblyCopyright("Copyright © 2016 CinemaSquid. Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")]
[assembly: AssemblyProduct("Jellyfin Server")]
[assembly: AssemblyCopyright("Copyright © 2016 CinemaSquid. Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: NeutralResourcesLanguage("en")]

View File

@@ -28,7 +28,6 @@ namespace BDInfo
{
public class TSPlaylistFile
{
private readonly IFileSystem _fileSystem;
private FileSystemMetadata FileInfo = null;
public string FileType = null;
public bool IsInitialized = false;
@@ -64,21 +63,19 @@ namespace BDInfo
new List<TSGraphicsStream>();
public TSPlaylistFile(BDROM bdrom,
FileSystemMetadata fileInfo, IFileSystem fileSystem)
FileSystemMetadata fileInfo)
{
BDROM = bdrom;
FileInfo = fileInfo;
_fileSystem = fileSystem;
Name = fileInfo.Name.ToUpper();
}
public TSPlaylistFile(BDROM bdrom,
string name,
List<TSStreamClip> clips, IFileSystem fileSystem)
List<TSStreamClip> clips)
{
BDROM = bdrom;
Name = name;
_fileSystem = fileSystem;
IsCustom = true;
foreach (var clip in clips)
{

View File

@@ -28,7 +28,6 @@ namespace BDInfo
{
public class TSStreamClipFile
{
private readonly IFileSystem _fileSystem;
public FileSystemMetadata FileInfo = null;
public string FileType = null;
public bool IsValid = false;
@@ -37,10 +36,9 @@ namespace BDInfo
public Dictionary<ushort, TSStream> Streams =
new Dictionary<ushort, TSStream>();
public TSStreamClipFile(FileSystemMetadata fileInfo, IFileSystem fileSystem)
public TSStreamClipFile(FileSystemMetadata fileInfo)
{
FileInfo = fileInfo;
_fileSystem = fileSystem;
Name = fileInfo.Name.ToUpper();
}

View File

@@ -19,6 +19,11 @@
- [LogicalPhallacy](https://github.com/LogicalPhallacy/)
- [RazeLighter777](https://github.com/RazeLighter777)
- [WillWill56](https://github.com/WillWill56)
- [Liggy](https://github.com/Liggy)
- [fruhnow](https://github.com/fruhnow)
- [Lynxy](https://github.com/Lynxy)
- [fasheng](https://github.com/fasheng)
- [ploughpuff](https://github.com/ploughpuff)
# Emby Contributors

View File

@@ -1,27 +1,34 @@
ARG DOTNET_VERSION=2
ARG DOTNET_VERSION=2.2
FROM microsoft/dotnet:${DOTNET_VERSION}-sdk as builder
FROM mcr.microsoft.com/dotnet/core/sdk:${DOTNET_VERSION} as builder
WORKDIR /repo
COPY . .
ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
RUN dotnet publish \
--configuration release \
--output /jellyfin \
Jellyfin.Server
RUN bash -c "source deployment/common.build.sh && \
build_jellyfin Jellyfin.Server Release linux-x64 /jellyfin"
FROM jellyfin/ffmpeg as ffmpeg
FROM microsoft/dotnet:${DOTNET_VERSION}-runtime
FROM mcr.microsoft.com/dotnet/core/runtime:${DOTNET_VERSION}
# libfontconfig1 is required for Skia
RUN apt-get update \
&& apt-get install --no-install-recommends --no-install-suggests -y \
libfontconfig1 \
&& apt-get clean autoclean \
&& apt-get autoremove \
&& rm -rf /var/lib/{apt,dpkg,cache,log} \
&& rm -rf /var/lib/apt/lists/* \
&& mkdir -p /cache /config /media \
&& chmod 777 /cache /config /media
COPY --from=ffmpeg / /
COPY --from=builder /jellyfin /jellyfin
ARG JELLYFIN_WEB_VERSION=10.3.0
RUN curl -L https://github.com/jellyfin/jellyfin-web/archive/v${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \
&& rm -rf /jellyfin/jellyfin-web \
&& mv jellyfin-web-${JELLYFIN_WEB_VERSION} /jellyfin/jellyfin-web
EXPOSE 8096
VOLUME /cache /config /media
ENTRYPOINT dotnet /jellyfin/jellyfin.dll --datadir /config --cachedir /cache
ENTRYPOINT dotnet /jellyfin/jellyfin.dll \
--datadir /config \
--cachedir /cache \
--ffmpeg /usr/local/bin/ffmpeg

View File

@@ -8,7 +8,7 @@ FROM alpine as qemu_extract
COPY --from=qemu /usr/bin qemu-arm-static.tar.gz
RUN tar -xzvf qemu-arm-static.tar.gz
FROM microsoft/dotnet:${DOTNET_VERSION}-sdk-stretch as builder
FROM mcr.microsoft.com/dotnet/core/sdk:${DOTNET_VERSION} as builder
WORKDIR /repo
COPY . .
ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
@@ -17,20 +17,27 @@ RUN find . -type f -exec sed -i 's/netcoreapp2.1/netcoreapp3.0/g' {} \;
# Discard objs - may cause failures if exists
RUN find . -type d -name obj | xargs -r rm -r
# Build
RUN dotnet publish \
-r linux-arm \
--configuration release \
--output /jellyfin \
Jellyfin.Server
RUN bash -c "source deployment/common.build.sh && \
build_jellyfin Jellyfin.Server Release linux-arm /jellyfin"
FROM microsoft/dotnet:${DOTNET_VERSION}-runtime-stretch-slim-arm32v7
FROM mcr.microsoft.com/dotnet/core/runtime:${DOTNET_VERSION}-stretch-slim-arm32v7
COPY --from=qemu_extract qemu-arm-static /usr/bin
RUN apt-get update \
&& apt-get install --no-install-recommends --no-install-suggests -y ffmpeg \
&& rm -rf /var/lib/apt/lists/* \
&& mkdir -p /cache /config /media \
&& chmod 777 /cache /config /media
COPY --from=builder /jellyfin /jellyfin
ARG JELLYFIN_WEB_VERSION=10.3.0
RUN curl -L https://github.com/jellyfin/jellyfin-web/archive/v${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \
&& rm -rf /jellyfin/jellyfin-web \
&& mv jellyfin-web-${JELLYFIN_WEB_VERSION} /jellyfin/jellyfin-web
EXPOSE 8096
VOLUME /cache /config /media
ENTRYPOINT dotnet /jellyfin/jellyfin.dll --datadir /config --cachedir /cache
ENTRYPOINT dotnet /jellyfin/jellyfin.dll \
--datadir /config \
--cachedir /cache \
--ffmpeg /usr/bin/ffmpeg

View File

@@ -9,7 +9,7 @@ COPY --from=qemu /usr/bin qemu-aarch64-static.tar.gz
RUN tar -xzvf qemu-aarch64-static.tar.gz
FROM microsoft/dotnet:${DOTNET_VERSION}-sdk-stretch as builder
FROM mcr.microsoft.com/dotnet/core/sdk:${DOTNET_VERSION} as builder
WORKDIR /repo
COPY . .
ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
@@ -18,20 +18,27 @@ RUN find . -type f -exec sed -i 's/netcoreapp2.1/netcoreapp3.0/g' {} \;
# Discard objs - may cause failures if exists
RUN find . -type d -name obj | xargs -r rm -r
# Build
RUN dotnet publish \
-r linux-arm64 \
--configuration release \
--output /jellyfin \
Jellyfin.Server
RUN bash -c "source deployment/common.build.sh && \
build_jellyfin Jellyfin.Server Release linux-arm64 /jellyfin"
FROM microsoft/dotnet:${DOTNET_VERSION}-runtime-stretch-slim-arm64v8
FROM mcr.microsoft.com/dotnet/core/runtime:${DOTNET_VERSION}-stretch-slim-arm64v8
COPY --from=qemu_extract qemu-aarch64-static /usr/bin
RUN apt-get update \
&& apt-get install --no-install-recommends --no-install-suggests -y ffmpeg \
&& rm -rf /var/lib/apt/lists/* \
&& mkdir -p /cache /config /media \
&& chmod 777 /cache /config /media
COPY --from=builder /jellyfin /jellyfin
ARG JELLYFIN_WEB_VERSION=10.3.0
RUN curl -L https://github.com/jellyfin/jellyfin-web/archive/v${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \
&& rm -rf /jellyfin/jellyfin-web \
&& mv jellyfin-web-${JELLYFIN_WEB_VERSION} /jellyfin/jellyfin-web
EXPOSE 8096
VOLUME /cache /config /media
ENTRYPOINT dotnet /jellyfin/jellyfin.dll --datadir /config --cachedir /cache
ENTRYPOINT dotnet /jellyfin/jellyfin.dll \
--datadir /config \
--cachedir /cache \
--ffmpeg /usr/bin/ffmpeg

2565
Doxyfile Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,36 +0,0 @@
namespace DvdLib.Ifo
{
public enum AudioCodec
{
AC3 = 0,
MPEG1 = 2,
MPEG2ext = 3,
LPCM = 4,
DTS = 6,
}
public enum ApplicationMode
{
Unspecified = 0,
Karaoke = 1,
Surround = 2,
}
public class AudioAttributes
{
public readonly AudioCodec Codec;
public readonly bool MultichannelExtensionPresent;
public readonly ApplicationMode Mode;
public readonly byte QuantDRC;
public readonly byte SampleRate;
public readonly byte Channels;
public readonly ushort LanguageCode;
public readonly byte LanguageExtension;
public readonly byte CodeExtension;
}
public class MultiChannelExtension
{
}
}

View File

@@ -26,17 +26,17 @@ namespace DvdLib.Ifo
if (vmgPath == null)
{
var allIfos = allFiles.Where(i => string.Equals(i.Extension, ".ifo", StringComparison.OrdinalIgnoreCase));
foreach (var ifo in allIfos)
foreach (var ifo in allFiles)
{
var num = ifo.Name.Split('_').ElementAtOrDefault(1);
var numbersRead = new List<ushort>();
if (!string.Equals(ifo.Extension, ".ifo", StringComparison.OrdinalIgnoreCase))
{
continue;
}
if (!string.IsNullOrEmpty(num) && ushort.TryParse(num, out var ifoNumber) && !numbersRead.Contains(ifoNumber))
var nums = ifo.Name.Split(new [] { '_' }, StringSplitOptions.RemoveEmptyEntries);
if (nums.Length >= 2 && ushort.TryParse(nums[1], out var ifoNumber))
{
ReadVTS(ifoNumber, ifo.FullName);
numbersRead.Add(ifoNumber);
}
}
}
@@ -76,7 +76,7 @@ namespace DvdLib.Ifo
}
}
private void ReadVTS(ushort vtsNum, List<FileSystemMetadata> allFiles)
private void ReadVTS(ushort vtsNum, IEnumerable<FileSystemMetadata> allFiles)
{
var filename = string.Format("VTS_{0:00}_0.IFO", vtsNum);

View File

@@ -1,17 +0,0 @@
using System.Collections.Generic;
namespace DvdLib.Ifo
{
public class ProgramChainCommandTable
{
public readonly ushort LastByteAddress;
public readonly List<VirtualMachineCommand> PreCommands;
public readonly List<VirtualMachineCommand> PostCommands;
public readonly List<VirtualMachineCommand> CellCommands;
}
public class VirtualMachineCommand
{
public readonly byte[] Command;
}
}

View File

@@ -25,13 +25,10 @@ namespace DvdLib.Ifo
public byte[] SubpictureStreamControl { get; private set; } // 32*4 entries
private ushort _nextProgramNumber;
public readonly ProgramChain Next;
private ushort _prevProgramNumber;
public readonly ProgramChain Previous;
private ushort _goupProgramNumber;
public readonly ProgramChain Goup; // ?? maybe Group
public ProgramPlaybackMode PlaybackMode { get; private set; }
public uint ProgramCount { get; private set; }
@@ -40,7 +37,6 @@ namespace DvdLib.Ifo
public byte[] Palette { get; private set; } // 16*4 entries
private ushort _commandTableOffset;
public readonly ProgramChainCommandTable CommandTable;
private ushort _programMapOffset;
private ushort _cellPlaybackOffset;

View File

@@ -1,46 +0,0 @@
namespace DvdLib.Ifo
{
public enum VideoCodec
{
MPEG1 = 0,
MPEG2 = 1,
}
public enum VideoFormat
{
NTSC = 0,
PAL = 1,
}
public enum AspectRatio
{
ar4to3 = 0,
ar16to9 = 3
}
public enum FilmMode
{
None = -1,
Camera = 0,
Film = 1,
}
public class VideoAttributes
{
public readonly VideoCodec Codec;
public readonly VideoFormat Format;
public readonly AspectRatio Aspect;
public readonly bool AutomaticPanScan;
public readonly bool AutomaticLetterBox;
public readonly bool Line21CCField1;
public readonly bool Line21CCField2;
public readonly int Width;
public readonly int Height;
public readonly bool Letterboxed;
public readonly FilmMode FilmMode;
public VideoAttributes()
{
}
}
}

View File

@@ -9,8 +9,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Jellyfin Project")]
[assembly: AssemblyProduct("Jellyfin: The Free Software Media System")]
[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")]
[assembly: AssemblyProduct("Jellyfin Server")]
[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: NeutralResourcesLanguage("en")]

View File

@@ -136,7 +136,7 @@ namespace Emby.Dlna.Api
{
var url = Request.AbsoluteUri;
var serverAddress = url.Substring(0, url.IndexOf("/dlna/", StringComparison.OrdinalIgnoreCase));
var xml = _dlnaManager.GetServerDescriptionXml(Request.Headers.ToDictionary(), request.UuId, serverAddress);
var xml = _dlnaManager.GetServerDescriptionXml(Request.Headers, request.UuId, serverAddress);
var cacheLength = TimeSpan.FromDays(1);
var cacheKey = Request.RawUrl.GetMD5();
@@ -147,21 +147,21 @@ namespace Emby.Dlna.Api
public object Get(GetContentDirectory request)
{
var xml = ContentDirectory.GetServiceXml(Request.Headers.ToDictionary());
var xml = ContentDirectory.GetServiceXml();
return _resultFactory.GetResult(Request, xml, XMLContentType);
}
public object Get(GetMediaReceiverRegistrar request)
{
var xml = MediaReceiverRegistrar.GetServiceXml(Request.Headers.ToDictionary());
var xml = MediaReceiverRegistrar.GetServiceXml();
return _resultFactory.GetResult(Request, xml, XMLContentType);
}
public object Get(GetConnnectionManager request)
{
var xml = ConnectionManager.GetServiceXml(Request.Headers.ToDictionary());
var xml = ConnectionManager.GetServiceXml();
return _resultFactory.GetResult(Request, xml, XMLContentType);
}
@@ -193,7 +193,7 @@ namespace Emby.Dlna.Api
return service.ProcessControlRequest(new ControlRequest
{
Headers = Request.Headers.ToDictionary(),
Headers = Request.Headers,
InputXml = requestStream,
TargetServerUuId = id,
RequestedUrl = Request.AbsoluteUri

View File

@@ -7,6 +7,7 @@ namespace Emby.Dlna.Configuration
public bool EnableServer { get; set; }
public bool EnableDebugLog { get; set; }
public bool BlastAliveMessages { get; set; }
public bool SendOnlyMatchedHost { get; set; }
public int ClientDiscoveryIntervalSeconds { get; set; }
public int BlastAliveMessageIntervalSeconds { get; set; }
public string DefaultUserId { get; set; }
@@ -16,6 +17,7 @@ namespace Emby.Dlna.Configuration
EnablePlayTo = true;
EnableServer = true;
BlastAliveMessages = true;
SendOnlyMatchedHost = true;
ClientDiscoveryIntervalSeconds = 60;
BlastAliveMessageIntervalSeconds = 1800;
}

View File

@@ -1,9 +1,7 @@
using System.Collections.Generic;
using Emby.Dlna.Service;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Model.Xml;
using Microsoft.Extensions.Logging;
namespace Emby.Dlna.ConnectionManager
@@ -13,18 +11,16 @@ namespace Emby.Dlna.ConnectionManager
private readonly IDlnaManager _dlna;
private readonly ILogger _logger;
private readonly IServerConfigurationManager _config;
protected readonly IXmlReaderSettingsFactory XmlReaderSettingsFactory;
public ConnectionManager(IDlnaManager dlna, IServerConfigurationManager config, ILogger logger, IHttpClient httpClient, IXmlReaderSettingsFactory xmlReaderSettingsFactory)
public ConnectionManager(IDlnaManager dlna, IServerConfigurationManager config, ILogger logger, IHttpClient httpClient)
: base(logger, httpClient)
{
_dlna = dlna;
_config = config;
_logger = logger;
XmlReaderSettingsFactory = xmlReaderSettingsFactory;
}
public string GetServiceXml(IDictionary<string, string> headers)
public string GetServiceXml()
{
return new ConnectionManagerXmlBuilder().GetXml();
}
@@ -34,7 +30,7 @@ namespace Emby.Dlna.ConnectionManager
var profile = _dlna.GetProfile(request.Headers) ??
_dlna.GetDefaultProfile();
return new ControlHandler(_config, _logger, XmlReaderSettingsFactory, profile).ProcessControlRequest(request);
return new ControlHandler(_config, _logger, profile).ProcessControlRequest(request);
}
}
}

View File

@@ -4,7 +4,6 @@ using Emby.Dlna.Service;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Xml;
using Microsoft.Extensions.Logging;
namespace Emby.Dlna.ConnectionManager
@@ -32,7 +31,8 @@ namespace Emby.Dlna.ConnectionManager
};
}
public ControlHandler(IServerConfigurationManager config, ILogger logger, IXmlReaderSettingsFactory xmlReaderSettingsFactory, DeviceProfile profile) : base(config, logger, xmlReaderSettingsFactory)
public ControlHandler(IServerConfigurationManager config, ILogger logger, DeviceProfile profile)
: base(config, logger)
{
_profile = profile;
}

View File

@@ -11,7 +11,6 @@ using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.TV;
using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.Xml;
using Microsoft.Extensions.Logging;
namespace Emby.Dlna.ContentDirectory
@@ -28,7 +27,6 @@ namespace Emby.Dlna.ContentDirectory
private readonly IMediaSourceManager _mediaSourceManager;
private readonly IUserViewManager _userViewManager;
private readonly IMediaEncoder _mediaEncoder;
protected readonly IXmlReaderSettingsFactory XmlReaderSettingsFactory;
private readonly ITVSeriesManager _tvSeriesManager;
public ContentDirectory(IDlnaManager dlna,
@@ -38,7 +36,12 @@ namespace Emby.Dlna.ContentDirectory
IServerConfigurationManager config,
IUserManager userManager,
ILogger logger,
IHttpClient httpClient, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, IUserViewManager userViewManager, IMediaEncoder mediaEncoder, IXmlReaderSettingsFactory xmlReaderSettingsFactory, ITVSeriesManager tvSeriesManager)
IHttpClient httpClient,
ILocalizationManager localization,
IMediaSourceManager mediaSourceManager,
IUserViewManager userViewManager,
IMediaEncoder mediaEncoder,
ITVSeriesManager tvSeriesManager)
: base(logger, httpClient)
{
_dlna = dlna;
@@ -51,7 +54,6 @@ namespace Emby.Dlna.ContentDirectory
_mediaSourceManager = mediaSourceManager;
_userViewManager = userViewManager;
_mediaEncoder = mediaEncoder;
XmlReaderSettingsFactory = xmlReaderSettingsFactory;
_tvSeriesManager = tvSeriesManager;
}
@@ -65,7 +67,7 @@ namespace Emby.Dlna.ContentDirectory
}
}
public string GetServiceXml(IDictionary<string, string> headers)
public string GetServiceXml()
{
return new ContentDirectoryXmlBuilder().GetXml();
}
@@ -94,7 +96,6 @@ namespace Emby.Dlna.ContentDirectory
_mediaSourceManager,
_userViewManager,
_mediaEncoder,
XmlReaderSettingsFactory,
_tvSeriesManager)
.ProcessControlRequest(request);
}

View File

@@ -25,7 +25,6 @@ using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Xml;
using Microsoft.Extensions.Logging;
namespace Emby.Dlna.ContentDirectory
@@ -51,8 +50,22 @@ namespace Emby.Dlna.ContentDirectory
private readonly DeviceProfile _profile;
public ControlHandler(ILogger logger, ILibraryManager libraryManager, DeviceProfile profile, string serverAddress, string accessToken, IImageProcessor imageProcessor, IUserDataManager userDataManager, User user, int systemUpdateId, IServerConfigurationManager config, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, IUserViewManager userViewManager, IMediaEncoder mediaEncoder, IXmlReaderSettingsFactory xmlReaderSettingsFactory, ITVSeriesManager tvSeriesManager)
: base(config, logger, xmlReaderSettingsFactory)
public ControlHandler(
ILogger logger,
ILibraryManager libraryManager,
DeviceProfile profile,
string serverAddress,
string accessToken,
IImageProcessor imageProcessor,
IUserDataManager userDataManager,
User user, int systemUpdateId,
IServerConfigurationManager config,
ILocalizationManager localization,
IMediaSourceManager mediaSourceManager,
IUserViewManager userViewManager,
IMediaEncoder mediaEncoder,
ITVSeriesManager tvSeriesManager)
: base(config, logger)
{
_libraryManager = libraryManager;
_userDataManager = userDataManager;
@@ -260,7 +273,7 @@ namespace Emby.Dlna.ContentDirectory
if (item.IsDisplayedAsFolder || serverItem.StubType.HasValue)
{
var childrenResult = (GetUserItems(item, serverItem.StubType, user, sortCriteria, start, requestedCount));
var childrenResult = GetUserItems(item, serverItem.StubType, user, sortCriteria, start, requestedCount);
_didlBuilder.WriteFolderElement(writer, item, serverItem.StubType, null, childrenResult.TotalRecordCount, filter, id);
}
@@ -273,7 +286,7 @@ namespace Emby.Dlna.ContentDirectory
}
else
{
var childrenResult = (GetUserItems(item, serverItem.StubType, user, sortCriteria, start, requestedCount));
var childrenResult = GetUserItems(item, serverItem.StubType, user, sortCriteria, start, requestedCount);
totalCount = childrenResult.TotalRecordCount;
provided = childrenResult.Items.Length;

View File

@@ -1,11 +1,11 @@
using System.Collections.Generic;
using System.IO;
using Microsoft.AspNetCore.Http;
namespace Emby.Dlna
{
public class ControlRequest
{
public IDictionary<string, string> Headers { get; set; }
public IHeaderDictionary Headers { get; set; }
public Stream InputXml { get; set; }
@@ -15,7 +15,7 @@ namespace Emby.Dlna
public ControlRequest()
{
Headers = new Dictionary<string, string>();
Headers = new HeaderDictionary();
}
}
}

View File

@@ -818,10 +818,9 @@ namespace Emby.Dlna.Didl
{
AddCommonFields(item, itemStubType, context, writer, filter);
var hasArtists = item as IHasArtist;
var hasAlbumArtists = item as IHasAlbumArtist;
if (hasArtists != null)
if (item is IHasArtist hasArtists)
{
foreach (var artist in hasArtists.Artists)
{

View File

@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
@@ -15,9 +16,10 @@ using MediaBrowser.Controller.Drawing;
using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Reflection;
using MediaBrowser.Model.Serialization;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Primitives;
namespace Emby.Dlna
{
@@ -29,7 +31,7 @@ namespace Emby.Dlna
private readonly ILogger _logger;
private readonly IJsonSerializer _jsonSerializer;
private readonly IServerApplicationHost _appHost;
private readonly IAssemblyInfo _assemblyInfo;
private static readonly Assembly _assembly = typeof(DlnaManager).Assembly;
private readonly Dictionary<string, Tuple<InternalProfileInfo, DeviceProfile>> _profiles = new Dictionary<string, Tuple<InternalProfileInfo, DeviceProfile>>(StringComparer.Ordinal);
@@ -38,7 +40,8 @@ namespace Emby.Dlna
IFileSystem fileSystem,
IApplicationPaths appPaths,
ILoggerFactory loggerFactory,
IJsonSerializer jsonSerializer, IServerApplicationHost appHost, IAssemblyInfo assemblyInfo)
IJsonSerializer jsonSerializer,
IServerApplicationHost appHost)
{
_xmlSerializer = xmlSerializer;
_fileSystem = fileSystem;
@@ -46,7 +49,6 @@ namespace Emby.Dlna
_logger = loggerFactory.CreateLogger("Dlna");
_jsonSerializer = jsonSerializer;
_appHost = appHost;
_assemblyInfo = assemblyInfo;
}
public async Task InitProfilesAsync()
@@ -203,16 +205,13 @@ namespace Emby.Dlna
}
}
public DeviceProfile GetProfile(IDictionary<string, string> headers)
public DeviceProfile GetProfile(IHeaderDictionary headers)
{
if (headers == null)
{
throw new ArgumentNullException(nameof(headers));
}
// Convert to case insensitive
headers = new Dictionary<string, string>(headers, StringComparer.OrdinalIgnoreCase);
var profile = GetProfiles().FirstOrDefault(i => i.Identification != null && IsMatch(headers, i.Identification));
if (profile != null)
@@ -228,12 +227,12 @@ namespace Emby.Dlna
return profile;
}
private bool IsMatch(IDictionary<string, string> headers, DeviceIdentification profileInfo)
private bool IsMatch(IHeaderDictionary headers, DeviceIdentification profileInfo)
{
return profileInfo.Headers.Any(i => IsMatch(headers, i));
}
private bool IsMatch(IDictionary<string, string> headers, HttpHeaderInfo header)
private bool IsMatch(IHeaderDictionary headers, HttpHeaderInfo header)
{
// Handle invalid user setup
if (string.IsNullOrEmpty(header.Name))
@@ -241,14 +240,14 @@ namespace Emby.Dlna
return false;
}
if (headers.TryGetValue(header.Name, out string value))
if (headers.TryGetValue(header.Name, out StringValues value))
{
switch (header.Match)
{
case HeaderMatchType.Equals:
return string.Equals(value, header.Value, StringComparison.OrdinalIgnoreCase);
case HeaderMatchType.Substring:
var isMatch = value.IndexOf(header.Value, StringComparison.OrdinalIgnoreCase) != -1;
var isMatch = value.ToString().IndexOf(header.Value, StringComparison.OrdinalIgnoreCase) != -1;
//_logger.LogDebug("IsMatch-Substring value: {0} testValue: {1} isMatch: {2}", value, header.Value, isMatch);
return isMatch;
case HeaderMatchType.Regex:
@@ -366,15 +365,18 @@ namespace Emby.Dlna
var systemProfilesPath = SystemProfilesPath;
foreach (var name in _assemblyInfo.GetManifestResourceNames(GetType())
.Where(i => i.StartsWith(namespaceName))
.ToList())
foreach (var name in _assembly.GetManifestResourceNames())
{
if (!name.StartsWith(namespaceName))
{
continue;
}
var filename = Path.GetFileName(name).Substring(namespaceName.Length);
var path = Path.Combine(systemProfilesPath, filename);
using (var stream = _assemblyInfo.GetManifestResourceStream(GetType(), name))
using (var stream = _assembly.GetManifestResourceStream(name))
{
var fileInfo = _fileSystem.GetFileInfo(path);
@@ -491,7 +493,7 @@ namespace Emby.Dlna
internal string Path { get; set; }
}
public string GetServerDescriptionXml(IDictionary<string, string> headers, string serverUuId, string serverAddress)
public string GetServerDescriptionXml(IHeaderDictionary headers, string serverUuId, string serverAddress)
{
var profile = GetProfile(headers) ??
GetDefaultProfile();
@@ -512,7 +514,7 @@ namespace Emby.Dlna
return new ImageStream
{
Format = format,
Stream = _assemblyInfo.GetManifestResourceStream(GetType(), resource)
Stream = _assembly.GetManifestResourceStream(resource)
};
}
}

View File

@@ -58,4 +58,9 @@
<EmbeddedResource Include="Profiles\Xml\Xbox One.xml" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
<PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="2.2.0" />
</ItemGroup>
</Project>

View File

@@ -1,5 +1,3 @@
using System.Collections.Generic;
namespace Emby.Dlna
{
public interface IUpnpService
@@ -7,9 +5,8 @@ namespace Emby.Dlna
/// <summary>
/// Gets the content directory XML.
/// </summary>
/// <param name="headers">The headers.</param>
/// <returns>System.String.</returns>
string GetServiceXml(IDictionary<string, string> headers);
string GetServiceXml();
/// <summary>
/// Processes the control request.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -1,5 +1,4 @@
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Emby.Dlna.PlayTo;
@@ -20,10 +19,10 @@ using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.Net;
using MediaBrowser.Model.System;
using MediaBrowser.Model.Xml;
using Microsoft.Extensions.Logging;
using Rssdp;
using Rssdp.Infrastructure;
using OperatingSystem = MediaBrowser.Common.System.OperatingSystem;
namespace Emby.Dlna.Main
{
@@ -48,9 +47,8 @@ namespace Emby.Dlna.Main
private readonly IDeviceDiscovery _deviceDiscovery;
private SsdpDevicePublisher _Publisher;
private readonly ISocketFactory _socketFactory;
private readonly IEnvironmentInfo _environmentInfo;
private readonly INetworkManager _networkManager;
private ISsdpCommunicationsServer _communicationsServer;
@@ -76,10 +74,8 @@ namespace Emby.Dlna.Main
IDeviceDiscovery deviceDiscovery,
IMediaEncoder mediaEncoder,
ISocketFactory socketFactory,
IEnvironmentInfo environmentInfo,
INetworkManager networkManager,
IUserViewManager userViewManager,
IXmlReaderSettingsFactory xmlReaderSettingsFactory,
ITVSeriesManager tvSeriesManager)
{
_config = config;
@@ -96,11 +92,11 @@ namespace Emby.Dlna.Main
_deviceDiscovery = deviceDiscovery;
_mediaEncoder = mediaEncoder;
_socketFactory = socketFactory;
_environmentInfo = environmentInfo;
_networkManager = networkManager;
_logger = loggerFactory.CreateLogger("Dlna");
ContentDirectory = new ContentDirectory.ContentDirectory(dlnaManager,
ContentDirectory = new ContentDirectory.ContentDirectory(
dlnaManager,
userDataManager,
imageProcessor,
libraryManager,
@@ -112,12 +108,11 @@ namespace Emby.Dlna.Main
mediaSourceManager,
userViewManager,
mediaEncoder,
xmlReaderSettingsFactory,
tvSeriesManager);
ConnectionManager = new ConnectionManager.ConnectionManager(dlnaManager, config, _logger, httpClient, xmlReaderSettingsFactory);
ConnectionManager = new ConnectionManager.ConnectionManager(dlnaManager, config, _logger, httpClient);
MediaReceiverRegistrar = new MediaReceiverRegistrar.MediaReceiverRegistrar(_logger, httpClient, config, xmlReaderSettingsFactory);
MediaReceiverRegistrar = new MediaReceiverRegistrar.MediaReceiverRegistrar(_logger, httpClient, config);
Current = this;
}
@@ -169,9 +164,10 @@ namespace Emby.Dlna.Main
{
if (_communicationsServer == null)
{
var enableMultiSocketBinding = _environmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.Windows;
var enableMultiSocketBinding = OperatingSystem.Id == OperatingSystemId.Windows ||
OperatingSystem.Id == OperatingSystemId.Linux;
_communicationsServer = new SsdpCommunicationsServer(_socketFactory, _networkManager, _logger, enableMultiSocketBinding)
_communicationsServer = new SsdpCommunicationsServer(_config, _socketFactory, _networkManager, _logger, enableMultiSocketBinding)
{
IsShared = true
};
@@ -229,7 +225,7 @@ namespace Emby.Dlna.Main
try
{
_Publisher = new SsdpDevicePublisher(_communicationsServer, _environmentInfo.OperatingSystemName, _environmentInfo.OperatingSystemVersion);
_Publisher = new SsdpDevicePublisher(_communicationsServer, _networkManager, OperatingSystem.Name, Environment.OSVersion.VersionString, _config.GetDlnaConfiguration().SendOnlyMatchedHost);
_Publisher.LogFunction = LogMessage;
_Publisher.SupportPnpRootDevice = false;
@@ -245,17 +241,17 @@ namespace Emby.Dlna.Main
private async Task RegisterServerEndpoints()
{
var addresses = (await _appHost.GetLocalIpAddresses(CancellationToken.None).ConfigureAwait(false)).ToList();
var addresses = await _appHost.GetLocalIpAddresses(CancellationToken.None).ConfigureAwait(false);
var udn = CreateUuid(_appHost.SystemId);
foreach (var address in addresses)
{
// TODO: Remove this condition on platforms that support it
//if (address.AddressFamily == IpAddressFamily.InterNetworkV6)
//{
// continue;
//}
if (address.AddressFamily == IpAddressFamily.InterNetworkV6)
{
// Not support IPv6 right now
continue;
}
var fullService = "urn:schemas-upnp-org:device:MediaServer:1";
@@ -268,6 +264,8 @@ namespace Emby.Dlna.Main
{
CacheLifetime = TimeSpan.FromSeconds(1800), //How long SSDP clients can cache this info.
Location = uri, // Must point to the URL that serves your devices UPnP description document.
Address = address,
SubnetMask = _networkManager.GetLocalIpSubnetMask(address),
FriendlyName = "Jellyfin",
Manufacturer = "Jellyfin",
ModelName = "Jellyfin Server",

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using Emby.Dlna.Service;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Model.Xml;
using Microsoft.Extensions.Logging;
namespace Emby.Dlna.MediaReceiverRegistrar
@@ -36,7 +35,8 @@ namespace Emby.Dlna.MediaReceiverRegistrar
};
}
public ControlHandler(IServerConfigurationManager config, ILogger logger, IXmlReaderSettingsFactory xmlReaderSettingsFactory) : base(config, logger, xmlReaderSettingsFactory)
public ControlHandler(IServerConfigurationManager config, ILogger logger)
: base(config, logger)
{
}
}

View File

@@ -1,8 +1,6 @@
using System.Collections.Generic;
using Emby.Dlna.Service;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Model.Xml;
using Microsoft.Extensions.Logging;
namespace Emby.Dlna.MediaReceiverRegistrar
@@ -10,16 +8,14 @@ namespace Emby.Dlna.MediaReceiverRegistrar
public class MediaReceiverRegistrar : BaseService, IMediaReceiverRegistrar
{
private readonly IServerConfigurationManager _config;
protected readonly IXmlReaderSettingsFactory XmlReaderSettingsFactory;
public MediaReceiverRegistrar(ILogger logger, IHttpClient httpClient, IServerConfigurationManager config, IXmlReaderSettingsFactory xmlReaderSettingsFactory)
public MediaReceiverRegistrar(ILogger logger, IHttpClient httpClient, IServerConfigurationManager config)
: base(logger, httpClient)
{
_config = config;
XmlReaderSettingsFactory = xmlReaderSettingsFactory;
}
public string GetServiceXml(IDictionary<string, string> headers)
public string GetServiceXml()
{
return new MediaReceiverRegistrarXmlBuilder().GetXml();
}
@@ -28,7 +24,7 @@ namespace Emby.Dlna.MediaReceiverRegistrar
{
return new ControlHandler(
_config,
Logger, XmlReaderSettingsFactory)
Logger)
.ProcessControlRequest(request);
}
}

View File

@@ -1,9 +0,0 @@
using System;
namespace Emby.Dlna.PlayTo
{
public class CurrentIdEventArgs : EventArgs
{
public string Id { get; set; }
}
}

View File

@@ -4,6 +4,7 @@ using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
using Emby.Dlna.Common;
using Emby.Dlna.Server;
@@ -733,26 +734,21 @@ namespace Emby.Dlna.PlayTo
return (true, null);
}
XElement uPnpResponse;
XElement uPnpResponse = null;
// Handle different variations sent back by devices
try
{
uPnpResponse = XElement.Parse(trackString);
uPnpResponse = ParseResponse(trackString);
}
catch (Exception)
catch (Exception ex)
{
// first try to add a root node with a dlna namesapce
try
{
uPnpResponse = XElement.Parse("<data xmlns:dlna=\"urn:schemas-dlna-org:device-1-0\">" + trackString + "</data>");
uPnpResponse = uPnpResponse.Descendants().First();
}
catch (Exception ex)
{
_logger.LogError(ex, "Unable to parse xml {0}", trackString);
return (true, null);
}
_logger.LogError(ex, "Uncaught exception while parsing xml");
}
if (uPnpResponse == null)
{
_logger.LogError("Failed to parse xml: \n {Xml}", trackString);
return (true, null);
}
var e = uPnpResponse.Element(uPnpNamespaces.items);
@@ -762,6 +758,43 @@ namespace Emby.Dlna.PlayTo
return (true, uTrack);
}
private XElement ParseResponse(string xml)
{
// Handle different variations sent back by devices
try
{
return XElement.Parse(xml);
}
catch (XmlException)
{
}
// first try to add a root node with a dlna namesapce
try
{
return XElement.Parse("<data xmlns:dlna=\"urn:schemas-dlna-org:device-1-0\">" + xml + "</data>")
.Descendants()
.First();
}
catch (XmlException)
{
}
// some devices send back invalid xml
try
{
return XElement.Parse(xml.Replace("&", "&amp;"));
}
catch (XmlException)
{
}
return null;
}
private static uBaseObject CreateUBaseObject(XElement container, string trackUri)
{
if (container == null)
@@ -1093,6 +1126,11 @@ namespace Emby.Dlna.PlayTo
private void OnPlaybackStart(uBaseObject mediaInfo)
{
if (string.IsNullOrWhiteSpace(mediaInfo.Url))
{
return;
}
PlaybackStart?.Invoke(this, new PlaybackStartEventArgs
{
MediaInfo = mediaInfo
@@ -1101,8 +1139,7 @@ namespace Emby.Dlna.PlayTo
private void OnPlaybackProgress(uBaseObject mediaInfo)
{
var mediaUrl = mediaInfo.Url;
if (string.IsNullOrWhiteSpace(mediaUrl))
if (string.IsNullOrWhiteSpace(mediaInfo.Url))
{
return;
}
@@ -1115,7 +1152,6 @@ namespace Emby.Dlna.PlayTo
private void OnPlaybackStop(uBaseObject mediaInfo)
{
PlaybackStopped?.Invoke(this, new PlaybackStoppedEventArgs
{
MediaInfo = mediaInfo

View File

@@ -6,6 +6,7 @@ using System.Threading;
using System.Threading.Tasks;
using Emby.Dlna.Didl;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities;
@@ -17,8 +18,8 @@ using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Events;
using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.Services;
using MediaBrowser.Model.Session;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Logging;
namespace Emby.Dlna.PlayTo
@@ -101,9 +102,10 @@ namespace Emby.Dlna.PlayTo
{
_sessionManager.ReportSessionEnded(_session.Id);
}
catch
catch (Exception ex)
{
// Could throw if the session is already gone
_logger.LogError(ex, "Error reporting the end of session {Id}", _session.Id);
}
}
@@ -111,20 +113,14 @@ namespace Emby.Dlna.PlayTo
{
var info = e.Argument;
info.Headers.TryGetValue("NTS", out string nts);
if (!info.Headers.TryGetValue("USN", out string usn)) usn = string.Empty;
if (!info.Headers.TryGetValue("NT", out string nt)) nt = string.Empty;
if (usn.IndexOf(_device.Properties.UUID, StringComparison.OrdinalIgnoreCase) != -1 &&
!_disposed)
if (!_disposed
&& info.Headers.TryGetValue("USN", out string usn)
&& usn.IndexOf(_device.Properties.UUID, StringComparison.OrdinalIgnoreCase) != -1
&& (usn.IndexOf("MediaRenderer:", StringComparison.OrdinalIgnoreCase) != -1
|| (info.Headers.TryGetValue("NT", out string nt)
&& nt.IndexOf("MediaRenderer:", StringComparison.OrdinalIgnoreCase) != -1)))
{
if (usn.IndexOf("MediaRenderer:", StringComparison.OrdinalIgnoreCase) != -1 ||
nt.IndexOf("MediaRenderer:", StringComparison.OrdinalIgnoreCase) != -1)
{
OnDeviceUnavailable();
}
OnDeviceUnavailable();
}
}
@@ -611,22 +607,34 @@ namespace Emby.Dlna.PlayTo
public void Dispose()
{
if (!_disposed)
{
_disposed = true;
_device.PlaybackStart -= _device_PlaybackStart;
_device.PlaybackProgress -= _device_PlaybackProgress;
_device.PlaybackStopped -= _device_PlaybackStopped;
_device.MediaChanged -= _device_MediaChanged;
//_deviceDiscovery.DeviceLeft -= _deviceDiscovery_DeviceLeft;
_device.OnDeviceUnavailable = null;
_device.Dispose();
}
Dispose(true);
GC.SuppressFinalize(this);
}
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
protected virtual void Dispose(bool disposing)
{
if (_disposed)
{
return;
}
if (disposing)
{
_device.Dispose();
}
_device.PlaybackStart -= _device_PlaybackStart;
_device.PlaybackProgress -= _device_PlaybackProgress;
_device.PlaybackStopped -= _device_PlaybackStopped;
_device.MediaChanged -= _device_MediaChanged;
_deviceDiscovery.DeviceLeft -= _deviceDiscovery_DeviceLeft;
_device.OnDeviceUnavailable = null;
_device = null;
_disposed = true;
}
private static readonly CultureInfo _usCulture = CultureInfo.ReadOnly(new CultureInfo("en-US"));
private Task SendGeneralCommand(GeneralCommand command, CancellationToken cancellationToken)
{
@@ -847,13 +855,13 @@ namespace Emby.Dlna.PlayTo
if (index == -1) return request;
var query = url.Substring(index + 1);
QueryParamCollection values = MyHttpUtility.ParseQueryString(query);
Dictionary<string, string> values = QueryHelpers.ParseQuery(query).ToDictionary(kv => kv.Key, kv => kv.Value.ToString());
request.DeviceProfileId = values.Get("DeviceProfileId");
request.DeviceId = values.Get("DeviceId");
request.MediaSourceId = values.Get("MediaSourceId");
request.LiveStreamId = values.Get("LiveStreamId");
request.IsDirectStream = string.Equals("true", values.Get("Static"), StringComparison.OrdinalIgnoreCase);
request.DeviceProfileId = values.GetValueOrDefault("DeviceProfileId");
request.DeviceId = values.GetValueOrDefault("DeviceId");
request.MediaSourceId = values.GetValueOrDefault("MediaSourceId");
request.LiveStreamId = values.GetValueOrDefault("LiveStreamId");
request.IsDirectStream = string.Equals("true", values.GetValueOrDefault("Static"), StringComparison.OrdinalIgnoreCase);
request.AudioStreamIndex = GetIntValue(values, "AudioStreamIndex");
request.SubtitleStreamIndex = GetIntValue(values, "SubtitleStreamIndex");
@@ -867,9 +875,9 @@ namespace Emby.Dlna.PlayTo
}
}
private static int? GetIntValue(QueryParamCollection values, string name)
private static int? GetIntValue(IReadOnlyDictionary<string, string> values, string name)
{
var value = values.Get(name);
var value = values.GetValueOrDefault(name);
if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result))
{
@@ -879,9 +887,9 @@ namespace Emby.Dlna.PlayTo
return null;
}
private static long GetLongValue(QueryParamCollection values, string name)
private static long GetLongValue(IReadOnlyDictionary<string, string> values, string name)
{
var value = values.Get(name);
var value = values.GetValueOrDefault(name);
if (long.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result))
{

View File

@@ -9,8 +9,6 @@ namespace Emby.Dlna.PlayTo
{
public class PlaylistItemFactory
{
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
public PlaylistItem Create(Photo item, DeviceProfile profile)
{
var playlistItem = new PlaylistItem

View File

@@ -107,12 +107,18 @@ namespace Emby.Dlna.PlayTo
foreach (var arg in action.ArgumentList)
{
if (arg.Direction == "out")
{
continue;
}
if (arg.Name == "InstanceID")
{
stateString += BuildArgumentXml(arg, "0");
}
else
{
stateString += BuildArgumentXml(arg, null);
}
}
return string.Format(CommandBase, action.Name, xmlNamespace, stateString);
@@ -125,11 +131,18 @@ namespace Emby.Dlna.PlayTo
foreach (var arg in action.ArgumentList)
{
if (arg.Direction == "out")
{
continue;
}
if (arg.Name == "InstanceID")
{
stateString += BuildArgumentXml(arg, "0");
}
else
{
stateString += BuildArgumentXml(arg, value.ToString(), commandParameter);
}
}
return string.Format(CommandBase, action.Name, xmlNamesapce, stateString);
@@ -142,11 +155,17 @@ namespace Emby.Dlna.PlayTo
foreach (var arg in action.ArgumentList)
{
if (arg.Name == "InstanceID")
{
stateString += BuildArgumentXml(arg, "0");
}
else if (dictionary.ContainsKey(arg.Name))
{
stateString += BuildArgumentXml(arg, dictionary[arg.Name]);
}
else
{
stateString += BuildArgumentXml(arg, value.ToString());
}
}
return string.Format(CommandBase, action.Name, xmlNamesapce, stateString);

View File

@@ -1,9 +0,0 @@
using System;
namespace Emby.Dlna.PlayTo
{
public class TransportStateEventArgs : EventArgs
{
public TRANSPORTSTATE State { get; set; }
}
}

View File

@@ -1,47 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
namespace Emby.Dlna.PlayTo
{
public class uParser
{
public static IList<uBaseObject> ParseBrowseXml(XDocument doc)
{
if (doc == null)
{
throw new ArgumentException("doc");
}
var list = new List<uBaseObject>();
var document = doc.Document;
if (document == null)
return list;
var item = (from result in document.Descendants("Result") select result).FirstOrDefault();
if (item == null)
return list;
var uPnpResponse = XElement.Parse((string)item);
var uObjects = from container in uPnpResponse.Elements(uPnpNamespaces.containers)
select new uParserObject { Element = container };
var uObjects2 = from container in uPnpResponse.Elements(uPnpNamespaces.items)
select new uParserObject { Element = container };
list.AddRange(uObjects.Concat(uObjects2).Select(CreateObjectFromXML).Where(uObject => uObject != null));
return list;
}
public static uBaseObject CreateObjectFromXML(uParserObject uItem)
{
return UpnpContainer.Create(uItem.Element);
}
}
}

View File

@@ -1,9 +0,0 @@
using System.Xml.Linq;
namespace Emby.Dlna.PlayTo
{
public class uParserObject
{
public XElement Element { get; set; }
}
}

View File

@@ -8,8 +8,8 @@ using System.Resources;
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Jellyfin Project")]
[assembly: AssemblyProduct("Jellyfin: The Free Software Media System")]
[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")]
[assembly: AssemblyProduct("Jellyfin Server")]
[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: NeutralResourcesLanguage("en")]

View File

@@ -7,7 +7,6 @@ using System.Xml;
using Emby.Dlna.Didl;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Extensions;
using MediaBrowser.Model.Xml;
using Microsoft.Extensions.Logging;
namespace Emby.Dlna.Service
@@ -18,13 +17,11 @@ namespace Emby.Dlna.Service
protected readonly IServerConfigurationManager Config;
protected readonly ILogger _logger;
protected readonly IXmlReaderSettingsFactory XmlReaderSettingsFactory;
protected BaseControlHandler(IServerConfigurationManager config, ILogger logger, IXmlReaderSettingsFactory xmlReaderSettingsFactory)
protected BaseControlHandler(IServerConfigurationManager config, ILogger logger)
{
Config = config;
_logger = logger;
XmlReaderSettingsFactory = xmlReaderSettingsFactory;
}
public ControlResponse ProcessControlRequest(ControlRequest request)
@@ -61,11 +58,13 @@ namespace Emby.Dlna.Service
using (var streamReader = new StreamReader(request.InputXml))
{
var readerSettings = XmlReaderSettingsFactory.Create(false);
readerSettings.CheckCharacters = false;
readerSettings.IgnoreProcessingInstructions = true;
readerSettings.IgnoreComments = true;
var readerSettings = new XmlReaderSettings()
{
ValidationType = ValidationType.None,
CheckCharacters = false,
IgnoreProcessingInstructions = true,
IgnoreComments = true
};
using (var reader = XmlReader.Create(streamReader, readerSettings))
{

View File

@@ -180,6 +180,12 @@ namespace Emby.Drawing
var supportedImageInfo = await GetSupportedImage(originalImagePath, dateModified).ConfigureAwait(false);
originalImagePath = supportedImageInfo.path;
if (!File.Exists(originalImagePath))
{
return (originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
}
dateModified = supportedImageInfo.dateModified;
bool requiresTransparency = TransparentImageTypes.Contains(Path.GetExtension(originalImagePath));
@@ -265,8 +271,6 @@ namespace Emby.Drawing
{
// If it fails for whatever reason, return the original image
_logger.LogError(ex, "Error encoding image");
// Just spit out the original file if all the options are default
return (originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
}
finally

View File

@@ -8,8 +8,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Jellyfin Project")]
[assembly: AssemblyProduct("Jellyfin: The Free Software Media System")]
[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")]
[assembly: AssemblyProduct("Jellyfin Server")]
[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

View File

@@ -7,6 +7,7 @@ using MediaBrowser.Model.Diagnostics;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.System;
using Microsoft.Extensions.Logging;
using OperatingSystem = MediaBrowser.Common.System.OperatingSystem;
namespace IsoMounter
{
@@ -17,9 +18,7 @@ namespace IsoMounter
#region Private Fields
private readonly IEnvironmentInfo EnvironmentInfo;
private readonly bool ExecutablesAvailable;
private readonly IFileSystem FileSystem;
private readonly ILogger _logger;
private readonly string MountCommand;
private readonly string MountPointRoot;
@@ -31,11 +30,8 @@ namespace IsoMounter
#region Constructor(s)
public LinuxIsoManager(ILogger logger, IFileSystem fileSystem, IEnvironmentInfo environment, IProcessFactory processFactory)
public LinuxIsoManager(ILogger logger, IProcessFactory processFactory)
{
EnvironmentInfo = environment;
FileSystem = fileSystem;
_logger = logger;
ProcessFactory = processFactory;
@@ -111,7 +107,7 @@ namespace IsoMounter
public bool CanMount(string path)
{
if (EnvironmentInfo.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Linux)
if (OperatingSystem.Id != OperatingSystemId.Linux)
{
return false;
}
@@ -120,7 +116,7 @@ namespace IsoMounter
Name,
path,
Path.GetExtension(path),
EnvironmentInfo.OperatingSystem,
OperatingSystem.Name,
ExecutablesAvailable
);

View File

@@ -9,8 +9,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Jellyfin Project")]
[assembly: AssemblyProduct("Jellyfin: The Free Software Media System")]
[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")]
[assembly: AssemblyProduct("Jellyfin Server")]
[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: NeutralResourcesLanguage("en")]

View File

@@ -9,8 +9,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Jellyfin Project")]
[assembly: AssemblyProduct("Jellyfin: The Free Software Media System")]
[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")]
[assembly: AssemblyProduct("Jellyfin Server")]
[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: NeutralResourcesLanguage("en")]

View File

@@ -2,7 +2,6 @@ using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
using Emby.Naming.Common;
namespace Emby.Naming.TV
@@ -22,7 +21,9 @@ namespace Emby.Naming.TV
// There were no failed tests without this block, but to be safe, we can keep it until
// the regex which require file extensions are modified so that they don't need them.
if (IsDirectory)
{
path += ".mp4";
}
EpisodePathParserResult result = null;
@@ -35,6 +36,7 @@ namespace Emby.Naming.TV
continue;
}
}
if (isNamed.HasValue)
{
if (expression.IsNamed != isNamed.Value)
@@ -42,6 +44,7 @@ namespace Emby.Naming.TV
continue;
}
}
if (isOptimistic.HasValue)
{
if (expression.IsOptimistic != isOptimistic.Value)
@@ -191,13 +194,20 @@ namespace Emby.Naming.TV
private void FillAdditional(string path, EpisodePathParserResult info, IEnumerable<EpisodeExpression> expressions)
{
var results = expressions
.Where(i => i.IsNamed)
.Select(i => Parse(path, i))
.Where(i => i.Success);
foreach (var result in results)
foreach (var i in expressions)
{
if (!i.IsNamed)
{
continue;
}
var result = Parse(path, i);
if (!result.Success)
{
continue;
}
if (string.IsNullOrEmpty(info.SeriesName))
{
info.SeriesName = result.SeriesName;
@@ -208,12 +218,10 @@ namespace Emby.Naming.TV
info.EndingEpsiodeNumber = result.EndingEpsiodeNumber;
}
if (!string.IsNullOrEmpty(info.SeriesName))
if (!string.IsNullOrEmpty(info.SeriesName)
&& (!info.EpisodeNumber.HasValue || info.EndingEpsiodeNumber.HasValue))
{
if (!info.EpisodeNumber.HasValue || info.EndingEpsiodeNumber.HasValue)
{
break;
}
break;
}
}
}

View File

@@ -11,101 +11,81 @@ namespace Emby.Notifications
public class CoreNotificationTypes : INotificationTypeFactory
{
private readonly ILocalizationManager _localization;
private readonly IServerApplicationHost _appHost;
public CoreNotificationTypes(ILocalizationManager localization, IServerApplicationHost appHost)
public CoreNotificationTypes(ILocalizationManager localization)
{
_localization = localization;
_appHost = appHost;
}
public IEnumerable<NotificationTypeInfo> GetNotificationTypes()
{
var knownTypes = new List<NotificationTypeInfo>
var knownTypes = new NotificationTypeInfo[]
{
new NotificationTypeInfo
{
Type = NotificationType.ApplicationUpdateInstalled.ToString()
},
new NotificationTypeInfo
{
Type = NotificationType.InstallationFailed.ToString()
},
new NotificationTypeInfo
{
Type = NotificationType.PluginInstalled.ToString()
},
new NotificationTypeInfo
{
Type = NotificationType.PluginError.ToString()
},
new NotificationTypeInfo
{
Type = NotificationType.PluginUninstalled.ToString()
},
new NotificationTypeInfo
{
Type = NotificationType.PluginUpdateInstalled.ToString()
},
new NotificationTypeInfo
{
Type = NotificationType.ServerRestartRequired.ToString()
},
new NotificationTypeInfo
{
Type = NotificationType.TaskFailed.ToString()
},
new NotificationTypeInfo
{
Type = NotificationType.NewLibraryContent.ToString()
},
new NotificationTypeInfo
{
Type = NotificationType.AudioPlayback.ToString()
},
new NotificationTypeInfo
{
Type = NotificationType.VideoPlayback.ToString()
},
new NotificationTypeInfo
{
Type = NotificationType.AudioPlaybackStopped.ToString()
},
new NotificationTypeInfo
{
Type = NotificationType.VideoPlaybackStopped.ToString()
},
new NotificationTypeInfo
{
Type = NotificationType.CameraImageUploaded.ToString()
},
new NotificationTypeInfo
{
Type = NotificationType.UserLockedOut.ToString()
}
};
if (!_appHost.CanSelfUpdate)
{
knownTypes.Add(new NotificationTypeInfo
},
new NotificationTypeInfo
{
Type = NotificationType.ApplicationUpdateAvailable.ToString()
});
}
}
};
foreach (var type in knownTypes)
{

View File

@@ -5,21 +5,17 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Updates;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Notifications;
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Activity;
using MediaBrowser.Model.Events;
using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.Notifications;
using MediaBrowser.Model.Tasks;
using Microsoft.Extensions.Logging;
namespace Emby.Notifications
@@ -29,43 +25,40 @@ namespace Emby.Notifications
/// </summary>
public class Notifications : IServerEntryPoint
{
private readonly IInstallationManager _installationManager;
private readonly IUserManager _userManager;
private readonly ILogger _logger;
private readonly ITaskManager _taskManager;
private readonly INotificationManager _notificationManager;
private readonly ILibraryManager _libraryManager;
private readonly ISessionManager _sessionManager;
private readonly IServerApplicationHost _appHost;
private Timer LibraryUpdateTimer { get; set; }
private readonly object _libraryChangedSyncLock = new object();
private readonly IConfigurationManager _config;
private readonly IDeviceManager _deviceManager;
private readonly ILocalizationManager _localization;
private readonly IActivityManager _activityManager;
private string[] _coreNotificationTypes;
public Notifications(IInstallationManager installationManager, IActivityManager activityManager, ILocalizationManager localization, IUserManager userManager, ILogger logger, ITaskManager taskManager, INotificationManager notificationManager, ILibraryManager libraryManager, ISessionManager sessionManager, IServerApplicationHost appHost, IConfigurationManager config, IDeviceManager deviceManager)
public Notifications(
IActivityManager activityManager,
ILocalizationManager localization,
ILogger logger,
INotificationManager notificationManager,
ILibraryManager libraryManager,
IServerApplicationHost appHost,
IConfigurationManager config)
{
_installationManager = installationManager;
_userManager = userManager;
_logger = logger;
_taskManager = taskManager;
_notificationManager = notificationManager;
_libraryManager = libraryManager;
_sessionManager = sessionManager;
_appHost = appHost;
_config = config;
_deviceManager = deviceManager;
_localization = localization;
_activityManager = activityManager;
_coreNotificationTypes = new CoreNotificationTypes(localization, appHost).GetNotificationTypes().Select(i => i.Type).ToArray();
_coreNotificationTypes = new CoreNotificationTypes(localization).GetNotificationTypes().Select(i => i.Type).ToArray();
}
public Task RunAsync()
@@ -124,10 +117,9 @@ namespace Emby.Notifications
return _config.GetConfiguration<NotificationOptions>("notifications");
}
async void _appHost_HasUpdateAvailableChanged(object sender, EventArgs e)
private async void _appHost_HasUpdateAvailableChanged(object sender, EventArgs e)
{
// This notification is for users who can't auto-update (aka running as service)
if (!_appHost.HasUpdateAvailable || _appHost.CanSelfUpdate)
if (!_appHost.HasUpdateAvailable)
{
return;
}
@@ -145,7 +137,7 @@ namespace Emby.Notifications
}
private readonly List<BaseItem> _itemsAdded = new List<BaseItem>();
void _libraryManager_ItemAdded(object sender, ItemChangeEventArgs e)
private void _libraryManager_ItemAdded(object sender, ItemChangeEventArgs e)
{
if (!FilterItem(e.Item))
{

View File

@@ -9,8 +9,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Jellyfin Project")]
[assembly: AssemblyProduct("Jellyfin: The Free Software Media System")]
[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")]
[assembly: AssemblyProduct("Jellyfin Server")]
[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: NeutralResourcesLanguage("en")]

View File

@@ -9,7 +9,6 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using Microsoft.Extensions.Logging;
using TagLib;
using TagLib.IFD;
@@ -21,13 +20,11 @@ namespace Emby.Photos
public class PhotoProvider : ICustomMetadataProvider<Photo>, IForcedProvider, IHasItemChangeMonitor
{
private readonly ILogger _logger;
private readonly IFileSystem _fileSystem;
private IImageProcessor _imageProcessor;
public PhotoProvider(ILogger logger, IFileSystem fileSystem, IImageProcessor imageProcessor)
public PhotoProvider(ILogger logger, IImageProcessor imageProcessor)
{
_logger = logger;
_fileSystem = fileSystem;
_imageProcessor = imageProcessor;
}

View File

@@ -9,8 +9,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Jellyfin Project")]
[assembly: AssemblyProduct("Jellyfin: The Free Software Media System")]
[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")]
[assembly: AssemblyProduct("Jellyfin Server")]
[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: NeutralResourcesLanguage("en")]

View File

@@ -30,13 +30,10 @@ namespace Emby.Server.Implementations.Activity
public class ActivityLogEntryPoint : IServerEntryPoint
{
private readonly IInstallationManager _installationManager;
//private readonly ILogger _logger;
private readonly ISessionManager _sessionManager;
private readonly ITaskManager _taskManager;
private readonly IActivityManager _activityManager;
private readonly ILocalizationManager _localization;
private readonly ILibraryManager _libraryManager;
private readonly ISubtitleManager _subManager;
private readonly IUserManager _userManager;
@@ -61,41 +58,37 @@ namespace Emby.Server.Implementations.Activity
public Task RunAsync()
{
_taskManager.TaskCompleted += _taskManager_TaskCompleted;
_taskManager.TaskCompleted += OnTaskCompleted;
_installationManager.PluginInstalled += _installationManager_PluginInstalled;
_installationManager.PluginUninstalled += _installationManager_PluginUninstalled;
_installationManager.PluginUpdated += _installationManager_PluginUpdated;
_installationManager.PackageInstallationFailed += _installationManager_PackageInstallationFailed;
_installationManager.PluginInstalled += OnPluginInstalled;
_installationManager.PluginUninstalled += OnPluginUninstalled;
_installationManager.PluginUpdated += OnPluginUpdated;
_installationManager.PackageInstallationFailed += OnPackageInstallationFailed;
_sessionManager.SessionStarted += _sessionManager_SessionStarted;
_sessionManager.AuthenticationFailed += _sessionManager_AuthenticationFailed;
_sessionManager.AuthenticationSucceeded += _sessionManager_AuthenticationSucceeded;
_sessionManager.SessionEnded += _sessionManager_SessionEnded;
_sessionManager.SessionStarted += OnSessionStarted;
_sessionManager.AuthenticationFailed += OnAuthenticationFailed;
_sessionManager.AuthenticationSucceeded += OnAuthenticationSucceeded;
_sessionManager.SessionEnded += OnSessionEnded;
_sessionManager.PlaybackStart += _sessionManager_PlaybackStart;
_sessionManager.PlaybackStopped += _sessionManager_PlaybackStopped;
_sessionManager.PlaybackStart += OnPlaybackStart;
_sessionManager.PlaybackStopped += OnPlaybackStopped;
//_subManager.SubtitlesDownloaded += _subManager_SubtitlesDownloaded;
_subManager.SubtitleDownloadFailure += _subManager_SubtitleDownloadFailure;
_subManager.SubtitleDownloadFailure += OnSubtitleDownloadFailure;
_userManager.UserCreated += _userManager_UserCreated;
_userManager.UserPasswordChanged += _userManager_UserPasswordChanged;
_userManager.UserDeleted += _userManager_UserDeleted;
_userManager.UserPolicyUpdated += _userManager_UserPolicyUpdated;
_userManager.UserLockedOut += _userManager_UserLockedOut;
_userManager.UserCreated += OnUserCreated;
_userManager.UserPasswordChanged += OnUserPasswordChanged;
_userManager.UserDeleted += OnUserDeleted;
_userManager.UserPolicyUpdated += OnUserPolicyUpdated;
_userManager.UserLockedOut += OnUserLockedOut;
//_config.ConfigurationUpdated += _config_ConfigurationUpdated;
//_config.NamedConfigurationUpdated += _config_NamedConfigurationUpdated;
_deviceManager.CameraImageUploaded += OnCameraImageUploaded;
_deviceManager.CameraImageUploaded += _deviceManager_CameraImageUploaded;
_appHost.ApplicationUpdated += _appHost_ApplicationUpdated;
_appHost.ApplicationUpdated += OnApplicationUpdated;
return Task.CompletedTask;
}
void _deviceManager_CameraImageUploaded(object sender, GenericEventArgs<CameraImageUploadInfo> e)
private void OnCameraImageUploaded(object sender, GenericEventArgs<CameraImageUploadInfo> e)
{
CreateLogEntry(new ActivityLogEntry
{
@@ -104,7 +97,7 @@ namespace Emby.Server.Implementations.Activity
});
}
void _userManager_UserLockedOut(object sender, GenericEventArgs<User> e)
private void OnUserLockedOut(object sender, GenericEventArgs<User> e)
{
CreateLogEntry(new ActivityLogEntry
{
@@ -114,7 +107,7 @@ namespace Emby.Server.Implementations.Activity
});
}
void _subManager_SubtitleDownloadFailure(object sender, SubtitleDownloadFailureEventArgs e)
private void OnSubtitleDownloadFailure(object sender, SubtitleDownloadFailureEventArgs e)
{
CreateLogEntry(new ActivityLogEntry
{
@@ -125,7 +118,7 @@ namespace Emby.Server.Implementations.Activity
});
}
void _sessionManager_PlaybackStopped(object sender, PlaybackStopEventArgs e)
private void OnPlaybackStopped(object sender, PlaybackStopEventArgs e)
{
var item = e.MediaInfo;
@@ -146,7 +139,7 @@ namespace Emby.Server.Implementations.Activity
return;
}
var user = e.Users.First();
var user = e.Users[0];
CreateLogEntry(new ActivityLogEntry
{
@@ -156,7 +149,7 @@ namespace Emby.Server.Implementations.Activity
});
}
void _sessionManager_PlaybackStart(object sender, PlaybackProgressEventArgs e)
private void OnPlaybackStart(object sender, PlaybackProgressEventArgs e)
{
var item = e.MediaInfo;
@@ -232,7 +225,7 @@ namespace Emby.Server.Implementations.Activity
return null;
}
void _sessionManager_SessionEnded(object sender, SessionEventArgs e)
private void OnSessionEnded(object sender, SessionEventArgs e)
{
string name;
var session = e.SessionInfo;
@@ -258,7 +251,7 @@ namespace Emby.Server.Implementations.Activity
});
}
void _sessionManager_AuthenticationSucceeded(object sender, GenericEventArgs<AuthenticationResult> e)
private void OnAuthenticationSucceeded(object sender, GenericEventArgs<AuthenticationResult> e)
{
var user = e.Argument.User;
@@ -271,7 +264,7 @@ namespace Emby.Server.Implementations.Activity
});
}
void _sessionManager_AuthenticationFailed(object sender, GenericEventArgs<AuthenticationRequest> e)
private void OnAuthenticationFailed(object sender, GenericEventArgs<AuthenticationRequest> e)
{
CreateLogEntry(new ActivityLogEntry
{
@@ -282,7 +275,7 @@ namespace Emby.Server.Implementations.Activity
});
}
void _appHost_ApplicationUpdated(object sender, GenericEventArgs<PackageVersionInfo> e)
private void OnApplicationUpdated(object sender, GenericEventArgs<PackageVersionInfo> e)
{
CreateLogEntry(new ActivityLogEntry
{
@@ -292,25 +285,7 @@ namespace Emby.Server.Implementations.Activity
});
}
void _config_NamedConfigurationUpdated(object sender, ConfigurationUpdateEventArgs e)
{
CreateLogEntry(new ActivityLogEntry
{
Name = string.Format(_localization.GetLocalizedString("MessageNamedServerConfigurationUpdatedWithValue"), e.Key),
Type = "NamedConfigurationUpdated"
});
}
void _config_ConfigurationUpdated(object sender, EventArgs e)
{
CreateLogEntry(new ActivityLogEntry
{
Name = _localization.GetLocalizedString("MessageServerConfigurationUpdated"),
Type = "ServerConfigurationUpdated"
});
}
void _userManager_UserPolicyUpdated(object sender, GenericEventArgs<User> e)
private void OnUserPolicyUpdated(object sender, GenericEventArgs<User> e)
{
CreateLogEntry(new ActivityLogEntry
{
@@ -320,7 +295,7 @@ namespace Emby.Server.Implementations.Activity
});
}
void _userManager_UserDeleted(object sender, GenericEventArgs<User> e)
private void OnUserDeleted(object sender, GenericEventArgs<User> e)
{
CreateLogEntry(new ActivityLogEntry
{
@@ -329,7 +304,7 @@ namespace Emby.Server.Implementations.Activity
});
}
void _userManager_UserPasswordChanged(object sender, GenericEventArgs<User> e)
private void OnUserPasswordChanged(object sender, GenericEventArgs<User> e)
{
CreateLogEntry(new ActivityLogEntry
{
@@ -339,7 +314,7 @@ namespace Emby.Server.Implementations.Activity
});
}
void _userManager_UserCreated(object sender, GenericEventArgs<User> e)
private void OnUserCreated(object sender, GenericEventArgs<User> e)
{
CreateLogEntry(new ActivityLogEntry
{
@@ -349,18 +324,7 @@ namespace Emby.Server.Implementations.Activity
});
}
void _subManager_SubtitlesDownloaded(object sender, SubtitleDownloadEventArgs e)
{
CreateLogEntry(new ActivityLogEntry
{
Name = string.Format(_localization.GetLocalizedString("SubtitlesDownloadedForItem"), Notifications.Notifications.GetItemName(e.Item)),
Type = "SubtitlesDownloaded",
ItemId = e.Item.Id.ToString("N"),
ShortOverview = string.Format(_localization.GetLocalizedString("ProviderValue"), e.Provider)
});
}
void _sessionManager_SessionStarted(object sender, SessionEventArgs e)
private void OnSessionStarted(object sender, SessionEventArgs e)
{
string name;
var session = e.SessionInfo;
@@ -386,7 +350,7 @@ namespace Emby.Server.Implementations.Activity
});
}
void _installationManager_PluginUpdated(object sender, GenericEventArgs<Tuple<IPlugin, PackageVersionInfo>> e)
private void OnPluginUpdated(object sender, GenericEventArgs<Tuple<IPlugin, PackageVersionInfo>> e)
{
CreateLogEntry(new ActivityLogEntry
{
@@ -397,7 +361,7 @@ namespace Emby.Server.Implementations.Activity
});
}
void _installationManager_PluginUninstalled(object sender, GenericEventArgs<IPlugin> e)
private void OnPluginUninstalled(object sender, GenericEventArgs<IPlugin> e)
{
CreateLogEntry(new ActivityLogEntry
{
@@ -406,7 +370,7 @@ namespace Emby.Server.Implementations.Activity
});
}
void _installationManager_PluginInstalled(object sender, GenericEventArgs<PackageVersionInfo> e)
private void OnPluginInstalled(object sender, GenericEventArgs<PackageVersionInfo> e)
{
CreateLogEntry(new ActivityLogEntry
{
@@ -416,7 +380,7 @@ namespace Emby.Server.Implementations.Activity
});
}
void _installationManager_PackageInstallationFailed(object sender, InstallationFailedEventArgs e)
private void OnPackageInstallationFailed(object sender, InstallationFailedEventArgs e)
{
var installationInfo = e.InstallationInfo;
@@ -429,7 +393,7 @@ namespace Emby.Server.Implementations.Activity
});
}
void _taskManager_TaskCompleted(object sender, TaskCompletionEventArgs e)
private void OnTaskCompleted(object sender, TaskCompletionEventArgs e)
{
var result = e.Result;
var task = e.Task;
@@ -468,48 +432,36 @@ namespace Emby.Server.Implementations.Activity
}
private void CreateLogEntry(ActivityLogEntry entry)
{
try
{
_activityManager.Create(entry);
}
catch
{
// Logged at lower levels
}
}
=> _activityManager.Create(entry);
public void Dispose()
{
_taskManager.TaskCompleted -= _taskManager_TaskCompleted;
_taskManager.TaskCompleted -= OnTaskCompleted;
_installationManager.PluginInstalled -= _installationManager_PluginInstalled;
_installationManager.PluginUninstalled -= _installationManager_PluginUninstalled;
_installationManager.PluginUpdated -= _installationManager_PluginUpdated;
_installationManager.PackageInstallationFailed -= _installationManager_PackageInstallationFailed;
_installationManager.PluginInstalled -= OnPluginInstalled;
_installationManager.PluginUninstalled -= OnPluginUninstalled;
_installationManager.PluginUpdated -= OnPluginUpdated;
_installationManager.PackageInstallationFailed -= OnPackageInstallationFailed;
_sessionManager.SessionStarted -= _sessionManager_SessionStarted;
_sessionManager.AuthenticationFailed -= _sessionManager_AuthenticationFailed;
_sessionManager.AuthenticationSucceeded -= _sessionManager_AuthenticationSucceeded;
_sessionManager.SessionEnded -= _sessionManager_SessionEnded;
_sessionManager.SessionStarted -= OnSessionStarted;
_sessionManager.AuthenticationFailed -= OnAuthenticationFailed;
_sessionManager.AuthenticationSucceeded -= OnAuthenticationSucceeded;
_sessionManager.SessionEnded -= OnSessionEnded;
_sessionManager.PlaybackStart -= _sessionManager_PlaybackStart;
_sessionManager.PlaybackStopped -= _sessionManager_PlaybackStopped;
_sessionManager.PlaybackStart -= OnPlaybackStart;
_sessionManager.PlaybackStopped -= OnPlaybackStopped;
_subManager.SubtitleDownloadFailure -= _subManager_SubtitleDownloadFailure;
_subManager.SubtitleDownloadFailure -= OnSubtitleDownloadFailure;
_userManager.UserCreated -= _userManager_UserCreated;
_userManager.UserPasswordChanged -= _userManager_UserPasswordChanged;
_userManager.UserDeleted -= _userManager_UserDeleted;
_userManager.UserPolicyUpdated -= _userManager_UserPolicyUpdated;
_userManager.UserLockedOut -= _userManager_UserLockedOut;
_userManager.UserCreated -= OnUserCreated;
_userManager.UserPasswordChanged -= OnUserPasswordChanged;
_userManager.UserDeleted -= OnUserDeleted;
_userManager.UserPolicyUpdated -= OnUserPolicyUpdated;
_userManager.UserLockedOut -= OnUserLockedOut;
_config.ConfigurationUpdated -= _config_ConfigurationUpdated;
_config.NamedConfigurationUpdated -= _config_NamedConfigurationUpdated;
_deviceManager.CameraImageUploaded -= OnCameraImageUploaded;
_deviceManager.CameraImageUploaded -= _deviceManager_CameraImageUploaded;
_appHost.ApplicationUpdated -= _appHost_ApplicationUpdated;
_appHost.ApplicationUpdated -= OnApplicationUpdated;
}
/// <summary>
@@ -531,6 +483,7 @@ namespace Emby.Server.Implementations.Activity
values.Add(CreateValueString(years, "year"));
days = days % DaysInYear;
}
// Number of months
if (days >= DaysInMonth)
{
@@ -538,25 +491,39 @@ namespace Emby.Server.Implementations.Activity
values.Add(CreateValueString(months, "month"));
days = days % DaysInMonth;
}
// Number of days
if (days >= 1)
{
values.Add(CreateValueString(days, "day"));
}
// Number of hours
if (span.Hours >= 1)
{
values.Add(CreateValueString(span.Hours, "hour"));
}
// Number of minutes
if (span.Minutes >= 1)
{
values.Add(CreateValueString(span.Minutes, "minute"));
}
// Number of seconds (include when 0 if no other components included)
if (span.Seconds >= 1 || values.Count == 0)
{
values.Add(CreateValueString(span.Seconds, "second"));
}
// Combine values into string
var builder = new StringBuilder();
for (int i = 0; i < values.Count; i++)
{
if (builder.Length > 0)
{
builder.Append(i == values.Count - 1 ? " and " : ", ");
}
builder.Append(values[i]);
}
// Return result

View File

@@ -39,8 +39,13 @@ namespace Emby.Server.Implementations.Activity
{
var result = _repo.GetActivityLogEntries(minDate, hasUserId, startIndex, limit);
foreach (var item in result.Items.Where(i => !i.UserId.Equals(Guid.Empty)))
foreach (var item in result.Items)
{
if (item.UserId == Guid.Empty)
{
continue;
}
var user = _userManager.GetUserById(item.UserId);
if (user != null)

View File

@@ -1,3 +1,4 @@
using System;
using System.IO;
using MediaBrowser.Common.Configuration;
@@ -14,50 +15,52 @@ namespace Emby.Server.Implementations.AppBase
/// </summary>
protected BaseApplicationPaths(
string programDataPath,
string appFolderPath,
string logDirectoryPath = null,
string configurationDirectoryPath = null,
string cacheDirectoryPath = null)
string logDirectoryPath,
string configurationDirectoryPath,
string cacheDirectoryPath,
string webDirectoryPath)
{
ProgramDataPath = programDataPath;
ProgramSystemPath = appFolderPath;
LogDirectoryPath = logDirectoryPath;
ConfigurationDirectoryPath = configurationDirectoryPath;
CachePath = cacheDirectoryPath;
WebPath = webDirectoryPath;
DataPath = Path.Combine(ProgramDataPath, "data");
}
/// <summary>
/// Gets the path to the program data folder
/// </summary>
/// <value>The program data path.</value>
public string ProgramDataPath { get; private set; }
/// <summary>
/// Gets the path to the web UI resources folder
/// </summary>
/// <value>The web UI resources path.</value>
public string WebPath { get; set; }
/// <summary>
/// Gets the path to the system folder
/// </summary>
public string ProgramSystemPath { get; private set; }
public string ProgramSystemPath { get; } = AppContext.BaseDirectory;
/// <summary>
/// The _data directory
/// </summary>
private string _dataDirectory;
/// <summary>
/// Gets the folder path to the data directory
/// </summary>
/// <value>The data directory.</value>
private string _dataPath;
public string DataPath
{
get
{
if (_dataDirectory == null)
{
_dataDirectory = Path.Combine(ProgramDataPath, "data");
Directory.CreateDirectory(_dataDirectory);
}
return _dataDirectory;
}
get => _dataPath;
private set => _dataPath = Directory.CreateDirectory(value).FullName;
}
private const string _virtualDataPath = "%AppDataPath%";
public string VirtualDataPath => _virtualDataPath;
/// <summary>
/// Gets the magic strings used for virtual path manipulation.
/// </summary>
public string VirtualDataPath { get; } = "%AppDataPath%";
/// <summary>
/// Gets the image cache path.
@@ -77,61 +80,17 @@ namespace Emby.Server.Implementations.AppBase
/// <value>The plugin configurations path.</value>
public string PluginConfigurationsPath => Path.Combine(PluginsPath, "configurations");
/// <summary>
/// Gets the path to where temporary update files will be stored
/// </summary>
/// <value>The plugin configurations path.</value>
public string TempUpdatePath => Path.Combine(ProgramDataPath, "updates");
/// <summary>
/// The _log directory
/// </summary>
private string _logDirectoryPath;
/// <summary>
/// Gets the path to the log directory
/// </summary>
/// <value>The log directory path.</value>
public string LogDirectoryPath
{
get
{
if (string.IsNullOrEmpty(_logDirectoryPath))
{
_logDirectoryPath = Path.Combine(ProgramDataPath, "logs");
Directory.CreateDirectory(_logDirectoryPath);
}
return _logDirectoryPath;
}
set => _logDirectoryPath = value;
}
/// <summary>
/// The _config directory
/// </summary>
private string _configurationDirectoryPath;
public string LogDirectoryPath { get; private set; }
/// <summary>
/// Gets the path to the application configuration root directory
/// </summary>
/// <value>The configuration directory path.</value>
public string ConfigurationDirectoryPath
{
get
{
if (string.IsNullOrEmpty(_configurationDirectoryPath))
{
_configurationDirectoryPath = Path.Combine(ProgramDataPath, "config");
Directory.CreateDirectory(_configurationDirectoryPath);
}
return _configurationDirectoryPath;
}
set => _configurationDirectoryPath = value;
}
public string ConfigurationDirectoryPath { get; private set; }
/// <summary>
/// Gets the path to the system configuration file
@@ -139,29 +98,11 @@ namespace Emby.Server.Implementations.AppBase
/// <value>The system configuration file path.</value>
public string SystemConfigurationFilePath => Path.Combine(ConfigurationDirectoryPath, "system.xml");
/// <summary>
/// The _cache directory
/// </summary>
private string _cachePath;
/// <summary>
/// Gets the folder path to the cache directory
/// </summary>
/// <value>The cache directory.</value>
public string CachePath
{
get
{
if (string.IsNullOrEmpty(_cachePath))
{
_cachePath = Path.Combine(ProgramDataPath, "cache");
Directory.CreateDirectory(_cachePath);
}
return _cachePath;
}
set => _cachePath = value;
}
public string CachePath { get; set; }
/// <summary>
/// Gets the folder path to the temp directory within the cache folder

View File

@@ -79,7 +79,7 @@ namespace Emby.Server.Implementations.AppBase
get
{
// Lazy load
LazyInitializer.EnsureInitialized(ref _configuration, ref _configurationLoaded, ref _configurationSyncLock, () => (BaseApplicationConfiguration)ConfigurationHelper.GetXmlConfiguration(ConfigurationType, CommonApplicationPaths.SystemConfigurationFilePath, XmlSerializer, FileSystem));
LazyInitializer.EnsureInitialized(ref _configuration, ref _configurationLoaded, ref _configurationSyncLock, () => (BaseApplicationConfiguration)ConfigurationHelper.GetXmlConfiguration(ConfigurationType, CommonApplicationPaths.SystemConfigurationFilePath, XmlSerializer));
return _configuration;
}
protected set

View File

@@ -1,7 +1,6 @@
using System;
using System.IO;
using System.Linq;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Serialization;
namespace Emby.Server.Implementations.AppBase
@@ -18,9 +17,8 @@ namespace Emby.Server.Implementations.AppBase
/// <param name="type">The type.</param>
/// <param name="path">The path.</param>
/// <param name="xmlSerializer">The XML serializer.</param>
/// <param name="fileSystem">The file system</param>
/// <returns>System.Object.</returns>
public static object GetXmlConfiguration(Type type, string path, IXmlSerializer xmlSerializer, IFileSystem fileSystem)
public static object GetXmlConfiguration(Type type, string path, IXmlSerializer xmlSerializer)
{
object configuration;

File diff suppressed because it is too large Load Diff

View File

@@ -14,11 +14,9 @@ namespace Emby.Server.Implementations.Archiving
/// </summary>
public class ZipClient : IZipClient
{
private readonly IFileSystem _fileSystem;
public ZipClient(IFileSystem fileSystem)
public ZipClient()
{
_fileSystem = fileSystem;
}
/// <summary>

View File

@@ -243,8 +243,7 @@ namespace Emby.Server.Implementations.Channels
{
foreach (var item in returnItems)
{
var task = RefreshLatestChannelItems(GetChannelProvider(item), CancellationToken.None);
Task.WaitAll(task);
RefreshLatestChannelItems(GetChannelProvider(item), CancellationToken.None).GetAwaiter().GetResult();
}
}
@@ -303,9 +302,7 @@ namespace Emby.Server.Implementations.Channels
}
numComplete++;
double percent = numComplete;
percent /= allChannelsList.Count;
double percent = (double)numComplete / allChannelsList.Count;
progress.Report(100 * percent);
}
@@ -658,9 +655,7 @@ namespace Emby.Server.Implementations.Channels
foreach (var item in result.Items)
{
var folder = item as Folder;
if (folder != null)
if (item is Folder folder)
{
await GetChannelItemsInternal(new InternalItemsQuery
{

View File

@@ -35,64 +35,52 @@ namespace Emby.Server.Implementations.Channels
public static string GetUserDistinctValue(User user)
{
var channels = user.Policy.EnabledChannels
.OrderBy(i => i)
.ToList();
.OrderBy(i => i);
return string.Join("|", channels.ToArray());
return string.Join("|", channels);
}
private void CleanDatabase(CancellationToken cancellationToken)
{
var installedChannelIds = ((ChannelManager)_channelManager).GetInstalledChannelIds();
var databaseIds = _libraryManager.GetItemIds(new InternalItemsQuery
var uninstalledChannels = _libraryManager.GetItemList(new InternalItemsQuery
{
IncludeItemTypes = new[] { typeof(Channel).Name }
IncludeItemTypes = new[] { typeof(Channel).Name },
ExcludeItemIds = installedChannelIds.ToArray()
});
var invalidIds = databaseIds
.Except(installedChannelIds)
.ToList();
foreach (var id in invalidIds)
foreach (var channel in uninstalledChannels)
{
cancellationToken.ThrowIfCancellationRequested();
CleanChannel(id, cancellationToken);
CleanChannel((Channel)channel, cancellationToken);
}
}
private void CleanChannel(Guid id, CancellationToken cancellationToken)
private void CleanChannel(Channel channel, CancellationToken cancellationToken)
{
_logger.LogInformation("Cleaning channel {0} from database", id);
_logger.LogInformation("Cleaning channel {0} from database", channel.Id);
// Delete all channel items
var allIds = _libraryManager.GetItemIds(new InternalItemsQuery
var items = _libraryManager.GetItemList(new InternalItemsQuery
{
ChannelIds = new[] { id }
ChannelIds = new[] { channel.Id }
});
foreach (var deleteId in allIds)
foreach (var item in items)
{
cancellationToken.ThrowIfCancellationRequested();
DeleteItem(deleteId);
_libraryManager.DeleteItem(item, new DeleteOptions
{
DeleteFileLocation = false
}, false);
}
// Finally, delete the channel itself
DeleteItem(id);
}
private void DeleteItem(Guid id)
{
var item = _libraryManager.GetItemById(id);
if (item == null)
{
return;
}
_libraryManager.DeleteItem(item, new DeleteOptions
_libraryManager.DeleteItem(channel, new DeleteOptions
{
DeleteFileLocation = false

View File

@@ -10,7 +10,7 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Channels
{
class RefreshChannelsScheduledTask : IScheduledTask, IConfigurableScheduledTask
public class RefreshChannelsScheduledTask : IScheduledTask, IConfigurableScheduledTask
{
private readonly IChannelManager _channelManager;
private readonly IUserManager _userManager;

View File

@@ -10,14 +10,18 @@ using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Extensions;
using MediaBrowser.Model.IO;
namespace Emby.Server.Implementations.Collections
{
public class CollectionImageProvider : BaseDynamicImageProvider<BoxSet>
{
public CollectionImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor) : base(fileSystem, providerManager, applicationPaths, imageProcessor)
public CollectionImageProvider(
IFileSystem fileSystem,
IProviderManager providerManager,
IApplicationPaths applicationPaths,
IImageProcessor imageProcessor)
: base(fileSystem, providerManager, applicationPaths, imageProcessor)
{
}
@@ -32,7 +36,7 @@ namespace Emby.Server.Implementations.Collections
return base.Supports(item);
}
protected override List<BaseItem> GetItemsWithImages(BaseItem item)
protected override IReadOnlyList<BaseItem> GetItemsWithImages(BaseItem item)
{
var playlist = (BoxSet)item;
@@ -76,7 +80,7 @@ namespace Emby.Server.Implementations.Collections
.ToList();
}
protected override string CreateImage(BaseItem item, List<BaseItem> itemsWithImages, string outputPathWithoutExtension, ImageType imageType, int imageIndex)
protected override string CreateImage(BaseItem item, IReadOnlyCollection<BaseItem> itemsWithImages, string outputPathWithoutExtension, ImageType imageType, int imageIndex)
{
return CreateSingleImage(itemsWithImages, outputPathWithoutExtension, ImageType.Primary);
}

View File

@@ -342,14 +342,12 @@ namespace Emby.Server.Implementations.Collections
{
private readonly CollectionManager _collectionManager;
private readonly IServerConfigurationManager _config;
private readonly IFileSystem _fileSystem;
private ILogger _logger;
public CollectionManagerEntryPoint(ICollectionManager collectionManager, IServerConfigurationManager config, IFileSystem fileSystem, ILogger logger)
public CollectionManagerEntryPoint(ICollectionManager collectionManager, IServerConfigurationManager config, ILogger logger)
{
_collectionManager = (CollectionManager)collectionManager;
_config = config;
_fileSystem = fileSystem;
_logger = logger;
}

View File

@@ -74,23 +74,14 @@ namespace Emby.Server.Implementations.Configuration
/// </summary>
private void UpdateMetadataPath()
{
string metadataPath;
if (string.IsNullOrWhiteSpace(Configuration.MetadataPath))
{
metadataPath = GetInternalMetadataPath();
((ServerApplicationPaths)ApplicationPaths).InternalMetadataPath = Path.Combine(ApplicationPaths.ProgramDataPath, "metadata");
}
else
{
metadataPath = Path.Combine(Configuration.MetadataPath, "metadata");
((ServerApplicationPaths)ApplicationPaths).InternalMetadataPath = Configuration.MetadataPath;
}
((ServerApplicationPaths)ApplicationPaths).InternalMetadataPath = metadataPath;
}
private string GetInternalMetadataPath()
{
return Path.Combine(ApplicationPaths.ProgramDataPath, "metadata");
}
/// <summary>

View File

@@ -0,0 +1,13 @@
using System.Collections.Generic;
namespace Emby.Server.Implementations
{
public static class ConfigurationOptions
{
public static readonly Dictionary<string, string> Configuration = new Dictionary<string, string>
{
{"HttpListenerHost:DefaultRedirectPath", "web/index.html"},
{"MusicBrainz:BaseUrl", "https://www.musicbrainz.org"}
};
}
}

View File

@@ -1,4 +1,6 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Security.Cryptography;
using System.Text;
@@ -8,6 +10,39 @@ namespace Emby.Server.Implementations.Cryptography
{
public class CryptographyProvider : ICryptoProvider
{
private static readonly HashSet<string> _supportedHashMethods = new HashSet<string>()
{
"MD5",
"System.Security.Cryptography.MD5",
"SHA",
"SHA1",
"System.Security.Cryptography.SHA1",
"SHA256",
"SHA-256",
"System.Security.Cryptography.SHA256",
"SHA384",
"SHA-384",
"System.Security.Cryptography.SHA384",
"SHA512",
"SHA-512",
"System.Security.Cryptography.SHA512"
};
public string DefaultHashMethod => "PBKDF2";
private RandomNumberGenerator _randomNumberGenerator;
private const int _defaultIterations = 1000;
public CryptographyProvider()
{
//FIXME: When we get DotNet Standard 2.1 we need to revisit how we do the crypto
//Currently supported hash methods from https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.cryptoconfig?view=netcore-2.1
//there might be a better way to autogenerate this list as dotnet updates, but I couldn't find one
//Please note the default method of PBKDF2 is not included, it cannot be used to generate hashes cleanly as it is actually a pbkdf with sha1
_randomNumberGenerator = RandomNumberGenerator.Create();
}
public Guid GetMD5(string str)
{
return new Guid(ComputeMD5(Encoding.Unicode.GetBytes(str)));
@@ -36,5 +71,98 @@ namespace Emby.Server.Implementations.Cryptography
return provider.ComputeHash(bytes);
}
}
public IEnumerable<string> GetSupportedHashMethods()
{
return _supportedHashMethods;
}
private byte[] PBKDF2(string method, byte[] bytes, byte[] salt, int iterations)
{
//downgrading for now as we need this library to be dotnetstandard compliant
//with this downgrade we'll add a check to make sure we're on the downgrade method at the moment
if (method == DefaultHashMethod)
{
using (var r = new Rfc2898DeriveBytes(bytes, salt, iterations))
{
return r.GetBytes(32);
}
}
throw new CryptographicException($"Cannot currently use PBKDF2 with requested hash method: {method}");
}
public byte[] ComputeHash(string hashMethod, byte[] bytes)
{
return ComputeHash(hashMethod, bytes, Array.Empty<byte>());
}
public byte[] ComputeHashWithDefaultMethod(byte[] bytes)
{
return ComputeHash(DefaultHashMethod, bytes);
}
public byte[] ComputeHash(string hashMethod, byte[] bytes, byte[] salt)
{
if (hashMethod == DefaultHashMethod)
{
return PBKDF2(hashMethod, bytes, salt, _defaultIterations);
}
else if (_supportedHashMethods.Contains(hashMethod))
{
using (var h = HashAlgorithm.Create(hashMethod))
{
if (salt.Length == 0)
{
return h.ComputeHash(bytes);
}
else
{
byte[] salted = new byte[bytes.Length + salt.Length];
Array.Copy(bytes, salted, bytes.Length);
Array.Copy(salt, 0, salted, bytes.Length, salt.Length);
return h.ComputeHash(salted);
}
}
}
else
{
throw new CryptographicException($"Requested hash method is not supported: {hashMethod}");
}
}
public byte[] ComputeHashWithDefaultMethod(byte[] bytes, byte[] salt)
{
return PBKDF2(DefaultHashMethod, bytes, salt, _defaultIterations);
}
public byte[] ComputeHash(PasswordHash hash)
{
int iterations = _defaultIterations;
if (!hash.Parameters.ContainsKey("iterations"))
{
hash.Parameters.Add("iterations", _defaultIterations.ToString(CultureInfo.InvariantCulture));
}
else
{
try
{
iterations = int.Parse(hash.Parameters["iterations"]);
}
catch (Exception e)
{
throw new InvalidDataException($"Couldn't successfully parse iterations value from string: {hash.Parameters["iterations"]}", e);
}
}
return PBKDF2(hash.Id, hash.HashBytes, hash.SaltBytes, iterations);
}
public byte[] GenerateSalt()
{
byte[] salt = new byte[64];
_randomNumberGenerator.GetBytes(salt);
return salt;
}
}
}

View File

@@ -224,7 +224,7 @@ namespace Emby.Server.Implementations.Data
});
}
db.ExecuteAll(string.Join(";", queries.ToArray()));
db.ExecuteAll(string.Join(";", queries));
Logger.LogInformation("PRAGMA synchronous=" + db.Query("PRAGMA synchronous").SelectScalarString().First());
}
@@ -232,23 +232,6 @@ namespace Emby.Server.Implementations.Data
protected virtual int? CacheSize => null;
internal static void CheckOk(int rc)
{
string msg = "";
if (raw.SQLITE_OK != rc)
{
throw CreateException((ErrorCode)rc, msg);
}
}
internal static Exception CreateException(ErrorCode rc, string msg)
{
var exp = new Exception(msg);
return exp;
}
private bool _disposed;
protected void CheckDisposed()
{
@@ -375,13 +358,6 @@ namespace Emby.Server.Implementations.Data
}
}
public class DummyToken : IDisposable
{
public void Dispose()
{
}
}
public static IDisposable Read(this ReaderWriterLockSlim obj)
{
//if (BaseSqliteRepository.ThreadSafeMode > 0)
@@ -390,6 +366,7 @@ namespace Emby.Server.Implementations.Data
//}
return new WriteLockToken(obj);
}
public static IDisposable Write(this ReaderWriterLockSlim obj)
{
//if (BaseSqliteRepository.ThreadSafeMode > 0)

View File

@@ -1,11 +1,8 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.IO;
using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Data
@@ -13,18 +10,12 @@ namespace Emby.Server.Implementations.Data
public class CleanDatabaseScheduledTask : ILibraryPostScanTask
{
private readonly ILibraryManager _libraryManager;
private readonly IItemRepository _itemRepo;
private readonly ILogger _logger;
private readonly IFileSystem _fileSystem;
private readonly IApplicationPaths _appPaths;
public CleanDatabaseScheduledTask(ILibraryManager libraryManager, IItemRepository itemRepo, ILogger logger, IFileSystem fileSystem, IApplicationPaths appPaths)
public CleanDatabaseScheduledTask(ILibraryManager libraryManager, ILogger logger)
{
_libraryManager = libraryManager;
_itemRepo = itemRepo;
_logger = logger;
_fileSystem = fileSystem;
_appPaths = appPaths;
}
public Task Run(IProgress<double> progress, CancellationToken cancellationToken)

View File

@@ -90,9 +90,10 @@ namespace Emby.Server.Implementations.Data
{
throw new ArgumentNullException(nameof(displayPreferences));
}
if (string.IsNullOrEmpty(displayPreferences.Id))
{
throw new ArgumentNullException(nameof(displayPreferences.Id));
throw new ArgumentException("Display preferences has an invalid Id", nameof(displayPreferences));
}
cancellationToken.ThrowIfCancellationRequested();

View File

@@ -22,9 +22,9 @@ using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Playlists;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.LiveTv;
using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Reflection;
using MediaBrowser.Model.Serialization;
using Microsoft.Extensions.Logging;
using SQLitePCL.pretty;
@@ -56,6 +56,8 @@ namespace Emby.Server.Implementations.Data
private readonly IServerConfigurationManager _config;
private IServerApplicationHost _appHost;
private readonly ILocalizationManager _localization;
public IImageProcessor ImageProcessor { get; set; }
/// <summary>
@@ -66,7 +68,7 @@ namespace Emby.Server.Implementations.Data
IServerApplicationHost appHost,
IJsonSerializer jsonSerializer,
ILoggerFactory loggerFactory,
IAssemblyInfo assemblyInfo)
ILocalizationManager localization)
: base(loggerFactory.CreateLogger(nameof(SqliteItemRepository)))
{
if (config == null)
@@ -82,7 +84,8 @@ namespace Emby.Server.Implementations.Data
_appHost = appHost;
_config = config;
_jsonSerializer = jsonSerializer;
_typeMapper = new TypeMapper(assemblyInfo);
_typeMapper = new TypeMapper();
_localization = localization;
DbFilePath = Path.Combine(_config.ApplicationPaths.DataPath, "library.db");
}
@@ -536,7 +539,7 @@ namespace Emby.Server.Implementations.Data
throw new ArgumentNullException(nameof(item));
}
SaveItems(new List<BaseItem> { item }, cancellationToken);
SaveItems(new [] { item }, cancellationToken);
}
public void SaveImages(BaseItem item)
@@ -576,7 +579,7 @@ namespace Emby.Server.Implementations.Data
/// or
/// cancellationToken
/// </exception>
public void SaveItems(List<BaseItem> items, CancellationToken cancellationToken)
public void SaveItems(IEnumerable<BaseItem> items, CancellationToken cancellationToken)
{
if (items == null)
{
@@ -587,7 +590,7 @@ namespace Emby.Server.Implementations.Data
CheckDisposed();
var tuples = new List<Tuple<BaseItem, List<Guid>, BaseItem, string, List<string>>>();
var tuples = new List<(BaseItem, List<Guid>, BaseItem, string, List<string>)>();
foreach (var item in items)
{
var ancestorIds = item.SupportsAncestors ?
@@ -599,7 +602,7 @@ namespace Emby.Server.Implementations.Data
var userdataKey = item.GetUserDataKeys().FirstOrDefault();
var inheritedTags = item.GetInheritedTags();
tuples.Add(new Tuple<BaseItem, List<Guid>, BaseItem, string, List<string>>(item, ancestorIds, topParent, userdataKey, inheritedTags));
tuples.Add((item, ancestorIds, topParent, userdataKey, inheritedTags));
}
using (WriteLock.Write())
@@ -615,7 +618,7 @@ namespace Emby.Server.Implementations.Data
}
}
private void SaveItemsInTranscation(IDatabaseConnection db, List<Tuple<BaseItem, List<Guid>, BaseItem, string, List<string>>> tuples)
private void SaveItemsInTranscation(IDatabaseConnection db, IEnumerable<(BaseItem, List<Guid>, BaseItem, string, List<string>)> tuples)
{
var statements = PrepareAllSafe(db, new string[]
{
@@ -966,7 +969,7 @@ namespace Emby.Server.Implementations.Data
if (item.ExtraIds.Length > 0)
{
saveItemStatement.TryBind("@ExtraIds", string.Join("|", item.ExtraIds.ToArray()));
saveItemStatement.TryBind("@ExtraIds", string.Join("|", item.ExtraIds));
}
else
{
@@ -1183,9 +1186,9 @@ namespace Emby.Server.Implementations.Data
/// <exception cref="ArgumentException"></exception>
public BaseItem RetrieveItem(Guid id)
{
if (id.Equals(Guid.Empty))
if (id == Guid.Empty)
{
throw new ArgumentNullException(nameof(id));
throw new ArgumentException(nameof(id), "Guid can't be empty");
}
CheckDisposed();
@@ -2079,14 +2082,14 @@ namespace Emby.Server.Implementations.Data
return false;
}
var sortingFields = query.OrderBy.Select(i => i.Item1);
var sortingFields = new HashSet<string>(query.OrderBy.Select(i => i.Item1), StringComparer.OrdinalIgnoreCase);
return sortingFields.Contains(ItemSortBy.IsFavoriteOrLiked, StringComparer.OrdinalIgnoreCase)
|| sortingFields.Contains(ItemSortBy.IsPlayed, StringComparer.OrdinalIgnoreCase)
|| sortingFields.Contains(ItemSortBy.IsUnplayed, StringComparer.OrdinalIgnoreCase)
|| sortingFields.Contains(ItemSortBy.PlayCount, StringComparer.OrdinalIgnoreCase)
|| sortingFields.Contains(ItemSortBy.DatePlayed, StringComparer.OrdinalIgnoreCase)
|| sortingFields.Contains(ItemSortBy.SeriesDatePlayed, StringComparer.OrdinalIgnoreCase)
return sortingFields.Contains(ItemSortBy.IsFavoriteOrLiked)
|| sortingFields.Contains(ItemSortBy.IsPlayed)
|| sortingFields.Contains(ItemSortBy.IsUnplayed)
|| sortingFields.Contains(ItemSortBy.PlayCount)
|| sortingFields.Contains(ItemSortBy.DatePlayed)
|| sortingFields.Contains(ItemSortBy.SeriesDatePlayed)
|| query.IsFavoriteOrLiked.HasValue
|| query.IsFavorite.HasValue
|| query.IsResumable.HasValue
@@ -2094,9 +2097,9 @@ namespace Emby.Server.Implementations.Data
|| query.IsLiked.HasValue;
}
private readonly List<ItemFields> allFields = Enum.GetNames(typeof(ItemFields))
private readonly ItemFields[] _allFields = Enum.GetNames(typeof(ItemFields))
.Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true))
.ToList();
.ToArray();
private string[] GetColumnNamesFromField(ItemFields field)
{
@@ -2151,18 +2154,26 @@ namespace Emby.Server.Implementations.Data
}
}
private static readonly HashSet<string> _programExcludeParentTypes = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
"Series",
"Season",
"MusicAlbum",
"MusicArtist",
"PhotoAlbum"
};
private static readonly HashSet<string> _programTypes = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
"Program",
"TvChannel",
"LiveTvProgram",
"LiveTvTvChannel"
};
private bool HasProgramAttributes(InternalItemsQuery query)
{
var excludeParentTypes = new string[]
{
"Series",
"Season",
"MusicAlbum",
"MusicArtist",
"PhotoAlbum"
};
if (excludeParentTypes.Contains(query.ParentType ?? string.Empty, StringComparer.OrdinalIgnoreCase))
if (_programExcludeParentTypes.Contains(query.ParentType))
{
return false;
}
@@ -2172,29 +2183,18 @@ namespace Emby.Server.Implementations.Data
return true;
}
var types = new string[]
{
"Program",
"TvChannel",
"LiveTvProgram",
"LiveTvTvChannel"
};
return types.Any(i => query.IncludeItemTypes.Contains(i, StringComparer.OrdinalIgnoreCase));
return query.IncludeItemTypes.Any(x => _programTypes.Contains(x));
}
private static readonly HashSet<string> _serviceTypes = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
"TvChannel",
"LiveTvTvChannel"
};
private bool HasServiceName(InternalItemsQuery query)
{
var excludeParentTypes = new string[]
{
"Series",
"Season",
"MusicAlbum",
"MusicArtist",
"PhotoAlbum"
};
if (excludeParentTypes.Contains(query.ParentType ?? string.Empty, StringComparer.OrdinalIgnoreCase))
if (_programExcludeParentTypes.Contains(query.ParentType))
{
return false;
}
@@ -2204,27 +2204,18 @@ namespace Emby.Server.Implementations.Data
return true;
}
var types = new string[]
{
"TvChannel",
"LiveTvTvChannel"
};
return types.Any(i => query.IncludeItemTypes.Contains(i, StringComparer.OrdinalIgnoreCase));
return query.IncludeItemTypes.Any(x => _serviceTypes.Contains(x));
}
private static readonly HashSet<string> _startDateTypes = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
"Program",
"LiveTvProgram"
};
private bool HasStartDate(InternalItemsQuery query)
{
var excludeParentTypes = new string[]
{
"Series",
"Season",
"MusicAlbum",
"MusicArtist",
"PhotoAlbum"
};
if (excludeParentTypes.Contains(query.ParentType ?? string.Empty, StringComparer.OrdinalIgnoreCase))
if (_programExcludeParentTypes.Contains(query.ParentType))
{
return false;
}
@@ -2234,13 +2225,7 @@ namespace Emby.Server.Implementations.Data
return true;
}
var types = new string[]
{
"Program",
"LiveTvProgram"
};
return types.Any(i => query.IncludeItemTypes.Contains(i, StringComparer.OrdinalIgnoreCase));
return query.IncludeItemTypes.Any(x => _startDateTypes.Contains(x));
}
private bool HasEpisodeAttributes(InternalItemsQuery query)
@@ -2263,16 +2248,26 @@ namespace Emby.Server.Implementations.Data
return query.IncludeItemTypes.Contains("Trailer", StringComparer.OrdinalIgnoreCase);
}
private static readonly HashSet<string> _artistExcludeParentTypes = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
"Series",
"Season",
"PhotoAlbum"
};
private static readonly HashSet<string> _artistsTypes = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
"Audio",
"MusicAlbum",
"MusicVideo",
"AudioBook",
"AudioPodcast"
};
private bool HasArtistFields(InternalItemsQuery query)
{
var excludeParentTypes = new string[]
{
"Series",
"Season",
"PhotoAlbum"
};
if (excludeParentTypes.Contains(query.ParentType ?? string.Empty, StringComparer.OrdinalIgnoreCase))
if (_artistExcludeParentTypes.Contains(query.ParentType))
{
return false;
}
@@ -2282,18 +2277,17 @@ namespace Emby.Server.Implementations.Data
return true;
}
var types = new string[]
{
"Audio",
"MusicAlbum",
"MusicVideo",
"AudioBook",
"AudioPodcast"
};
return types.Any(i => query.IncludeItemTypes.Contains(i, StringComparer.OrdinalIgnoreCase));
return query.IncludeItemTypes.Any(x => _artistsTypes.Contains(x));
}
private static readonly HashSet<string> _seriesTypes = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
"Book",
"AudioBook",
"Episode",
"Season"
};
private bool HasSeriesFields(InternalItemsQuery query)
{
if (string.Equals(query.ParentType, "PhotoAlbum", StringComparison.OrdinalIgnoreCase))
@@ -2306,26 +2300,18 @@ namespace Emby.Server.Implementations.Data
return true;
}
var types = new string[]
{
"Book",
"AudioBook",
"Episode",
"Season"
};
return types.Any(i => query.IncludeItemTypes.Contains(i, StringComparer.OrdinalIgnoreCase));
return query.IncludeItemTypes.Any(x => _seriesTypes.Contains(x));
}
private string[] GetFinalColumnsToSelect(InternalItemsQuery query, string[] startColumns)
private List<string> GetFinalColumnsToSelect(InternalItemsQuery query, IEnumerable<string> startColumns)
{
var list = startColumns.ToList();
foreach (var field in allFields)
foreach (var field in _allFields)
{
if (!HasField(query, field))
{
foreach (var fieldToRemove in GetColumnNamesFromField(field).ToList())
foreach (var fieldToRemove in GetColumnNamesFromField(field))
{
list.Remove(fieldToRemove);
}
@@ -2419,11 +2405,14 @@ namespace Emby.Server.Implementations.Data
list.Add(builder.ToString());
var excludeIds = query.ExcludeItemIds.ToList();
excludeIds.Add(item.Id);
excludeIds.AddRange(item.ExtraIds);
var oldLen = query.ExcludeItemIds.Length;
var newLen = oldLen + item.ExtraIds.Length + 1;
var excludeIds = new Guid[newLen];
query.ExcludeItemIds.CopyTo(excludeIds, 0);
excludeIds[oldLen] = item.Id;
item.ExtraIds.CopyTo(excludeIds, oldLen + 1);
query.ExcludeItemIds = excludeIds.ToArray();
query.ExcludeItemIds = excludeIds;
query.ExcludeProviderIds = item.ProviderIds;
}
@@ -2444,7 +2433,7 @@ namespace Emby.Server.Implementations.Data
list.Add(builder.ToString());
}
return list.ToArray();
return list;
}
private void BindSearchParams(InternalItemsQuery query, IStatement statement)
@@ -2723,18 +2712,17 @@ namespace Emby.Server.Implementations.Data
private void AddItem(List<BaseItem> items, BaseItem newItem)
{
var providerIds = newItem.ProviderIds.ToList();
for (var i = 0; i < items.Count; i++)
{
var item = items[i];
foreach (var providerId in providerIds)
foreach (var providerId in newItem.ProviderIds)
{
if (providerId.Key == MetadataProviders.TmdbCollection.ToString())
{
continue;
}
if (item.GetProviderId(providerId.Key) == providerId.Value)
{
if (newItem.SourceType == SourceType.Library)
@@ -2753,15 +2741,15 @@ namespace Emby.Server.Implementations.Data
{
var elapsed = (DateTime.UtcNow - startDate).TotalMilliseconds;
int slowThreshold = 1000;
int slowThreshold = 100;
#if DEBUG
slowThreshold = 250;
slowThreshold = 10;
#endif
if (elapsed >= slowThreshold)
{
Logger.LogWarning("{0} query time (slow): {1}ms. Query: {2}",
Logger.LogWarning("{0} query time (slow): {1:g}. Query: {2}",
methodName,
elapsed,
commandText);
@@ -2806,7 +2794,7 @@ namespace Emby.Server.Implementations.Data
var whereText = whereClauses.Count == 0 ?
string.Empty :
" where " + string.Join(" AND ", whereClauses.ToArray());
" where " + string.Join(" AND ", whereClauses);
commandText += whereText
+ GetGroupBy(query)
@@ -2930,25 +2918,31 @@ namespace Emby.Server.Implementations.Data
private string GetOrderByText(InternalItemsQuery query)
{
var orderBy = query.OrderBy.ToList();
var enableOrderInversion = false;
if (query.SimilarTo != null && orderBy.Count == 0)
if (string.IsNullOrEmpty(query.SearchTerm))
{
orderBy.Add(new ValueTuple<string, SortOrder>("SimilarityScore", SortOrder.Descending));
orderBy.Add(new ValueTuple<string, SortOrder>(ItemSortBy.Random, SortOrder.Ascending));
int oldLen = query.OrderBy.Length;
if (query.SimilarTo != null && oldLen == 0)
{
var arr = new (string, SortOrder)[oldLen + 2];
query.OrderBy.CopyTo(arr, 0);
arr[oldLen] = ("SimilarityScore", SortOrder.Descending);
arr[oldLen + 1] = (ItemSortBy.Random, SortOrder.Ascending);
query.OrderBy = arr;
}
}
else
{
query.OrderBy = new []
{
("SearchScore", SortOrder.Descending),
(ItemSortBy.SortName, SortOrder.Ascending)
};
}
if (!string.IsNullOrEmpty(query.SearchTerm))
{
orderBy = new List<(string, SortOrder)>();
orderBy.Add(new ValueTuple<string, SortOrder>("SearchScore", SortOrder.Descending));
orderBy.Add(new ValueTuple<string, SortOrder>(ItemSortBy.SortName, SortOrder.Ascending));
}
var orderBy = query.OrderBy;
query.OrderBy = orderBy.ToArray();
if (orderBy.Count == 0)
if (orderBy.Length == 0)
{
return string.Empty;
}
@@ -2957,6 +2951,7 @@ namespace Emby.Server.Implementations.Data
{
var columnMap = MapOrderByField(i.Item1, query);
var columnAscending = i.Item2 == SortOrder.Ascending;
const bool enableOrderInversion = false;
if (columnMap.Item2 && enableOrderInversion)
{
columnAscending = !columnAscending;
@@ -2968,7 +2963,7 @@ namespace Emby.Server.Implementations.Data
}));
}
private ValueTuple<string, bool> MapOrderByField(string name, InternalItemsQuery query)
private (string, bool) MapOrderByField(string name, InternalItemsQuery query)
{
if (string.Equals(name, ItemSortBy.AirTime, StringComparison.OrdinalIgnoreCase))
{
@@ -3218,7 +3213,7 @@ namespace Emby.Server.Implementations.Data
var whereText = whereClauses.Count == 0 ?
string.Empty :
" where " + string.Join(" AND ", whereClauses.ToArray());
" where " + string.Join(" AND ", whereClauses);
commandText += whereText
+ GetGroupBy(query)
@@ -4378,7 +4373,7 @@ namespace Emby.Server.Implementations.Data
}
else if (query.Years.Length > 1)
{
var val = string.Join(",", query.Years.ToArray());
var val = string.Join(",", query.Years);
whereClauses.Add("ProductionYear in (" + val + ")");
}
@@ -4952,7 +4947,12 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
return result;
}
return new[] { value }.Where(IsValidType);
if (IsValidType(value))
{
return new[] { value };
}
return Array.Empty<string>();
}
public void DeleteItem(Guid id, CancellationToken cancellationToken)
@@ -5215,32 +5215,32 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
}
}
public QueryResult<Tuple<BaseItem, ItemCounts>> GetAllArtists(InternalItemsQuery query)
public QueryResult<(BaseItem, ItemCounts)> GetAllArtists(InternalItemsQuery query)
{
return GetItemValues(query, new[] { 0, 1 }, typeof(MusicArtist).FullName);
}
public QueryResult<Tuple<BaseItem, ItemCounts>> GetArtists(InternalItemsQuery query)
public QueryResult<(BaseItem, ItemCounts)> GetArtists(InternalItemsQuery query)
{
return GetItemValues(query, new[] { 0 }, typeof(MusicArtist).FullName);
}
public QueryResult<Tuple<BaseItem, ItemCounts>> GetAlbumArtists(InternalItemsQuery query)
public QueryResult<(BaseItem, ItemCounts)> GetAlbumArtists(InternalItemsQuery query)
{
return GetItemValues(query, new[] { 1 }, typeof(MusicArtist).FullName);
}
public QueryResult<Tuple<BaseItem, ItemCounts>> GetStudios(InternalItemsQuery query)
public QueryResult<(BaseItem, ItemCounts)> GetStudios(InternalItemsQuery query)
{
return GetItemValues(query, new[] { 3 }, typeof(Studio).FullName);
}
public QueryResult<Tuple<BaseItem, ItemCounts>> GetGenres(InternalItemsQuery query)
public QueryResult<(BaseItem, ItemCounts)> GetGenres(InternalItemsQuery query)
{
return GetItemValues(query, new[] { 2 }, typeof(Genre).FullName);
}
public QueryResult<Tuple<BaseItem, ItemCounts>> GetMusicGenres(InternalItemsQuery query)
public QueryResult<(BaseItem, ItemCounts)> GetMusicGenres(InternalItemsQuery query)
{
return GetItemValues(query, new[] { 2 }, typeof(MusicGenre).FullName);
}
@@ -5317,7 +5317,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
}
}
private QueryResult<Tuple<BaseItem, ItemCounts>> GetItemValues(InternalItemsQuery query, int[] itemValueTypes, string returnType)
private QueryResult<(BaseItem, ItemCounts)> GetItemValues(InternalItemsQuery query, int[] itemValueTypes, string returnType)
{
if (query == null)
{
@@ -5335,7 +5335,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
var typeClause = itemValueTypes.Length == 1 ?
("Type=" + itemValueTypes[0].ToString(CultureInfo.InvariantCulture)) :
("Type in (" + string.Join(",", itemValueTypes.Select(i => i.ToString(CultureInfo.InvariantCulture)).ToArray()) + ")");
("Type in (" + string.Join(",", itemValueTypes.Select(i => i.ToString(CultureInfo.InvariantCulture))) + ")");
InternalItemsQuery typeSubQuery = null;
@@ -5363,11 +5363,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
whereClauses.Add("guid in (select ItemId from ItemValues where ItemValues.CleanValue=A.CleanName AND " + typeClause + ")");
var typeWhereText = whereClauses.Count == 0 ?
string.Empty :
" where " + string.Join(" AND ", whereClauses);
itemCountColumnQuery += typeWhereText;
itemCountColumnQuery += " where " + string.Join(" AND ", whereClauses);
itemCountColumns = new Dictionary<string, string>()
{
@@ -5400,7 +5396,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
IsSeries = query.IsSeries
};
columns = GetFinalColumnsToSelect(query, columns.ToArray()).ToList();
columns = GetFinalColumnsToSelect(query, columns);
var commandText = "select "
+ string.Join(",", columns)
@@ -5492,8 +5488,8 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
{
return connection.RunInTransaction(db =>
{
var list = new List<Tuple<BaseItem, ItemCounts>>();
var result = new QueryResult<Tuple<BaseItem, ItemCounts>>();
var list = new List<(BaseItem, ItemCounts)>();
var result = new QueryResult<(BaseItem, ItemCounts)>();
var statements = PrepareAllSafe(db, statementTexts);
@@ -5531,7 +5527,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
{
var countStartColumn = columns.Count - 1;
list.Add(new Tuple<BaseItem, ItemCounts>(item, GetItemCounts(row, countStartColumn, typesToCount)));
list.Add((item, GetItemCounts(row, countStartColumn, typesToCount)));
}
}
@@ -6196,8 +6192,13 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
item.ColorTransfer = reader[34].ToString();
}
if (item.Type == MediaStreamType.Subtitle){
item.localizedUndefined = _localization.GetLocalizedString("Undefined");
item.localizedDefault = _localization.GetLocalizedString("Default");
item.localizedForced = _localization.GetLocalizedString("Forced");
}
return item;
}
}
}

View File

@@ -119,9 +119,9 @@ namespace Emby.Server.Implementations.Data
{
list.Add(row[0].ReadGuidFromBlob());
}
catch
catch (Exception ex)
{
Logger.LogError(ex, "Error while getting user");
}
}
}

View File

@@ -55,6 +55,8 @@ namespace Emby.Server.Implementations.Data
{
TryMigrateToLocalUsersTable(connection);
}
RemoveEmptyPasswordHashes();
}
}
@@ -73,6 +75,38 @@ namespace Emby.Server.Implementations.Data
}
}
private void RemoveEmptyPasswordHashes()
{
foreach (var user in RetrieveAllUsers())
{
// If the user password is the sha1 hash of the empty string, remove it
if (!string.Equals(user.Password, "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709", StringComparison.Ordinal)
|| !string.Equals(user.Password, "$SHA1$DA39A3EE5E6B4B0D3255BFEF95601890AFD80709", StringComparison.Ordinal))
{
continue;
}
user.Password = null;
var serialized = _jsonSerializer.SerializeToBytes(user);
using (WriteLock.Write())
using (var connection = CreateConnection())
{
connection.RunInTransaction(db =>
{
using (var statement = db.PrepareStatement("update LocalUsersv2 set data=@data where Id=@InternalId"))
{
statement.TryBind("@InternalId", user.InternalId);
statement.TryBind("@data", serialized);
statement.MoveNext();
}
}, TransactionMode);
}
}
}
/// <summary>
/// Save a user in the repo
/// </summary>

View File

@@ -1,7 +1,6 @@
using System;
using System.Collections.Concurrent;
using System.Linq;
using MediaBrowser.Model.Reflection;
namespace Emby.Server.Implementations.Data
{
@@ -10,16 +9,13 @@ namespace Emby.Server.Implementations.Data
/// </summary>
public class TypeMapper
{
private readonly IAssemblyInfo _assemblyInfo;
/// <summary>
/// This holds all the types in the running assemblies so that we can de-serialize properly when we don't have strong types
/// </summary>
private readonly ConcurrentDictionary<string, Type> _typeMap = new ConcurrentDictionary<string, Type>();
public TypeMapper(IAssemblyInfo assemblyInfo)
public TypeMapper()
{
_assemblyInfo = assemblyInfo;
}
/// <summary>
@@ -45,8 +41,7 @@ namespace Emby.Server.Implementations.Data
/// <returns>Type.</returns>
private Type LookupType(string typeName)
{
return _assemblyInfo
.GetCurrentAssemblies()
return AppDomain.CurrentDomain.GetAssemblies()
.Select(a => a.GetType(typeName))
.FirstOrDefault(t => t != null);
}

View File

@@ -11,7 +11,6 @@ namespace Emby.Server.Implementations.Devices
{
private readonly IApplicationPaths _appPaths;
private readonly ILogger _logger;
private readonly IFileSystem _fileSystem;
private readonly object _syncLock = new object();
@@ -86,19 +85,10 @@ namespace Emby.Server.Implementations.Devices
private string _id;
public DeviceId(
IApplicationPaths appPaths,
ILoggerFactory loggerFactory,
IFileSystem fileSystem)
public DeviceId(IApplicationPaths appPaths, ILoggerFactory loggerFactory)
{
if (fileSystem == null)
{
throw new ArgumentNullException(nameof(fileSystem));
}
_appPaths = appPaths;
_logger = loggerFactory.CreateLogger("SystemId");
_fileSystem = fileSystem;
}
public string Value => _id ?? (_id = GetDeviceId());

View File

@@ -34,8 +34,6 @@ namespace Emby.Server.Implementations.Devices
private readonly IFileSystem _fileSystem;
private readonly ILibraryMonitor _libraryMonitor;
private readonly IServerConfigurationManager _config;
private readonly ILogger _logger;
private readonly INetworkManager _network;
private readonly ILibraryManager _libraryManager;
private readonly ILocalizationManager _localizationManager;
@@ -55,17 +53,13 @@ namespace Emby.Server.Implementations.Devices
IUserManager userManager,
IFileSystem fileSystem,
ILibraryMonitor libraryMonitor,
IServerConfigurationManager config,
ILoggerFactory loggerFactory,
INetworkManager network)
IServerConfigurationManager config)
{
_json = json;
_userManager = userManager;
_fileSystem = fileSystem;
_libraryMonitor = libraryMonitor;
_config = config;
_logger = loggerFactory.CreateLogger(nameof(DeviceManager));
_network = network;
_libraryManager = libraryManager;
_localizationManager = localizationManager;
_authRepo = authRepo;
@@ -414,14 +408,12 @@ namespace Emby.Server.Implementations.Devices
{
private readonly DeviceManager _deviceManager;
private readonly IServerConfigurationManager _config;
private readonly IFileSystem _fileSystem;
private ILogger _logger;
public DeviceManagerEntryPoint(IDeviceManager deviceManager, IServerConfigurationManager config, IFileSystem fileSystem, ILogger logger)
public DeviceManagerEntryPoint(IDeviceManager deviceManager, IServerConfigurationManager config, ILogger logger)
{
_deviceManager = (DeviceManager)deviceManager;
_config = config;
_fileSystem = fileSystem;
_logger = logger;
}

View File

@@ -9,14 +9,14 @@ namespace Emby.Server.Implementations.Diagnostics
{
public class CommonProcess : IProcess
{
public event EventHandler Exited;
private readonly ProcessOptions _options;
private readonly Process _process;
private bool _disposed = false;
private bool _hasExited;
public CommonProcess(ProcessOptions options)
{
_options = options;
StartInfo = options;
var startInfo = new ProcessStartInfo
{
@@ -27,10 +27,10 @@ namespace Emby.Server.Implementations.Diagnostics
CreateNoWindow = options.CreateNoWindow,
RedirectStandardError = options.RedirectStandardError,
RedirectStandardInput = options.RedirectStandardInput,
RedirectStandardOutput = options.RedirectStandardOutput
RedirectStandardOutput = options.RedirectStandardOutput,
ErrorDialog = options.ErrorDialog
};
startInfo.ErrorDialog = options.ErrorDialog;
if (options.IsHidden)
{
@@ -45,11 +45,22 @@ namespace Emby.Server.Implementations.Diagnostics
if (options.EnableRaisingEvents)
{
_process.EnableRaisingEvents = true;
_process.Exited += _process_Exited;
_process.Exited += OnProcessExited;
}
}
private bool _hasExited;
public event EventHandler Exited;
public ProcessOptions StartInfo { get; }
public StreamWriter StandardInput => _process.StandardInput;
public StreamReader StandardError => _process.StandardError;
public StreamReader StandardOutput => _process.StandardOutput;
public int ExitCode => _process.ExitCode;
private bool HasExited
{
get
@@ -72,25 +83,6 @@ namespace Emby.Server.Implementations.Diagnostics
}
}
private void _process_Exited(object sender, EventArgs e)
{
_hasExited = true;
if (Exited != null)
{
Exited(this, e);
}
}
public ProcessOptions StartInfo => _options;
public StreamWriter StandardInput => _process.StandardInput;
public StreamReader StandardError => _process.StandardError;
public StreamReader StandardOutput => _process.StandardOutput;
public int ExitCode => _process.ExitCode;
public void Start()
{
_process.Start();
@@ -108,7 +100,7 @@ namespace Emby.Server.Implementations.Diagnostics
public Task<bool> WaitForExitAsync(int timeMs)
{
//Note: For this function to work correctly, the option EnableRisingEvents needs to be set to true.
// Note: For this function to work correctly, the option EnableRisingEvents needs to be set to true.
if (HasExited)
{
@@ -130,7 +122,29 @@ namespace Emby.Server.Implementations.Diagnostics
public void Dispose()
{
_process.Dispose();
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (_disposed)
{
return;
}
if (disposing)
{
_process?.Dispose();
}
_disposed = true;
}
private void OnProcessExited(object sender, EventArgs e)
{
_hasExited = true;
Exited?.Invoke(this, e);
}
}
}

View File

@@ -5,8 +5,6 @@ using System.Linq;
using System.Threading.Tasks;
using MediaBrowser.Common;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
@@ -21,8 +19,6 @@ using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Extensions;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Querying;
using Microsoft.Extensions.Logging;
@@ -36,13 +32,9 @@ namespace Emby.Server.Implementations.Dto
private readonly IItemRepository _itemRepo;
private readonly IImageProcessor _imageProcessor;
private readonly IServerConfigurationManager _config;
private readonly IFileSystem _fileSystem;
private readonly IProviderManager _providerManager;
private readonly Func<IChannelManager> _channelManagerFactory;
private readonly IApplicationHost _appHost;
private readonly Func<IDeviceManager> _deviceManager;
private readonly Func<IMediaSourceManager> _mediaSourceManager;
private readonly Func<ILiveTvManager> _livetvManager;
@@ -52,12 +44,8 @@ namespace Emby.Server.Implementations.Dto
IUserDataManager userDataRepository,
IItemRepository itemRepo,
IImageProcessor imageProcessor,
IServerConfigurationManager config,
IFileSystem fileSystem,
IProviderManager providerManager,
Func<IChannelManager> channelManagerFactory,
IApplicationHost appHost,
Func<IDeviceManager> deviceManager,
Func<IMediaSourceManager> mediaSourceManager,
Func<ILiveTvManager> livetvManager)
{
@@ -66,12 +54,8 @@ namespace Emby.Server.Implementations.Dto
_userDataRepository = userDataRepository;
_itemRepo = itemRepo;
_imageProcessor = imageProcessor;
_config = config;
_fileSystem = fileSystem;
_providerManager = providerManager;
_channelManagerFactory = channelManagerFactory;
_appHost = appHost;
_deviceManager = deviceManager;
_mediaSourceManager = mediaSourceManager;
_livetvManager = livetvManager;
}
@@ -95,15 +79,8 @@ namespace Emby.Server.Implementations.Dto
return GetBaseItemDto(item, options, user, owner);
}
public BaseItemDto[] GetBaseItemDtos(List<BaseItem> items, DtoOptions options, User user = null, BaseItem owner = null)
{
return GetBaseItemDtos(items, items.Count, options, user, owner);
}
public BaseItemDto[] GetBaseItemDtos(BaseItem[] items, DtoOptions options, User user = null, BaseItem owner = null)
{
return GetBaseItemDtos(items, items.Length, options, user, owner);
}
public BaseItemDto[] GetBaseItemDtos(IReadOnlyList<BaseItem> items, DtoOptions options, User user = null, BaseItem owner = null)
=> GetBaseItemDtos(items, items.Count, options, user, owner);
public BaseItemDto[] GetBaseItemDtos(IEnumerable<BaseItem> items, int itemCount, DtoOptions options, User user = null, BaseItem owner = null)
{

View File

@@ -9,12 +9,10 @@
<ProjectReference Include="..\MediaBrowser.Providers\MediaBrowser.Providers.csproj" />
<ProjectReference Include="..\MediaBrowser.WebDashboard\MediaBrowser.WebDashboard.csproj" />
<ProjectReference Include="..\MediaBrowser.XbmcMetadata\MediaBrowser.XbmcMetadata.csproj" />
<ProjectReference Include="..\SocketHttpListener\SocketHttpListener.csproj" />
<ProjectReference Include="..\Emby.Dlna\Emby.Dlna.csproj" />
<ProjectReference Include="..\Mono.Nat\Mono.Nat.csproj" />
<ProjectReference Include="..\MediaBrowser.Api\MediaBrowser.Api.csproj" />
<ProjectReference Include="..\MediaBrowser.LocalMetadata\MediaBrowser.LocalMetadata.csproj" />
<ProjectReference Include="..\OpenSubtitlesHandler\OpenSubtitlesHandler.csproj" />
<ProjectReference Include="..\Emby.Photos\Emby.Photos.csproj" />
<ProjectReference Include="..\Emby.Drawing\Emby.Drawing.csproj" />
<ProjectReference Include="..\Emby.XmlTv\Emby.XmlTv\Emby.XmlTv.csproj" />
@@ -22,9 +20,19 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Hosting.Server.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
<PackageReference Include="Microsoft.AspNetCore.Http.Extensions" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.ResponseCompression" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.WebSockets" Version="2.2.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="2.2.0" />
<PackageReference Include="ServiceStack.Text.Core" Version="5.4.0" />
<PackageReference Include="sharpcompress" Version="0.22.0" />
<PackageReference Include="SimpleInjector" Version="4.4.2" />
<PackageReference Include="SQLitePCL.pretty.netstandard" Version="1.0.0" />
<PackageReference Include="UTF.Unknown" Version="1.0.0-beta1" />
</ItemGroup>
@@ -38,6 +46,21 @@
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<!-- Code analysers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.6.3" />
<PackageReference Include="StyleCop.Analyzers" Version="1.0.2" />
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" />
</ItemGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="Localization\iso6392.txt" />
<EmbeddedResource Include="Localization\countries.json" />

View File

@@ -388,7 +388,7 @@ namespace Emby.Server.Implementations.EntryPoints
FoldersRemovedFrom = foldersRemovedFrom.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToArray(),
CollectionFolders = GetTopParentIds(newAndRemoved, user, allUserRootChildren).ToArray()
CollectionFolders = GetTopParentIds(newAndRemoved, allUserRootChildren).ToArray()
};
}
@@ -407,7 +407,7 @@ namespace Emby.Server.Implementations.EntryPoints
return item.SourceType == SourceType.Library;
}
private IEnumerable<string> GetTopParentIds(List<BaseItem> items, User user, List<Folder> allUserRootChildren)
private IEnumerable<string> GetTopParentIds(List<BaseItem> items, List<Folder> allUserRootChildren)
{
var list = new List<string>();

View File

@@ -14,7 +14,7 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.EntryPoints
{
class UserDataChangeNotifier : IServerEntryPoint
public class UserDataChangeNotifier : IServerEntryPoint
{
private readonly ISessionManager _sessionManager;
private readonly ILogger _logger;

View File

@@ -1,36 +0,0 @@
using System;
using System.Runtime.InteropServices;
using MediaBrowser.Model.System;
namespace Emby.Server.Implementations.EnvironmentInfo
{
public class EnvironmentInfo : IEnvironmentInfo
{
public EnvironmentInfo(MediaBrowser.Model.System.OperatingSystem operatingSystem)
{
OperatingSystem = operatingSystem;
}
public MediaBrowser.Model.System.OperatingSystem OperatingSystem { get; private set; }
public string OperatingSystemName
{
get
{
switch (OperatingSystem)
{
case MediaBrowser.Model.System.OperatingSystem.Android: return "Android";
case MediaBrowser.Model.System.OperatingSystem.BSD: return "BSD";
case MediaBrowser.Model.System.OperatingSystem.Linux: return "Linux";
case MediaBrowser.Model.System.OperatingSystem.OSX: return "macOS";
case MediaBrowser.Model.System.OperatingSystem.Windows: return "Windows";
default: throw new Exception($"Unknown OS {OperatingSystem}");
}
}
}
public string OperatingSystemVersion => Environment.OSVersion.Version.ToString() + " " + Environment.OSVersion.ServicePack.ToString();
public Architecture SystemArchitecture => RuntimeInformation.OSArchitecture;
}
}

View File

@@ -1,24 +0,0 @@
namespace Emby.Server.Implementations.FFMpeg
{
/// <summary>
/// Class FFMpegInfo
/// </summary>
public class FFMpegInfo
{
/// <summary>
/// Gets or sets the path.
/// </summary>
/// <value>The path.</value>
public string EncoderPath { get; set; }
/// <summary>
/// Gets or sets the probe path.
/// </summary>
/// <value>The probe path.</value>
public string ProbePath { get; set; }
/// <summary>
/// Gets or sets the version.
/// </summary>
/// <value>The version.</value>
public string Version { get; set; }
}
}

View File

@@ -1,17 +0,0 @@
namespace Emby.Server.Implementations.FFMpeg
{
public class FFMpegInstallInfo
{
public string Version { get; set; }
public string FFMpegFilename { get; set; }
public string FFProbeFilename { get; set; }
public string ArchiveType { get; set; }
public FFMpegInstallInfo()
{
Version = "Path";
FFMpegFilename = "ffmpeg";
FFProbeFilename = "ffprobe";
}
}
}

View File

@@ -1,141 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Net;
using MediaBrowser.Model.IO;
using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.FFMpeg
{
public class FFMpegLoader
{
private readonly IHttpClient _httpClient;
private readonly IApplicationPaths _appPaths;
private readonly ILogger _logger;
private readonly IZipClient _zipClient;
private readonly IFileSystem _fileSystem;
private readonly FFMpegInstallInfo _ffmpegInstallInfo;
public FFMpegLoader(ILogger logger, IApplicationPaths appPaths, IHttpClient httpClient, IZipClient zipClient, IFileSystem fileSystem, FFMpegInstallInfo ffmpegInstallInfo)
{
_logger = logger;
_appPaths = appPaths;
_httpClient = httpClient;
_zipClient = zipClient;
_fileSystem = fileSystem;
_ffmpegInstallInfo = ffmpegInstallInfo;
}
public FFMpegInfo GetFFMpegInfo(IStartupOptions options)
{
var customffMpegPath = options.FFmpegPath;
var customffProbePath = options.FFprobePath;
if (!string.IsNullOrWhiteSpace(customffMpegPath) && !string.IsNullOrWhiteSpace(customffProbePath))
{
return new FFMpegInfo
{
ProbePath = customffProbePath,
EncoderPath = customffMpegPath,
Version = "external"
};
}
var downloadInfo = _ffmpegInstallInfo;
var prebuiltFolder = _appPaths.ProgramSystemPath;
var prebuiltffmpeg = Path.Combine(prebuiltFolder, downloadInfo.FFMpegFilename);
var prebuiltffprobe = Path.Combine(prebuiltFolder, downloadInfo.FFProbeFilename);
if (File.Exists(prebuiltffmpeg) && File.Exists(prebuiltffprobe))
{
return new FFMpegInfo
{
ProbePath = prebuiltffprobe,
EncoderPath = prebuiltffmpeg,
Version = "external"
};
}
var version = downloadInfo.Version;
if (string.Equals(version, "0", StringComparison.OrdinalIgnoreCase))
{
return new FFMpegInfo();
}
var rootEncoderPath = Path.Combine(_appPaths.ProgramDataPath, "ffmpeg");
var versionedDirectoryPath = Path.Combine(rootEncoderPath, version);
var info = new FFMpegInfo
{
ProbePath = Path.Combine(versionedDirectoryPath, downloadInfo.FFProbeFilename),
EncoderPath = Path.Combine(versionedDirectoryPath, downloadInfo.FFMpegFilename),
Version = version
};
Directory.CreateDirectory(versionedDirectoryPath);
var excludeFromDeletions = new List<string> { versionedDirectoryPath };
if (!File.Exists(info.ProbePath) || !File.Exists(info.EncoderPath))
{
// ffmpeg not present. See if there's an older version we can start with
var existingVersion = GetExistingVersion(info, rootEncoderPath);
// No older version. Need to download and block until complete
if (existingVersion == null)
{
return new FFMpegInfo();
}
else
{
info = existingVersion;
versionedDirectoryPath = Path.GetDirectoryName(info.EncoderPath);
excludeFromDeletions.Add(versionedDirectoryPath);
}
}
// Allow just one of these to be overridden, if desired.
if (!string.IsNullOrWhiteSpace(customffMpegPath))
{
info.EncoderPath = customffMpegPath;
}
if (!string.IsNullOrWhiteSpace(customffProbePath))
{
info.ProbePath = customffProbePath;
}
return info;
}
private FFMpegInfo GetExistingVersion(FFMpegInfo info, string rootEncoderPath)
{
var encoderFilename = Path.GetFileName(info.EncoderPath);
var probeFilename = Path.GetFileName(info.ProbePath);
foreach (var directory in _fileSystem.GetDirectoryPaths(rootEncoderPath)
.ToList())
{
var allFiles = _fileSystem.GetFilePaths(directory, true).ToList();
var encoder = allFiles.FirstOrDefault(i => string.Equals(Path.GetFileName(i), encoderFilename, StringComparison.OrdinalIgnoreCase));
var probe = allFiles.FirstOrDefault(i => string.Equals(Path.GetFileName(i), probeFilename, StringComparison.OrdinalIgnoreCase));
if (!string.IsNullOrWhiteSpace(encoder) &&
!string.IsNullOrWhiteSpace(probe))
{
return new FFMpegInfo
{
EncoderPath = encoder,
ProbePath = probe,
Version = Path.GetFileName(Path.GetDirectoryName(probe))
};
}
}
return null;
}
}
}

View File

@@ -15,6 +15,7 @@ using MediaBrowser.Common.Net;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Net;
using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers;
namespace Emby.Server.Implementations.HttpClientManager
{
@@ -179,11 +180,11 @@ namespace Emby.Server.Implementations.HttpClientManager
foreach (var header in options.RequestHeaders)
{
if (string.Equals(header.Key, "Accept", StringComparison.OrdinalIgnoreCase))
if (string.Equals(header.Key, HeaderNames.Accept, StringComparison.OrdinalIgnoreCase))
{
request.Accept = header.Value;
}
else if (string.Equals(header.Key, "User-Agent", StringComparison.OrdinalIgnoreCase))
else if (string.Equals(header.Key, HeaderNames.UserAgent, StringComparison.OrdinalIgnoreCase))
{
SetUserAgent(request, header.Value);
hasUserAgent = true;
@@ -327,7 +328,6 @@ namespace Emby.Server.Implementations.HttpClientManager
}
httpWebRequest.ContentType = contentType;
httpWebRequest.ContentLength = bytes.Length;
(await httpWebRequest.GetRequestStreamAsync().ConfigureAwait(false)).Write(bytes, 0, bytes.Length);
}
catch (Exception ex)
@@ -539,21 +539,10 @@ namespace Emby.Server.Implementations.HttpClientManager
var contentLength = GetContentLength(httpResponse);
if (contentLength.HasValue)
using (var stream = httpResponse.GetResponseStream())
using (var fs = _fileSystem.GetFileStream(tempFile, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
{
using (var fs = _fileSystem.GetFileStream(tempFile, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
{
await httpResponse.GetResponseStream().CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, options.CancellationToken).ConfigureAwait(false);
}
}
else
{
// We're not able to track progress
using (var stream = httpResponse.GetResponseStream())
using (var fs = _fileSystem.GetFileStream(tempFile, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
{
await stream.CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, options.CancellationToken).ConfigureAwait(false);
}
await stream.CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, options.CancellationToken).ConfigureAwait(false);
}
options.Progress.Report(100);

View File

@@ -5,15 +5,19 @@ using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using Emby.Server.Implementations.IO;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Services;
using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers;
namespace Emby.Server.Implementations.HttpServer
{
public class FileWriter : IHttpResult
{
private readonly IStreamHelper _streamHelper;
private ILogger Logger { get; set; }
private readonly IFileSystem _fileSystem;
private string RangeHeader { get; set; }
private bool IsHeadRequest { get; set; }
@@ -42,25 +46,27 @@ namespace Emby.Server.Implementations.HttpServer
public string Path { get; set; }
public FileWriter(string path, string contentType, string rangeHeader, ILogger logger, IFileSystem fileSystem)
public FileWriter(string path, string contentType, string rangeHeader, ILogger logger, IFileSystem fileSystem, IStreamHelper streamHelper)
{
if (string.IsNullOrEmpty(contentType))
{
throw new ArgumentNullException(nameof(contentType));
}
_streamHelper = streamHelper;
_fileSystem = fileSystem;
Path = path;
Logger = logger;
RangeHeader = rangeHeader;
Headers["Content-Type"] = contentType;
Headers[HeaderNames.ContentType] = contentType;
TotalContentLength = fileSystem.GetFileInfo(path).Length;
Headers["Accept-Ranges"] = "bytes";
Headers[HeaderNames.AcceptRanges] = "bytes";
if (string.IsNullOrWhiteSpace(rangeHeader))
{
Headers["Content-Length"] = TotalContentLength.ToString(UsCulture);
StatusCode = HttpStatusCode.OK;
}
else
@@ -93,13 +99,10 @@ namespace Emby.Server.Implementations.HttpServer
RangeStart = requestedRange.Key;
RangeLength = 1 + RangeEnd - RangeStart;
// Content-Length is the length of what we're serving, not the original content
var lengthString = RangeLength.ToString(UsCulture);
Headers["Content-Length"] = lengthString;
var rangeString = string.Format("bytes {0}-{1}/{2}", RangeStart, RangeEnd, TotalContentLength);
Headers["Content-Range"] = rangeString;
var rangeString = $"bytes {RangeStart}-{RangeEnd}/{TotalContentLength}";
Headers[HeaderNames.ContentRange] = rangeString;
Logger.LogInformation("Setting range response values for {0}. RangeRequest: {1} Content-Length: {2}, Content-Range: {3}", Path, RangeHeader, lengthString, rangeString);
Logger.LogInformation("Setting range response values for {0}. RangeRequest: {1} Content-Range: {2}", Path, RangeHeader, rangeString);
}
/// <summary>
@@ -145,8 +148,7 @@ namespace Emby.Server.Implementations.HttpServer
}
}
private string[] SkipLogExtensions = new string[]
{
private static readonly string[] SkipLogExtensions = {
".js",
".html",
".css"
@@ -163,8 +165,10 @@ namespace Emby.Server.Implementations.HttpServer
}
var path = Path;
var offset = RangeStart;
var count = RangeLength;
if (string.IsNullOrWhiteSpace(RangeHeader) || (RangeStart <= 0 && RangeEnd >= TotalContentLength - 1))
if (string.IsNullOrWhiteSpace(RangeHeader) || RangeStart <= 0 && RangeEnd >= TotalContentLength - 1)
{
var extension = System.IO.Path.GetExtension(path);
@@ -173,20 +177,15 @@ namespace Emby.Server.Implementations.HttpServer
Logger.LogDebug("Transmit file {0}", path);
}
//var count = FileShare == FileShareMode.ReadWrite ? TotalContentLength : 0;
await response.TransmitFile(path, 0, 0, FileShare, cancellationToken).ConfigureAwait(false);
return;
offset = 0;
count = 0;
}
await response.TransmitFile(path, RangeStart, RangeLength, FileShare, cancellationToken).ConfigureAwait(false);
await response.TransmitFile(path, offset, count, FileShare, _fileSystem, _streamHelper, cancellationToken).ConfigureAwait(false);
}
finally
{
if (OnComplete != null)
{
OnComplete();
}
OnComplete?.Invoke();
}
}
@@ -203,8 +202,5 @@ namespace Emby.Server.Implementations.HttpServer
get => (HttpStatusCode)Status;
set => Status = (int)value;
}
public string StatusDescription { get; set; }
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
@@ -10,6 +11,7 @@ using System.Threading;
using System.Threading.Tasks;
using Emby.Server.Implementations.Net;
using Emby.Server.Implementations.Services;
using Emby.Server.Implementations.SocketSharp;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller;
@@ -19,19 +21,20 @@ using MediaBrowser.Model.Events;
using MediaBrowser.Model.Extensions;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Services;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Internal;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using ServiceStack.Text.Jsv;
namespace Emby.Server.Implementations.HttpServer
{
public class HttpListenerHost : IHttpServer, IDisposable
{
private string DefaultRedirectPath { get; set; }
private readonly ILogger _logger;
public string[] UrlPrefixes { get; private set; }
private IHttpListener _listener;
public event EventHandler<GenericEventArgs<IWebSocketConnection>> WebSocketConnected;
private readonly IServerConfigurationManager _config;
@@ -39,6 +42,7 @@ namespace Emby.Server.Implementations.HttpServer
private readonly IServerApplicationHost _appHost;
private readonly IJsonSerializer _jsonSerializer;
private readonly IXmlSerializer _xmlSerializer;
private readonly IHttpListener _socketListener;
private readonly Func<Type, Func<string, object>> _funcParseFn;
public Action<IRequest, IResponse, object>[] ResponseFilters { get; set; }
@@ -53,20 +57,23 @@ namespace Emby.Server.Implementations.HttpServer
IServerApplicationHost applicationHost,
ILoggerFactory loggerFactory,
IServerConfigurationManager config,
string defaultRedirectPath,
IConfiguration configuration,
INetworkManager networkManager,
IJsonSerializer jsonSerializer,
IXmlSerializer xmlSerializer,
Func<Type, Func<string, object>> funcParseFn)
IHttpListener socketListener)
{
_appHost = applicationHost;
_logger = loggerFactory.CreateLogger("HttpServer");
Logger = loggerFactory.CreateLogger("HttpServer");
_config = config;
DefaultRedirectPath = defaultRedirectPath;
DefaultRedirectPath = configuration["HttpListenerHost:DefaultRedirectPath"];
_networkManager = networkManager;
_jsonSerializer = jsonSerializer;
_xmlSerializer = xmlSerializer;
_funcParseFn = funcParseFn;
_socketListener = socketListener;
_socketListener.WebSocketConnected = OnWebSocketConnected;
_funcParseFn = t => s => JsvReader.GetParseFn(t)(s);
Instance = this;
ResponseFilters = Array.Empty<Action<IRequest, IResponse, object>>();
@@ -74,7 +81,7 @@ namespace Emby.Server.Implementations.HttpServer
public string GlobalResponse { get; set; }
protected ILogger Logger => _logger;
protected ILogger Logger { get; }
public object CreateInstance(Type type)
{
@@ -140,11 +147,11 @@ namespace Emby.Server.Implementations.HttpServer
return;
}
var connection = new WebSocketConnection(e.WebSocket, e.Endpoint, _jsonSerializer, _logger)
var connection = new WebSocketConnection(e.WebSocket, e.Endpoint, _jsonSerializer, Logger)
{
OnReceive = ProcessWebSocketMessageReceived,
Url = e.Url,
QueryString = e.QueryString ?? new QueryParamCollection()
QueryString = e.QueryString ?? new QueryCollection()
};
connection.Closed += Connection_Closed;
@@ -196,6 +203,7 @@ namespace Emby.Server.Implementations.HttpServer
case DirectoryNotFoundException _:
case FileNotFoundException _:
case ResourceNotFoundException _: return 404;
case MethodNotAllowedException _: return 405;
case RemoteServiceUnavailableException _: return 502;
default: return 500;
}
@@ -209,16 +217,16 @@ namespace Emby.Server.Implementations.HttpServer
if (logExceptionStackTrace)
{
_logger.LogError(ex, "Error processing request");
Logger.LogError(ex, "Error processing request");
}
else if (logExceptionMessage)
{
_logger.LogError(ex.Message);
Logger.LogError(ex.Message);
}
var httpRes = httpReq.Response;
if (httpRes.IsClosed)
if (httpRes.OriginalResponse.HasStarted)
{
return;
}
@@ -231,7 +239,7 @@ namespace Emby.Server.Implementations.HttpServer
}
catch (Exception errorEx)
{
_logger.LogError(errorEx, "Error this.ProcessRequest(context)(Exception while writing error to the response)");
Logger.LogError(errorEx, "Error this.ProcessRequest(context)(Exception while writing error to the response)");
}
}
@@ -274,39 +282,6 @@ namespace Emby.Server.Implementations.HttpServer
}
}
if (_listener != null)
{
_logger.LogInformation("Stopping HttpListener...");
var task = _listener.Stop();
Task.WaitAll(task);
_logger.LogInformation("HttpListener stopped");
}
}
private static readonly string[] _skipLogExtensions =
{
".js",
".css",
".woff",
".woff2",
".ttf",
".html"
};
private bool EnableLogging(string url, string localPath)
{
var extension = GetExtension(url);
return ((string.IsNullOrEmpty(extension) || !_skipLogExtensions.Contains(extension))
&& (string.IsNullOrEmpty(localPath) || localPath.IndexOf("system/ping", StringComparison.OrdinalIgnoreCase) == -1));
}
private static string GetExtension(string url)
{
var parts = url.Split(new[] { '?' }, 2);
return Path.GetExtension(parts[0]);
}
public static string RemoveQueryStringByKey(string url, string key)
@@ -314,7 +289,7 @@ namespace Emby.Server.Implementations.HttpServer
var uri = new Uri(url);
// this gets all the query string key value pairs as a collection
var newQueryString = MyHttpUtility.ParseQueryString(uri.Query);
var newQueryString = QueryHelpers.ParseQuery(uri.Query);
var originalCount = newQueryString.Count;
@@ -335,7 +310,7 @@ namespace Emby.Server.Implementations.HttpServer
string pagePathWithoutQueryString = url.Split(new[] { '?' }, StringSplitOptions.RemoveEmptyEntries)[0];
return newQueryString.Count > 0
? string.Format("{0}?{1}", pagePathWithoutQueryString, newQueryString)
? QueryHelpers.AddQueryString(pagePathWithoutQueryString, newQueryString.ToDictionary(kv => kv.Key, kv => kv.Value.ToString()))
: pagePathWithoutQueryString;
}
@@ -444,12 +419,11 @@ namespace Emby.Server.Implementations.HttpServer
/// <summary>
/// Overridable method that can be used to implement a custom hnandler
/// </summary>
protected async Task RequestHandler(IHttpRequest httpReq, string urlString, string host, string localPath, CancellationToken cancellationToken)
public async Task RequestHandler(IHttpRequest httpReq, string urlString, string host, string localPath, CancellationToken cancellationToken)
{
var date = DateTime.Now;
var stopWatch = new Stopwatch();
stopWatch.Start();
var httpRes = httpReq.Response;
bool enableLog = false;
bool logHeaders = false;
string urlToLog = null;
string remoteIp = httpReq.RemoteIp;
@@ -496,18 +470,8 @@ namespace Emby.Server.Implementations.HttpServer
return;
}
var operationName = httpReq.OperationName;
enableLog = EnableLogging(urlString, localPath);
urlToLog = urlString;
logHeaders = enableLog && urlToLog.IndexOf("/videos/", StringComparison.OrdinalIgnoreCase) != -1;
if (enableLog)
{
urlToLog = GetUrlToLog(urlString);
LoggerUtils.LogRequest(_logger, urlToLog, httpReq.HttpMethod, httpReq.UserAgent, logHeaders ? httpReq.Headers : null);
}
urlToLog = GetUrlToLog(urlString);
Logger.LogDebug("HTTP {HttpMethod} {Url} UserAgent: {UserAgent} \nHeaders: {@Headers}", urlToLog, httpReq.UserAgent ?? string.Empty, httpReq.HttpMethod, httpReq.Headers);
if (string.Equals(localPath, "/emby/", StringComparison.OrdinalIgnoreCase) ||
string.Equals(localPath, "/mediabrowser/", StringComparison.OrdinalIgnoreCase))
@@ -515,6 +479,7 @@ namespace Emby.Server.Implementations.HttpServer
RedirectToUrl(httpRes, DefaultRedirectPath);
return;
}
if (string.Equals(localPath, "/emby", StringComparison.OrdinalIgnoreCase) ||
string.Equals(localPath, "/mediabrowser", StringComparison.OrdinalIgnoreCase))
{
@@ -560,16 +525,19 @@ namespace Emby.Server.Implementations.HttpServer
RedirectToUrl(httpRes, DefaultRedirectPath);
return;
}
if (string.Equals(localPath, "/web/", StringComparison.OrdinalIgnoreCase))
{
RedirectToUrl(httpRes, "../" + DefaultRedirectPath);
return;
}
if (string.Equals(localPath, "/", StringComparison.OrdinalIgnoreCase))
{
RedirectToUrl(httpRes, DefaultRedirectPath);
return;
}
if (string.IsNullOrEmpty(localPath))
{
RedirectToUrl(httpRes, "/" + DefaultRedirectPath);
@@ -605,33 +573,21 @@ namespace Emby.Server.Implementations.HttpServer
if (handler != null)
{
await handler.ProcessRequestAsync(this, httpReq, httpRes, Logger, operationName, cancellationToken).ConfigureAwait(false);
await handler.ProcessRequestAsync(this, httpReq, httpRes, Logger, httpReq.OperationName, cancellationToken).ConfigureAwait(false);
}
else
{
await ErrorHandler(new FileNotFoundException(), httpReq, false, false).ConfigureAwait(false);
}
}
catch (OperationCanceledException ex)
catch (Exception ex) when (ex is SocketException || ex is IOException || ex is OperationCanceledException)
{
await ErrorHandler(ex, httpReq, false, false).ConfigureAwait(false);
}
catch (IOException ex)
{
await ErrorHandler(ex, httpReq, false, false).ConfigureAwait(false);
}
catch (SocketException ex)
{
await ErrorHandler(ex, httpReq, false, false).ConfigureAwait(false);
}
catch (SecurityException ex)
{
await ErrorHandler(ex, httpReq, false, true).ConfigureAwait(false);
}
catch (Exception ex)
{
var logException = !string.Equals(ex.GetType().Name, "SocketException", StringComparison.OrdinalIgnoreCase);
@@ -640,15 +596,15 @@ namespace Emby.Server.Implementations.HttpServer
}
finally
{
httpRes.Close();
if (enableLog)
stopWatch.Stop();
var elapsed = stopWatch.Elapsed;
if (elapsed.TotalMilliseconds > 500)
{
var statusCode = httpRes.StatusCode;
var duration = DateTime.Now - date;
LoggerUtils.LogResponse(_logger, statusCode, urlToLog, remoteIp, duration, logHeaders ? httpRes.Headers : null);
Logger.LogWarning("HTTP Response {StatusCode} to {RemoteIp}. Time (slow): {Elapsed:g}. {Url}", httpRes.StatusCode, remoteIp, elapsed, urlToLog);
}
else
{
Logger.LogDebug("HTTP Response {StatusCode} to {RemoteIp}. Time: {Elapsed:g}. {Url}", httpRes.StatusCode, remoteIp, elapsed, urlToLog);
}
}
}
@@ -661,12 +617,11 @@ namespace Emby.Server.Implementations.HttpServer
var pathParts = pathInfo.TrimStart('/').Split('/');
if (pathParts.Length == 0)
{
_logger.LogError("Path parts empty for PathInfo: {pathInfo}, Url: {RawUrl}", pathInfo, httpReq.RawUrl);
Logger.LogError("Path parts empty for PathInfo: {PathInfo}, Url: {RawUrl}", pathInfo, httpReq.RawUrl);
return null;
}
var restPath = ServiceHandler.FindMatchingRestPath(httpReq.HttpMethod, pathInfo, out string contentType);
if (restPath != null)
{
return new ServiceHandler
@@ -676,15 +631,13 @@ namespace Emby.Server.Implementations.HttpServer
};
}
_logger.LogError("Could not find handler for {PathInfo}", pathInfo);
Logger.LogError("Could not find handler for {PathInfo}", pathInfo);
return null;
}
private static Task Write(IResponse response, string text)
{
var bOutput = Encoding.UTF8.GetBytes(text);
response.SetContentLength(bOutput.Length);
return response.OutputStream.WriteAsync(bOutput, 0, bOutput.Length);
}
@@ -703,6 +656,7 @@ namespace Emby.Server.Implementations.HttpServer
}
else
{
// TODO what is this?
var httpsUrl = url
.Replace("http://", "https://", StringComparison.OrdinalIgnoreCase)
.Replace(":" + _config.Configuration.PublicPort.ToString(CultureInfo.InvariantCulture), ":" + _config.Configuration.PublicHttpsPort.ToString(CultureInfo.InvariantCulture), StringComparison.OrdinalIgnoreCase);
@@ -723,13 +677,15 @@ namespace Emby.Server.Implementations.HttpServer
/// Adds the rest handlers.
/// </summary>
/// <param name="services">The services.</param>
public void Init(IEnumerable<IService> services, IEnumerable<IWebSocketListener> listeners)
/// <param name="listeners"></param>
/// <param name="urlPrefixes"></param>
public void Init(IEnumerable<IService> services, IEnumerable<IWebSocketListener> listeners, IEnumerable<string> urlPrefixes)
{
_webSocketListeners = listeners.ToArray();
UrlPrefixes = urlPrefixes.ToArray();
ServiceController = new ServiceController();
_logger.LogInformation("Calling ServiceStack AppHost.Init");
Logger.LogInformation("Calling ServiceStack AppHost.Init");
var types = services.Select(r => r.GetType()).ToArray();
@@ -737,7 +693,7 @@ namespace Emby.Server.Implementations.HttpServer
ResponseFilters = new Action<IRequest, IResponse, object>[]
{
new ResponseFilter(_logger).FilterResponse
new ResponseFilter(Logger).FilterResponse
};
}
@@ -799,8 +755,12 @@ namespace Emby.Server.Implementations.HttpServer
return _jsonSerializer.DeserializeFromStreamAsync(stream, type);
}
//TODO Add Jellyfin Route Path Normalizer
public Task ProcessWebSocketRequest(HttpContext context)
{
return _socketListener.ProcessWebSocketRequest(context);
}
//TODO Add Jellyfin Route Path Normalizer
private static string NormalizeEmbyRoutePath(string path)
{
if (path.StartsWith("/", StringComparison.OrdinalIgnoreCase))
@@ -833,6 +793,7 @@ namespace Emby.Server.Implementations.HttpServer
private bool _disposed;
private readonly object _disposeLock = new object();
protected virtual void Dispose(bool disposing)
{
if (_disposed) return;
@@ -861,7 +822,7 @@ namespace Emby.Server.Implementations.HttpServer
return Task.CompletedTask;
}
_logger.LogDebug("Websocket message received: {0}", result.MessageType);
Logger.LogDebug("Websocket message received: {0}", result.MessageType);
var tasks = _webSocketListeners.Select(i => Task.Run(async () =>
{
@@ -871,7 +832,7 @@ namespace Emby.Server.Implementations.HttpServer
}
catch (Exception ex)
{
_logger.LogError(ex, "{0} failed processing WebSocket message {1}", i.GetType().Name, result.MessageType ?? string.Empty);
Logger.LogError(ex, "{0} failed processing WebSocket message {1}", i.GetType().Name, result.MessageType ?? string.Empty);
}
}));
@@ -882,18 +843,5 @@ namespace Emby.Server.Implementations.HttpServer
{
Dispose(true);
}
public void StartServer(string[] urlPrefixes, IHttpListener httpListener)
{
UrlPrefixes = urlPrefixes;
_listener = httpListener;
_listener.WebSocketConnected = OnWebSocketConnected;
_listener.ErrorHandler = ErrorHandler;
_listener.RequestHandler = RequestHandler;
_listener.Start(UrlPrefixes);
}
}
}

View File

@@ -16,6 +16,8 @@ using MediaBrowser.Model.IO;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Services;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers;
using IRequest = MediaBrowser.Model.Services.IRequest;
using MimeTypes = MediaBrowser.Model.Net.MimeTypes;
@@ -32,17 +34,16 @@ namespace Emby.Server.Implementations.HttpServer
private readonly ILogger _logger;
private readonly IFileSystem _fileSystem;
private readonly IJsonSerializer _jsonSerializer;
private IBrotliCompressor _brotliCompressor;
private readonly IStreamHelper _streamHelper;
/// <summary>
/// Initializes a new instance of the <see cref="HttpResultFactory" /> class.
/// </summary>
public HttpResultFactory(ILoggerFactory loggerfactory, IFileSystem fileSystem, IJsonSerializer jsonSerializer, IBrotliCompressor brotliCompressor)
public HttpResultFactory(ILoggerFactory loggerfactory, IFileSystem fileSystem, IJsonSerializer jsonSerializer, IStreamHelper streamHelper)
{
_fileSystem = fileSystem;
_jsonSerializer = jsonSerializer;
_brotliCompressor = brotliCompressor;
_streamHelper = streamHelper;
_logger = loggerfactory.CreateLogger("HttpResultFactory");
}
@@ -76,7 +77,7 @@ namespace Emby.Server.Implementations.HttpServer
public object GetRedirectResult(string url)
{
var responseHeaders = new Dictionary<string, string>();
responseHeaders["Location"] = url;
responseHeaders[HeaderNames.Location] = url;
var result = new HttpResult(Array.Empty<byte>(), "text/plain", HttpStatusCode.Redirect);
@@ -90,16 +91,16 @@ namespace Emby.Server.Implementations.HttpServer
/// </summary>
private IHasHeaders GetHttpResult(IRequest requestContext, Stream content, string contentType, bool addCachePrevention, IDictionary<string, string> responseHeaders = null)
{
var result = new StreamWriter(content, contentType, _logger);
var result = new StreamWriter(content, contentType);
if (responseHeaders == null)
{
responseHeaders = new Dictionary<string, string>();
}
if (addCachePrevention && !responseHeaders.TryGetValue("Expires", out string expires))
if (addCachePrevention && !responseHeaders.TryGetValue(HeaderNames.Expires, out string expires))
{
responseHeaders["Expires"] = "-1";
responseHeaders[HeaderNames.Expires] = "0";
}
AddResponseHeaders(result, responseHeaders);
@@ -131,7 +132,7 @@ namespace Emby.Server.Implementations.HttpServer
content = Array.Empty<byte>();
}
result = new StreamWriter(content, contentType, contentLength, _logger);
result = new StreamWriter(content, contentType);
}
else
{
@@ -143,9 +144,9 @@ namespace Emby.Server.Implementations.HttpServer
responseHeaders = new Dictionary<string, string>();
}
if (addCachePrevention && !responseHeaders.TryGetValue("Expires", out string expires))
if (addCachePrevention && !responseHeaders.TryGetValue(HeaderNames.Expires, out string _))
{
responseHeaders["Expires"] = "-1";
responseHeaders[HeaderNames.Expires] = "0";
}
AddResponseHeaders(result, responseHeaders);
@@ -175,7 +176,7 @@ namespace Emby.Server.Implementations.HttpServer
bytes = Array.Empty<byte>();
}
result = new StreamWriter(bytes, contentType, contentLength, _logger);
result = new StreamWriter(bytes, contentType);
}
else
{
@@ -187,9 +188,9 @@ namespace Emby.Server.Implementations.HttpServer
responseHeaders = new Dictionary<string, string>();
}
if (addCachePrevention && !responseHeaders.TryGetValue("Expires", out string expires))
if (addCachePrevention && !responseHeaders.TryGetValue(HeaderNames.Expires, out string _))
{
responseHeaders["Expires"] = "-1";
responseHeaders[HeaderNames.Expires] = "0";
}
AddResponseHeaders(result, responseHeaders);
@@ -214,7 +215,7 @@ namespace Emby.Server.Implementations.HttpServer
responseHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
}
responseHeaders["Expires"] = "-1";
responseHeaders[HeaderNames.Expires] = "0";
return ToOptimizedResultInternal(requestContext, result, responseHeaders);
}
@@ -246,9 +247,9 @@ namespace Emby.Server.Implementations.HttpServer
private static string GetCompressionType(IRequest request)
{
var acceptEncoding = request.Headers["Accept-Encoding"];
var acceptEncoding = request.Headers[HeaderNames.AcceptEncoding].ToString();
if (acceptEncoding != null)
if (string.IsNullOrEmpty(acceptEncoding))
{
//if (_brotliCompressor != null && acceptEncoding.IndexOf("br", StringComparison.OrdinalIgnoreCase) != -1)
// return "br";
@@ -277,9 +278,10 @@ namespace Emby.Server.Implementations.HttpServer
private object ToOptimizedResultInternal<T>(IRequest request, T dto, IDictionary<string, string> responseHeaders = null)
{
var contentType = request.ResponseContentType;
// TODO: @bond use Span and .Equals
var contentType = request.ResponseContentType?.Split(';')[0].Trim().ToLowerInvariant();
switch (GetRealContentType(contentType))
switch (contentType)
{
case "application/xml":
case "text/xml":
@@ -325,21 +327,21 @@ namespace Emby.Server.Implementations.HttpServer
}
content = Compress(content, requestedCompressionType);
responseHeaders["Content-Encoding"] = requestedCompressionType;
responseHeaders[HeaderNames.ContentEncoding] = requestedCompressionType;
responseHeaders["Vary"] = "Accept-Encoding";
responseHeaders[HeaderNames.Vary] = HeaderNames.AcceptEncoding;
var contentLength = content.Length;
if (isHeadRequest)
{
var result = new StreamWriter(Array.Empty<byte>(), contentType, contentLength, _logger);
var result = new StreamWriter(Array.Empty<byte>(), contentType);
AddResponseHeaders(result, responseHeaders);
return result;
}
else
{
var result = new StreamWriter(content, contentType, contentLength, _logger);
var result = new StreamWriter(content, contentType);
AddResponseHeaders(result, responseHeaders);
return result;
}
@@ -347,23 +349,19 @@ namespace Emby.Server.Implementations.HttpServer
private byte[] Compress(byte[] bytes, string compressionType)
{
if (string.Equals(compressionType, "br", StringComparison.OrdinalIgnoreCase))
return CompressBrotli(bytes);
if (string.Equals(compressionType, "deflate", StringComparison.OrdinalIgnoreCase))
{
return Deflate(bytes);
}
if (string.Equals(compressionType, "gzip", StringComparison.OrdinalIgnoreCase))
{
return GZip(bytes);
}
throw new NotSupportedException(compressionType);
}
private byte[] CompressBrotli(byte[] bytes)
{
return _brotliCompressor.Compress(bytes);
}
private static byte[] Deflate(byte[] bytes)
{
// In .NET FX incompat-ville, you can't access compressed bytes without closing DeflateStream
@@ -390,13 +388,6 @@ namespace Emby.Server.Implementations.HttpServer
}
}
public static string GetRealContentType(string contentType)
{
return contentType == null
? null
: contentType.Split(';')[0].ToLowerInvariant().Trim();
}
private static string SerializeToXmlString(object from)
{
using (var ms = new MemoryStream())
@@ -424,12 +415,12 @@ namespace Emby.Server.Implementations.HttpServer
/// </summary>
private object GetCachedResult(IRequest requestContext, IDictionary<string, string> responseHeaders, StaticResultOptions options)
{
bool noCache = (requestContext.Headers.Get("Cache-Control") ?? string.Empty).IndexOf("no-cache", StringComparison.OrdinalIgnoreCase) != -1;
bool noCache = (requestContext.Headers[HeaderNames.CacheControl].ToString()).IndexOf("no-cache", StringComparison.OrdinalIgnoreCase) != -1;
AddCachingHeaders(responseHeaders, options.CacheDuration, noCache, options.DateLastModified);
if (!noCache)
{
DateTime.TryParse(requestContext.Headers.Get("If-Modified-Since"), out var ifModifiedSinceHeader);
DateTime.TryParse(requestContext.Headers[HeaderNames.IfModifiedSince], out var ifModifiedSinceHeader);
if (IsNotModified(ifModifiedSinceHeader, options.CacheDuration, options.DateLastModified))
{
@@ -530,7 +521,7 @@ namespace Emby.Server.Implementations.HttpServer
options.ResponseHeaders = options.ResponseHeaders ?? new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
var contentType = options.ContentType;
if (!string.IsNullOrEmpty(requestContext.Headers.Get("If-Modified-Since")))
if (!StringValues.IsNullOrEmpty(requestContext.Headers[HeaderNames.IfModifiedSince]))
{
// See if the result is already cached in the browser
var result = GetCachedResult(requestContext, options.ResponseHeaders, options);
@@ -548,11 +539,11 @@ namespace Emby.Server.Implementations.HttpServer
AddCachingHeaders(responseHeaders, options.CacheDuration, false, options.DateLastModified);
AddAgeHeader(responseHeaders, options.DateLastModified);
var rangeHeader = requestContext.Headers.Get("Range");
var rangeHeader = requestContext.Headers[HeaderNames.Range];
if (!isHeadRequest && !string.IsNullOrEmpty(options.Path))
{
var hasHeaders = new FileWriter(options.Path, contentType, rangeHeader, _logger, _fileSystem)
var hasHeaders = new FileWriter(options.Path, contentType, rangeHeader, _logger, _fileSystem, _streamHelper)
{
OnComplete = options.OnComplete,
OnError = options.OnError,
@@ -590,11 +581,6 @@ namespace Emby.Server.Implementations.HttpServer
}
else
{
if (totalContentLength.HasValue)
{
responseHeaders["Content-Length"] = totalContentLength.Value.ToString(UsCulture);
}
if (isHeadRequest)
{
using (stream)
@@ -603,7 +589,7 @@ namespace Emby.Server.Implementations.HttpServer
}
}
var hasHeaders = new StreamWriter(stream, contentType, _logger)
var hasHeaders = new StreamWriter(stream, contentType)
{
OnComplete = options.OnComplete,
OnError = options.OnError
@@ -614,11 +600,6 @@ namespace Emby.Server.Implementations.HttpServer
}
}
/// <summary>
/// The us culture
/// </summary>
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
/// <summary>
/// Adds the caching responseHeaders.
/// </summary>
@@ -627,23 +608,23 @@ namespace Emby.Server.Implementations.HttpServer
{
if (noCache)
{
responseHeaders["Cache-Control"] = "no-cache, no-store, must-revalidate";
responseHeaders["pragma"] = "no-cache, no-store, must-revalidate";
responseHeaders[HeaderNames.CacheControl] = "no-cache, no-store, must-revalidate";
responseHeaders[HeaderNames.Pragma] = "no-cache, no-store, must-revalidate";
return;
}
if (cacheDuration.HasValue)
{
responseHeaders["Cache-Control"] = "public, max-age=" + cacheDuration.Value.TotalSeconds;
responseHeaders[HeaderNames.CacheControl] = "public, max-age=" + cacheDuration.Value.TotalSeconds;
}
else
{
responseHeaders["Cache-Control"] = "public";
responseHeaders[HeaderNames.CacheControl] = "public";
}
if (lastModifiedDate.HasValue)
{
responseHeaders["Last-Modified"] = lastModifiedDate.ToString();
responseHeaders[HeaderNames.LastModified] = lastModifiedDate.ToString();
}
}
@@ -656,7 +637,7 @@ namespace Emby.Server.Implementations.HttpServer
{
if (lastDateModified.HasValue)
{
responseHeaders["Age"] = Convert.ToInt64((DateTime.UtcNow - lastDateModified.Value).TotalSeconds).ToString(CultureInfo.InvariantCulture);
responseHeaders[HeaderNames.Age] = Convert.ToInt64((DateTime.UtcNow - lastDateModified.Value).TotalSeconds).ToString(CultureInfo.InvariantCulture);
}
}
@@ -714,9 +695,4 @@ namespace Emby.Server.Implementations.HttpServer
}
}
}
public interface IBrotliCompressor
{
byte[] Compress(byte[] content);
}
}

View File

@@ -1,10 +1,9 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Emby.Server.Implementations.Net;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Services;
using Microsoft.AspNetCore.Http;
namespace Emby.Server.Implementations.HttpServer
{
@@ -28,21 +27,11 @@ namespace Emby.Server.Implementations.HttpServer
/// <value>The web socket handler.</value>
Action<WebSocketConnectEventArgs> WebSocketConnected { get; set; }
/// <summary>
/// Gets or sets the web socket connecting.
/// </summary>
/// <value>The web socket connecting.</value>
Action<WebSocketConnectingEventArgs> WebSocketConnecting { get; set; }
/// <summary>
/// Starts this instance.
/// </summary>
/// <param name="urlPrefixes">The URL prefixes.</param>
void Start(IEnumerable<string> urlPrefixes);
/// <summary>
/// Stops this instance.
/// </summary>
Task Stop();
Task ProcessWebSocketRequest(HttpContext ctx);
}
}

View File

@@ -1,55 +0,0 @@
using System;
using System.Globalization;
using MediaBrowser.Model.Services;
using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.HttpServer
{
public static class LoggerUtils
{
public static void LogRequest(ILogger logger, string url, string method, string userAgent, QueryParamCollection headers)
{
if (headers == null)
{
logger.LogInformation("{0} {1}. UserAgent: {2}", "HTTP " + method, url, userAgent ?? string.Empty);
}
else
{
var headerText = string.Empty;
var index = 0;
foreach (var i in headers)
{
if (index > 0)
{
headerText += ", ";
}
headerText += i.Name + "=" + i.Value;
index++;
}
logger.LogInformation("HTTP {0} {1}. {2}", method, url, headerText);
}
}
/// <summary>
/// Logs the response.
/// </summary>
/// <param name="logger">The logger.</param>
/// <param name="statusCode">The status code.</param>
/// <param name="url">The URL.</param>
/// <param name="endPoint">The end point.</param>
/// <param name="duration">The duration.</param>
public static void LogResponse(ILogger logger, int statusCode, string url, string endPoint, TimeSpan duration, QueryParamCollection headers)
{
var durationMs = duration.TotalMilliseconds;
var logSuffix = durationMs >= 1000 && durationMs < 60000 ? "ms (slow)" : "ms";
//var headerText = headers == null ? string.Empty : "Headers: " + string.Join(", ", headers.Where(i => i.Name.IndexOf("Access-", StringComparison.OrdinalIgnoreCase) == -1).Select(i => i.Name + "=" + i.Value).ToArray());
var headerText = string.Empty;
logger.LogInformation("HTTP Response {0} to {1}. Time: {2}{3}. {4} {5}", statusCode, endPoint, Convert.ToInt32(durationMs).ToString(CultureInfo.InvariantCulture), logSuffix, url, headerText);
}
}
}

Some files were not shown because too many files have changed in this diff Show More