Compare commits

..

282 Commits

Author SHA1 Message Date
Kayomani
bdb19e09ff Build fix 2015-09-21 20:13:12 +01:00
Kayomani
49fa67e64e Update version 2015-09-21 20:05:44 +01:00
Kayomani
770fc83ee8 ShowRSS should use raw title #173 2015-09-21 19:58:17 +01:00
Kayomani
e373bb6916 Synology config #182 2015-09-21 19:42:17 +01:00
Kayomani
f4a1f69063 Merge branch 'master' into develop 2015-09-21 19:30:24 +01:00
Kayomani
ae6504dd62 Merge pull request #180 from Kantraz/patch-2
Update NxtGn.cs
2015-09-21 19:28:15 +01:00
Kayomani
df4f1ee69f #183 T411 Category mapping 2015-09-21 19:26:15 +01:00
Kayomani
6b503711fd #181 Fix links are not cleaned before being sent to the webui. Fix failed requests not being forwarded to the caller. Add size display to web ui. 2015-09-21 18:48:53 +01:00
Kantraz
c81bb20684 Update NxtGn.cs 2015-09-18 14:21:22 +02:00
Kayomani
a30ff1a24a Update readme 2015-09-06 22:56:12 +01:00
Kayomani
be4d740830 Update readme 2015-09-06 22:55:37 +01:00
Kayomani
897a8707d7 Merge v0.6.4 2015-09-06 22:52:52 +01:00
Kayomani
eb8ebc3db8 Bump version 0.6.4 2015-09-06 22:52:02 +01:00
Kayomani
2c26fcb7a4 Remove shields from website as its slow! 2015-09-04 19:26:00 +01:00
Kayomani
7bb79a66ef Fix torrentday non local login 2015-09-04 19:16:40 +01:00
Kayomani
0d959a02f8 Torznab removes aprostrophies but filtering is done with them causing items to be incorrectly removed #158 2015-08-31 20:59:35 +01:00
Kayomani
3630ef8c41 CouchPotato - Change prefilter to allow results with no year #158 2015-08-31 20:52:15 +01:00
Kayomani
b083789197 Fix torrentless magnet links failing on the torrentpotato endpoint #157 2015-08-26 19:38:50 +01:00
Kayomani
1793d1e53d Fix nxtgn logo size 2015-08-26 17:33:43 +01:00
René Simonsen
990a2fb5c4 Since CouchPotato will not drop a release that matches by name, even if the IMDB id doesn't match, I've added to Jackett that it doesn't return releases that have an IMDB that doesn't match the one we're searching for.
This should prevent CouchPotato from grabbing wrong movies (for example downloading San Andreas Quake instead of San Andreas).

Updated nxtgn indexer to implement the changed interface in develop compared to master. Implemented missing imdb id on TorrentPotato, and changed JsonResponse to not include null values (to prevent imdb property being shown when we don't know it)

Added thetvdb and imdb id to torznab, as they are part of the torznab specification, albeit optional.

Added imdb ID for movies.

Will now only look at the first 3 pages when searching. To prevent flooding server when searching for a common term.

A category is now assigned to releases.

Changed nxtgn banner to only be copied if newer upon build.

Added support for nxtgn.org

# Conflicts:
#	src/Jackett/Jackett.csproj
2015-08-26 17:25:16 +01:00
Kayomani
2717c5da93 Implement animetorrents #150 2015-08-25 21:30:32 +01:00
Kayomani
b3430a0c55 Add metatags to the website 2015-08-24 20:46:11 +01:00
Kayomani
acf10555fd Fix display issue with the readme 2015-08-23 22:34:51 +01:00
Kayomani
42ab3ac253 Fix display issue with the readme 2015-08-23 22:33:26 +01:00
Kayomani
8d2c3b1c26 Merge pull request #148 from zone117x/develop
Merge v0.6.3
2015-08-23 22:21:06 +01:00
Kayomani
de1ccbb6fd Bump version 2015-08-23 22:11:18 +01:00
Kayomani
110fbc2ad1 Implement EuTorrents 2015-08-23 21:45:52 +01:00
Kayomani
a3312e765c Implement Avistaz 2015-08-23 21:28:21 +01:00
Kayomani
f70de19f9d Update reame 2015-08-23 20:31:12 +01:00
unknown
b7fe30f894 Implemented Strike categories 2015-08-22 18:02:41 -06:00
unknown
09246c0dfc Implemented BitHDTV categories 2015-08-22 16:06:07 -06:00
unknown
bd4b31ded5 RARBG API request throttling 2015-08-22 15:21:29 -06:00
unknown
c3ebbbdb60 Fix Strike indexer 2015-08-22 15:07:08 -06:00
unknown
dae49d8d8c Implemented indexer configuration result status to prevent double query test on some indexers 2015-08-22 14:57:13 -06:00
unknown
3375e11a8b Fix RARBG magnet link 2015-08-19 18:31:51 -06:00
Kayomani
0cffd405c7 PrivateHD category mapping fix 2015-08-19 22:58:21 +01:00
Kayomani
8164e6cffb HDTorrents category mapping 2015-08-19 22:51:16 +01:00
Kayomani
1f4e6e9544 PreToMe category mapping 2015-08-19 22:10:47 +01:00
unknown
60cfcc9f68 Fix for ThePirateBay 2015-08-18 20:21:15 -06:00
unknown
c509dd4cde Do not throw exceptions on parse error 2015-08-18 20:19:44 -06:00
unknown
34f02d4afc BeyondHD bug fix 2015-08-18 20:05:21 -06:00
unknown
278a6c49d7 Fix for BeyondHD and improved category mapping 2015-08-18 20:03:37 -06:00
unknown
5c35257058 Re-implemented RARGB 2015-08-16 17:24:06 -06:00
unknown
01b60e3200 Added published date to website downloads 2015-08-16 15:51:15 -06:00
Kayomani
c27d0a0f54 Merge pull request #138 from zone117x/develop
Merge v0.6.2
2015-08-16 18:54:55 +01:00
Kayomani
9f46b9e043 Fix issue with add indexer not working and rejig the UI a bit. 2015-08-16 18:34:45 +01:00
Kayomani
b50ce4a0ab Display called indexers instead of result indexers 2015-08-14 22:48:51 +01:00
Kayomani
ec73e0dfcd Bump version number 2015-08-14 22:33:02 +01:00
Kayomani
239ecd418a Metasearch , fix for empty queries being converted to a single space, parent categories are now autoexpanded. 2015-08-14 22:20:51 +01:00
Matthew Little
697a7f80c9 Update README.md 2015-08-13 17:35:11 -06:00
Matthew Little
e7c628f814 Update README.md 2015-08-13 17:19:38 -06:00
Matthew Little
e986d15c16 Update README.md 2015-08-13 17:17:38 -06:00
Kayomani
aee521f37a Morethan category mapping 2015-08-13 23:41:21 +01:00
Kayomani
d9c3fd6b62 Fix when viewing the cache from a mobile 2015-08-13 23:06:15 +01:00
Kayomani
dbe1fab435 Revert project change 2015-08-13 22:54:37 +01:00
Kayomani
4703ad852a Category mapping on TorrentLeech and AnimeBytes. Fix sparadic issue where downloads fail due to the url being too long. 2015-08-13 22:51:49 +01:00
Kayomani
a35fc5b4e9 Implement web site 2015-08-12 21:33:39 +01:00
unknown
a336749d20 no message 2015-08-12 11:31:59 -06:00
unknown
69f4d86479 Progress on using T4 template for newznab category definitions 2015-08-12 11:27:43 -06:00
Kayomani
9bb4fbd58c Improve filelist category mapping 2015-08-11 23:24:55 +01:00
Kayomani
bd4d50dcca Implement filelist and disable browser caching 2015-08-11 23:10:15 +01:00
Kayomani
d7bfedc3ef Prefilter couchpoato results 2015-08-11 19:48:25 +01:00
unknown
79a51eb21a Fixed result category mapping for bB and BeyondHD 2015-08-10 20:14:00 -06:00
unknown
b770b29d01 Implemented BeyondHD categories 2015-08-10 19:59:11 -06:00
unknown
690cd3acc9 Added categories to bB 2015-08-10 19:36:42 -06:00
unknown
9b712769b5 Added additional torznab categories, implemented AlphaRatio categories 2015-08-10 19:15:15 -06:00
Kayomani
2e42f60434 Fix scenetime 2015-08-10 21:46:58 +01:00
Kayomani
c6ff505b42 Implement TVChaos UK 2015-08-10 21:33:16 +01:00
Kayomani
3ca4f2c429 Merge pull request #135 from zone117x/develop
Merge 6.1
2015-08-09 23:11:58 +01:00
Kayomani
82a5930992 Bump version number 2015-08-09 23:08:53 +01:00
Kayomani
80d18e9754 Fix downloads not being proxied 2015-08-08 20:05:05 +01:00
Kayomani
e4c6e051e0 Implement not local/recaptcha login for torrentday 2015-08-08 10:26:29 +01:00
Kayomani
71f9e435d8 Implement recaptcha for torrentday (This will only work for localhost) 2015-08-08 00:15:42 +01:00
Kayomani
0291dffb43 Implement server backhole downloading 2015-08-07 22:57:54 +01:00
Kayomani
3bdf3c8a6a Saved password security 2015-08-07 20:09:13 +01:00
Kayomani
fa8d2a3705 Add category mapping to private hd 2015-08-06 23:23:40 +01:00
Kayomani
8259c6e728 RuTor Bugfix 2015-08-06 22:53:53 +01:00
Kayomani
167bfd303c Implement RuTor 2015-08-06 22:35:35 +01:00
Kayomani
89e5d68351 Add category mapping to torrentday, make logs viewable from web ui and change log messages to report new/old release count. 2015-08-06 20:07:58 +01:00
Matthew Little
c15512abf0 Update README.md 2015-08-06 10:46:55 -06:00
Kayomani
a69c91b2bf Fix for files not being copied to the output folder 2015-08-05 23:23:32 +01:00
Kayomani
e711ba1f24 Fix Safari not working not working (Untested). Fix cached download links not proxying the torrent download. 2015-08-05 23:00:09 +01:00
Kayomani
a5f97d8ac2 Fix torrentday 2015-08-05 19:22:02 +01:00
Kayomani
80adfeef7a Invalid command line options now show errors 2015-08-05 19:13:58 +01:00
unknown
4eaeb74f94 Implemented Demonoid 2015-08-04 21:07:46 -06:00
unknown
33a6dd2e21 Abstracted & unified indexer config logic (logins are now saved), implemented indexer config migrations, fixed nCore implementation 2015-08-03 15:38:45 -06:00
unknown
4832ac3571 Pulled in Sonarr's libcurl dll mapping, removed LINUX compiler flag from CurlSharp 2015-08-03 11:04:48 -06:00
Matthew Little
aecc92c1fa Merge pull request #124 from damwthomas/ncore-
Ncore
2015-08-03 11:01:58 -06:00
unknown
94d74dbfe2 Removed unneeded instructions from web UI 2015-08-02 20:59:25 -06:00
unknown
b082a40717 Fix console.csproj to load in MonoDevelop 2015-08-02 16:14:30 -06:00
unknown
b651e8a794 Fixed version in Inno script 2015-08-02 15:55:23 -06:00
unknown
aa5123e6ad Distribution script bug fix 2015-08-02 15:13:10 -06:00
unknown
7b7de3dac6 Fixed "cannot await in body of catch clause" warning 2015-08-02 15:10:51 -06:00
unknown
6ade9fdede Fixed installer build script 2015-08-02 14:44:07 -06:00
unknown
6f252bab66 Updated distribution script with mono build 2015-08-02 14:39:56 -06:00
unknown
00006389ac build script fix 2015-08-02 14:26:48 -06:00
Matthew Little
35d3e2d9b5 Merge pull request #125 from zone117x/develop
Develop
2015-08-02 14:18:39 -06:00
unknown
a95d0a47b5 Fixed indexer card WebUI height 2015-08-02 13:09:22 -06:00
unknown
2d42e55c68 Fixed bB indexer login 2015-08-02 12:44:36 -06:00
unknown
54edea2137 Fixed TorrentDay login, fixed nested redirect loops 2015-08-02 12:37:59 -06:00
unknown
4a568b9a3d Fixed Strike 2015-08-02 12:18:06 -06:00
unknown
71fb184383 Fixed Speed.cd login 2015-08-02 12:14:21 -06:00
unknown
77eebd8eb6 Remove support for RARBG (official support now in Sonarr, and recently broke in Jackett anyway) 2015-08-02 12:12:32 -06:00
unknown
1aa663f8e7 Merge branch 'develop' of https://github.com/zone117x/Jackett into develop 2015-08-02 11:57:09 -06:00
unknown
5ebdd16045 Fixed Freshon Login 2015-08-02 11:56:52 -06:00
Kayomani
a911b3932e Add CouchPotato interface 2015-08-02 18:55:39 +01:00
unknown
10eeef88f5 Fixed BitMeTV login, fixed failed login callback failing if async 2015-08-02 11:28:59 -06:00
unknown
39ed16a241 Fixed BitMeTV login exception crashing app 2015-08-02 10:30:31 -06:00
Kayomani
cab5b89c40 Update readme 2015-07-31 21:46:17 +01:00
Thomas
5ebb73ec4d nCore
Still a problem with the login & search doesn't work anymore with the
RequestStringWithCookiesAndRetry function.
2015-07-31 22:32:18 +02:00
Kayomani
66612e91af Fix: Redhat/NSS based libcurl not being able to access certain indexers 2015-07-31 20:27:59 +01:00
Thomas
491d6722e1 merge
merge
2015-07-31 21:17:56 +02:00
Kayomani
43d188c751 Implement torrentbytes 2015-07-30 21:09:38 +01:00
Kayomani
20871e650d Fix compilation under mono #117. Allow explicit web client selection. Init curl at application start. 2015-07-30 18:50:46 +01:00
Kayomani
0f30905e54 Fix testing indexers 2015-07-29 21:11:30 +01:00
Kayomani
490f8e47e5 #93 Change IPT to be category aware and render availible categories to the front end. 2015-07-29 20:30:28 +01:00
Kayomani
9f04d5fa2a Update nuget for 4.5 2015-07-29 18:55:08 +01:00
Kayomani
5f11b4501c Fix AnimeBytes caps, Change to 4.5 #117, change all trackers to retry failed requests 2015-07-29 18:47:51 +01:00
Kayomani
f9097ec290 Fix project not copying new tracker logo 2015-07-29 00:58:57 +01:00
Kayomani
92dc9ec152 Upgrade fix and testing an indexer now adds to the cache 2015-07-29 00:56:08 +01:00
Kayomani
4e4f60d0cb Add indexer: Immortalseed. Add category mapping framework. 2015-07-29 00:10:04 +01:00
Kayomani
5ea58dbbab #120 Linux defaults to allowing external access. 2015-07-28 20:29:05 +01:00
Kayomani
0184dbd560 Post refactor fixes 2015-07-28 20:22:23 +01:00
Kayomani
d305d5a8e5 Indexer refactor complete. This is going to need lots of testing! 2015-07-28 00:06:49 +01:00
Kayomani
9f8663e810 Re-add correctly cased 2015-07-27 18:57:07 +01:00
Kayomani
15be1a9315 Remove wrongly cased file 2015-07-27 18:56:42 +01:00
unknown
9a3a7fa4af Version increment 2015-07-26 15:47:34 -06:00
unknown
3fb8be044d Route fixes 2015-07-26 15:45:35 -06:00
unknown
cdff1d2d40 Distribution fix 2015-07-26 15:20:08 -06:00
unknown
dc56a77047 Created github distribution app 2015-07-26 15:14:29 -06:00
Kayomani
0a9f19b256 Add anime cap to ipt and remove New tag from PTM 2015-07-26 19:01:08 +01:00
Kayomani
3add87e072 Add missing IPT anime category 2015-07-26 18:05:16 +01:00
Kayomani
dba21c5c3e Change file to lower case and fix console issue 2015-07-26 17:27:04 +01:00
Kayomani
bd8819dd72 Change bakabt to lower case as in convention and fix duplicate command line option 2015-07-26 17:15:37 +01:00
unknown
e5a407998d Revert bakabt casing change 2015-07-26 10:05:34 -06:00
unknown
4cb25b9e4b Merge branch 'master' of https://github.com/zone117x/Jackett into develop 2015-07-26 10:04:17 -06:00
unknown
2c8fa00791 Fixed logo image requests using Name rather than ID 2015-07-26 10:02:27 -06:00
Kayomani
652fa35fa7 Merge pull request #113 from sdesbure/master
Use correct name for bakabt.png
2015-07-26 16:33:32 +01:00
Sylvain Desbureaux
014b3f8b6a use correct name for bakabt.png
older one was not using the correct case, which causes an error on unix (BakaBT.png is the correct not bakabt.png)
2015-07-26 17:07:00 +02:00
Kayomani
3b87369458 New: Viewable release cache 2015-07-26 15:22:20 +01:00
Kayomani
8c2141b04f Fix wrong description for PTM 2015-07-26 11:57:29 +01:00
Kayomani
9f840475a1 Fix PTM not parsing dates 2015-07-26 11:53:38 +01:00
Kayomani
e5a54df60c Tweak read me 2015-07-26 11:39:27 +01:00
Kayomani
36f894e3f4 Merge changes 2015-07-26 11:36:57 +01:00
Kayomani
1f6046bbe0 Fix IPT 2015-07-26 11:27:50 +01:00
unknown
01dc9cb0a5 Replaced most indexers' byte size string parsing with shared helper function 2015-07-25 21:53:53 -06:00
unknown
abdca8cee8 Implemented HD-Space 2015-07-25 21:48:18 -06:00
unknown
fd9c79e289 Implemented pretome 2015-07-25 20:33:01 -06:00
Kayomani
676a1824db Merge BakaBT Fix 2015-07-26 01:22:26 +01:00
Kayomani
289d011991 BakaBT fix minium ratio not set 2015-07-26 01:17:19 +01:00
Kayomani
c9072b5d67 Merge pull request #108 from zone117x/develop
BakaBT + Switch from x64 back to any cpu
2015-07-26 01:08:16 +01:00
Kayomani
5713841499 Baka BT Remove Season from search query 2015-07-26 01:04:16 +01:00
Kayomani
7ef1f1e460 Fix logo not copying 2015-07-26 00:53:45 +01:00
Kayomani
ad50101d82 Implement BakaBT, change Console to not build as x64, Add test framework 2015-07-26 00:51:55 +01:00
Matthew Little
4faaec0090 Update README.md 2015-07-25 10:29:28 -06:00
Matthew Little
c35d3328d5 Update README.md 2015-07-25 10:28:34 -06:00
Kayomani
f56587fb24 Merge pull request #106 from zone117x/develop
Fix SCC not saving and AlphaRatio
2015-07-25 11:49:11 +01:00
Kayomani
e47cf66093 Fix SCC not saving and AlphaRatio 2015-07-25 11:47:01 +01:00
Kayomani
073ddbe272 Resolve Merge conflict 2015-07-25 10:26:01 +01:00
Kayomani
a31098fbe7 Fix SCC and duplicate console option 2015-07-25 10:24:15 +01:00
Kayomani
af9b4e99e2 Merge fixes from develop 2015-07-25 09:35:25 +01:00
Kayomani
59a62daa34 Make lib curl more stable 2015-07-25 09:34:15 +01:00
unknown
2c1ff1a881 Fix for SceneTime timezone on mono 2015-07-24 19:25:30 -06:00
unknown
9fceea9aa8 Fixed extra slashes in URLs 2015-07-24 18:41:24 -06:00
unknown
c3fe26f4b5 Fix for SceneTime 2015-07-24 18:27:35 -06:00
unknown
63b0ca6b72 FreshonTV fix 2015-07-24 18:23:31 -06:00
Kayomani
58f43b8b44 Merge pull request #105 from zone117x/develop
Merge fixes from testing
2015-07-24 22:54:44 +01:00
Kayomani
92a573d804 Various bugfixes. 2015-07-24 22:38:31 +01:00
Kayomani
44800491c0 Added UI for allowing external access, stop server listening on the old port when changing ports. Config migration bug fixes. 2015-07-24 20:15:08 +01:00
Kayomani
64acf70b77 Merge pull request #104 from zone117x/develop
Command line args.  Supercede pull #102 from sdesbure:master
2015-07-24 00:09:32 +01:00
Kayomani
800e764f60 Command line args. Superceade pull #102 from sdesbure:master 2015-07-24 00:07:36 +01:00
Kayomani
469c44b923 Merge branch 'master' of https://github.com/zone117x/Jackett.git 2015-07-23 22:15:41 +01:00
Kayomani
90118b402a Merge branch 'develop' 2015-07-23 22:14:55 +01:00
Kayomani
5366cb42b7 Fix unreliable torrentleech date parsing 2015-07-23 22:14:36 +01:00
Kayomani
541320033e Merge pull request #103 from zone117x/develop
Passwords inputs are now the correct type. Fix configure_indexer not returning errors. Fix build warning. Change AB, HDT, MTTV, PHD, ST to use generic web client.
2015-07-23 21:37:42 +01:00
Kayomani
f8eb72414d Passwords inputs are now the correct type. Fix configure_indexer not returning errors. Fix build warning. Change AB, HDT, MTTV, PHD, ST to use generic web client. 2015-07-23 21:36:23 +01:00
Matthew Little
9579719376 Merge pull request #101 from zone117x/develop
Develop
2015-07-22 23:20:21 -06:00
Matthew Little
cef4a5c94d Update README.md 2015-07-22 23:18:41 -06:00
unknown
8a7ab0c5f1 Implemented PrivateHD 2015-07-22 23:16:35 -06:00
unknown
15ee194035 Abstracted common "time ago" date string parsing logic 2015-07-22 23:16:13 -06:00
unknown
bb32831e9f Fixed bug with download proxy url using indexerName instead of indexerID 2015-07-22 21:21:29 -06:00
Matthew Little
c93830325e Update README.md 2015-07-22 18:25:08 -06:00
Kayomani
dced67726b Merge remote-tracking branch 'refs/remotes/origin/develop' 2015-07-23 00:10:27 +01:00
Kayomani
5b87e2f694 Revert "Revert "Refactored to use the RageID lookup disabled, removed Sonarr API setup""
This reverts commit b3ecee2cc9.
2015-07-23 00:09:55 +01:00
Kayomani
9a15f8a965 Couple of bugfixes 2015-07-22 23:48:02 +01:00
Kayomani
d016c6f8ad Fix trackers with non alphanumerics in the name not resolving 2015-07-22 23:06:46 +01:00
Kayomani
8824aa62e5 0.5 Rc1 - Reimplement port change+tray, fix IPT+SSC. Installer fixes. 2015-07-22 23:00:52 +01:00
Kayomani
b85ff8503c Add missed file 2015-07-20 22:30:08 +01:00
Kayomani
3e8688eea8 Merge pull request #99 from zone117x/feature/ServiceRefactor
Merge Feature/service refactor
2015-07-20 22:26:42 +01:00
Kayomani
abfe32661a Merge changes 2015-07-20 22:18:02 +01:00
Kayomani
a908b2b691 Web auth 2015-07-20 22:08:05 +01:00
unknown
d02a19b94b Fix loopback & localhost entry points for mono 2015-07-19 18:26:07 -06:00
unknown
a37f1df313 Fix loopback address not working 2015-07-19 18:06:21 -06:00
unknown
2fa280deae readme change 2015-07-19 17:27:03 -06:00
unknown
a1a45fefb7 Add bB to readme 2015-07-19 17:26:45 -06:00
unknown
8cef953284 Fixed bB cookie persistence 2015-07-19 17:22:08 -06:00
unknown
54a3271d73 Fixed AnimeBytes torznab category 2015-07-19 17:20:16 -06:00
unknown
68d6fef4f2 Merge branch 'feature/ServiceRefactor' of https://github.com/zone117x/Jackett into feature/ServiceRefactor 2015-07-19 17:05:40 -06:00
unknown
5fb7e3a2ae Implemented torznab capabilities feature 2015-07-19 17:05:30 -06:00
Kayomani
52fd3e67a4 Fix issue #65 - Parsing issues due to culuture differences. 2015-07-19 22:57:15 +01:00
Kayomani
507e0d5496 Add logging 2015-07-19 22:31:36 +01:00
Kayomani
fb8db7db57 Merge branch 'feature/ServiceRefactor' of https://github.com/zone117x/Jackett.git 2015-07-19 21:22:25 +01:00
Kayomani
37ae1d6226 Add missing route 2015-07-19 21:22:23 +01:00
unknown
63b48a2af5 Implemented bB tracker 2015-07-19 14:21:31 -06:00
unknown
ffa868e466 Fix for Strike date change 2015-07-19 14:21:14 -06:00
Kayomani
396e4b2d50 Fix merge conflict 2015-07-19 21:16:31 +01:00
Kayomani
03bb51b1ef Add missing files 2015-07-19 21:15:23 +01:00
unknown
977875f622 Fixed indexer register by name 2015-07-19 13:38:41 -06:00
unknown
32c3323de7 Indexer ID rather than class name 2015-07-19 13:28:08 -06:00
unknown
4a993efd6a Fixed TestIndexer async Task 2015-07-19 12:25:47 -06:00
unknown
0001bfbf78 Merge branch 'feature/ServiceRefactor' of https://github.com/zone117x/Jackett into feature/ServiceRefactor 2015-07-19 11:37:18 -06:00
unknown
c2add69276 Fix indexer class lookup by string when name has non-alphanumeric chars 2015-07-19 11:37:08 -06:00
Kayomani
9a93b62247 Tidy up 2015-07-19 18:31:25 +01:00
Kayomani
644cf939ca Bug fix 2015-07-19 18:23:29 +01:00
Kayomani
0dcebe9ced Change indexers to use new api 2015-07-19 18:18:54 +01:00
unknown
b3ecee2cc9 Revert "Refactored to use the RageID lookup disabled, removed Sonarr API setup"
This reverts commit b279c871b1.
2015-07-19 10:59:07 -06:00
unknown
ce4e437733 Added change port argument to console app 2015-07-19 10:57:33 -06:00
unknown
f6d3150784 Added build.bat & installer.iss as solution items 2015-07-19 10:57:05 -06:00
unknown
e9aa7834f2 Minor settings migration bug fix 2015-07-19 10:35:56 -06:00
unknown
89b672f296 Readded SpeedCD to solution 2015-07-19 10:35:34 -06:00
Kayomani
43f5f5eda2 Merge pull request #95 from Kayomani/feature/Refactor2
Feature/refactor2
2015-07-19 15:41:48 +01:00
Kayomani
795688c218 Reinstate changes from merge 2015-07-19 15:22:26 +01:00
Kayomani
3bb22020a6 Fix csproj 2015-07-19 15:03:39 +01:00
Kayomani
32ef46501c Undo Organizational improvements and build warnings fixed 2015-07-19 14:56:48 +01:00
Kayomani
aa23903434 Tray 2015-07-19 14:33:27 +01:00
Kayomani
e50e937a69 Refactor done 2015-07-19 14:22:50 +01:00
unknown
ce7c5fdd48 Implemented speed.cd 2015-07-18 20:19:09 -06:00
unknown
d476174233 Organizational improvements and build warnings fixed 2015-07-18 19:03:24 -06:00
unknown
65aa3211aa Fixed blocking query in ShowRSS 2015-07-18 19:02:47 -06:00
unknown
919d1b4783 Fix showing console error when settings directory cannot be created 2015-07-18 19:02:29 -06:00
unknown
4f5f0402a4 Strike bug fix 2015-07-18 19:00:38 -06:00
Kayomani
e6c2138b32 Interim commit 2015-07-19 01:59:30 +01:00
Kayomani
b366374cf2 Refactor 2015-07-19 01:27:41 +01:00
unknown
b279c871b1 Refactored to use the RageID lookup disabled, removed Sonarr API setup 2015-07-18 14:35:02 -06:00
Matthew Little
7cfa590b94 Merge pull request #88 from Kayomani/hotfix/Bugfixes
HDTorrents bugfix, change AnimeBytes to work with RageId queries and reduce sizes of cards to improve presentation with the large number of indexers
2015-07-18 11:03:01 -06:00
Kayomani
5874a744d7 HDTorrents bugfix and reduce sizes of cards to improve presentation with the large number of indexers 2015-07-18 10:59:18 +01:00
Matthew Little
debc2a45b7 Merge pull request #85 from sdesbure/master
Add of FrenchTorrentDb site
2015-07-16 18:10:58 -06:00
Matthew Little
b90c3d6f83 Merge pull request #81 from damwthomas/ChangingPort
Change port
2015-07-16 18:08:12 -06:00
Sylvain Desbureaux
7ecc89f30f done the Download method for FrenchTorrentDb 2015-07-17 00:24:38 +02:00
Sylvain Desbureaux
dc63db44fc reverting src/Jackett/packages.config 2015-07-17 00:20:14 +02:00
Sylvain Desbureaux
4c89da4bc7 only needed changes in src/Jackett/Jackett.csproj 2015-07-17 00:19:41 +02:00
Sylvain Desbureaux
52b7e53952 No need of Noesis.Javascript 2015-07-16 02:03:19 +02:00
Sylvain Desbureaux
ff6c3a82fa added FrenchTorrentDb in the list of supported sites 2015-07-16 02:01:39 +02:00
Sylvain Desbureaux
1be41c4aff Added FrenchTorrentDb site 2015-07-16 01:59:38 +02:00
ThomasAmpen
46f15f314a Change port 2015-07-14 21:07:55 +02:00
unknown
47a5a7edd5 Readme update 2015-07-13 01:18:10 -06:00
unknown
f91c92326c T411 auto re-fetch token after 48 hours 2015-07-13 01:17:21 -06:00
unknown
2eebea0683 Implemented T411 2015-07-13 01:13:16 -06:00
unknown
cf7d4cb518 App version increment 2015-07-12 23:57:56 -06:00
unknown
ddd86d2279 Improvement for TPB - combined TV and HDTV search into one 2015-07-12 23:57:14 -06:00
unknown
4996bd57e1 Don't use https for HD-Torrents (doesn't work on mono) 2015-07-12 23:39:41 -06:00
unknown
3fd4b08da2 App version increment 2015-07-12 20:03:04 -06:00
unknown
1a7f3c2e3e Readme update 2015-07-12 20:01:36 -06:00
unknown
f4ad01dda7 Implemented BeyondHD 2015-07-12 20:01:02 -06:00
unknown
f2f50e21fa Moved AnimeBytes helper class into its main class file 2015-07-12 20:00:47 -06:00
unknown
5f011d3222 Implemented SceneTime 2015-07-12 15:43:00 -06:00
unknown
757c3ee87a Minor improvements, bug fixes 2015-07-12 13:50:24 -06:00
Matthew Little
c21c83a13e Merge pull request #79 from damwthomas/master
HDTorrents
2015-07-12 13:18:01 -06:00
ThomasAmpen
9595dad645 Forgotten parse 2015-07-12 19:58:46 +02:00
ThomasAmpen
dd658b2e77 DeletedExtentionmethod 2015-07-12 19:54:37 +02:00
ThomasAmpen
389926d86b BrowserUtil, tryparse added 2015-07-12 19:52:32 +02:00
ThomasAmpen
5744e6ff08 Merge branch 'zone117x/master' 2015-07-12 18:54:45 +02:00
ThomasAmpen
ba89d25563 pull from master 2015-07-12 18:23:40 +02:00
damwthomas
6e575a70e3 Merge pull request #2 from damwthomas/HDTorrents
Hdtorrents
2015-07-12 17:49:36 +02:00
ThomasAmpen
bd8463387b HDTorrents 2015-07-12 17:48:37 +02:00
Matthew Little
3b22973b6d Update README.md 2015-07-11 14:34:13 -06:00
unknown
3a6899343a Incremented to app version 0.4.0 2015-07-11 14:30:16 -06:00
unknown
56bbee2f1f Strip most non alphanumeric characters from show titles before searching 2015-07-11 14:23:43 -06:00
unknown
b58566c782 Timezone publish date fixes for Bit-HDTV, BitMeTv, and MoreThanTV 2015-07-11 14:06:13 -06:00
ThomasAmpen
79ee4b4da0 HdTorrents 2015-07-11 21:27:57 +02:00
unknown
dd31c249fd TorrentShack fix for an unlikely bug 2015-07-11 13:26:57 -06:00
unknown
c6357bf30f Fixes for loading saved cookie problems 2015-07-11 12:54:15 -06:00
unknown
e0e3c12d5e Fixed torrent file download for GetStrike 2015-07-11 11:09:52 -06:00
unknown
8e0b138086 Fix for custom PirateBay url 2015-07-11 11:00:44 -06:00
unknown
a6213c1b9a Display app version in web interface 2015-07-11 10:53:18 -06:00
unknown
9ffa461ae3 Fixed autostart feature 2015-07-11 10:42:00 -06:00
unknown
257fbc07b2 Changed app settings location to longer require root on unix 2015-07-11 10:29:20 -06:00
unknown
8d08279895 Bug fixes for number parsing, fixed ThePirateBay indexer 2015-07-11 10:24:41 -06:00
ThomasAmpen
ecdd1f655b Pull from master 2015-07-09 22:24:20 +02:00
Matthew Little
edb629adb4 Update README.md 2015-07-09 14:08:13 -06:00
Matthew Little
43b0403ab4 Merge pull request #78 from Kayomani/master
Add AnimeBytes Tracker
2015-07-09 13:50:25 -06:00
Kayomani
7cf55f41d6 Add AnimeBytes Tracker 2015-07-09 18:44:19 +01:00
836 changed files with 60458 additions and 81056 deletions

15
.gitattributes vendored
View File

@@ -1,15 +0,0 @@
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto
# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
# Declare files that will always have LF line endings on checkout.
*.yml text eol=lf
# Declare files that will always have CRLF line endings on checkout.
*.cs text eol=crlf
# Denote all files that are truly binary and should not be modified.
*.png binary
*.jpg binary

View File

@@ -1,9 +0,0 @@
**Please use the search bar** at the top of the page and make sure you are not creating an already submitted issue. Duplicating issues makes it more difficult for everyone to follow. Your issue may have already been solved in the past as well.
Provide a description of the feature request or bug, the more details the better.
If you are experiencing an issue with a tracker, a **full enhanced log must be included**. Instructions for obtaining logs are here: https://github.com/Jackett/Jackett#troubleshooting
**Jackett version**:
**Mono version** (if not using Windows):
-------------------------------

Binary file not shown.

Before

Width:  |  Height:  |  Size: 480 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 439 KiB

View File

@@ -1,7 +0,0 @@
Duplicate of #{{ chosenIssue.number }}
Hi @{{ payload.sender.login }},
This issue looks similar to #{{ chosenIssue.number }}.
To prevent issue tracker clutter, this issue will now be closed. If you feel this issue isn't a duplicate of #{{ chosenIssue.number }}, then feel free to post a comment on this issue stating why it's not a duplicate. Your comment will automatically re-open this issue.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -1,9 +0,0 @@
Hi @{{ payload.sender.login }},
You've created an issue, but haven't provided any details to allow the community to assist you. To prevent issue tracker clutter, this issue will now be closed. Please provide the information needed below and your comment will automatically re-open this issue.
Provide a description of the feature request or bug, the more details the better.
If you are experiencing an issue with a tracker, a **full enhanced log must be included**. Instructions for obtaining logs are here: https://github.com/Jackett/Jackett#troubleshooting
**Jackett version**:
**Mono version** (if not using Windows):

View File

@@ -1,3 +0,0 @@
Hi @{{ payload.data.user.login }},
No response has been received for {{ days }} days. To prevent issue tracker clutter, this issue will now be closed. To re-open the issue, please provide the information requested and the issue will automatically re-open.

View File

@@ -1,7 +0,0 @@
Hi @{{ payload.pull_request.user.login }},
Thanks for your contribution to Jackett!
If you are adding a new indexer, please ensure that you've added it to the readme as well
A human will be along soon to review

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

9
.gitignore vendored
View File

@@ -194,10 +194,5 @@ FakesAssemblies/
# Visual Studio 6 workspace options file
*.opt
/tools
/BuildOutput
/Artifacts
/TestResults
*.DS_Store
.idea/
launchSettings.json
/Build.mono
/Build.windows

33
Build.bat Normal file
View File

@@ -0,0 +1,33 @@
rmdir /s /q build.windows
rmdir /s /q build.mono
rmdir /s /q Output
cd src
Msbuild Jackett.sln /t:Clean,Build /p:Configuration=Release /verbosity:minimal
cd ..
xcopy src\Jackett.Console\bin\Release build.windows\ /e /y
copy /Y src\Jackett.Service\bin\Release\JackettService.exe build.windows\JackettService.exe
copy /Y src\Jackett.Service\bin\Release\JackettService.exe.config build.windows\JackettService.exe.config
copy /Y src\Jackett.Tray\bin\Release\JackettTray.exe build.windows\JackettTray.exe
copy /Y src\Jackett.Tray\bin\Release\JackettTray.exe.config build.windows\JackettTray.exe.config
copy /Y LICENSE build.windows\LICENSE
copy /Y README.md build.windows\README.md
cd src
Msbuild Jackett.sln /t:Clean
call "C:\Program Files (x86)\Mono\bin\xbuild.bat" Jackett.sln /t:Build /p:Configuration=Release /verbosity:minimal
cd ..
xcopy src\Jackett.Console\bin\Release build.mono\ /e /y
copy /Y src\Jackett.Service\bin\Release\JackettService.exe build.mono\JackettService.exe
copy /Y src\Jackett.Service\bin\Release\JackettService.exe.config build.mono\JackettService.exe.config
copy /Y src\Jackett.Tray\bin\Release\JackettTray.exe build.mono\JackettTray.exe
copy /Y src\Jackett.Tray\bin\Release\JackettTray.exe.config build.mono\JackettTray.exe.config
copy /Y LICENSE build.mono\LICENSE
copy /Y README.md build.mono\README.md
copy /Y Upstart.config build.mono\Upstart.config
iscc Installer.iss

View File

@@ -2,9 +2,9 @@
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
#define MyAppName "Jackett"
#define MyAppVersion GetFileVersion(MyFileForVersion)
#define MyAppPublisher "Jackett"
#define MyAppURL "https://github.com/Jackett/Jackett"
#define MyAppVersion GetFileVersion("build.windows/Jackett.dll")
#define MyAppPublisher "Jackett Inc."
#define MyAppURL "https://github.com/zone117x/Jackett"
#define MyAppExeName "JackettTray.exe"
[Setup]
@@ -22,14 +22,11 @@ AppUpdatesURL={#MyAppURL}
DefaultDirName={pf}\{#MyAppName}
DefaultGroupName={#MyAppName}
DisableProgramGroupPage=yes
OutputBaseFilename={#MyOutputFilename}
SetupIconFile=src\Jackett.Tray\jackett.ico
UninstallDisplayIcon={commonappdata}\Jackett\{#MyAppExeName}
VersionInfoVersion={#MyAppVersion}
UninstallDisplayName={#MyAppName}
OutputBaseFilename=setup
SetupIconFile=src\Jackett.Console\jackett.ico
UninstallDisplayIcon={app}\JackettConsole.exe
Compression=lzma
SolidCompression=yes
DisableDirPage=yes
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
@@ -39,24 +36,26 @@ Name: "windowsService"; Description: "Install as a Windows Service"
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
[Files]
Source: "{#MySourceFolder}\*"; DestDir: "{commonappdata}\Jackett"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "build.windows\JackettTray.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "build.windows\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
[Icons]
Name: "{group}\{#MyAppName}"; Filename: "{commonappdata}\Jackett\{#MyAppExeName}"
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"
Name: "{commondesktop}\{#MyAppName}"; Filename: "{commonappdata}\Jackett\{#MyAppExeName}"; Tasks: desktopicon
Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
[Run]
Filename: "{commonappdata}\Jackett\JackettConsole.exe"; Parameters: "--Uninstall"; Flags: waituntilterminated runhidden;
Filename: "{commonappdata}\Jackett\JackettConsole.exe"; Parameters: "--ReserveUrls"; Flags: waituntilterminated runhidden;
Filename: "{commonappdata}\Jackett\JackettConsole.exe"; Parameters: "--Install"; Flags: waituntilterminated runhidden; Tasks: windowsService
Filename: "{commonappdata}\Jackett\JackettConsole.exe"; Parameters: "--Start"; Flags: waituntilterminated runhidden; Tasks: windowsService
Filename: "{commonappdata}\Jackett\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
[Run]
Filename: "{app}\JackettConsole.exe"; Parameters: "--Uninstall"; Flags: waituntilterminated;
Filename: "{app}\JackettConsole.exe"; Parameters: "--ReserveUrls"; Flags: waituntilterminated;
Filename: "{app}\JackettConsole.exe"; Parameters: "--MigrateSettings"; Flags: waituntilterminated;
Filename: "{app}\JackettConsole.exe"; Parameters: "--Install"; Flags: waituntilterminated; Tasks: windowsService
Filename: "{app}\JackettConsole.exe"; Parameters: "--Start"; Flags: waituntilterminated; Tasks: windowsService
[UninstallRun]
Filename: "{commonappdata}\Jackett\JackettConsole.exe"; Parameters: "--Uninstall"; Flags: waituntilterminated skipifdoesntexist runhidden
Filename: "{sys}\taskkill.exe"; Parameters: "/f /im {#MyAppExeName}"; Flags: waituntilterminated skipifdoesntexist runhidden
Filename: "{sys}\taskkill.exe"; Parameters: "/f /im JackettConsole.exe"; Flags: waituntilterminated skipifdoesntexist runhidden
Filename: "{app}\JackettConsole.exe"; Parameters: "--Uninstall"; Flags: waituntilterminated skipifdoesntexist

534
README.md
View File

@@ -1,428 +1,106 @@
# Jackett
[![GitHub issues](https://img.shields.io/github/issues/Jackett/Jackett.svg?maxAge=60&style=flat-square)](https://github.com/Jackett/Jackett/issues)
[![GitHub pull requests](https://img.shields.io/github/issues-pr/Jackett/Jackett.svg?maxAge=60&style=flat-square)](https://github.com/Jackett/Jackett/pulls)
[![Build status](https://ci.appveyor.com/api/projects/status/gaybh5mvyx418nsp/branch/master?svg=true)](https://ci.appveyor.com/project/Jackett/jackett)
[![Github Releases](https://img.shields.io/github/downloads/Jackett/Jackett/total.svg?maxAge=60&style=flat-square)](https://github.com/Jackett/Jackett/releases/latest)
[![Docker Pulls](https://img.shields.io/docker/pulls/linuxserver/jackett.svg?maxAge=60&style=flat-square)](https://hub.docker.com/r/linuxserver/jackett/)
[![Discord](https://img.shields.io/badge/discord-chat-7289DA.svg?maxAge=60&style=flat-square)](https://discord.gg/J865QuA)
This project is a new fork and is recruiting development help. If you are able to help out please contact us.
Jackett works as a proxy server: it translates queries from apps ([Sonarr](https://github.com/Sonarr/Sonarr), [Radarr](https://github.com/Radarr/Radarr), [SickRage](https://sickrage.github.io/), [CouchPotato](https://couchpota.to/), [Mylar](https://github.com/evilhero/mylar), [DuckieTV](https://github.com/SchizoDuckie/DuckieTV), etc) into tracker-site-specific http queries, parses the html response, then sends results back to the requesting software. This allows for getting recent uploads (like RSS) and performing searches. Jackett is a single repository of maintained indexer scraping & translation logic - removing the burden from other apps.
Developer note: The software implements the [Torznab](https://github.com/Sonarr/Sonarr/wiki/Implementing-a-Torznab-indexer) (with [nZEDb](https://github.com/nZEDb/nZEDb/blob/dev/docs/newznab_api_specification.txt) category numbering) and [TorrentPotato](https://github.com/RuudBurger/CouchPotatoServer/wiki/Couchpotato-torrent-provider) APIs.
#### Supported Systems
* Windows using .NET 4.6.1 or above [Download here](https://www.microsoft.com/net/framework/versions/net461).
* Linux and macOS using Mono 5.8 or above. [Download here](http://www.mono-project.com/download/).
### Supported Public Trackers
* 1337x
* Anidex
* Anime Tosho
* AniRena
* btbit
* BTDB
* BT-Scene
* cpasbien
* ETTV
* ExtraTorrent.ag
* EZTV
* Frozen Layer
* GkTorrent
* Horrible Subs
* Idope
* Il Corsaro Nero <!-- maintained by bonny1992 -->
* Il Corsaro Blu
* Isohunt2
* KickAssTorrent
* KickAssTorrent (thekat.se clone)
* LimeTorrents
* MagnetDL
* MejorTorrent <!-- maintained by ivandelabeldad -->
* NextTorrent
* Newpct (aka: tvsinpagar, descargas2020, torrentlocura, torrentrapid, etc)
* Nyaa.si
* Nyaa-Pantsu
* Nyoo
* RARBG
* RuTor
* ShowRSS
* sukebei.Nyaa.si
* sukebei-Pantsu
* The Pirate Bay
* TNTVillage <!-- maintained by bonny1992 -->
* Tokyo Toshokan
* Torlock
* Torrent Downloads
* Torrent9
* TorrentKim
* Torrentz2
* World Wide Torrents
* YIFY (YTS)
* YTS.ag
* Zooqle
### Supported Semi-Private Trackers
* 7tor
* CzTorrent
* Deildu
* Gay-Torrents.net
* Kinozal
* LostFilm.tv
* Mega-Bliz
* Metal Tracker
* MVGroup Forum
* MVGroup Main
* Newstudio
* NetHD
* NoName Club
* RuTracker
* SkTorrent
* Union Fansub
* Xtreme Zone
* YggTorrent
* Ztracker
### Supported Private Trackers
* 2 Fast 4 You
* 3D Torrents
* Abnormal
* Acid-Lounge
* AlphaRatio
* AnimeBytes
* AnimeTorrents
* AOX
* Apollo (XANAX)
* ArabaFenice
* Arche Torrent
* AsianDVDClub
* AST4u
* Audiobook Torrents
* Awesome-HD
* Avistaz
* B2S-Share
* Back-ups
* BakaBT [![(invite needed)][inviteneeded]](#)
* bB
* BeyondHD
* BIGTorrent
* Bit-City Reloaded
* BIT-HDTV
* Bithorlo
* BitHUmen
* BitMe
* BitMeTV
* BitSoup [![(invite needed)][inviteneeded]](#)
* Bitspyder
* BitTorrentFiles [![(invite needed)][inviteneeded]](#)
* BJ-Share
* BlueBird
* Blutopia
* Brasil Tracker
* BroadcastTheNet
* BrokenStones
* BTNext
* BTXpress
* Carpathians
* CCFBits
* CGPeers
* CHDBits
* Cinematik
* Cinemageddon
* CinemaZ
* Classix
* DanishBits
* DataScene
* Demonoid
* Diablo Torrent
* DigitalHive
* Downloadville
* Dragonworld Reloaded
* Dream Team
* EliteHD [![(invite needed)][inviteneeded]](#)
* Elit Tracker
* Elite-Tracker
* Empornium
* EoT-Forum
* eStone
* Ethor.net (Thor's Land)
* FANO.IN
* FileList
* Femdomcult
* Freedom-HD
* FullMixMusic
* FunFile
* FunkyTorrents
* Fuzer
* GayTorrent.ru
* GazelleGames
* Gfxnews
* GFXPeers
* GigaTorrents
* GimmePeers <!-- maintained by jamesb2147 -->
* Girotottent
* GODS [![(invite needed)][inviteneeded]](#)
* Greek Team
* HacheDe
* Hardbay
* HD-Forever
* HD-Only
* HD-Space
* HD-Spain
* HD-Torrents
* HD-Bits.com
* HDBits
* HDChina
* HDCity
* HDHome
* HDME
* HDSky
* HDTorrents.it
* Hebits
* Hon3y HD
* Hyperay
* ICE Torrent
* I Love Classics
* Immortalseed
* inPeril
* Insane Tracker
* IPTorrents
* JPopsuki
* Kapaki
* Karagarga
* LinkoManija
* LosslessClub
* M-Team - TP
* Magico
* Majomparádé
* Manicomio Share
* Mononoké-BT
* MoreThanTV
* MyAnonamouse
* myAmity
* MySpleen
* NCore
* Nebulance
* New Real World
* Norbits <!-- added by DiseaseNO but no longer maintained? -->
* notwhat.cd
* Ourbits
* Passione Torrent <!-- maintained by bonny1992 -->
* PassThePopcorn
* PirateTheNet
* PiXELHD
* PolishSource
* PolishTracker
* Pretome
* PrivateHD
* Psytorrents
* PTFiles
* PuntoTorrent
* Racing4Everyone (R4E)
* Redacted (PassTheHeadphones)
* RevolutionTT
* RGU
* RoDVD
* SceneFZ
* SceneReactor
* SceneTime
* SDBits
* Secret Cinema
* Shareisland
* ShareSpaceDB
* Shazbat
* Shellife
* Speed-Share
* SpeedCD
* SpeedTorrent Reloaded
* SportsCult
* SportHD
* Superbits
* Tasmanit
* TBPlus
* TehConnection.me
* TenYardTracker
* The Empire
* The Geeks
* The Horror Charnel
* The Occult
* The New Retro
* The Place
* The Shinning
* The Show
* The Vault
* The-Torrents
* Torrent Network
* Torrent Sector Crew
* Torrent.LT
* TorrentBD
* TorrentBytes
* TorrentCCF [![(invite needed)][inviteneeded]](#)
* TorrentDay
* Torrentech
* TorrentHeaven
* TorrentHR
* Torrenting
* Torrentland
* TorrentLeech
* Torrents.Md
* TorrentSeeds
* Torrent-Syndikat
* TOrrent-tuRK (TORK)
* TorViet
* ToTheGlory
* TranceTraffic
* Trezzor
* TV Chaos UK
* TV-Vault
* u-torrents (SceneFZ)
* UHDBits
* Ultimate Gamer Club
* Waffles
* World-In-HD
* WorldOfP2P
* x264
* xBytesV2
* XSpeeds
* Xthor
* Your Exotic Torrents
* Zamunda.net
* Zelka.org
Trackers marked with [![(invite needed)][inviteneeded]](#) have no active maintainer and are missing features or are broken. If you have an invite for them please send it to kaso1717 -at- gmail.com to get them fixed/improved.
### Aggregate indexers
A special "all" indexer is available at `/api/v2.0/indexers/all/results/torznab/api`.
It will query all configured indexers and return the combined results.
To get all Jackett indexers including their capabilities you can use `t=indexers` on the all indexer. To get only configured/unconfigured indexers you can also add `configured=true/false` as query parameter.
## Installation on Windows
We recommend you install Jackett as a Windows service using the supplied installer. You may also download the zipped version if you would like to configure everything manually.
To get started with using the installer for Jackett, follow the steps below:
1. Download the latest version of the Windows installer, "Jackett.Installer.Windows.exe" from the [releases](https://github.com/Jackett/Jackett/releases/latest) page.
2. When prompted if you would like this app to make changes to your computer, select "yes".
3. If you would like to install Jackett as a Windows Service, make sure the "Install as Windows Service" checkbox is filled.
4. Once the installation has finished, check the "Launch Jackett" box to get started.
5. Navigate your web browser to: http://127.0.0.1:9117
6. You're now ready to begin adding your trackers and using Jackett.
When installed as a service the tray icon acts as a way to open/start/stop Jackett. If you opted to not install it as a service then Jackett will run its web server from the tray tool.
Jackett can also be run from the command line if you would like to see log messages (Ensure the server isn't already running from the tray/service). This can be done by using "JackettConsole.exe" (for Command Prompt), found in the Jackett data folder: "%ProgramData%\Jackett".
## Installation on Linux
1. Install [Mono 5.8](http://www.mono-project.com/download/#download-lin) or better (using the latest stable release is recommended)
* Follow the instructions on the mono website and install the `mono-devel` and the `ca-certificates-mono` packages.
* On Red Hat/CentOS/openSUSE/Fedora the `mono-locale-extras` package is also required.
2. Install libcurl:
* Debian/Ubunutu: `apt-get install libcurl4-openssl-dev`
* Redhat/Fedora: `yum install libcurl-devel`
* For other distros see the [Curl docs](http://curl.haxx.se/dlwiz/?type=devel).
3. Download and extract the latest `Jackett.Binaries.Mono.tar.gz` release from the [releases page](https://github.com/Jackett/Jackett/releases) and run Jackett using mono with the command `mono --debug JackettConsole.exe`.
Detailed instructions for [Ubuntu 14.x](http://www.htpcguides.com/install-jackett-on-ubuntu-14-x-for-custom-torrents-in-sonarr/) and [Ubuntu 15.x](http://www.htpcguides.com/install-jackett-ubuntu-15-x-for-custom-torrents-in-sonarr/)
If you want to run it with a user without a /home directory you need to add `Environment=XDG_CONFIG_HOME=/path/to/folder` to your systemd file, this folder will be used to store your config files.
Mono must be compiled with the Roslyn compiler (default), using MCS will cause "An error has occurred." errors (See https://github.com/Jackett/Jackett/issues/2704).
## Installation on macOS
### Prerequisites
Install [Mono 5.8](http://www.mono-project.com/download/#download-mac) or better (using the latest pkg installer is recommended).
* Setup ssl support by running `curl -sS https://curl.haxx.se/ca/cacert.pem | cert-sync --user /dev/stdin`
### Install as service
1. Download and extract the latest `Jackett.Binaries.Mono.tar.gz` release from the [releases page](https://github.com/Jackett/Jackett/releases).
2. Open the extracted folder and double-click on `install_service_macos`.
3. If the installation was a success, you can close the Terminal window.
The service will start on each logon. You can always stop it by running `launchctl unload ~/Library/LaunchAgents/org.user.Jackett.plist` from Terminal. You can start it again it using `launchctl load ~/Library/LaunchAgents/org.user.Jackett.plist`.
Logs are stored as usual under `~/.config/Jackett/log.txt`.
### Run without installing as a service
Download and extract the latest `Jackett.Binaries.Mono.tar.gz` release from the [releases page](https://github.com/Jackett/Jackett/releases) and run Jackett using mono with the command `mono --debug JackettConsole.exe`.
## Installation using Docker
Detailed instructions are available at [LinuxServer.io Jackett Docker](https://hub.docker.com/r/linuxserver/jackett/). The Jackett Docker is highly recommended, especially if you are having Mono stability issues or having issues running Mono on your system eg. QNAP, Synology. Thanks to [LinuxServer.io](https://linuxserver.io)
## Installation on Synology
Jackett is available as beta package from [SynoCommunity](https://synocommunity.com/)
## Running Jackett behind a reverse proxy
When running jackett behind a reverse proxy make sure that the original hostname of the request is passed to Jackett. If HTTPS is used also set the X-Forwarded-Proto header to "https". Don't forget to adjust the "Base Path Override" Jackett option accordingly.
Example config for apache:
```
<Location /jackett>
ProxyPreserveHost On
RequestHeader set X-Forwarded-Proto expr=%{REQUEST_SCHEME}
ProxyPass http://127.0.0.1:9117
ProxyPassReverse http://127.0.0.1:9117
</Location>
```
## Troubleshooting
* __Command line switches__
You can pass various options when running via the command line, see --help for details.
* __Error "The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel."__
This is often caused by missing CA certificates.
Try reimporting the certificates in this case:
- On Linux (as user root): `wget -O - https://curl.haxx.se/ca/cacert.pem | cert-sync /dev/stdin`
- On macOS: `curl -sS https://curl.haxx.se/ca/cacert.pem | cert-sync --user /dev/stdin`
* __Enable enhanced logging__
You can get *enhanced* logging with the command line switches `-t -l` or by enabling `Enhanced logging` via the web interface (followed by clicking on the `Apply Server Settings` button).
Please post logs if you are unable to resolve your issue with these switches ensuring to remove your username/password/cookies.
The logfiles (log.txt/updater.txt) are stored in `%ProgramData%\Jackett` on Windows and `~/.config/Jackett/` on Linux/macOS.
## Configuring OMDb
This feature is used as a fallback to get the movie/series title if only the IMDB ID is provided in the request.
To use it, please just request a free API key on [OMDb](http://www.omdbapi.com/apikey.aspx) (1,000 daily requests limit) and paste the key in Jackett
## Creating an issue
Please supply as much information about the problem you are experiencing as possible. Your issue has a much greater chance of being resolved if logs are supplied so that we can see what is going on. Creating an issue with '### isn't working' doesn't help anyone to fix the problem.
## Contributing
All contributions are welcome just send a pull request. Jackett's framework allows our team (and any other volunteering dev) to implement new trackers in an hour or two. If you'd like support for a new tracker but are not a developer then feel free to leave a request on the [issues page](https://github.com/Jackett/Jackett/issues). It is recommended to use Visual Studio 2017 when making code changes in this project. You can download the community version for free [here](https://www.visualstudio.com/downloads/).
## Building from source
### Windows
* Install the .NET Core [SDK](https://www.microsoft.com/net/download/windows)
* Open the Jackett solution in Visual Studio 2017 (version 15.7 or above)
* Right click on the Jackett solution and click 'Rebuild Solution' to restore nuget packages
* Select Jackett.Console as startup project
* Build/Start the project
### Linux
```bash
sudo apt install mono-complete nuget msbuild # install build tools (debian/ubuntu)
git clone https://github.com/Jackett/Jackett.git
cd Jackett/src
nuget restore Jackett.sln # prepare dependencies
msbuild Jackett.Console/Jackett.Console.csproj /t:Build /p:Configuration=Debug # compile
mono Jackett.Console/bin/Debug/JackettConsole.exe # run jackett
```
## Screenshots
![screenshot](https://i.imgur.com/0d1nl7g.png "screenshot")
[inviteneeded]: https://raw.githubusercontent.com/Jackett/Jackett/master/.github/label-inviteneeded.png
## Jackett
#### Download
Downloads on the [Releases page](https://github.com/zone117x/Jackett/releases)
#### Overview
This software creates a [Torznab](https://github.com/Sonarr/Sonarr/wiki/Implementing-a-Torznab-indexer) (with [nZEDb](https://github.com/nZEDb/nZEDb/blob/master/docs/newznab_api_specification.txt) category numbering) and [TorrentPotato](https://github.com/RuudBurger/CouchPotatoServer/wiki/Couchpotato-torrent-provider) API server on your machine. Torznab enables software such as [Sonarr](https://sonarr.tv) to access data from your favorite indexers in a similar fashion to rss but with added features such as searching. TorrentPotato is an interface accessible to [CouchPotato](https://couchpota.to/).
Jackett works as a proxy server: it translates queries from apps (Sonarr, SickRage, CouchPotato, Mylar, etc) into tracker-site-specific http queries, parses the html response, then sends results back to the requesting software. This allows for getting recent uploads (like RSS) and performing searches. Jackett is a single repository of maintained indexer scraping & translation logic - removing the burden from other apps.
We were previously focused on TV but are working on extending searches to allow for searching other items such as movies, comics, and music.
#### Supported Systems
* Windows using .NET 4.5
* Linux and OSX using Mono 4 (v3 should work but you may experience crashes).
#### Supported Trackers
* [AlphaRatio](https://alpharatio.cc/)
* [AnimeBytes](https://animebytes.tv/)
* [AnimeTorrents](http://animetorrents.me/)
* [Avistaz](https://avistaz.to/)
* [BakaBT](http://bakabt.me/)
* [bB](http://reddit.com/r/baconbits)
* [BeyondHD](https://beyondhd.me/)
* [BIT-HDTV](https://www.bit-hdtv.com)
* [BitMeTV](http://www.bitmetv.org/)
* [Demonoid](http://www.demonoid.pw/)
* [EuTorrents](https://eutorrents.to/)
* [FileList](http://filelist.ro/)
* [FrenchTorrentDb](http://www.frenchtorrentdb.com/)
* [Freshon](https://freshon.tv/)
* [HD-Space](https://hd-space.org/)
* [HD-Torrents.org](https://hd-torrents.org/)
* [Immortalseed.me](http://immortalseed.me)
* [IPTorrents](https://iptorrents.com/)
* [MoreThan.tv](https://morethan.tv/)
* [NextGen](https://nxtgn.org/)
* [pretome](https://pretome.info)
* [PrivateHD](https://privatehd.to/)
* [RARGB](https://rarbg.to/)
* [RuTor](http://rutor.org/)
* [SceneAccess](https://sceneaccess.eu/login)
* [SceneTime](https://www.scenetime.com/)
* [ShowRSS](https://showrss.info/)
* [Strike](https://getstrike.net/)
* [T411](http://www.t411.io/)
* [The Pirate Bay](https://thepiratebay.se/)
* [TorrentBytes](https://www.torrentbytes.net/)
* [TorrentDay](https://torrentday.eu/)
* [TorrentLeech](http://www.torrentleech.org/)
* [TorrentShack](http://torrentshack.me/)
* [Torrentz](https://torrentz.eu/)
* [TV Chaos UK](https://tvchaosuk.com/)
#### Installation on Windows
Grab the latest release from the [website](http://jackett.net/Download).
We recommend you install Jackett as a Windows service using the supplied installer. When installed as a service the tray icon acts as a way to open/start/stop Jackett. If you opted to not install it as a service then Jackett will run its web server from the tray tool.
Jackett can also be run from the command line using JackettConsole.exe if you would like to see log messages (Ensure the server isn't already running from the tray/service).
#### Installation on Linux/OSX
1. Install [Mono 4](http://www.mono-project.com/download/) or better
2. Install libcurl:
* Debian/Ubunutu: apt-get install libcurl-dev
* Redhat/Fedora: yum install libcurl-devel
* For other distros see the [Curl docs](http://curl.haxx.se/dlwiz/?type=devel).
3. Download and extract the latest ```.tar.bz2``` release from the [website](http://jackett.net/Download) and run Jackett using mono with the command "mono JackettConsole.exe".
#### Installation on Synology
1. Install Sonarr & Mono 3.10 from synocommunity.
2. Install Mono beta 3.12 from the main Synology repo (Or newer if available).
3. Download jackett and place it in /opt/Jackett
4. cd /opt
5. chown -R {user who will run jackett} Jackett
6. Copy Upstart.config to /etc/init/jackett.conf and replace the braces {} in the script with the username that you wish to run Jackett with.
9. From anywhere on command line type "start jackett" . You should see output telling you that Jackett is running and you should be able to browse to {IP Address}:9117 . If not you should check /var/log/upstart/jackett.log and see what that says.
#### Troubleshooting
* Command line switches
You can pass various options when running via the command line, see --help for details.
* Unable to connect to certain trackers on Linux
Try running with the "--SSLFix true" if you are on Redhat/Fedora/NNS based libcurl. If the tracker is currently configured try removing it and adding it again. Alternatively try running with a different client via --UseClient (Warning: safecurl just executes curl and your details may be seen from the process list).
* Enable logging
You can get additional logging with the switches "-t -l". Please post logs if you are unable to resolve your issue with these switches ensuring to remove your username/password/cookies.
### Additional Trackers
Jackett's framework allows our team (and any other volunteering dev) to implement new trackers in an hour or two. If you'd like support for a new tracker then feel free to leave a request on the [issues page](https://github.com/zone117x/Jackett/issues) or contact us on IRC (see below). Pull requests must be made to the develop branch.
### Contact & Support
Use the github issues pages or talk to us directly at: [irc.freenode.net#jackett](http://webchat.freenode.net/?channels=#jackett).
### Screenshots
![screenshot](http://i.imgur.com/t1sVva6.png "screenshot")

View File

@@ -1,40 +0,0 @@
version: 0.9.{build}
skip_tags: true
image: Visual Studio 2017
configuration: Release
assembly_info:
patch: true
file: '**\AssemblyInfo.*'
assembly_version: '{version}'
assembly_file_version: '{version}'
assembly_informational_version: '{version}'
dotnet_csproj:
patch: true
file: '**\*.csproj'
version: '{version}'
package_version: '{version}'
assembly_version: '{version}'
file_version: '{version}'
informational_version: '{version}'
build_script:
- ps: .\build.ps1
test: off
before_deploy:
- ps: ${env:release_description} = ( Get-Content -LiteralPath BuildOutput/ReleaseNotes.txt -Encoding UTF8 ) -join "`n";
deploy:
- provider: GitHub
tag: v$(appveyor_build_version)
description: $(release_description)
auth_token:
secure: hOg+16YTIbq4kO9u4D1YVOTbWDqgCX6mAQYMbnmBBSw2CiUsZh7OKbupoUb3FtWa
artifact: /^(?:(?![Ee]xperimental).)*$/
draft: true
on:
branch: master
notifications:
- provider: Webhook
url: https://skyhook.glitch.me/api/webhooks/346588605843767297/_VWi5abKliaWsBmQO7AX69tD28FhqSLjKyLBwkSwwT13uyWJQHx5TSWK_iAs-0RzmyvZ/appveyor
method: POST
on_build_success: true
on_build_failure: true
on_build_status_changed: true

View File

@@ -1,381 +0,0 @@
#tool nuget:?package=NUnit.ConsoleRunner
#addin nuget:?package=Cake.Git
//////////////////////////////////////////////////////////////////////
// ARGUMENTS
//////////////////////////////////////////////////////////////////////
var target = Argument("target", "Default");
var configuration = Argument("configuration", "Debug");
//////////////////////////////////////////////////////////////////////
// PREPARATION
//////////////////////////////////////////////////////////////////////
// Define directories.
var workingDir = MakeAbsolute(Directory("./"));
var artifactsDirName = "Artifacts";
var testResultsDirName = "TestResults";
var windowsBuildFullFramework = "./BuildOutput/FullFramework/Windows";
var monoBuildFullFramework = "./BuildOutput/FullFramework/Mono";
//////////////////////////////////////////////////////////////////////
// TASKS
//////////////////////////////////////////////////////////////////////
Task("Info")
.Does(() =>
{
Information(@"Jackett Cake build script starting...");
Information(@"Requires InnoSetup and C:\cygwin to be present for packaging (Pre-installed on AppVeyor)");
Information(@"Working directory is: " + workingDir);
});
Task("Clean")
.IsDependentOn("Info")
.Does(() =>
{
CleanDirectories("./src/**/obj");
CleanDirectories("./src/**/bin");
CleanDirectories("./BuildOutput");
CleanDirectories("./" + artifactsDirName);
CleanDirectories("./" + testResultsDirName);
Information("Clean completed");
});
Task("Restore-NuGet-Packages")
.IsDependentOn("Clean")
.Does(() =>
{
NuGetRestore("./src/Jackett.sln");
});
Task("Build")
.IsDependentOn("Restore-NuGet-Packages")
.Does(() =>
{
var buildSettings = new MSBuildSettings()
.SetConfiguration(configuration)
.UseToolVersion(MSBuildToolVersion.VS2017);
MSBuild("./src/Jackett.sln", buildSettings);
});
Task("Run-Unit-Tests")
.IsDependentOn("Build")
.Does(() =>
{
CreateDirectory("./" + testResultsDirName);
var resultsFile = $"./{testResultsDirName}/JackettTestResult.xml";
NUnit3("./src/**/bin/" + configuration + "/**/*.Test.dll", new NUnit3Settings
{
Results = new[] { new NUnit3Result { FileName = resultsFile } }
});
if(AppVeyor.IsRunningOnAppVeyor)
{
AppVeyor.UploadTestResults(resultsFile, AppVeyorTestResultsType.NUnit3);
}
});
Task("Copy-Files-Full-Framework")
.IsDependentOn("Run-Unit-Tests")
.Does(() =>
{
var windowsOutput = windowsBuildFullFramework + "/Jackett";
CopyDirectory("./src/Jackett.Console/bin/" + configuration, windowsOutput);
CopyFiles("./src/Jackett.Updater/bin/" + configuration + "/net452" + "/JackettUpdater.*", windowsOutput); //builds against multiple frameworks
CopyFiles("./Upstart.config", windowsOutput);
CopyFiles("./LICENSE", windowsOutput);
CopyFiles("./README.md", windowsOutput);
var monoOutput = monoBuildFullFramework + "/Jackett";
CopyDirectory(windowsBuildFullFramework, monoBuildFullFramework);
DeleteFiles(monoOutput + "/JackettService.*");
DeleteFiles(monoOutput + "/JackettTray.*");
Information("Full framework file copy completed");
});
Task("Check-Packaging-Platform")
.IsDependentOn("Copy-Files-Full-Framework")
.Does(() =>
{
if (IsRunningOnWindows())
{
CreateDirectory("./" + artifactsDirName);
Information("Platform is Windows");
}
else
{
throw new Exception("Packaging is currently only implemented for a Windows environment");
}
});
Task("Package-Files-Full-Framework-Mono")
.IsDependentOn("Check-Packaging-Platform")
.Does(() =>
{
Gzip(monoBuildFullFramework, $"./{artifactsDirName}", "Jackett", "Jackett.Binaries.Mono.tar.gz");
Information(@"Full Framework Mono Binaries Gzip Completed");
});
Task("Package-Full-Framework")
.IsDependentOn("Package-Files-Full-Framework-Mono")
.Does(() =>
{
Information("Full Framework Packaging Completed");
});
Task("Kestrel-Full-Framework")
.IsDependentOn("Package-Full-Framework")
.Does(() =>
{
CleanDirectories("./src/**/obj");
CleanDirectories("./src/**/bin");
NuGetRestore("./src/Jackett.sln");
var buildSettings = new MSBuildSettings()
.SetConfiguration(configuration)
.UseToolVersion(MSBuildToolVersion.VS2017);
MSBuild("./src/Jackett.sln", buildSettings);
});
Task("Experimental-Kestrel-Windows-Full-Framework")
.IsDependentOn("Kestrel-Full-Framework")
.Does(() =>
{
string serverProjectPath = "./src/Jackett.Server/Jackett.Server.csproj";
string buildOutputPath = "./BuildOutput/Experimental/net461/win7-x86/Jackett";
DotNetCorePublish(serverProjectPath, "net461", "win7-x86");
CopyFiles("./src/Jackett.Service/bin/" + configuration + "/JackettService.*", buildOutputPath);
CopyFiles("./src/Jackett.Tray/bin/" + configuration + "/JackettTray.*", buildOutputPath);
CopyFiles("./src/Jackett.Updater/bin/" + configuration + "/net461" + "/JackettUpdater.*", buildOutputPath); //builds against multiple frameworks
Zip("./BuildOutput/Experimental/net461/win7-x86", $"./{artifactsDirName}/Jackett.Binaries.Windows.zip");
//InnoSetup
string sourceFolder = MakeAbsolute(Directory(buildOutputPath)).ToString();
InnoSetupSettings settings = new InnoSetupSettings();
settings.OutputDirectory = workingDir + "/" + artifactsDirName;
settings.Defines = new Dictionary<string, string>
{
{ "MyFileForVersion", sourceFolder + "/Jackett.Common.dll" },
{ "MySourceFolder", sourceFolder },
{ "MyOutputFilename", "Jackett.Installer.Windows" },
};
InnoSetup("./Installer.iss", settings);
});
Task("Experimental-Kestrel-Mono-Full-Framework")
.IsDependentOn("Kestrel-Full-Framework")
.Does(() =>
{
string serverProjectPath = "./src/Jackett.Server/Jackett.Server.csproj";
string buildOutputPath = "./BuildOutput/Experimental/net461/linux-x64/Jackett";
DotNetCorePublish(serverProjectPath, "net461", "linux-x64");
CopyFiles("./src/Jackett.Updater/bin/" + configuration + "/net461" + "/JackettUpdater.*", buildOutputPath); //builds against multiple frameworks
//There is an issue with Mono 5.8 (fixed in Mono 5.12) where its expecting to use its own patched version of System.Net.Http.dll, instead of the version supplied in folder
//https://github.com/dotnet/corefx/issues/19914
//https://bugzilla.xamarin.com/show_bug.cgi?id=60315
//The workaround is to delete System.Net.Http.dll and patch the .exe.config file
DeleteFile(buildOutputPath + "/System.Net.Http.dll");
var configFile = File(buildOutputPath + "/JackettConsole.exe.config");
XmlPoke(configFile, "configuration/runtime/*[name()='assemblyBinding']/*[name()='dependentAssembly']/*[name()='assemblyIdentity'][@name='System.Net.Http']/../*[name()='bindingRedirect']/@newVersion", "4.0.0.0");
Gzip("./BuildOutput/Experimental/net461/linux-x64", $"./{artifactsDirName}", "Jackett", "Experimental.Jackett.Binaries.Mono.tar.gz");
});
Task("Experimental-DotNetCore")
.IsDependentOn("Kestrel-Full-Framework")
.Does(() =>
{
string serverProjectPath = "./src/Jackett.Server/Jackett.Server.csproj";
DotNetCorePublish(serverProjectPath, "netcoreapp2.1", "win-x86");
DotNetCorePublish(serverProjectPath, "netcoreapp2.1", "linux-x64");
DotNetCorePublish(serverProjectPath, "netcoreapp2.1", "osx-x64");
Zip("./BuildOutput/Experimental/netcoreapp2.1/win-x86", $"./{artifactsDirName}/Experimental.netcoreapp.win-x86.zip");
Zip("./BuildOutput/Experimental/netcoreapp2.1/osx-x64", $"./{artifactsDirName}/Experimental.netcoreapp.osx-x64.zip");
Gzip("./BuildOutput/Experimental/netcoreapp2.1/linux-x64", $"./{artifactsDirName}", "Jackett", "Experimental.netcoreapp.linux-x64.tar.gz");
});
Task("Experimental")
.IsDependentOn("Experimental-Kestrel-Windows-Full-Framework")
.IsDependentOn("Experimental-Kestrel-Mono-Full-Framework")
//.IsDependentOn("Experimental-DotNetCore")
.Does(() =>
{
Information("Experimental builds completed");
});
Task("Appveyor-Push-Artifacts")
.IsDependentOn("Package-Full-Framework")
.IsDependentOn("Experimental")
.Does(() =>
{
if (AppVeyor.IsRunningOnAppVeyor)
{
foreach (var file in GetFiles(workingDir + $"/{artifactsDirName}/*"))
{
AppVeyor.UploadArtifact(file.FullPath);
}
}
else
{
Information(@"Skipping as not running in AppVeyor Environment");
}
});
Task("Release-Notes")
.IsDependentOn("Appveyor-Push-Artifacts")
.Does(() =>
{
string latestTag = GitDescribe(".", false, GitDescribeStrategy.Tags, 0);
Information($"Latest tag is: {latestTag}" + Environment.NewLine);
List<GitCommit> relevantCommits = new List<GitCommit>();
var commitCollection = GitLog("./", 50);
foreach(GitCommit commit in commitCollection)
{
var commitTag = GitDescribe(".", commit.Sha, false, GitDescribeStrategy.Tags, 0);
if (commitTag == latestTag)
{
relevantCommits.Add(commit);
}
else
{
break;
}
}
relevantCommits = relevantCommits.AsEnumerable().Reverse().Skip(1).ToList();
if (relevantCommits.Count() > 0)
{
List<string> notesList = new List<string>();
foreach(GitCommit commit in relevantCommits)
{
notesList.Add($"{commit.MessageShort} (Thank you @{commit.Author.Name})");
}
string buildNote = String.Join(Environment.NewLine, notesList);
Information(buildNote);
System.IO.File.WriteAllLines(workingDir + "\\BuildOutput\\ReleaseNotes.txt", notesList.ToArray());
}
else
{
Information($"No commit messages found to create release notes");
}
});
private void RunCygwinCommand(string utility, string utilityArguments)
{
var cygwinDir = @"C:\cygwin\bin\";
var utilityProcess = cygwinDir + utility + ".exe";
Information("CygWin Utility: " + utility);
Information("CygWin Directory: " + cygwinDir);
Information("Utility Location: " + utilityProcess);
Information("Utility Arguments: " + utilityArguments);
IEnumerable<string> redirectedStandardOutput;
IEnumerable<string> redirectedErrorOutput;
var exitCodeWithArgument =
StartProcess(
utilityProcess,
new ProcessSettings {
Arguments = utilityArguments,
WorkingDirectory = cygwinDir,
RedirectStandardOutput = true
},
out redirectedStandardOutput,
out redirectedErrorOutput
);
Information(utility + " output:" + Environment.NewLine + string.Join(Environment.NewLine, redirectedStandardOutput.ToArray()));
// Throw exception if anything was written to the standard error.
if (redirectedErrorOutput != null && redirectedErrorOutput.Any())
{
throw new Exception(
string.Format(
utility + " Errors ocurred: {0}",
string.Join(", ", redirectedErrorOutput)));
}
Information(utility + " Exit code: {0}", exitCodeWithArgument);
}
private string RelativeWinPathToCygPath(string relativePath)
{
var cygdriveBase = "/cygdrive/" + workingDir.ToString().Replace(":", "").Replace("\\", "/");
var cygPath = cygdriveBase + relativePath.TrimStart('.');
return cygPath;
}
private void Gzip(string sourceFolder, string outputDirectory, string tarCdirectoryOption, string outputFileName)
{
var cygSourcePath = RelativeWinPathToCygPath(sourceFolder);
var tarFileName = outputFileName.Remove(outputFileName.Length - 3, 3);
var tarArguments = @"-cvf " + cygSourcePath + "/" + tarFileName + " -C " + cygSourcePath + $" {tarCdirectoryOption} --mode ='755'";
var gzipArguments = @"-k " + cygSourcePath + "/" + tarFileName;
RunCygwinCommand("Tar", tarArguments);
RunCygwinCommand("Gzip", gzipArguments);
MoveFile($"{sourceFolder}/{tarFileName}.gz", $"{outputDirectory}/{tarFileName}.gz");
}
private void DotNetCorePublish(string projectPath, string framework, string runtime)
{
var settings = new DotNetCorePublishSettings
{
Framework = framework,
Runtime = runtime,
OutputDirectory = $"./BuildOutput/Experimental/{framework}/{runtime}/Jackett"
};
DotNetCorePublish(projectPath, settings);
}
//////////////////////////////////////////////////////////////////////
// TASK TARGETS
//////////////////////////////////////////////////////////////////////
Task("Default")
.IsDependentOn("Release-Notes")
.Does(() =>
{
Information("Default Task Completed");
});
//////////////////////////////////////////////////////////////////////
// EXECUTION
//////////////////////////////////////////////////////////////////////
RunTarget(target);

235
build.ps1
View File

@@ -1,235 +0,0 @@
##########################################################################
# This is the Cake bootstrapper script for PowerShell.
# This file was downloaded from https://github.com/cake-build/resources
# Feel free to change this file to fit your needs.
##########################################################################
<#
.SYNOPSIS
This is a Powershell script to bootstrap a Cake build.
.DESCRIPTION
This Powershell script will download NuGet if missing, restore NuGet tools (including Cake)
and execute your Cake build script with the parameters you provide.
.PARAMETER Script
The build script to execute.
.PARAMETER Target
The build script target to run.
.PARAMETER Configuration
The build configuration to use.
.PARAMETER Verbosity
Specifies the amount of information to be displayed.
.PARAMETER ShowDescription
Shows description about tasks.
.PARAMETER DryRun
Performs a dry run.
.PARAMETER Experimental
Uses the nightly builds of the Roslyn script engine.
.PARAMETER Mono
Uses the Mono Compiler rather than the Roslyn script engine.
.PARAMETER SkipToolPackageRestore
Skips restoring of packages.
.PARAMETER ScriptArgs
Remaining arguments are added here.
.LINK
https://cakebuild.net
#>
[CmdletBinding()]
Param(
[string]$Script = "build.cake",
[string]$Target,
[string]$Configuration,
[ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")]
[string]$Verbosity,
[switch]$ShowDescription,
[Alias("WhatIf", "Noop")]
[switch]$DryRun,
[switch]$Experimental,
[switch]$Mono,
[switch]$SkipToolPackageRestore,
[Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)]
[string[]]$ScriptArgs
)
[Reflection.Assembly]::LoadWithPartialName("System.Security") | Out-Null
function MD5HashFile([string] $filePath)
{
if ([string]::IsNullOrEmpty($filePath) -or !(Test-Path $filePath -PathType Leaf))
{
return $null
}
[System.IO.Stream] $file = $null;
[System.Security.Cryptography.MD5] $md5 = $null;
try
{
$md5 = [System.Security.Cryptography.MD5]::Create()
$file = [System.IO.File]::OpenRead($filePath)
return [System.BitConverter]::ToString($md5.ComputeHash($file))
}
finally
{
if ($file -ne $null)
{
$file.Dispose()
}
}
}
function GetProxyEnabledWebClient
{
$wc = New-Object System.Net.WebClient
$proxy = [System.Net.WebRequest]::GetSystemWebProxy()
$proxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials
$wc.Proxy = $proxy
return $wc
}
Write-Host "Preparing to run build script..."
if(!$PSScriptRoot){
$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
}
$TOOLS_DIR = Join-Path $PSScriptRoot "tools"
$ADDINS_DIR = Join-Path $TOOLS_DIR "Addins"
$MODULES_DIR = Join-Path $TOOLS_DIR "Modules"
$NUGET_EXE = Join-Path $TOOLS_DIR "nuget.exe"
$CAKE_EXE = Join-Path $TOOLS_DIR "Cake/Cake.exe"
$NUGET_URL = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"
$PACKAGES_CONFIG = Join-Path $TOOLS_DIR "packages.config"
$PACKAGES_CONFIG_MD5 = Join-Path $TOOLS_DIR "packages.config.md5sum"
$ADDINS_PACKAGES_CONFIG = Join-Path $ADDINS_DIR "packages.config"
$MODULES_PACKAGES_CONFIG = Join-Path $MODULES_DIR "packages.config"
# Make sure tools folder exists
if ((Test-Path $PSScriptRoot) -and !(Test-Path $TOOLS_DIR)) {
Write-Verbose -Message "Creating tools directory..."
New-Item -Path $TOOLS_DIR -Type directory | out-null
}
# Make sure that packages.config exist.
if (!(Test-Path $PACKAGES_CONFIG)) {
Write-Verbose -Message "Downloading packages.config..."
try {
$wc = GetProxyEnabledWebClient
$wc.DownloadFile("https://cakebuild.net/download/bootstrapper/packages", $PACKAGES_CONFIG) } catch {
Throw "Could not download packages.config."
}
}
# Try find NuGet.exe in path if not exists
if (!(Test-Path $NUGET_EXE)) {
Write-Verbose -Message "Trying to find nuget.exe in PATH..."
$existingPaths = $Env:Path -Split ';' | Where-Object { (![string]::IsNullOrEmpty($_)) -and (Test-Path $_ -PathType Container) }
$NUGET_EXE_IN_PATH = Get-ChildItem -Path $existingPaths -Filter "nuget.exe" | Select -First 1
if ($NUGET_EXE_IN_PATH -ne $null -and (Test-Path $NUGET_EXE_IN_PATH.FullName)) {
Write-Verbose -Message "Found in PATH at $($NUGET_EXE_IN_PATH.FullName)."
$NUGET_EXE = $NUGET_EXE_IN_PATH.FullName
}
}
# Try download NuGet.exe if not exists
if (!(Test-Path $NUGET_EXE)) {
Write-Verbose -Message "Downloading NuGet.exe..."
try {
$wc = GetProxyEnabledWebClient
$wc.DownloadFile($NUGET_URL, $NUGET_EXE)
} catch {
Throw "Could not download NuGet.exe."
}
}
# Save nuget.exe path to environment to be available to child processed
$ENV:NUGET_EXE = $NUGET_EXE
# Restore tools from NuGet?
if(-Not $SkipToolPackageRestore.IsPresent) {
Push-Location
Set-Location $TOOLS_DIR
# Check for changes in packages.config and remove installed tools if true.
[string] $md5Hash = MD5HashFile($PACKAGES_CONFIG)
if((!(Test-Path $PACKAGES_CONFIG_MD5)) -Or
($md5Hash -ne (Get-Content $PACKAGES_CONFIG_MD5 ))) {
Write-Verbose -Message "Missing or changed package.config hash..."
Get-ChildItem -Exclude packages.config,nuget.exe,Cake.Bakery |
Remove-Item -Recurse
}
Write-Verbose -Message "Restoring tools from NuGet..."
$NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$TOOLS_DIR`""
if ($LASTEXITCODE -ne 0) {
Throw "An error occurred while restoring NuGet tools."
}
else
{
$md5Hash | Out-File $PACKAGES_CONFIG_MD5 -Encoding "ASCII"
}
Write-Verbose -Message ($NuGetOutput | out-string)
Pop-Location
}
# Restore addins from NuGet
if (Test-Path $ADDINS_PACKAGES_CONFIG) {
Push-Location
Set-Location $ADDINS_DIR
Write-Verbose -Message "Restoring addins from NuGet..."
$NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$ADDINS_DIR`""
if ($LASTEXITCODE -ne 0) {
Throw "An error occurred while restoring NuGet addins."
}
Write-Verbose -Message ($NuGetOutput | out-string)
Pop-Location
}
# Restore modules from NuGet
if (Test-Path $MODULES_PACKAGES_CONFIG) {
Push-Location
Set-Location $MODULES_DIR
Write-Verbose -Message "Restoring modules from NuGet..."
$NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$MODULES_DIR`""
if ($LASTEXITCODE -ne 0) {
Throw "An error occurred while restoring NuGet modules."
}
Write-Verbose -Message ($NuGetOutput | out-string)
Pop-Location
}
# Make sure that Cake has been installed.
if (!(Test-Path $CAKE_EXE)) {
Throw "Could not find Cake.exe at $CAKE_EXE"
}
# Build Cake arguments
$cakeArguments = @("$Script");
if ($Target) { $cakeArguments += "-target=$Target" }
if ($Configuration) { $cakeArguments += "-configuration=$Configuration" }
if ($Verbosity) { $cakeArguments += "-verbosity=$Verbosity" }
if ($ShowDescription) { $cakeArguments += "-showdescription" }
if ($DryRun) { $cakeArguments += "-dryrun" }
if ($Experimental) { $cakeArguments += "-experimental" }
if ($Mono) { $cakeArguments += "-mono" }
$cakeArguments += $ScriptArgs
# Start Cake
Write-Host "Running build script..."
&$CAKE_EXE $cakeArguments
exit $LASTEXITCODE

View File

@@ -1,8 +1,7 @@
using System;
using System.Runtime.InteropServices;
using CurlSharp.Enums;
namespace CurlSharp.Callbacks
namespace CurlSharp
{
/// <summary>
/// Called when cURL has debug information for the client.
@@ -27,16 +26,12 @@ namespace CurlSharp.Callbacks
/// <description>Debug information as a string.</description>
/// </item>
/// <item>
/// <term>size</term>
/// <description>The size in bytes.</description>
/// </item>
/// <item>
/// <term>extraData</term>
/// <description>Client-provided extra data.</description>
/// </item>
/// </list>
/// </remarks>
public delegate void CurlDebugCallback(CurlInfoType infoType, String message, int size, Object extraData);
public delegate void CurlDebugCallback(CurlInfoType infoType, String message, Object extraData);
/// <summary>
/// Called when cURL has header data for the client.

View File

@@ -1,7 +1,6 @@
using System;
using CurlSharp.Enums;
namespace CurlSharp.Callbacks
namespace CurlSharp
{
/// <summary>
/// Called when <c>cURL</c> wants to lock a shared resource.

View File

@@ -2,7 +2,7 @@
*
* CurlS#arp
*
* Copyright (c) 2013-2017 Dr. Masroor Ehsan (masroore@gmail.com)
* Copyright (c) 2013 Dr. Masroor Ehsan (masroore@gmail.com)
* Portions copyright (c) 2004, 2005 Jeff Phillips (jeff@jeffp.net)
*
* This software is licensed as described in the file LICENSE, which you
@@ -19,7 +19,6 @@
using System;
using System.Runtime.InteropServices;
using CurlSharp.Enums;
namespace CurlSharp
{
@@ -73,7 +72,7 @@ namespace CurlSharp
/// </returns>
public static CurlCode GlobalInit(CurlInitFlag flags)
{
_initCode = NativeMethods.curl_global_init((int) flags);
_initCode = NativeMethods.curl_global_init((int)flags);
#if USE_LIBCURLSHIM
if (_initCode == CurlCode.Ok)
NativeMethods.curl_shim_initialize();
@@ -100,6 +99,48 @@ namespace CurlSharp
}
}
/// <summary>
/// URL encode a String.
/// </summary>
/// <param name="url">The string to URL encode.</param>
/// <param name="length">
/// Input string length;
/// use 0 for cURL to determine.
/// </param>
/// <returns>A new URL encoded string.</returns>
/// <exception cref="System.InvalidOperationException">
/// Thrown if cURL isn't properly initialized.
/// </exception>
public static string Escape(string url, int length)
{
EnsureCurl();
var p = NativeMethods.curl_escape(url, length);
var s = Marshal.PtrToStringAnsi(p);
NativeMethods.curl_free(p);
return s;
}
/// <summary>
/// URL decode a String.
/// </summary>
/// <param name="url">The string to URL decode.</param>
/// <param name="length">
/// Input string length;
/// use 0 for cURL to determine.
/// </param>
/// <returns>A new URL decoded string.</returns>
/// <exception cref="System.InvalidOperationException">
/// Thrown if cURL isn't properly initialized.
/// </exception>
public static string Unescape(string url, int length)
{
EnsureCurl();
var p = NativeMethods.curl_unescape(url, length);
var s = Marshal.PtrToStringAnsi(p);
NativeMethods.curl_free(p);
return s;
}
/// <summary>
/// Get a <see cref="CurlVersionInfoData" /> object.
/// </summary>

View File

@@ -2,7 +2,7 @@
*
* CurlS#arp
*
* Copyright (c) 2013-2017 Dr. Masroor Ehsan (masroore@gmail.com)
* Copyright (c) 2014 Dr. Masroor Ehsan (masroore@gmail.com)
* Portions copyright (c) 2004, 2005 Jeff Phillips (jeff@jeffp.net)
*
* This software is licensed as described in the file LICENSE, which you
@@ -19,8 +19,6 @@
using System;
using System.Runtime.InteropServices;
using CurlSharp.Callbacks;
using CurlSharp.Enums;
namespace CurlSharp
{
@@ -58,7 +56,7 @@ namespace CurlSharp
private bool _cookieSession;
private CurlShare _curlShare;
private string _customRequest;
private object _debugData;
private Object _debugData;
private int _dnsCacheTimeout;
private bool _dnsUseGlobalCache;
private string _egdSocket;
@@ -81,7 +79,7 @@ namespace CurlSharp
private bool _ftpUseEprt;
private bool _ftpUseEpsv;
private GCHandle _hThis;
private object _headerData;
private Object _headerData;
private CurlHttpAuth _httpAuth;
private bool _httpGet;
private CurlHttpMultiPartForm _httpMultiPartForm;
@@ -90,8 +88,10 @@ namespace CurlSharp
private bool _ignoreContentLength;
private long _infileSize;
private string _interface;
private object _ioctlData;
private Object _ioctlData;
private string _krb4Level;
private CurlCode _lastErrorCode;
private string _lastErrorDescription;
private int _lowSpeedLimit;
private int _lowSpeedTime;
private int _maxConnects;
@@ -118,7 +118,6 @@ namespace CurlSharp
private NativeMethods._CurlDebugCallback _pcbDebug;
private NativeMethods._CurlIoctlCallback _pcbIoctl;
private NativeMethods._CurlProgressCallback _pcbProgress;
private NativeMethods._CurlSslCtxCallback _pcbSslCtx;
#endif
private CurlDebugCallback _pfCurlDebug;
private CurlHeaderCallback _pfCurlHeader;
@@ -131,27 +130,27 @@ namespace CurlSharp
private bool _post;
private int _postFieldSize;
private string _postFields;
private object _progressData;
private Object _privateData;
private Object _progressData;
private string _proxy;
private int _proxyPort;
private string _proxyUserPwd;
private bool _put;
private string _randomFile;
private string _range;
private object _readData;
private Object _readData;
private string _referer;
private int _resumeFrom;
private string _sourceUrl;
private string _sslCert;
private string _sslCertPasswd;
private string _sslCipherList;
private object _sslContextData;
private Object _sslContextData;
private string _sslEngine;
private bool _sslEngineDefault;
private string _sslKey;
private string _sslKeyPasswd;
private bool _sslVerifyPeer;
private bool _sslVerifyHost;
private bool _tcpNoDelay;
private int _timeValue;
private int _timeout;
@@ -162,7 +161,7 @@ namespace CurlSharp
private string _userAgent;
private string _userPwd;
private bool _verbose;
private object _writeData;
private Object _writeData;
private string _writeInfo;
/// <summary>
@@ -181,7 +180,6 @@ namespace CurlSharp
Curl.EnsureCurl();
_pCurl = NativeMethods.curl_easy_init();
ensureHandle();
NativeMethods.curl_easy_setopt(_pCurl, CurlOption.NoSignal, 1L);
NativeMethods.curl_easy_setopt(_pCurl, CurlOption.NoProgress, IntPtr.Zero);
#if USE_LIBCURLSHIM
_pMyStrings = NativeMethods.curl_shim_alloc_strings();
@@ -201,7 +199,11 @@ namespace CurlSharp
installDelegates();
}
public object Private { get; set; }
public object Private
{
get { return _privateData; }
set { _privateData = value; }
}
public object WriteData
{
@@ -225,8 +227,6 @@ namespace CurlSharp
/// <returns></returns>
private CurlCode setWriteData(object data)
{
freeHandle(ref _curlWriteData);
_curlWriteData = getHandle(data);
return setCurlOpt(_curlWriteData, CurlOption.WriteData);
}
@@ -292,18 +292,6 @@ namespace CurlSharp
return setCurlOpt(_curlDebugData, CurlOption.DebugData);
}
private IntPtr _curlSslCtxData = IntPtr.Zero;
/// <summary>
/// Object to pass to OnSslCtxCallback.
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
private CurlCode setSslCtxData(object data)
{
_curlSslCtxData = getHandle(data);
return setCurlOpt(_curlSslCtxData, CurlOption.SslCtxData);
}
private IntPtr _curlIoctlData = IntPtr.Zero;
@@ -367,17 +355,6 @@ namespace CurlSharp
}
}
public object SslCtxData
{
get { return _sslContextData; }
set
{
_sslContextData = value;
#if !USE_LIBCURLSHIM
setSslCtxData(value);
#endif
}
}
public object IoctlData
{
@@ -449,7 +426,7 @@ namespace CurlSharp
_ftpAuth = value;
var l = Convert.ToInt32(value);
setLastError(NativeMethods.curl_easy_setopt(_pCurl, CurlOption.FtpSslAuth, (IntPtr) l),
CurlOption.FtpSslAuth);
CurlOption.FtpSslAuth);
}
}
@@ -461,7 +438,7 @@ namespace CurlSharp
_httpVersion = value;
var l = Convert.ToInt32(value);
setLastError(NativeMethods.curl_easy_setopt(_pCurl, CurlOption.HttpVersion, (IntPtr) l),
CurlOption.HttpVersion);
CurlOption.HttpVersion);
}
}
@@ -473,7 +450,7 @@ namespace CurlSharp
_httpAuth = value;
var l = Convert.ToInt32(value);
setLastError(NativeMethods.curl_easy_setopt(_pCurl, CurlOption.HttpAuth, (IntPtr) l),
CurlOption.HttpAuth);
CurlOption.HttpAuth);
}
}
@@ -485,7 +462,7 @@ namespace CurlSharp
_ftpSsl = value;
var l = Convert.ToInt32(value);
setLastError(NativeMethods.curl_easy_setopt(_pCurl, CurlOption.FtpSsl, (IntPtr) l),
CurlOption.FtpSsl);
CurlOption.FtpSsl);
}
}
@@ -497,7 +474,7 @@ namespace CurlSharp
_closePolicy = value;
var l = Convert.ToInt32(value);
setLastError(NativeMethods.curl_easy_setopt(_pCurl, CurlOption.ClosePolicy, (IntPtr) l),
CurlOption.ClosePolicy);
CurlOption.ClosePolicy);
}
}
@@ -537,13 +514,11 @@ namespace CurlSharp
set { setFunctionOptions(CurlOption.IoctlFunction, value); }
}
public CurlSslContextCallback SslContextFunction
{
get { return _pfCurlSslContext; }
set { setFunctionOptions(CurlOption.SslCtxFunction, value); }
}
public string LastErrorDescription { get; private set; }
public string LastErrorDescription
{
get { return _lastErrorDescription; }
}
public bool NoProgress
{
@@ -617,12 +592,6 @@ namespace CurlSharp
set { setBoolOption(CurlOption.SslVerifyPeer, ref _sslVerifyPeer, value); }
}
public bool SslVerifyhost
{
get { return _sslVerifyHost; }
set { setBoolOption(CurlOption.SslVerifyhost, ref _sslVerifyHost, value); }
}
public bool FreshConnect
{
get { return _freshConnect; }
@@ -1137,7 +1106,10 @@ namespace CurlSharp
get { return getSlistInfo(CurlInfo.SslEngines); }
}
public CurlCode LastErrorCode { get; private set; }
public CurlCode LastErrorCode
{
get { return _lastErrorCode; }
}
/// <summary>
/// Cleanup unmanaged resources.
@@ -1150,7 +1122,7 @@ namespace CurlSharp
private void resetPrivateVariables()
{
Private = null;
_privateData = null;
_pfCurlWrite = null;
_writeData = null;
@@ -1207,10 +1179,10 @@ namespace CurlSharp
/// </summary>
private void setLastError(CurlCode code, CurlOption opt)
{
if ((LastErrorCode == CurlCode.Ok) && (code != CurlCode.Ok))
if (LastErrorCode == CurlCode.Ok && code != CurlCode.Ok)
{
LastErrorCode = code;
LastErrorDescription = string.Format("Error: {0} setting option {1}", StrError(code), opt);
_lastErrorCode = code;
_lastErrorDescription = string.Format("Error: {0} setting option {1}", StrError(code), opt);
}
}
@@ -1219,10 +1191,10 @@ namespace CurlSharp
/// </summary>
private void setLastError(CurlCode code, CurlInfo info)
{
if ((LastErrorCode == CurlCode.Ok) && (code != CurlCode.Ok))
if (LastErrorCode == CurlCode.Ok && code != CurlCode.Ok)
{
LastErrorCode = code;
LastErrorDescription = string.Format("Error: {0} getting info {1}", StrError(code), info);
_lastErrorCode = code;
_lastErrorDescription = string.Format("Error: {0} getting info {1}", StrError(code), info);
}
}
@@ -1261,7 +1233,6 @@ namespace CurlSharp
freeHandle(ref _curlProgressData);
freeHandle(ref _curlHeaderData);
freeHandle(ref _curlIoctlData);
freeHandle(ref _curlSslCtxData);
#endif
NativeMethods.curl_easy_cleanup(_pCurl);
@@ -1322,12 +1293,6 @@ namespace CurlSharp
private void setStringOption(CurlOption option, out string field, string value)
{
// all string options are copied by the library, the only exception to this rule is PostFields option
if (option == CurlOption.PostFields)
option = CurlOption.CopyPostFields;
if ((option == CurlOption.CopyPostFields) && (PostFieldSize == 0))
PostFieldSize = System.Text.Encoding.UTF8.GetByteCount(value);
setStringOption(option, value);
field = value;
}
@@ -1348,13 +1313,7 @@ namespace CurlSharp
#else
// convert the string to a null-terminated one
var buffer = System.Text.Encoding.UTF8.GetBytes(value + "\0");
unsafe
{
fixed (byte* bufPtr = &buffer[0])
{
setLastError(NativeMethods.curl_easy_setopt(_pCurl, option, buffer), option);
}
}
setLastError(NativeMethods.curl_easy_setopt(_pCurl, option, buffer), option);
#endif
}
}
@@ -1378,7 +1337,7 @@ namespace CurlSharp
/// <see cref="CurlCode.BadFunctionArgument" />
/// will be returned if the type of value of <c>parameter</c> is invalid.
/// </returns>
public CurlCode SetOpt(CurlOption option, object parameter)
public CurlCode SetOpt(CurlOption option, Object parameter)
{
ensureHandle();
var retCode = CurlCode.Ok;
@@ -1387,8 +1346,10 @@ namespace CurlSharp
if ((int) option < CURLOPTTYPE_OBJECTPOINT)
{
var i = 0;
if ((option == CurlOption.DnsUseGlobalCache) || (option == CurlOption.SourcePort))
if (option == CurlOption.DnsUseGlobalCache || option == CurlOption.SourcePort)
{
return CurlCode.BadFunctionArgument;
}
if (option == CurlOption.TimeValue)
{
@@ -1404,17 +1365,17 @@ namespace CurlSharp
retCode = NativeMethods.curl_easy_setopt(_pCurl, option, (IntPtr) i);
}
// object cases: the majority
// object cases: the majority
else if ((int) option < CURLOPTTYPE_FUNCTIONPOINT)
{
return setObjectOptions(option, parameter);
}
// FUNCTIONPOINT args, for delegates
// FUNCTIONPOINT args, for delegates
else if ((int) option < CURLOPTTYPE_OFF_T)
{
return setFunctionOptions(option, parameter);
}
// otherwise, it's one of those 64-bit off_t guys!
// otherwise, it's one of those 64-bit off_t guys!
else
{
var i = Convert.ToInt64(parameter);
@@ -1429,9 +1390,9 @@ namespace CurlSharp
var retCode = CurlCode.Ok;
switch (option)
{
// various data items
// various data items
case CurlOption.Private:
Private = parameter;
_privateData = parameter;
break;
case CurlOption.WriteData:
_writeData = parameter;
@@ -1448,15 +1409,12 @@ namespace CurlSharp
case CurlOption.HeaderData:
_headerData = parameter;
break;
case CurlOption.SslCtxData:
_sslContextData = parameter;
break;
case CurlOption.IoctlData:
_ioctlData = parameter;
break;
// items that can't be set externally or
// obsolete items
// items that can't be set externally or
// obsolete items
case CurlOption.ErrorBuffer:
case CurlOption.Stderr:
case CurlOption.SourceHost:
@@ -1464,7 +1422,7 @@ namespace CurlSharp
case CurlOption.PasvHost:
return CurlCode.BadFunctionArgument;
// singular case for share
// singular case for share
case CurlOption.Share:
{
_curlShare = parameter as CurlShare;
@@ -1472,7 +1430,7 @@ namespace CurlSharp
break;
}
// multipart HTTP post
// multipart HTTP post
case CurlOption.HttpPost:
{
_httpMultiPartForm = parameter as CurlHttpMultiPartForm;
@@ -1480,7 +1438,7 @@ namespace CurlSharp
break;
}
// items curl wants as a curl_slist
// items curl wants as a curl_slist
case CurlOption.HttpHeader:
case CurlOption.Prequote:
case CurlOption.Quote:
@@ -1494,12 +1452,12 @@ namespace CurlSharp
break;
}
// string items
// string items
default:
{
var s = parameter as string;
setStringOption(option, s);
retCode = LastErrorCode;
retCode = _lastErrorCode;
break;
}
}
@@ -1602,14 +1560,6 @@ namespace CurlSharp
break;
}
case CurlOption.SslCtxFunction:
{
var sf = pfn as CurlSslContextCallback;
if (sf == null)
return CurlCode.BadFunctionArgument;
_pfCurlSslContext = sf;
break;
}
case CurlOption.IoctlFunction:
{
@@ -1640,13 +1590,7 @@ namespace CurlSharp
public CurlCode Perform()
{
ensureHandle();
var nativeRet = NativeMethods.curl_easy_perform(_pCurl);
#if !USE_LIBCURLSHIM
freeHandle(ref _curlWriteData);
#endif
return nativeRet;
return NativeMethods.curl_easy_perform(_pCurl);
}
/// <summary>
@@ -1662,60 +1606,12 @@ namespace CurlSharp
return new CurlEasy(this);
}
/// <summary>
/// URL encode a String.
/// </summary>
/// <param name="url">The string to URL encode.</param>
/// <param name="length">
/// Input string length;
/// use 0 for cURL to determine.
/// </param>
/// <returns>A new URL encoded string.</returns>
/// <exception cref="NullReferenceException">
/// This is thrown if
/// the native <c>CURL*</c> handle wasn't created successfully.
/// </exception>
public string Escape(string url)
{
ensureHandle();
var length = System.Text.Encoding.ASCII.GetBytes(url).Length;
var p = NativeMethods.curl_easy_escape(_pCurl, url, length);
var s = Marshal.PtrToStringAnsi(p);
NativeMethods.curl_free(p);
return s;
}
/// <summary>
/// URL decode a String.
/// </summary>
/// <param name="url">The string to URL decode.</param>
/// <param name="length">
/// Input string length;
/// use 0 for cURL to determine.
/// </param>
/// <returns>A new URL decoded string.</returns>
/// <exception cref="NullReferenceException">
/// This is thrown if
/// the native <c>CURL*</c> handle wasn't created successfully.
/// </exception>
public string Unescape(string url)
{
ensureHandle();
var length = System.Text.Encoding.ASCII.GetBytes(url).Length;
var p = NativeMethods.curl_easy_unescape(_pCurl, url, length, out int outLength);
var s = Marshal.PtrToStringAnsi(p, outLength);
NativeMethods.curl_free(p);
return s;
}
/// <summary>
/// Get a string description of an error code.
/// </summary>
/// <param name="code">Error code.</param>
/// <returns>String description of the error code.</returns>
public string StrError(CurlCode code)
public String StrError(CurlCode code)
{
return Marshal.PtrToStringAnsi(NativeMethods.curl_easy_strerror(code));
}
@@ -1739,7 +1635,7 @@ namespace CurlSharp
/// This is thrown if
/// the native <c>CURL*</c> handle wasn't created successfully.
/// </exception>
public CurlCode GetInfo(CurlInfo info, ref object objInfo)
public CurlCode GetInfo(CurlInfo info, ref Object objInfo)
{
ensureHandle();
var retCode = CurlCode.Ok;
@@ -1755,7 +1651,7 @@ namespace CurlSharp
// private data
if (info == CurlInfo.Private)
{
objInfo = Private;
objInfo = _privateData;
return retCode;
}
@@ -1785,7 +1681,7 @@ namespace CurlSharp
{
ensureHandle();
// ensure it's an integral type
if (((int) info < CURLINFO_LONG) || ((int) info >= CURLINFO_DOUBLE))
if ((int) info < CURLINFO_LONG || (int) info >= CURLINFO_DOUBLE)
{
setLastError(CurlCode.BadFunctionArgument, info);
return -1;
@@ -1883,7 +1779,7 @@ namespace CurlSharp
var retCode = CurlCode.Ok;
var ptr = IntPtr.Zero;
if (((int) info < CURLINFO_STRING) || ((int) info >= CURLINFO_LONG))
if ((int) info < CURLINFO_STRING || (int) info >= CURLINFO_LONG)
return CurlCode.BadFunctionArgument;
retCode = NativeMethods.curl_easy_getinfo(_pCurl, info, ref ptr);
if (retCode == CurlCode.Ok)
@@ -1943,7 +1839,7 @@ namespace CurlSharp
var ptr = IntPtr.Zero;
// ensure it's an integral type
if (((int) info < CURLINFO_LONG) || ((int) info >= CURLINFO_DOUBLE))
if ((int) info < CURLINFO_LONG || (int) info >= CURLINFO_DOUBLE)
return CurlCode.BadFunctionArgument;
retCode = NativeMethods.curl_easy_getinfo(_pCurl, info, ref ptr);
@@ -1980,8 +1876,10 @@ namespace CurlSharp
retCode = NativeMethods.curl_easy_getinfo(_pCurl, info, ref ptr);
if (retCode == CurlCode.Ok)
{
if ((int) ptr < 0)
dt = new DateTime(0);
}
return retCode;
}
@@ -2010,38 +1908,34 @@ namespace CurlSharp
_pcbProgress = _curlProgressCallback;
_pcbDebug = _curlDebugCallback;
_pcbHeader = _curlHeaderCallback;
_pcbSslCtx = _curlSslCtxCallback;
_pcbIoctl = _curlIoctlCallback;
setLastError(NativeMethods.curl_easy_setopt(_pCurl, CurlOption.WriteFunction, _pcbWrite),
CurlOption.WriteFunction);
setLastError(NativeMethods.curl_easy_setopt(_pCurl, CurlOption.ReadFunction, _pcbRead),
CurlOption.ReadFunction);
setLastError(NativeMethods.curl_easy_setopt(_pCurl, CurlOption.ProgressFunction, _pcbProgress),
CurlOption.ProgressFunction);
setLastError(NativeMethods.curl_easy_setopt(_pCurl, CurlOption.HeaderFunction, _pcbHeader),
CurlOption.HeaderFunction);
setLastError(NativeMethods.curl_easy_setopt(_pCurl, CurlOption.DebugFunction, _pcbDebug),
CurlOption.DebugFunction);
setLastError(NativeMethods.curl_easy_setopt(_pCurl, CurlOption.SslCtxFunction, _pcbSslCtx),
CurlOption.SslCtxFunction);
setLastError(NativeMethods.curl_easy_setopt(_pCurl, CurlOption.IoctlFunction, _pcbIoctl),
CurlOption.IoctlFunction);
setLastError(NativeMethods.curl_easy_setopt_cb(_pCurl, CurlOption.WriteFunction, _pcbWrite),
CurlOption.WriteFunction);
setLastError(NativeMethods.curl_easy_setopt_cb(_pCurl, CurlOption.ReadFunction, _pcbRead),
CurlOption.ReadFunction);
setLastError(NativeMethods.curl_easy_setopt_cb(_pCurl, CurlOption.ProgressFunction, _pcbProgress),
CurlOption.ProgressFunction);
setLastError(NativeMethods.curl_easy_setopt_cb(_pCurl, CurlOption.HeaderFunction, _pcbHeader),
CurlOption.HeaderFunction);
setLastError(NativeMethods.curl_easy_setopt_cb(_pCurl, CurlOption.DebugFunction, _pcbDebug),
CurlOption.DebugFunction);
setLastError(NativeMethods.curl_easy_setopt_cb(_pCurl, CurlOption.IoctlFunction, _pcbIoctl),
CurlOption.IoctlFunction);
setLastError(NativeMethods.curl_easy_setopt(_pCurl, CurlOption.NoProgress, (IntPtr) 0),
CurlOption.NoProgress);
CurlOption.NoProgress);
setWriteData(null);
setReadData(null);
setHeaderData(null);
setProgressData(null);
setDebugData(null);
setSslCtxData(null);
setIoctlData(null);
#endif
}
#if USE_LIBCURLSHIM
// called by libcurlshim
// called by libcurlshim
private static int _shimWriteCallback(IntPtr buf, int sz, int nmemb, IntPtr parm)
{
var bytes = sz*nmemb;
@@ -2064,7 +1958,9 @@ namespace CurlSharp
var b = new byte[bytes];
var gch = (GCHandle) parm;
var curlEasy = (CurlEasy) gch.Target;
if (curlEasy?._pfCurlRead == null)
if (curlEasy == null)
return 0;
if (curlEasy._pfCurlRead == null)
return 0;
var nRead = curlEasy._pfCurlRead(b, sz, nmemb, curlEasy._readData);
if (nRead > 0)
@@ -2080,7 +1976,9 @@ namespace CurlSharp
{
var gch = (GCHandle) parm;
var curlEasy = (CurlEasy) gch.Target;
if (curlEasy?._pfCurlProgress == null)
if (curlEasy == null)
return 0;
if (curlEasy._pfCurlProgress == null)
return 0;
var nprog = curlEasy._pfCurlProgress(curlEasy._progressData, dlTotal, dlNow, ulTotal, ulNow);
return nprog;
@@ -2091,10 +1989,12 @@ namespace CurlSharp
{
var gch = (GCHandle) parm;
var curlEasy = (CurlEasy) gch.Target;
if (curlEasy?._pfCurlDebug == null)
if (curlEasy == null)
return 0;
if (curlEasy._pfCurlDebug == null)
return 0;
var message = Marshal.PtrToStringAnsi(msgBuf, msgBufSize);
curlEasy._pfCurlDebug(infoType, message, msgBufSize, curlEasy._debugData);
curlEasy._pfCurlDebug(infoType, message, curlEasy._debugData);
return 0;
}
@@ -2179,7 +2079,7 @@ namespace CurlSharp
if (_pfCurlDebug != null)
{
var userdata = getObject(pUserData);
_pfCurlDebug(infoType, message, size, userdata);
_pfCurlDebug(infoType, message, userdata);
}
return 0;
}
@@ -2207,7 +2107,7 @@ namespace CurlSharp
private CurlIoError _curlIoctlCallback(CurlIoCommand cmd, IntPtr parm)
{
if ((_pfCurlIoctl == null) || (_ioctlData == null))
if (_pfCurlIoctl == null || _ioctlData == null)
return CurlIoError.UnknownCommand;
return _pfCurlIoctl(cmd, _ioctlData);
}

View File

@@ -2,7 +2,7 @@
*
* CurlS#arp
*
* Copyright (c) 2013-2017 Dr. Masroor Ehsan (masroore@gmail.com)
* Copyright (c) 2014 Dr. Masroor Ehsan (masroore@gmail.com)
* Portions copyright (c) 2004, 2005 Jeff Phillips (jeff@jeffp.net)
*
* This software is licensed as described in the file LICENSE, which you
@@ -19,7 +19,6 @@
using System;
using System.Runtime.InteropServices;
using CurlSharp.Enums;
namespace CurlSharp
{
@@ -32,7 +31,7 @@ namespace CurlSharp
public CurlFormOption Option;
/// <summary>Value for the option.</summary>
public object Value;
public Object Value;
}
/// <summary>
@@ -78,7 +77,10 @@ namespace CurlSharp
}
// for CurlEasy.SetOpt()
internal IntPtr GetHandle() => _pItems[0];
internal IntPtr GetHandle()
{
return _pItems[0];
}
/// <summary>
/// Add a multi-part form section.
@@ -184,7 +186,7 @@ namespace CurlSharp
var formArrayPos = 0;
var argArrayPos = 0;
var ptrArrayPos = 0;
object obj = null;
Object obj = null;
while ((retCode == CurlFormCode.Ok) &&
(ptrArrayPos < nRealCount))
@@ -205,14 +207,14 @@ namespace CurlSharp
{
iCode = (CurlFormOption) Convert.ToInt32(
args.GetValue(argArrayPos++));
obj = iCode == CurlFormOption.End
obj = (iCode == CurlFormOption.End)
? null
: args.GetValue(argArrayPos++);
}
switch (iCode)
{
// handle byte-array pointer-related items
// handle byte-array pointer-related items
case CurlFormOption.PtrName:
case CurlFormOption.PtrContents:
case CurlFormOption.BufferPtr:
@@ -238,7 +240,7 @@ namespace CurlSharp
break;
}
// length values
// length values
case CurlFormOption.NameLength:
case CurlFormOption.ContentsLength:
case CurlFormOption.BufferLength:
@@ -247,7 +249,7 @@ namespace CurlSharp
Convert.ToInt32(obj);
break;
// strings
// strings
case CurlFormOption.CopyName:
case CurlFormOption.CopyContents:
case CurlFormOption.FileContent:
@@ -257,7 +259,7 @@ namespace CurlSharp
case CurlFormOption.Buffer:
{
aPointers[ptrArrayPos++] = (IntPtr) iCode;
var s = obj as string;
var s = obj as String;
if (s == null)
retCode = CurlFormCode.UnknownOption;
else
@@ -271,7 +273,7 @@ namespace CurlSharp
break;
}
// array case: already handled
// array case: already handled
case CurlFormOption.Array:
if (aForms != null)
retCode = CurlFormCode.IllegalArray;
@@ -283,7 +285,7 @@ namespace CurlSharp
}
break;
// slist
// slist
case CurlFormOption.ContentHeader:
{
aPointers[ptrArrayPos++] = (IntPtr) iCode;
@@ -295,12 +297,12 @@ namespace CurlSharp
break;
}
// erroneous stuff
// erroneous stuff
case CurlFormOption.Nothing:
retCode = CurlFormCode.Incomplete;
break;
// end
// end
case CurlFormOption.End:
if (aForms != null) // end of form
{
@@ -311,7 +313,7 @@ namespace CurlSharp
aPointers[ptrArrayPos++] = (IntPtr) iCode;
break;
// default is unknown
// default is unknown
default:
retCode = CurlFormCode.UnknownOption;
break;
@@ -329,9 +331,9 @@ namespace CurlSharp
retCode = (CurlFormCode) NativeMethods.curl_shim_formadd(_pItems, aPointers, nRealCount);
#else
retCode = (CurlFormCode) NativeMethods.curl_formadd(ref _pItems[0], ref _pItems[1],
(int) aPointers[0], aPointers[1],
(int) aPointers[2], aPointers[3],
(int) aPointers[4]);
(int) aPointers[0], aPointers[1],
(int) aPointers[2], aPointers[3],
(int) aPointers[4]);
#endif
}
@@ -348,7 +350,7 @@ namespace CurlSharp
case CurlFormOption.ContentType:
case CurlFormOption.Filename:
case CurlFormOption.Buffer:
// byte buffer cases
// byte buffer cases
case CurlFormOption.PtrName:
case CurlFormOption.PtrContents:
case CurlFormOption.BufferPtr:

View File

@@ -2,7 +2,7 @@
*
* CurlS#arp
*
* Copyright (c) 2013-2017 Dr. Masroor Ehsan (masroore@gmail.com)
* Copyright (c) 2014 Dr. Masroor Ehsan (masroore@gmail.com)
* Portions copyright (c) 2004, 2005 Jeff Phillips (jeff@jeffp.net)
*
* This software is licensed as described in the file LICENSE, which you
@@ -20,7 +20,6 @@
using System;
using System.Collections;
using System.Runtime.InteropServices;
using CurlSharp.Enums;
namespace CurlSharp
{
@@ -40,7 +39,6 @@ namespace CurlSharp
private NativeMethods.fd_set _fd_read, _fd_write, _fd_except;
#endif
private IntPtr _pMulti;
private CurlPipelining _pipelining;
/// <summary>
/// Constructor
@@ -76,7 +74,10 @@ namespace CurlSharp
/// <summary>
/// Max file descriptor
/// </summary>
public int MaxFd => _maxFd;
public int MaxFd
{
get { return _maxFd; }
}
/// <summary>
/// Cleanup unmanaged resources.
@@ -148,17 +149,6 @@ namespace CurlSharp
return NativeMethods.curl_multi_add_handle(_pMulti, p);
}
public CurlPipelining Pipelining
{
get { return _pipelining; }
set
{
ensureHandle();
_pipelining = value;
NativeMethods.curl_multi_setopt(_pMulti, CurlMultiOption.Pipelining, (long) value);
}
}
/// <summary>
/// Remove an CurlEasy object.
/// </summary>
@@ -188,7 +178,10 @@ namespace CurlSharp
/// string description.
/// </param>
/// <returns>The string description.</returns>
public string StrError(CurlMultiCode errorNum) => Marshal.PtrToStringAnsi(NativeMethods.curl_multi_strerror(errorNum));
public String StrError(CurlMultiCode errorNum)
{
return Marshal.PtrToStringAnsi(NativeMethods.curl_multi_strerror(errorNum));
}
/// <summary>
/// Read/write data to/from each CurlEasy object.
@@ -276,6 +269,8 @@ namespace CurlSharp
if (_bGotMultiInfo)
return _multiInfo;
_bGotMultiInfo = true;
#if USE_LIBCURLSHIM
var nMsgs = 0;
var pInfo = NativeMethods.curl_shim_multi_info_read(_pMulti, ref nMsgs);
@@ -291,14 +286,17 @@ namespace CurlSharp
}
NativeMethods.curl_shim_multi_info_free(pInfo);
}
_bGotMultiInfo = true;
#else
_multiInfo = null;
throw new NotImplementedException("CurlMulti.InfoRead()");
#endif
#pragma warning disable CS0162 // Unreachable code detected when not compiling with the shim
return _multiInfo;
#pragma warning restore CS0162 // Unreachable code detected when not compiling with the shim
#else
throw new NotImplementedException(
"Sorry, CurlMulti.InfoRead is not implemented on this system."
);
#endif
}
}
}
}

View File

@@ -2,7 +2,7 @@
*
* CurlS#arp
*
* Copyright (c) 2013-2017 Dr. Masroor Ehsan (masroore@gmail.com)
* Copyright (c) 2013 Dr. Masroor Ehsan (masroore@gmail.com)
* Portions copyright (c) 2004, 2005 Jeff Phillips (jeff@jeffp.net)
*
* This software is licensed as described in the file LICENSE, which you
@@ -17,8 +17,6 @@
*
**************************************************************************/
using CurlSharp.Enums;
namespace CurlSharp
{
/// <summary>
@@ -28,28 +26,40 @@ namespace CurlSharp
public sealed class CurlMultiInfo
{
// private members
private readonly CurlEasy _mCurlEasy;
private readonly CurlMessage _msg;
private readonly CurlCode _result;
internal CurlMultiInfo(CurlMessage msg, CurlEasy curlEasy, CurlCode result)
{
Msg = msg;
CurlEasyHandle = curlEasy;
Result = result;
_msg = msg;
_mCurlEasy = curlEasy;
_result = result;
}
/// <summary>
/// Get the status code from the <see cref="CurlMessage" /> enumeration.
/// </summary>
public CurlMessage Msg { get; }
public CurlMessage Msg
{
get { return _msg; }
}
/// <summary>
/// Get the <see cref="CurlEasy" /> object for this child.
/// </summary>
public CurlEasy CurlEasyHandle { get; }
public CurlEasy CurlEasyHandle
{
get { return _mCurlEasy; }
}
/// <summary>
/// Get the return code for the transfer, as a
/// <see cref="CurlCode" />.
/// </summary>
public CurlCode Result { get; }
public CurlCode Result
{
get { return _result; }
}
}
}

View File

@@ -19,8 +19,6 @@
using System;
using System.Runtime.InteropServices;
using CurlSharp.Callbacks;
using CurlSharp.Enums;
namespace CurlSharp
{
@@ -33,12 +31,17 @@ namespace CurlSharp
{
// private members
private GCHandle _hThis; // for handle extraction
private CurlShareCode _lastErrorCode;
private string _lastErrorDescription;
#if USE_LIBCURLSHIM
private NativeMethods._ShimLockCallback _pDelLock; // lock delegate
private NativeMethods._ShimUnlockCallback _pDelUnlock; // unlock delegate
#endif
private IntPtr _pShare; // share handle
private CurlShareLockCallback _pfLock; // client lock delegate
private CurlShareUnlockCallback _pfUnlock; // client unlock delegate
private IntPtr _ptrThis; // numeric handle
private Object _userData; // user data for delegates
/// <summary>
/// Constructor
@@ -62,11 +65,23 @@ namespace CurlSharp
installDelegates();
}
public object UserData { get; set; }
public object UserData
{
get { return _userData; }
set { _userData = value; }
}
public CurlShareUnlockCallback UnlockFunction { get; set; }
public CurlShareUnlockCallback UnlockFunction
{
get { return _pfUnlock; }
set { _pfUnlock = value; }
}
public CurlShareLockCallback LockFunction { get; set; }
public CurlShareLockCallback LockFunction
{
get { return _pfLock; }
set { _pfLock = value; }
}
public CurlLockData Share
{
@@ -78,9 +93,15 @@ namespace CurlSharp
set { setShareOption(CurlShareOption.Unshare, value); }
}
public CurlShareCode LastErrorCode { get; private set; }
public CurlShareCode LastErrorCode
{
get { return _lastErrorCode; }
}
public string LastErrorDescription { get; private set; }
public string LastErrorDescription
{
get { return _lastErrorDescription; }
}
/// <summary>
/// Cleanup unmanaged resources.
@@ -119,7 +140,7 @@ namespace CurlSharp
/// This is thrown if
/// the native <c>share</c> handle wasn't created successfully.
/// </exception>
public CurlShareCode SetOpt(CurlShareOption option, object parameter)
public CurlShareCode SetOpt(CurlShareOption option, Object parameter)
{
EnsureHandle();
var retCode = CurlShareCode.Ok;
@@ -130,14 +151,14 @@ namespace CurlSharp
var lf = parameter as CurlShareLockCallback;
if (lf == null)
return CurlShareCode.BadOption;
LockFunction = lf;
_pfLock = lf;
break;
case CurlShareOption.UnlockFunction:
var ulf = parameter as CurlShareUnlockCallback;
if (ulf == null)
return CurlShareCode.BadOption;
UnlockFunction = ulf;
_pfUnlock = ulf;
break;
case CurlShareOption.Share:
@@ -149,7 +170,7 @@ namespace CurlSharp
}
case CurlShareOption.UserData:
UserData = parameter;
_userData = parameter;
break;
default:
@@ -161,10 +182,10 @@ namespace CurlSharp
private void setLastError(CurlShareCode code, CurlShareOption opt)
{
if ((LastErrorCode == CurlShareCode.Ok) && (code != CurlShareCode.Ok))
if (_lastErrorCode == CurlShareCode.Ok && code != CurlShareCode.Ok)
{
LastErrorCode = code;
LastErrorDescription = $"Error: {StrError(code)} setting option {opt}";
_lastErrorCode = code;
_lastErrorDescription = string.Format("Error: {0} setting option {1}", StrError(code), opt);
}
}
@@ -185,8 +206,10 @@ namespace CurlSharp
/// string description.
/// </param>
/// <returns>The string description.</returns>
public string StrError(CurlShareCode errorNum)
=> Marshal.PtrToStringAnsi(NativeMethods.curl_share_strerror(errorNum));
public String StrError(CurlShareCode errorNum)
{
return Marshal.PtrToStringAnsi(NativeMethods.curl_share_strerror(errorNum));
}
private void Dispose(bool disposing)
{
@@ -206,7 +229,10 @@ namespace CurlSharp
}
}
internal IntPtr GetHandle() => _pShare;
internal IntPtr GetHandle()
{
return _pShare;
}
private void EnsureHandle()
{
@@ -217,7 +243,7 @@ namespace CurlSharp
private void installDelegates()
{
_hThis = GCHandle.Alloc(this);
_ptrThis = (IntPtr) _hThis;
_ptrThis = (IntPtr)_hThis;
#if USE_LIBCURLSHIM
_pDelLock = LockDelegate;
_pDelUnlock = UnlockDelegate;
@@ -229,14 +255,22 @@ namespace CurlSharp
{
var gch = (GCHandle) userPtr;
var share = (CurlShare) gch.Target;
share?.LockFunction?.Invoke((CurlLockData) data, (CurlLockAccess) access, share.UserData);
if (share == null)
return;
if (share.LockFunction == null)
return;
share.LockFunction((CurlLockData) data, (CurlLockAccess) access, share.UserData);
}
internal static void UnlockDelegate(int data, IntPtr userPtr)
{
var gch = (GCHandle) userPtr;
var share = (CurlShare) gch.Target;
share?.UnlockFunction?.Invoke((CurlLockData) data, share.UserData);
if (share == null)
return;
if (share.UnlockFunction == null)
return;
share.UnlockFunction((CurlLockData) data, share.UserData);
}
}
}

View File

@@ -1,12 +1,103 @@
<Project Sdk="Microsoft.NET.Sdk">
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<TargetFrameworks>net452;netstandard2.0</TargetFrameworks>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{74420A79-CC16-442C-8B1E-7C1B913844F0}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>CurlSharp</RootNamespace>
<AssemblyName>CurlSharp</AssemblyName>
<FileAlignment>512</FileAlignment>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<PackageId>CurlSharp</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG</DefineConstants>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>full</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefineConstants>
</DefineConstants>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Curl.cs" />
<Compile Include="CurlEasy.cs" />
<Compile Include="CurlHttpMultiPartForm.cs" />
<Compile Include="CurlMulti.cs" />
<Compile Include="CurlMultiInfo.cs" />
<Compile Include="CurlShare.cs" />
<Compile Include="CurlSlist.cs" />
<Compile Include="CurlSslContext.cs" />
<Compile Include="CurlVersionInfoData.cs" />
<Compile Include="NativeMethods.cs" />
<Compile Include="Enums\CurlClosePolicy.cs" />
<Compile Include="Enums\CurlCode.cs" />
<Compile Include="Enums\CurlFormCode.cs" />
<Compile Include="Enums\CurlFormOption.cs" />
<Compile Include="Enums\CurlFtpAuth.cs" />
<Compile Include="Enums\CurlFtpSsl.cs" />
<Compile Include="Enums\CurlHttpAuth.cs" />
<Compile Include="Enums\CurlHttpVersion.cs" />
<Compile Include="Enums\CurlInfo.cs" />
<Compile Include="Enums\CurlInfoType.cs" />
<Compile Include="Enums\CurlInitFlag.cs" />
<Compile Include="Enums\CurlIoCommand.cs" />
<Compile Include="Enums\CurlIoError.cs" />
<Compile Include="Enums\CurlIpResolve.cs" />
<Compile Include="Enums\CurlLockAccess.cs" />
<Compile Include="Enums\CurlLockData.cs" />
<Compile Include="Enums\CurlMessage.cs" />
<Compile Include="Enums\CurlMultiCode.cs" />
<Compile Include="Enums\CurlNetrcOption.cs" />
<Compile Include="Enums\CurlOption.cs" />
<Compile Include="Enums\CurlProxyType.cs" />
<Compile Include="Enums\CurlShareCode.cs" />
<Compile Include="Enums\CurlShareOption.cs" />
<Compile Include="Enums\CurlSslVersion.cs" />
<Compile Include="Enums\CurlTimeCond.cs" />
<Compile Include="Enums\CurlVersion.cs" />
<Compile Include="Enums\CurlVersionFeatureBitmask.cs" />
<Compile Include="Callbacks\CurlEasyCallbacks.cs" />
<Compile Include="Callbacks\CurlShareCallbacks.cs" />
<Compile Include="SSLFix.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
<ItemGroup />
<ProjectExtensions>
<MonoDevelop>
<Properties>
<Policies>
<TextStylePolicy inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/x-csharp" />
<CSharpFormattingPolicy IndentSwitchBody="True" IndentBlocksInsideExpressions="True" AnonymousMethodBraceStyle="NextLine" PropertyBraceStyle="NextLine" PropertyGetBraceStyle="NextLine" PropertySetBraceStyle="NextLine" EventBraceStyle="NextLine" EventAddBraceStyle="NextLine" EventRemoveBraceStyle="NextLine" StatementBraceStyle="NextLine" ElseNewLinePlacement="NewLine" CatchNewLinePlacement="NewLine" FinallyNewLinePlacement="NewLine" WhileNewLinePlacement="DoNotCare" ArrayInitializerWrapping="DoNotChange" ArrayInitializerBraceStyle="NextLine" BeforeMethodDeclarationParentheses="False" BeforeMethodCallParentheses="False" BeforeConstructorDeclarationParentheses="False" NewLineBeforeConstructorInitializerColon="NewLine" NewLineAfterConstructorInitializerColon="SameLine" BeforeDelegateDeclarationParentheses="False" NewParentheses="False" SpacesBeforeBrackets="False" inheritsSet="Mono" inheritsScope="text/x-csharp" scope="text/x-csharp" />
</Policies>
</Properties>
</MonoDevelop>
</ProjectExtensions>
</Project>

View File

@@ -2,7 +2,7 @@
*
* CurlS#arp
*
* Copyright (c) 2013-2017 Dr. Masroor Ehsan (masroore@gmail.com)
* Copyright (c) 2013 Dr. Masroor Ehsan (masroore@gmail.com)
* Portions copyright (c) 2004, 2005 Jeff Phillips (jeff@jeffp.net)
*
* This software is licensed as described in the file LICENSE, which you
@@ -20,7 +20,6 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using CurlSharp.Enums;
namespace CurlSharp
{
@@ -32,6 +31,19 @@ namespace CurlSharp
/// </summary>
public class CurlSlist : IDisposable
{
#if !USE_LIBCURLSHIM
[StructLayout(LayoutKind.Sequential)]
private class curl_slist
{
/// char*
[MarshalAs(UnmanagedType.LPStr)] public string data;
/// curl_slist*
public IntPtr next;
}
#endif
private IntPtr _handle;
/// <summary>
/// Constructor
/// </summary>
@@ -42,12 +54,12 @@ namespace CurlSharp
public CurlSlist()
{
Curl.EnsureCurl();
Handle = IntPtr.Zero;
_handle = IntPtr.Zero;
}
public CurlSlist(IntPtr handle)
{
Handle = handle;
_handle = handle;
}
/// <summary>
@@ -57,13 +69,13 @@ namespace CurlSharp
{
get
{
if (Handle == IntPtr.Zero)
if (_handle == IntPtr.Zero)
return null;
var strings = new List<string>();
#if !USE_LIBCURLSHIM
var slist = new curl_slist();
Marshal.PtrToStructure(Handle, slist);
Marshal.PtrToStructure(_handle, slist);
while (true)
{
@@ -78,17 +90,6 @@ namespace CurlSharp
}
}
internal IntPtr Handle { get; private set; }
/// <summary>
/// Free all internal strings.
/// </summary>
public void Dispose()
{
GC.SuppressFinalize(this);
Dispose(true);
}
/// <summary>
/// Destructor
/// </summary>
@@ -104,38 +105,40 @@ namespace CurlSharp
public void Append(string str)
{
#if USE_LIBCURLSHIM
Handle = NativeMethods.curl_shim_add_string_to_slist(Handle, str);
_handle = NativeMethods.curl_shim_add_string_to_slist(_handle, str);
#else
Handle = NativeMethods.curl_slist_append(Handle, str);
_handle = NativeMethods.curl_slist_append(_handle, str);
#endif
}
/// <summary>
/// Free all internal strings.
/// </summary>
public void Dispose()
{
GC.SuppressFinalize(this);
Dispose(true);
}
internal IntPtr Handle
{
get { return _handle; }
}
private void Dispose(bool disposing)
{
lock (this)
{
if (Handle != IntPtr.Zero)
if (_handle != IntPtr.Zero)
{
#if USE_LIBCURLSHIM
NativeMethods.curl_shim_free_slist(Handle);
NativeMethods.curl_shim_free_slist(_handle);
#else
NativeMethods.curl_slist_free_all(Handle);
NativeMethods.curl_slist_free_all(_handle);
#endif
Handle = IntPtr.Zero;
_handle = IntPtr.Zero;
}
}
}
#if !USE_LIBCURLSHIM
[StructLayout(LayoutKind.Sequential)]
private class curl_slist
{
/// char*
[MarshalAs(UnmanagedType.LPStr)] public string data;
/// curl_slist*
public IntPtr next;
}
#endif
}
}

View File

@@ -2,7 +2,7 @@
*
* CurlS#arp
*
* Copyright (c) 2013-2017 Dr. Masroor Ehsan (masroore@gmail.com)
* Copyright (c) 2013 Dr. Masroor Ehsan (masroore@gmail.com)
* Portions copyright (c) 2004, 2005 Jeff Phillips (jeff@jeffp.net)
*
* This software is licensed as described in the file LICENSE, which you
@@ -18,7 +18,6 @@
**************************************************************************/
using System;
using CurlSharp.Callbacks;
namespace CurlSharp
{
@@ -32,14 +31,19 @@ namespace CurlSharp
/// </summary>
public sealed class CurlSslContext
{
private readonly IntPtr _pvContext;
internal CurlSslContext(IntPtr pvContext)
{
Context = pvContext;
_pvContext = pvContext;
}
/// <summary>
/// Get the underlying OpenSSL context.
/// </summary>
public IntPtr Context { get; }
public IntPtr Context
{
get { return _pvContext; }
}
}
}

View File

@@ -2,7 +2,7 @@
*
* CurlS#arp
*
* Copyright (c) 2013-2017 Dr. Masroor Ehsan (masroore@gmail.com)
* Copyright (c) 2013 Dr. Masroor Ehsan (masroore@gmail.com)
* Portions copyright (c) 2004, 2005 Jeff Phillips (jeff@jeffp.net)
*
* This software is licensed as described in the file LICENSE, which you
@@ -18,7 +18,7 @@
**************************************************************************/
using System;
using CurlSharp.Enums;
using System.Runtime.InteropServices;
namespace CurlSharp
{

View File

@@ -1,4 +1,4 @@
namespace CurlSharp.Enums
namespace CurlSharp
{
/// <summary>
/// Contains values used to specify the order in which cached connections

View File

@@ -1,4 +1,4 @@
namespace CurlSharp.Enums
namespace CurlSharp
{
/// <summary>
/// Status code returned from <see cref="CurlEasy" /> functions.

View File

@@ -17,7 +17,7 @@
* $Id: Enums.cs,v 1.1 2005/02/17 22:47:25 jeffreyphillips Exp $
**************************************************************************/
namespace CurlSharp.Enums
namespace CurlSharp
{
/// <summary>
/// One of these is returned by <see cref="CurlHttpMultiPartForm.AddSection" />.

View File

@@ -1,4 +1,4 @@
namespace CurlSharp.Enums
namespace CurlSharp
{
/// <summary>
/// These are options available to build a multi-part form section

View File

@@ -1,4 +1,4 @@
namespace CurlSharp.Enums
namespace CurlSharp
{
/// <summary>
/// This enumeration contains values used to specify the FTP Ssl

View File

@@ -1,4 +1,4 @@
namespace CurlSharp.Enums
namespace CurlSharp
{
/// <summary>
/// This enumeration contains values used to specify the FTP Ssl level

View File

@@ -1,4 +1,4 @@
namespace CurlSharp.Enums
namespace CurlSharp
{
/// <summary>
/// This enumeration contains values used to specify the HTTP authentication

View File

@@ -1,4 +1,4 @@
namespace CurlSharp.Enums
namespace CurlSharp
{
/// <summary>
/// Contains values used to specify the HTTP version level when using
@@ -23,24 +23,9 @@ namespace CurlSharp.Enums
/// </summary>
Http1_1 = 2,
/// <summary>
/// Enforce HTTP 2 requests.
/// </summary>
Http2_0 = 3,
/// <summary>
/// Enforce version 2 for HTTPS, version 1.1 for HTTP.
/// </summary>
Http2_Tls = 4,
/// <summary>
/// Enforce HTTP 2 without HTTP/1.1 upgrade.
/// </summary>
Http2_PriorKnowledge = 5,
/// <summary>
/// Last entry in enumeration; do not use in application code.
/// </summary>
Last = 6
}
Last = 3
};
}

View File

@@ -1,4 +1,4 @@
namespace CurlSharp.Enums
namespace CurlSharp
{
/// <summary>
/// This enumeration is used to extract information associated with an

View File

@@ -1,4 +1,4 @@
namespace CurlSharp.Enums
namespace CurlSharp
{
/// <summary>
/// A member of this enumeration is passed as the first parameter to the

View File

@@ -1,4 +1,4 @@
namespace CurlSharp.Enums
namespace CurlSharp
{
/// <summary>
/// Contains values used to initialize libcurl internally. One of

View File

@@ -1,4 +1,4 @@
namespace CurlSharp.Enums
namespace CurlSharp
{
/// <summary>
/// Your handler for the <see cref="CurlEasy.CurlIoctlCallback" />

View File

@@ -1,4 +1,4 @@
namespace CurlSharp.Enums
namespace CurlSharp
{
/// <summary>
/// Your handler for the <see cref="CurlEasy.CurlIoctlCallback" /> delegate

View File

@@ -1,4 +1,4 @@
namespace CurlSharp.Enums
namespace CurlSharp
{
/// <summary>
/// This enumeration contains values used to specify the IP resolution

View File

@@ -1,4 +1,4 @@
namespace CurlSharp.Enums
namespace CurlSharp
{
/// <summary>
/// Values containing the type of shared access requested when libcurl

View File

@@ -1,4 +1,4 @@
namespace CurlSharp.Enums
namespace CurlSharp
{
/// <summary>
/// Members of this enumeration should be passed to

View File

@@ -1,4 +1,4 @@
namespace CurlSharp.Enums
namespace CurlSharp
{
/// <summary>
/// The status code associated with an <see cref="CurlEasy" /> object in a

View File

@@ -1,4 +1,4 @@
namespace CurlSharp.Enums
namespace CurlSharp
{
/// <summary>
/// Contains return codes for many of the functions in the

View File

@@ -1,46 +0,0 @@
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
//
// Copyright (c) 2017, Dr. Masroor Ehsan. All rights reserved.
//
// $Id:$
//
// Last modified: 25.01.2017 1:29 AM
//
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
namespace CurlSharp.Enums
{
public enum CurlMultiOption
{
/* This is the socket callback function pointer */
SocketFunction = CurlOptType.FunctionPoint + 1,
/* This is the argument passed to the socket callback */
SocketData = CurlOptType.ObjectPoint + 2,
/* set to 1 to enable pipelining for this multi handle */
Pipelining = CurlOptType.Long + 3,
/* This is the timer callback function pointer */
TimerFunction = CurlOptType.FunctionPoint + 4,
/* This is the argument passed to the timer callback */
TimerDate = CurlOptType.ObjectPoint + 5,
/* maximum number of entries in the connection cache */
MaxConnects = CurlOptType.Long + 6,
/* maximum number of (pipelining) connections to one host */
MaxHostConnections = CurlOptType.Long + 7,
/* maximum number of requests in a pipeline */
MaxPipelineLength = CurlOptType.Long + 8,
/* a connection with a content-length longer than this will not be considered for pipelining */
ContentLengthPenaltySize = CurlOptType.Offset + 9,
/* a connection with a chunk length longer than this will not be considered for pipelining */
ChunkLengthPenaltySize = CurlOptType.Offset + 10,
/* a list of site names(+port) that are blacklisted from pipelining */
PipeliningSiteBlackList = CurlOptType.ObjectPoint + 11,
/* a list of server types that are blacklisted from pipelining */
PipeliningServerBlackList = CurlOptType.ObjectPoint + 12,
/* maximum number of open connections in total */
MaxTotalConnections = CurlOptType.Long + 13,
/* This is the server push callback function pointer */
PushFunction = CurlOptType.FunctionPoint + 14,
/* This is the argument passed to the server push callback */
PushData = CurlOptType.ObjectPoint + 15
}
}

View File

@@ -1,4 +1,4 @@
namespace CurlSharp.Enums
namespace CurlSharp
{
/// <summary>
/// Contains values used to specify the preference of libcurl between

View File

@@ -1,21 +0,0 @@
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
//
// Copyright (c) 2017, Dr. Masroor Ehsan. All rights reserved.
//
// $Id:$
//
// Last modified: 25.01.2017 1:31 AM
//
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
namespace CurlSharp.Enums
{
public enum CurlOptType
{
Long = 0,
ObjectPoint = 10000,
StringPoint = 10000,
FunctionPoint = 20000,
Offset = 30000
}
}

View File

@@ -17,9 +17,7 @@
*
**************************************************************************/
using CurlSharp.Callbacks;
namespace CurlSharp.Enums
namespace CurlSharp
{
/// <summary>
/// One of these is passed as the first parameter to
@@ -1077,32 +1075,6 @@ namespace CurlSharp.Enums
/// </summary>
SslCipherList = 10083,
/// <summary>
/// Object reference to pass to the ssl context delegate set by the option
/// <c>SslCtxFunction</c>, this is the pointer you'll get as the
/// second parameter, otherwise <c>null</c>. (Added in 7.11.0)
/// </summary>
SslCtxData = 10109,
/// <summary>
/// Reference to an <see cref="CurlEasy.CurlSslContextCallback" /> delegate.
/// This delegate gets called by libcurl just before the initialization of
/// an Ssl connection after having processed all other Ssl related options
/// to give a last chance to an application to modify the behaviour of
/// openssl's ssl initialization. The <see cref="CurlSslContext" /> parameter
/// wraps a pointer to an openssl SSL_CTX. If an error is returned no attempt
/// to establish a connection is made and the perform operation will return
/// the error code from this callback function. Set the parm argument with
/// the <c>SslCtxData</c> option. This option was introduced
/// in 7.11.0.
/// <note>
/// To use this properly, a non-trivial amount of knowledge of the openssl
/// libraries is necessary. Using this function allows for example to use
/// openssl callbacks to add additional validation code for certificates,
/// and even to change the actual URI of an HTTPS request.
/// </note>
/// </summary>
SslCtxFunction = 20108,
/// <summary>
/// Pass an <c>int</c>. Set if we should verify the common name from the

View File

@@ -1,21 +0,0 @@
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
//
// Copyright (c) 2017, Dr. Masroor Ehsan. All rights reserved.
//
// $Id:$
//
// Last modified: 25.01.2017 1:23 AM
//
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
namespace CurlSharp.Enums
{
/* bitmask bits for CURLMOPT_PIPELINING */
public enum CurlPipelining : long
{
Nothing = 0,
Http1 = 1,
Multiplex = 2
}
}

View File

@@ -1,4 +1,4 @@
namespace CurlSharp.Enums
namespace CurlSharp
{
/// <summary>
/// This enumeration contains values used to specify the proxy type when

View File

@@ -1,4 +1,4 @@
namespace CurlSharp.Enums
namespace CurlSharp
{
/// <summary>
/// Contains return codes from many of the functions in the

View File

@@ -1,4 +1,4 @@
namespace CurlSharp.Enums
namespace CurlSharp
{
/// <summary>
/// A member of this enumeration is passed to the function

View File

@@ -1,4 +1,4 @@
namespace CurlSharp.Enums
namespace CurlSharp
{
/// <summary>
/// Contains values used to specify the Ssl version level when using

View File

@@ -1,4 +1,4 @@
namespace CurlSharp.Enums
namespace CurlSharp
{
/// <summary>
/// Contains values used to specify the time condition when using

View File

@@ -1,4 +1,4 @@
namespace CurlSharp.Enums
namespace CurlSharp
{
/// <summary>
/// A member of this enumeration is passed to the function

View File

@@ -1,4 +1,4 @@
namespace CurlSharp.Enums
namespace CurlSharp
{
/// <summary>
/// A bitmask of libcurl features OR'd together as the value of the

View File

@@ -1,29 +0,0 @@
Copyright (c) 2013, Masroor Ehsan Choudhury
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
* Neither the name of the {organization} nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
https://github.com/masroore/CurlSharp

View File

@@ -2,9 +2,8 @@
*
* CurlS#arp
*
* Copyright (c) 2013-2017 Dr. Masroor Ehsan (masroore@gmail.com)
* Copyright (c) 2014 Dr. Masroor Ehsan (masroore@gmail.com)
* Portions copyright (c) 2004, 2005 Jeff Phillips (jeff@jeffp.net)
* Portions copyright (c) 2017 Katelyn Gigante (https://github.com/silasary)
*
* This software is licensed as described in the file LICENSE, which you
* should have received as part of this distribution.
@@ -21,599 +20,383 @@
//#define USE_LIBCURLSHIM
using System;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using CurlSharp.Enums;
namespace CurlSharp
{
/// <summary>
/// P/Invoke signatures.
/// </summary>
internal static unsafe class NativeMethods
{
private const string LIBCURL = "libcurl";
/// <summary>
/// P/Invoke signatures.
/// </summary>
internal static unsafe class NativeMethods
{
#if WIN64
private const string CURL_LIB = "libcurl64.dll";
private const string LIBCURLSHIM = "libcurlshim";
private const string LIBC_LINUX = "libc";
#if USE_LIBCURLSHIM
private const string CURLSHIM_LIB = "libcurlshim64.dll";
#endif
#else
#if LINUX
private const string CURL_LIB = "libcurl";
#else
private const string CURL_LIB = "libcurl.dll";
#if USE_LIBCURLSHIM
private const string CURLSHIM_LIB = "libcurlshim.dll";
#endif
#endif
#endif
#if !USE_LIBCURLSHIM
#if LINUX
private const string WINSOCK_LIB = "libc";
#else
private const string WINSOCK_LIB = "ws2_32.dll";
private const string LIB_DIR_WIN64 = "amd64";
private const string LIB_DIR_WIN32 = "i386";
static NativeMethods()
{
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
{
if (Environment.Is64BitOperatingSystem)
{
SetDllDirectory(Path.Combine(AssemblyDirectory, LIB_DIR_WIN64));
}
else
{
SetDllDirectory(Path.Combine(AssemblyDirectory, LIB_DIR_WIN32));
}
}
#if USE_LIBCURLSHIM
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
throw new InvalidOperationException("Can not run on other platform than Win NET");
#endif
}
#endif
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetDllDirectory(string lpPathName);
// internal delegates from cURL
private static string AssemblyDirectory
{
get
{
var codeBase = typeof(NativeMethods).GetTypeInfo().Assembly.CodeBase;
var uri = new UriBuilder(codeBase);
var path = Uri.UnescapeDataString(uri.Path);
return Path.GetDirectoryName(path);
}
}
// libcurl imports
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern CurlCode curl_global_init (int flags);
#region curl_global_init
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern void curl_global_cleanup ();
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern CurlCode curl_global_init(int flags);
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern IntPtr curl_escape (String url, int length);
#endregion
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern IntPtr curl_unescape (String url, int length);
#region curl_global_cleanup
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern void curl_free (IntPtr p);
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern void curl_global_cleanup();
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr curl_version ();
#endregion
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr curl_easy_init ();
#region curl_easy_escape
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern void curl_easy_cleanup (IntPtr pCurl);
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern IntPtr curl_easy_escape(IntPtr pEasy, string url, int length);
[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
internal delegate int _CurlGenericCallback (IntPtr ptr, int sz, int nmemb, IntPtr userdata);
[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
internal delegate int _CurlProgressCallback (
IntPtr extraData, double dlTotal, double dlNow, double ulTotal, double ulNow);
[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
internal delegate int _CurlDebugCallback (
IntPtr ptrCurl, CurlInfoType infoType, string message, int size, IntPtr ptrUserData);
[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
internal delegate int _CurlSslCtxCallback (IntPtr ctx, IntPtr parm);
[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
internal delegate CurlIoError _CurlIoctlCallback (CurlIoCommand cmd, IntPtr parm);
// curl_easy_setopt() overloads
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern CurlCode curl_easy_setopt (IntPtr pCurl, CurlOption opt, IntPtr parm);
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern CurlCode curl_easy_setopt (IntPtr pCurl, CurlOption opt, string parm);
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern CurlCode curl_easy_setopt (IntPtr pCurl, CurlOption opt, byte[] parm);
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern CurlCode curl_easy_setopt (IntPtr pCurl, CurlOption opt, long parm);
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern CurlCode curl_easy_setopt (IntPtr pCurl, CurlOption opt, bool parm);
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "curl_easy_setopt")]
internal static extern CurlCode curl_easy_setopt_cb (IntPtr pCurl, CurlOption opt, _CurlGenericCallback parm);
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "curl_easy_setopt")]
internal static extern CurlCode curl_easy_setopt_cb (IntPtr pCurl, CurlOption opt, _CurlProgressCallback parm);
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "curl_easy_setopt")]
internal static extern CurlCode curl_easy_setopt_cb (IntPtr pCurl, CurlOption opt, _CurlDebugCallback parm);
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "curl_easy_setopt")]
internal static extern CurlCode curl_easy_setopt_cb (IntPtr pCurl, CurlOption opt, _CurlSslCtxCallback parm);
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "curl_easy_setopt")]
internal static extern CurlCode curl_easy_setopt_cb (IntPtr pCurl, CurlOption opt, _CurlIoctlCallback parm);
#if !USE_LIBCURLSHIM
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern CurlMultiCode curl_multi_fdset (IntPtr pmulti,
[In, Out] ref fd_set read_fd_set,
[In, Out] ref fd_set write_fd_set,
[In, Out] ref fd_set exc_fd_set,
[In, Out] ref int max_fd);
[StructLayout (LayoutKind.Sequential)]
internal struct fd_set
{
internal uint fd_count;
//[MarshalAs(UnmanagedType.ByValArray, SizeConst = FD_SETSIZE)] internal IntPtr[] fd_array;
internal fixed uint fd_array[FD_SETSIZE];
#endregion
internal const int FD_SETSIZE = 64;
#region curl_easy_unescape
internal void Cleanup ()
{
//fd_array = null;
}
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern IntPtr curl_easy_unescape(IntPtr pEasy, string url, int inLength, out int outLength);
internal static fd_set Create ()
{
return new fd_set {
//fd_array = new IntPtr[FD_SETSIZE],
fd_count = 0
};
}
internal static fd_set Create (IntPtr socket)
{
var handle = Create ();
handle.fd_count = 1;
handle.fd_array [0] = (uint)socket;
return handle;
}
}
internal static void FD_ZERO (fd_set fds)
{
for (var i = 0; i < fd_set.FD_SETSIZE; i++) {
//fds.fd_array[i] = (IntPtr) 0;
fds.fd_array [i] = 0;
}
fds.fd_count = 0;
}
[StructLayout (LayoutKind.Sequential)]
internal struct timeval
{
/// <summary>
/// Time interval, in seconds.
/// </summary>
internal int tv_sec;
/// <summary>
/// Time interval, in microseconds.
/// </summary>
internal int tv_usec;
internal static timeval Create (int milliseconds)
{
return new timeval {
tv_sec = milliseconds / 1000,
tv_usec = (milliseconds % 1000) * 1000
};
}
};
[DllImport (WINSOCK_LIB, EntryPoint = "select")]
internal static extern int select (
int nfds, // number of sockets, (ignored in winsock)
[In, Out] ref fd_set readfds, // read sockets to watch
[In, Out] ref fd_set writefds, // write sockets to watch
[In, Out] ref fd_set exceptfds, // error sockets to watch
ref timeval timeout);
//[DllImport(WINSOCK_LIB, EntryPoint = "select")]
//internal static extern int select(int ndfs, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, timeval* timeout);
#endif
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern CurlCode curl_easy_perform (IntPtr pCurl);
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr curl_easy_duphandle (IntPtr pCurl);
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr curl_easy_strerror (CurlCode err);
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern CurlCode curl_easy_getinfo (IntPtr pCurl, CurlInfo info, ref IntPtr pInfo);
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern CurlCode curl_easy_getinfo (IntPtr pCurl, CurlInfo info, ref double dblVal);
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern void curl_easy_reset (IntPtr pCurl);
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr curl_multi_init ();
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern CurlMultiCode curl_multi_cleanup (IntPtr pmulti);
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern CurlMultiCode curl_multi_add_handle (IntPtr pmulti, IntPtr peasy);
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern CurlMultiCode curl_multi_remove_handle (IntPtr pmulti, IntPtr peasy);
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr curl_multi_strerror (CurlMultiCode errorNum);
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern CurlMultiCode curl_multi_perform (IntPtr pmulti, ref int runningHandles);
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern void curl_formfree (IntPtr pForm);
#if !USE_LIBCURLSHIM
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern int curl_formadd (ref IntPtr pHttppost, ref IntPtr pLastPost,
int codeFirst, IntPtr bufFirst,
int codeNext, IntPtr bufNext,
int codeLast);
#endif
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr curl_share_init ();
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern CurlShareCode curl_share_cleanup (IntPtr pShare);
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr curl_share_strerror (CurlShareCode errorCode);
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern CurlShareCode curl_share_setopt (IntPtr pShare, CurlShareOption optCode, IntPtr option);
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern IntPtr curl_slist_append (IntPtr slist, string data);
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern CurlShareCode curl_slist_free_all (IntPtr pList);
#endregion
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr curl_version_info (CurlVersion ver);
#region curl_free
#if USE_LIBCURLSHIM
// libcurlshim imports
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern void curl_shim_initialize();
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern void curl_free(IntPtr p);
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern void curl_shim_cleanup();
#endregion
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr curl_shim_alloc_strings();
#region curl_version
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl,
CharSet = CharSet.Ansi)]
internal static extern IntPtr curl_shim_add_string_to_slist(
IntPtr pStrings, String str);
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr curl_version();
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl,
CharSet = CharSet.Ansi)]
internal static extern IntPtr curl_shim_get_string_from_slist(
IntPtr pSlist, ref IntPtr pStr);
#endregion
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl,
CharSet = CharSet.Ansi)]
internal static extern IntPtr curl_shim_add_string(IntPtr pStrings, String str);
#region curl_version_info
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern void curl_shim_free_strings(IntPtr pStrings);
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr curl_version_info(CurlVersion ver);
#endregion
#region curl_easy_init
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr curl_easy_init();
#endregion
#region curl_easy_cleanup
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern void curl_easy_cleanup(IntPtr pCurl);
#endregion
#region curl_easy_setopt
#region Delegates
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int _CurlGenericCallback(IntPtr ptr, int sz, int nmemb, IntPtr userdata);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int _CurlProgressCallback(
IntPtr extraData,
double dlTotal,
double dlNow,
double ulTotal,
double ulNow);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int _CurlDebugCallback(
IntPtr ptrCurl,
CurlInfoType infoType,
string message,
int size,
IntPtr ptrUserData);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int _CurlSslCtxCallback(IntPtr ctx, IntPtr parm);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate CurlIoError _CurlIoctlCallback(CurlIoCommand cmd, IntPtr parm);
#endregion
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern CurlCode curl_easy_setopt(IntPtr pCurl, CurlOption opt, IntPtr parm);
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern CurlCode curl_easy_setopt(IntPtr pCurl, CurlOption opt, string parm);
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern CurlCode curl_easy_setopt(IntPtr pCurl, CurlOption opt, byte[] parm);
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern CurlCode curl_easy_setopt(IntPtr pCurl, CurlOption opt, long parm);
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern CurlCode curl_easy_setopt(IntPtr pCurl, CurlOption opt, bool parm);
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern CurlCode curl_easy_setopt(IntPtr pCurl, CurlOption opt, _CurlGenericCallback parm);
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern CurlCode curl_easy_setopt(IntPtr pCurl, CurlOption opt, _CurlProgressCallback parm);
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern CurlCode curl_easy_setopt(IntPtr pCurl, CurlOption opt, _CurlDebugCallback parm);
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern CurlCode curl_easy_setopt(IntPtr pCurl, CurlOption opt, _CurlSslCtxCallback parm);
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern CurlCode curl_easy_setopt(IntPtr pCurl, CurlOption opt, _CurlIoctlCallback parm);
#endregion
#region curl_easy_perform
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern CurlCode curl_easy_perform(IntPtr pCurl);
#endregion
#region curl_easy_duphandle
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr curl_easy_duphandle(IntPtr pCurl);
#endregion
#region curl_easy_strerror
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr curl_easy_strerror(CurlCode err);
#endregion
#region curl_easy_getinfo
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern CurlCode curl_easy_getinfo(IntPtr pCurl, CurlInfo info, ref IntPtr pInfo);
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern CurlCode curl_easy_getinfo(IntPtr pCurl, CurlInfo info, ref double dblVal);
#endregion
#region curl_easy_reset
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern void curl_easy_reset(IntPtr pCurl);
#endregion
#region curl_multi_init
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr curl_multi_init();
#endregion
#region curl_multi_cleanup
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern CurlMultiCode curl_multi_cleanup(IntPtr pmulti);
#endregion
#region curl_multi_add_handle
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern CurlMultiCode curl_multi_add_handle(IntPtr pmulti, IntPtr peasy);
#endregion
#region curl_multi_remove_handle
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern CurlMultiCode curl_multi_remove_handle(IntPtr pmulti, IntPtr peasy);
#endregion
#region curl_multi_setopt
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern CurlMultiCode curl_multi_setopt(IntPtr pmulti, CurlMultiOption opt, bool parm);
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern CurlMultiCode curl_multi_setopt(IntPtr pmulti, CurlMultiOption opt, long parm);
#endregion
#region curl_multi_strerror
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr curl_multi_strerror(CurlMultiCode errorNum);
#endregion
#region curl_multi_perform
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern CurlMultiCode curl_multi_perform(IntPtr pmulti, ref int runningHandles);
#endregion
#if !USE_LIBCURLSHIM
#region curl_multi_fdset
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern CurlMultiCode curl_multi_fdset(IntPtr pmulti,
[In] [Out] ref fd_set read_fd_set,
[In] [Out] ref fd_set write_fd_set,
[In] [Out] ref fd_set exc_fd_set,
[In] [Out] ref int max_fd);
[StructLayout(LayoutKind.Sequential)]
public struct fd_set
{
public uint fd_count;
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = FD_SETSIZE)] public IntPtr[] fd_array;
public fixed uint fd_array[FD_SETSIZE];
public const int FD_SETSIZE = 64;
public void Cleanup()
{
// fd_array = null;
}
public static fd_set Create()
{
return new fd_set
{
// fd_array = new IntPtr[FD_SETSIZE],
fd_count = 0
};
}
public static fd_set Create(IntPtr socket)
{
var handle = Create();
handle.fd_count = 1;
handle.fd_array[0] = (uint)socket;
return handle;
}
}
public static void FD_ZERO(fd_set fds)
{
for (var i = 0; i < fd_set.FD_SETSIZE; i++)
{
fds.fd_array[i] = 0;
}
fds.fd_count = 0;
}
#endregion
#region select
[StructLayout(LayoutKind.Sequential)]
public struct timeval
{
/// <summary>
/// Time interval, in seconds.
/// </summary>
public int tv_sec;
/// <summary>
/// Time interval, in microseconds.
/// </summary>
public int tv_usec;
public static timeval Create(int milliseconds)
{
return new timeval
{
tv_sec = milliseconds / 1000,
tv_usec = milliseconds % 1000 * 1000
};
}
}
[DllImport(LIBC_LINUX, EntryPoint = "select")]
private static extern int select_unix(
int nfds, // number of sockets, (ignored in winsock)
[In] [Out] ref fd_set readfds, // read sockets to watch
[In] [Out] ref fd_set writefds, // write sockets to watch
[In] [Out] ref fd_set exceptfds, // error sockets to watch
ref timeval timeout);
[DllImport(WINSOCK_LIB, EntryPoint = "select")]
private static extern int select_win(
int nfds, // number of sockets, (ignored in winsock)
[In] [Out] ref fd_set readfds, // read sockets to watch
[In] [Out] ref fd_set writefds, // write sockets to watch
[In] [Out] ref fd_set exceptfds, // error sockets to watch
ref timeval timeout);
public static int select(
int nfds, // number of sockets, (ignored in winsock)
[In] [Out] ref fd_set readfds, // read sockets to watch
[In] [Out] ref fd_set writefds, // write sockets to watch
[In] [Out] ref fd_set exceptfds, // error sockets to watch
ref timeval timeout)
{
int result;
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
{
result = select_win(
nfds, // number of sockets, (ignored in winsock)
ref readfds, // read sockets to watch
ref writefds, // write sockets to watch
ref exceptfds, // error sockets to watch
ref timeout);
}
else
{
result = select_unix(
nfds, // number of sockets, (ignored in winsock)
ref readfds, // read sockets to watch
ref writefds, // write sockets to watch
ref exceptfds, // error sockets to watch
ref timeout);
}
return result;
}
#endregion
#endif
#region curl_share_init
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr curl_share_init();
#endregion
#region curl_share_cleanup
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern CurlShareCode curl_share_cleanup(IntPtr pShare);
#endregion
#region curl_share_strerror
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr curl_share_strerror(CurlShareCode errorCode);
#endregion
#region curl_share_setopt
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern CurlShareCode curl_share_setopt(
IntPtr pShare,
CurlShareOption optCode,
IntPtr option);
#endregion
#region curl_formadd
#if !USE_LIBCURLSHIM
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern int curl_formadd(ref IntPtr pHttppost, ref IntPtr pLastPost,
int codeFirst, IntPtr bufFirst,
int codeNext, IntPtr bufNext,
int codeLast);
#endif
#endregion
#region curl_formfree
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern void curl_formfree(IntPtr pForm);
#endregion
#region curl_slist_append
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern IntPtr curl_slist_append(IntPtr slist, string data);
#endregion
#region curl_slist_free_all
[DllImport(LIBCURL, CallingConvention = CallingConvention.Cdecl)]
public static extern void curl_slist_free_all(IntPtr pList);
#endregion
#if USE_LIBCURLSHIM
#region libcurlshim imports
[DllImport(LIBCURLSHIM, CallingConvention = CallingConvention.Cdecl)]
public static extern void curl_shim_initialize();
[DllImport(LIBCURLSHIM, CallingConvention = CallingConvention.Cdecl)]
public static extern void curl_shim_cleanup();
[DllImport(LIBCURLSHIM, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr curl_shim_alloc_strings();
[DllImport(LIBCURLSHIM, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern IntPtr curl_shim_add_string_to_slist(IntPtr pStrings, string str);
[DllImport(LIBCURLSHIM, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern IntPtr curl_shim_get_string_from_slist(IntPtr pSlist, ref IntPtr pStr);
[DllImport(LIBCURLSHIM, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern IntPtr curl_shim_add_string(IntPtr pStrings, string str);
[DllImport(LIBCURLSHIM, CallingConvention = CallingConvention.Cdecl)]
public static extern void curl_shim_free_strings(IntPtr pStrings);
[DllImport(LIBCURLSHIM, CallingConvention = CallingConvention.Cdecl)]
public static extern int curl_shim_install_delegates(
IntPtr pCurl,
IntPtr pThis,
_ShimWriteCallback pWrite,
_ShimReadCallback pRead,
_ShimProgressCallback pProgress,
_ShimDebugCallback pDebug,
_ShimHeaderCallback pHeader,
_ShimSslCtxCallback pCtx,
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern int curl_shim_install_delegates(IntPtr pCurl, IntPtr pThis,
_ShimWriteCallback pWrite, _ShimReadCallback pRead,
_ShimProgressCallback pProgress, _ShimDebugCallback pDebug,
_ShimHeaderCallback pHeader, _ShimSslCtxCallback pCtx,
_ShimIoctlCallback pIoctl);
[DllImport(LIBCURLSHIM, CallingConvention = CallingConvention.Cdecl)]
public static extern void curl_shim_cleanup_delegates(IntPtr pThis);
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern void curl_shim_cleanup_delegates(IntPtr pThis);
[DllImport(LIBCURLSHIM, CallingConvention = CallingConvention.Cdecl)]
public static extern void curl_shim_get_file_time(
int unixTime,
ref int yy,
ref int mm,
ref int dd,
ref int hh,
ref int mn,
ref int ss);
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern void curl_shim_get_file_time(int unixTime,
ref int yy, ref int mm, ref int dd, ref int hh, ref int mn, ref int ss);
[DllImport(LIBCURLSHIM, CallingConvention = CallingConvention.Cdecl)]
public static extern void curl_shim_free_slist(IntPtr p);
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern void curl_shim_free_slist(IntPtr p);
[DllImport(LIBCURLSHIM, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr curl_shim_alloc_fd_sets();
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr curl_shim_alloc_fd_sets();
[DllImport(LIBCURLSHIM, CallingConvention = CallingConvention.Cdecl)]
public static extern void curl_shim_free_fd_sets(IntPtr fdsets);
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern void curl_shim_free_fd_sets(IntPtr fdsets);
[DllImport(LIBCURLSHIM, CallingConvention = CallingConvention.Cdecl)]
public static extern CurlMultiCode curl_shim_multi_fdset(IntPtr multi, IntPtr fdsets, ref int maxFD);
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern CurlMultiCode curl_shim_multi_fdset(IntPtr multi,
IntPtr fdsets, ref int maxFD);
[DllImport(LIBCURLSHIM, CallingConvention = CallingConvention.Cdecl)]
public static extern int curl_shim_select(int maxFD, IntPtr fdsets, int milliseconds);
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern int curl_shim_select(int maxFD, IntPtr fdsets,
int milliseconds);
[DllImport(LIBCURLSHIM, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr curl_shim_multi_info_read(IntPtr multi, ref int nMsgs);
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr curl_shim_multi_info_read(IntPtr multi,
ref int nMsgs);
[DllImport(LIBCURLSHIM, CallingConvention = CallingConvention.Cdecl)]
public static extern void curl_shim_multi_info_free(IntPtr multiInfo);
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern void curl_shim_multi_info_free(IntPtr multiInfo);
[DllImport(LIBCURLSHIM, CallingConvention = CallingConvention.Cdecl)]
public static extern int curl_shim_formadd(IntPtr[] ppForms, IntPtr[] pParams, int nParams);
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern int curl_shim_formadd(IntPtr[] ppForms, IntPtr[] pParams, int nParams);
[DllImport(LIBCURLSHIM, CallingConvention = CallingConvention.Cdecl)]
public static extern int curl_shim_install_share_delegates(
IntPtr pShare,
IntPtr pThis,
_ShimLockCallback pLock,
_ShimUnlockCallback pUnlock);
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern int curl_shim_install_share_delegates(IntPtr pShare,
IntPtr pThis, _ShimLockCallback pLock, _ShimUnlockCallback pUnlock);
[DllImport(LIBCURLSHIM, CallingConvention = CallingConvention.Cdecl)]
public static extern void curl_shim_cleanup_share_delegates(IntPtr pShare);
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern void curl_shim_cleanup_share_delegates(IntPtr pShare);
[DllImport(LIBCURLSHIM, CallingConvention = CallingConvention.Cdecl)]
public static extern int curl_shim_get_version_int_value(IntPtr p, int offset);
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern int curl_shim_get_version_int_value(IntPtr p, int offset);
[DllImport(LIBCURLSHIM, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr curl_shim_get_version_char_ptr(IntPtr p, int offset);
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr curl_shim_get_version_char_ptr(IntPtr p, int offset);
[DllImport(LIBCURLSHIM, CallingConvention = CallingConvention.Cdecl)]
public static extern int curl_shim_get_number_of_protocols(IntPtr p, int offset);
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern int curl_shim_get_number_of_protocols(IntPtr p, int offset);
[DllImport(LIBCURLSHIM, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr curl_shim_get_protocol_string(IntPtr p, int offset, int index);
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr curl_shim_get_protocol_string(IntPtr p, int offset, int index);
public delegate void _ShimLockCallback(int data, int access, IntPtr userPtr);
internal delegate void _ShimLockCallback(int data, int access, IntPtr userPtr);
public delegate void _ShimUnlockCallback(int data, IntPtr userPtr);
internal delegate void _ShimUnlockCallback(int data, IntPtr userPtr);
public delegate int _ShimDebugCallback(CurlInfoType infoType, IntPtr msgBuf, int msgBufSize, IntPtr parm);
internal delegate int _ShimDebugCallback(CurlInfoType infoType, IntPtr msgBuf, int msgBufSize, IntPtr parm);
public delegate int _ShimHeaderCallback(IntPtr buf, int sz, int nmemb, IntPtr stream);
internal delegate int _ShimHeaderCallback(IntPtr buf, int sz, int nmemb, IntPtr stream);
public delegate CurlIoError _ShimIoctlCallback(CurlIoCommand cmd, IntPtr parm);
internal delegate CurlIoError _ShimIoctlCallback(CurlIoCommand cmd, IntPtr parm);
public delegate int _ShimProgressCallback(
IntPtr parm,
double dlTotal,
double dlNow,
double ulTotal,
double ulNow);
internal delegate int _ShimProgressCallback(IntPtr parm, double dlTotal, double dlNow, double ulTotal, double ulNow);
public delegate int _ShimReadCallback(IntPtr buf, int sz, int nmemb, IntPtr parm);
internal delegate int _ShimReadCallback(IntPtr buf, int sz, int nmemb, IntPtr parm);
public delegate int _ShimSslCtxCallback(IntPtr ctx, IntPtr parm);
public delegate int _ShimWriteCallback(IntPtr buf, int sz, int nmemb, IntPtr parm);
#endregion
internal delegate int _ShimSslCtxCallback(IntPtr ctx, IntPtr parm);
internal delegate int _ShimWriteCallback(IntPtr buf, int sz, int nmemb, IntPtr parm);
#endif
}
}
}

View File

@@ -0,0 +1,22 @@
using System.Reflection;
using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle ("CurlSharp")]
[assembly: AssemblyDescription ("")]
[assembly: AssemblyConfiguration ("")]
[assembly: AssemblyCompany ("")]
[assembly: AssemblyProduct ("")]
[assembly: AssemblyCopyright ("max")]
[assembly: AssemblyTrademark ("")]
[assembly: AssemblyCulture ("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion ("1.0.*")]
// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.
//[assembly: AssemblyDelaySign(false)]
//[assembly: AssemblyKeyFile("")]

View File

@@ -1,114 +0,0 @@
CurlSharp
=========
CurlSharp is a .Net binding and object-oriented wrapper for [libcurl](http://curl.haxx.se/libcurl/).
libcurl is a web-client library that can provide cross-platform .Net applications with an easy way to implement such things as:
- HTTP ( GET / HEAD / PUT / POST / multi-part / form-data )
- FTP ( upload / download / list / 3rd-party )
- HTTPS, FTPS, SSL, TLS ( via OpenSSL or GnuTLS )
- Proxies, proxy tunneling, cookies, user+password authentication.
- File transfer resume, byte ranges, multiple asynchronous transfers.
- and much more...
CurlSharp provides simple get/set properties for libcurl's options and information functions, event-based hooks to libcurl's I/O, status, and progress callbacks, and wraps the c-style file I/O behind simple filename properties. The `CurlEasy` class contains has more than 100 different properties and methods to handle a wide variety of URL transfer requirements. While this may seem overwhelming at first glance, the good news is you will probably need only a tiny subset of these for most situations.
The CurlSharp library consists of these parts:
- Pure C# P/Invoke bindings to the libcurl API.
- Optional libcurlshim helper DLL [WIN32].
- The `CurlEasy` class which provides a wrapper around a `curl_easy` session.
- The `CurlMulti` class, which serves as a container for multiple CurlEasy objects, and provides a wrapper around a `curl_multi` session.
- The `CurlShare` class which provides an infrastructure for serializing access to data shared by multiple `CurlEasy` objects, including cookie data and DNS hosts. It implements the `curl_share_xxx` API.
- The `CurlHttpMultiPartForm` to easily construct multi-part forms.
- The `CurlSlist` class which wraps a linked list of strings used in cURL.
CurlSharp is available for these platforms:
- [Stable] Windows 32-bit
- [Experimental] Win64 port
- [Experimental] Mono Linux & OS X support
#### Examples ####
A simple HTTP download program...
```c#
using System;
using CurlSharp;
internal class EasyGet
{
public static void Main(String[] args)
{
Curl.GlobalInit(CurlInitFlag.All);
try
{
using (var easy = new CurlEasy())
{
easy.Url = "http://www.google.com/";
easy.WriteFunction = OnWriteData;
easy.Perform();
}
}
finally
{
Curl.GlobalCleanup();
}
}
public static Int32 OnWriteData(byte[] buf, Int32 size, Int32 nmemb, object data)
{
Console.Write(Encoding.UTF8.GetString(buf));
return size*nmemb;
}
}
```
Simple HTTP Post example:
```c#
using (var easy = new CurlEasy())
{
easy.Url = "http://hostname/testpost.php";
easy.Post = true;
var postData = "parm1=12345&parm2=Hello+world%21";
easy.PostFields = postData;
easy.PostFieldSize = postData.Length;
easy.Perform();
}
```
HTTP/2.0 download:
```c#
using (var easy = new CurlEasy())
{
easy.Url = "https://google.com/";
easy.WriteFunction = OnWriteData;
// HTTP/2 please
easy.HttpVersion = CurlHttpVersion.Http2_0;
// skip SSL verification during debugging
easy.SslVerifyPeer = false;
easy.SslVerifyhost = false;
easy.Perform();
}
```
More samples are included in the Samples folder.
#### Credits ####
CurlSharp Written by Dr. Masroor Ehsan.
CurlSharp is based on original code by Jeff Phillips [libcurl.NET](http://sourceforge.net/projects/libcurl-net/). Original code has been modified and greatly enhanced.
----------
CurlSharp Copyright © 2013-17 Dr. Masroor Ehsan

View File

@@ -1,4 +1,10 @@
namespace CurlSharp
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CurlSharp
{
public class SSLFix
{

View File

@@ -1,618 +0,0 @@
//********************************************************************************************
//Author: Sergey Stoyan, CliverSoft.com
// http://cliversoft.com
// stoyan@cliversoft.com
// sergey.stoyan@gmail.com
// 27 February 2007
//********************************************************************************************
using System;
using System.Text.RegularExpressions;
namespace DateTimeRoutines
{
/// <summary>
/// Miscellaneous and parsing methods for DateTime
/// </summary>
public static class DateTimeRoutines
{
#region miscellaneous methods
/// <summary>
/// Amount of seconds elapsed between 1970-01-01 00:00:00 and the date-time.
/// </summary>
/// <param name="date_time">date-time</param>
/// <returns>seconds</returns>
public static uint GetSecondsSinceUnixEpoch(this DateTime date_time)
{
TimeSpan t = date_time - new DateTime(1970, 1, 1);
int ss = (int)t.TotalSeconds;
if (ss < 0)
return 0;
return (uint)ss;
}
#endregion
#region parsing definitions
/// <summary>
/// Defines a substring where date-time was found and result of conversion
/// </summary>
public class ParsedDateTime
{
/// <summary>
/// Index of first char of a date substring found in the string
/// </summary>
readonly public int IndexOfDate = -1;
/// <summary>
/// Length a date substring found in the string
/// </summary>
readonly public int LengthOfDate = -1;
/// <summary>
/// Index of first char of a time substring found in the string
/// </summary>
readonly public int IndexOfTime = -1;
/// <summary>
/// Length of a time substring found in the string
/// </summary>
readonly public int LengthOfTime = -1;
/// <summary>
/// DateTime found in the string
/// </summary>
readonly public DateTime DateTime;
/// <summary>
/// True if a date was found within the string
/// </summary>
readonly public bool IsDateFound;
/// <summary>
/// True if a time was found within the string
/// </summary>
readonly public bool IsTimeFound;
/// <summary>
/// UTC offset if it was found within the string
/// </summary>
readonly public TimeSpan UtcOffset;
/// <summary>
/// True if UTC offset was found in the string
/// </summary>
readonly public bool IsUtcOffsetFound;
/// <summary>
/// Utc gotten from DateTime if IsUtcOffsetFound is True
/// </summary>
public DateTime UtcDateTime;
internal ParsedDateTime(int index_of_date, int length_of_date, int index_of_time, int length_of_time, DateTime date_time)
{
IndexOfDate = index_of_date;
LengthOfDate = length_of_date;
IndexOfTime = index_of_time;
LengthOfTime = length_of_time;
DateTime = date_time;
IsDateFound = index_of_date > -1;
IsTimeFound = index_of_time > -1;
UtcOffset = new TimeSpan(25, 0, 0);
IsUtcOffsetFound = false;
UtcDateTime = new DateTime(1, 1, 1);
}
internal ParsedDateTime(int index_of_date, int length_of_date, int index_of_time, int length_of_time, DateTime date_time, TimeSpan utc_offset)
{
IndexOfDate = index_of_date;
LengthOfDate = length_of_date;
IndexOfTime = index_of_time;
LengthOfTime = length_of_time;
DateTime = date_time;
IsDateFound = index_of_date > -1;
IsTimeFound = index_of_time > -1;
UtcOffset = utc_offset;
IsUtcOffsetFound = Math.Abs(utc_offset.TotalHours) < 12;
if (!IsUtcOffsetFound)
UtcDateTime = new DateTime(1, 1, 1);
else
{
if (index_of_date < 0)//to avoid negative date exception when date is undefined
{
TimeSpan ts = date_time.TimeOfDay + utc_offset;
if (ts < new TimeSpan(0))
UtcDateTime = new DateTime(1, 1, 2) + ts;
else
UtcDateTime = new DateTime(1, 1, 1) + ts;
}
else
UtcDateTime = date_time + utc_offset;
}
}
}
/// <summary>
/// Date that is accepted in the following cases:
/// - no date was parsed by TryParseDateOrTime();
/// - no year was found by TryParseDate();
/// It is ignored if DefaultDateIsNow = true was set after DefaultDate
/// </summary>
public static DateTime DefaultDate
{
set
{
_DefaultDate = value;
DefaultDateIsNow = false;
}
get
{
if (DefaultDateIsNow)
return DateTime.Now;
else
return _DefaultDate;
}
}
static DateTime _DefaultDate = DateTime.Now;
/// <summary>
/// If true then DefaultDate property is ignored and DefaultDate is always DateTime.Now
/// </summary>
public static bool DefaultDateIsNow = true;
/// <summary>
/// Defines default date-time format.
/// </summary>
public enum DateTimeFormat
{
/// <summary>
/// month number goes before day number
/// </summary>
USA_DATE,
/// <summary>
/// day number goes before month number
/// </summary>
UK_DATE,
///// <summary>
///// time is specifed through AM or PM
///// </summary>
//USA_TIME,
}
#endregion
#region parsing derived methods for DateTime output
/// <summary>
/// Tries to find date and time within the passed string and return it as DateTime structure.
/// </summary>
/// <param name="str">string that contains date and/or time</param>
/// <param name="default_format">format to be used preferably in ambivalent instances</param>
/// <param name="date_time">parsed date-time output</param>
/// <returns>true if both date and time were found, else false</returns>
static public bool TryParseDateTime(this string str, DateTimeFormat default_format, out DateTime date_time)
{
ParsedDateTime parsed_date_time;
if (!TryParseDateTime(str, default_format, out parsed_date_time))
{
date_time = new DateTime(1, 1, 1);
return false;
}
date_time = parsed_date_time.DateTime;
return true;
}
/// <summary>
/// Tries to find date and/or time within the passed string and return it as DateTime structure.
/// If only date was found, time in the returned DateTime is always 0:0:0.
/// If only time was found, date in the returned DateTime is DefaultDate.
/// </summary>
/// <param name="str">string that contains date and(or) time</param>
/// <param name="default_format">format to be used preferably in ambivalent instances</param>
/// <param name="date_time">parsed date-time output</param>
/// <returns>true if date and/or time was found, else false</returns>
static public bool TryParseDateOrTime(this string str, DateTimeFormat default_format, out DateTime date_time)
{
ParsedDateTime parsed_date_time;
if (!TryParseDateOrTime(str, default_format, out parsed_date_time))
{
date_time = new DateTime(1, 1, 1);
return false;
}
date_time = parsed_date_time.DateTime;
return true;
}
/// <summary>
/// Tries to find time within the passed string and return it as DateTime structure.
/// It recognizes only time while ignoring date, so date in the returned DateTime is always 1/1/1.
/// </summary>
/// <param name="str">string that contains time</param>
/// <param name="default_format">format to be used preferably in ambivalent instances</param>
/// <param name="time">parsed time output</param>
/// <returns>true if time was found, else false</returns>
public static bool TryParseTime(this string str, DateTimeFormat default_format, out DateTime time)
{
ParsedDateTime parsed_time;
if (!TryParseTime(str, default_format, out parsed_time, null))
{
time = new DateTime(1, 1, 1);
return false;
}
time = parsed_time.DateTime;
return true;
}
/// <summary>
/// Tries to find date within the passed string and return it as DateTime structure.
/// It recognizes only date while ignoring time, so time in the returned DateTime is always 0:0:0.
/// If year of the date was not found then it accepts the current year.
/// </summary>
/// <param name="str">string that contains date</param>
/// <param name="default_format">format to be used preferably in ambivalent instances</param>
/// <param name="date">parsed date output</param>
/// <returns>true if date was found, else false</returns>
static public bool TryParseDate(this string str, DateTimeFormat default_format, out DateTime date)
{
ParsedDateTime parsed_date;
if (!TryParseDate(str, default_format, out parsed_date))
{
date = new DateTime(1, 1, 1);
return false;
}
date = parsed_date.DateTime;
return true;
}
#endregion
#region parsing derived methods for ParsedDateTime output
/// <summary>
/// Tries to find date and time within the passed string and return it as ParsedDateTime object.
/// </summary>
/// <param name="str">string that contains date-time</param>
/// <param name="default_format">format to be used preferably in ambivalent instances</param>
/// <param name="parsed_date_time">parsed date-time output</param>
/// <returns>true if both date and time were found, else false</returns>
static public bool TryParseDateTime(this string str, DateTimeFormat default_format, out ParsedDateTime parsed_date_time)
{
if (DateTimeRoutines.TryParseDateOrTime(str, default_format, out parsed_date_time)
&& parsed_date_time.IsDateFound
&& parsed_date_time.IsTimeFound
)
return true;
parsed_date_time = null;
return false;
}
/// <summary>
/// Tries to find time within the passed string and return it as ParsedDateTime object.
/// It recognizes only time while ignoring date, so date in the returned ParsedDateTime is always 1/1/1
/// </summary>
/// <param name="str">string that contains date-time</param>
/// <param name="default_format">format to be used preferably in ambivalent instances</param>
/// <param name="parsed_time">parsed date-time output</param>
/// <returns>true if time was found, else false</returns>
static public bool TryParseTime(this string str, DateTimeFormat default_format, out ParsedDateTime parsed_time)
{
return TryParseTime(str, default_format, out parsed_time, null);
}
/// <summary>
/// Tries to find date and/or time within the passed string and return it as ParsedDateTime object.
/// If only date was found, time in the returned ParsedDateTime is always 0:0:0.
/// If only time was found, date in the returned ParsedDateTime is DefaultDate.
/// </summary>
/// <param name="str">string that contains date-time</param>
/// <param name="default_format">format to be used preferably in ambivalent instances</param>
/// <param name="parsed_date_time">parsed date-time output</param>
/// <returns>true if date or time was found, else false</returns>
static public bool TryParseDateOrTime(this string str, DateTimeFormat default_format, out ParsedDateTime parsed_date_time)
{
parsed_date_time = null;
ParsedDateTime parsed_date;
ParsedDateTime parsed_time;
if (!TryParseDate(str, default_format, out parsed_date))
{
if (!TryParseTime(str, default_format, out parsed_time, null))
return false;
DateTime date_time = new DateTime(DefaultDate.Year, DefaultDate.Month, DefaultDate.Day, parsed_time.DateTime.Hour, parsed_time.DateTime.Minute, parsed_time.DateTime.Second);
parsed_date_time = new ParsedDateTime(-1, -1, parsed_time.IndexOfTime, parsed_time.LengthOfTime, date_time, parsed_time.UtcOffset);
}
else
{
if (!TryParseTime(str, default_format, out parsed_time, parsed_date))
{
DateTime date_time = new DateTime(parsed_date.DateTime.Year, parsed_date.DateTime.Month, parsed_date.DateTime.Day, 0, 0, 0);
parsed_date_time = new ParsedDateTime(parsed_date.IndexOfDate, parsed_date.LengthOfDate, -1, -1, date_time);
}
else
{
DateTime date_time = new DateTime(parsed_date.DateTime.Year, parsed_date.DateTime.Month, parsed_date.DateTime.Day, parsed_time.DateTime.Hour, parsed_time.DateTime.Minute, parsed_time.DateTime.Second);
parsed_date_time = new ParsedDateTime(parsed_date.IndexOfDate, parsed_date.LengthOfDate, parsed_time.IndexOfTime, parsed_time.LengthOfTime, date_time, parsed_time.UtcOffset);
}
}
return true;
}
#endregion
#region parsing base methods
/// <summary>
/// Tries to find time within the passed string (relatively to the passed parsed_date if any) and return it as ParsedDateTime object.
/// It recognizes only time while ignoring date, so date in the returned ParsedDateTime is always 1/1/1
/// </summary>
/// <param name="str">string that contains date</param>
/// <param name="default_format">format to be used preferably in ambivalent instances</param>
/// <param name="parsed_time">parsed date-time output</param>
/// <param name="parsed_date">ParsedDateTime object if the date was found within this string, else NULL</param>
/// <returns>true if time was found, else false</returns>
public static bool TryParseTime(this string str, DateTimeFormat default_format, out ParsedDateTime parsed_time, ParsedDateTime parsed_date)
{
parsed_time = null;
string time_zone_r;
if(default_format == DateTimeFormat.USA_DATE)
time_zone_r = @"(?:\s*(?'time_zone'UTC|GMT|CST|EST))?";
else
time_zone_r = @"(?:\s*(?'time_zone'UTC|GMT))?";
Match m;
if (parsed_date != null && parsed_date.IndexOfDate > -1)
{//look around the found date
//look for <date> hh:mm:ss <UTC offset>
m = Regex.Match(str.Substring(parsed_date.IndexOfDate + parsed_date.LengthOfDate), @"(?<=^\s*,?\s+|^\s*at\s*|^\s*[T\-]\s*)(?'hour'\d{2})\s*:\s*(?'minute'\d{2})\s*:\s*(?'second'\d{2})\s+(?'offset_sign'[\+\-])(?'offset_hh'\d{2}):?(?'offset_mm'\d{2})(?=$|[^\d\w])", RegexOptions.Compiled);
if (!m.Success)
//look for <date> [h]h:mm[:ss] [PM/AM] [UTC/GMT]
m = Regex.Match(str.Substring(parsed_date.IndexOfDate + parsed_date.LengthOfDate), @"(?<=^\s*,?\s+|^\s*at\s*|^\s*[T\-]\s*)(?'hour'\d{1,2})\s*:\s*(?'minute'\d{2})\s*(?::\s*(?'second'\d{2}))?(?:\s*(?'ampm'AM|am|PM|pm))?"+time_zone_r+@"(?=$|[^\d\w])", RegexOptions.Compiled);
if (!m.Success)
//look for [h]h:mm:ss [PM/AM] [UTC/GMT] <date>
m = Regex.Match(str.Substring(0, parsed_date.IndexOfDate), @"(?<=^|[^\d])(?'hour'\d{1,2})\s*:\s*(?'minute'\d{2})\s*(?::\s*(?'second'\d{2}))?(?:\s*(?'ampm'AM|am|PM|pm))?"+time_zone_r+@"(?=$|[\s,]+)", RegexOptions.Compiled);
if (!m.Success)
//look for [h]h:mm:ss [PM/AM] [UTC/GMT] within <date>
m = Regex.Match(str.Substring(parsed_date.IndexOfDate, parsed_date.LengthOfDate), @"(?<=^|[^\d])(?'hour'\d{1,2})\s*:\s*(?'minute'\d{2})\s*(?::\s*(?'second'\d{2}))?(?:\s*(?'ampm'AM|am|PM|pm))?"+time_zone_r+@"(?=$|[\s,]+)", RegexOptions.Compiled);
}
else//look anywhere within string
{
//look for hh:mm:ss <UTC offset>
m = Regex.Match(str, @"(?<=^|\s+|\s*T\s*)(?'hour'\d{2})\s*:\s*(?'minute'\d{2})\s*:\s*(?'second'\d{2})\s+(?'offset_sign'[\+\-])(?'offset_hh'\d{2}):?(?'offset_mm'\d{2})?(?=$|[^\d\w])", RegexOptions.Compiled);
if (!m.Success)
//look for [h]h:mm[:ss] [PM/AM] [UTC/GMT]
m = Regex.Match(str, @"(?<=^|\s+|\s*T\s*)(?'hour'\d{1,2})\s*:\s*(?'minute'\d{2})\s*(?::\s*(?'second'\d{2}))?(?:\s*(?'ampm'AM|am|PM|pm))?"+time_zone_r+@"(?=$|[^\d\w])", RegexOptions.Compiled);
}
if (!m.Success)
return false;
//try
//{
int hour = int.Parse(m.Groups["hour"].Value);
if (hour < 0 || hour > 23)
return false;
int minute = int.Parse(m.Groups["minute"].Value);
if (minute < 0 || minute > 59)
return false;
int second = 0;
if (!string.IsNullOrEmpty(m.Groups["second"].Value))
{
second = int.Parse(m.Groups["second"].Value);
if (second < 0 || second > 59)
return false;
}
if (string.Compare(m.Groups["ampm"].Value, "PM", true) == 0 && hour < 12)
hour += 12;
else if (string.Compare(m.Groups["ampm"].Value, "AM", true) == 0 && hour == 12)
hour -= 12;
DateTime date_time = new DateTime(1, 1, 1, hour, minute, second);
if (m.Groups["offset_hh"].Success)
{
int offset_hh = int.Parse(m.Groups["offset_hh"].Value);
int offset_mm = 0;
if (m.Groups["offset_mm"].Success)
offset_mm = int.Parse(m.Groups["offset_mm"].Value);
TimeSpan utc_offset = new TimeSpan(offset_hh, offset_mm, 0);
if (m.Groups["offset_sign"].Value == "-")
utc_offset = -utc_offset;
parsed_time = new ParsedDateTime(-1, -1, m.Index, m.Length, date_time, utc_offset);
return true;
}
if (m.Groups["time_zone"].Success)
{
TimeSpan utc_offset;
switch (m.Groups["time_zone"].Value)
{
case "UTC":
case "GMT":
utc_offset = new TimeSpan(0, 0, 0);
break;
case "CST":
utc_offset = new TimeSpan(-6, 0, 0);
break;
case "EST":
utc_offset = new TimeSpan(-5, 0, 0);
break;
default:
throw new Exception("Time zone: " + m.Groups["time_zone"].Value + " is not defined.");
}
parsed_time = new ParsedDateTime(-1, -1, m.Index, m.Length, date_time, utc_offset);
return true;
}
parsed_time = new ParsedDateTime(-1, -1, m.Index, m.Length, date_time);
//}
//catch(Exception e)
//{
// return false;
//}
return true;
}
/// <summary>
/// Tries to find date within the passed string and return it as ParsedDateTime object.
/// It recognizes only date while ignoring time, so time in the returned ParsedDateTime is always 0:0:0.
/// If year of the date was not found then it accepts the current year.
/// </summary>
/// <param name="str">string that contains date</param>
/// <param name="default_format">format to be used preferably in ambivalent instances</param>
/// <param name="parsed_date">parsed date output</param>
/// <returns>true if date was found, else false</returns>
static public bool TryParseDate(this string str, DateTimeFormat default_format, out ParsedDateTime parsed_date)
{
parsed_date = null;
if (string.IsNullOrEmpty(str))
return false;
//look for dd/mm/yy
Match m = Regex.Match(str, @"(?<=^|[^\d])(?'day'\d{1,2})\s*(?'separator'[\\/\.])+\s*(?'month'\d{1,2})\s*\'separator'+\s*(?'year'\d{2}|\d{4})(?=$|[^\d])", RegexOptions.Compiled | RegexOptions.IgnoreCase);
if (m.Success)
{
DateTime date;
if ((default_format ^ DateTimeFormat.USA_DATE) == DateTimeFormat.USA_DATE)
{
if (!convert_to_date(int.Parse(m.Groups["year"].Value), int.Parse(m.Groups["day"].Value), int.Parse(m.Groups["month"].Value), out date))
return false;
}
else
{
if (!convert_to_date(int.Parse(m.Groups["year"].Value), int.Parse(m.Groups["month"].Value), int.Parse(m.Groups["day"].Value), out date))
return false;
}
parsed_date = new ParsedDateTime(m.Index, m.Length, -1, -1, date);
return true;
}
//look for [yy]yy-mm-dd
m = Regex.Match(str, @"(?<=^|[^\d])(?'year'\d{2}|\d{4})\s*(?'separator'[\-])\s*(?'month'\d{1,2})\s*\'separator'+\s*(?'day'\d{1,2})(?=$|[^\d])", RegexOptions.Compiled | RegexOptions.IgnoreCase);
if (m.Success)
{
DateTime date;
if (!convert_to_date(int.Parse(m.Groups["year"].Value), int.Parse(m.Groups["month"].Value), int.Parse(m.Groups["day"].Value), out date))
return false;
parsed_date = new ParsedDateTime(m.Index, m.Length, -1, -1, date);
return true;
}
//look for month dd yyyy
m = Regex.Match(str, @"(?:^|[^\d\w])(?'month'Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[uarychilestmbro]*\s+(?'day'\d{1,2})(?:-?st|-?th|-?rd|-?nd)?\s*,?\s*(?'year'\d{4})(?=$|[^\d\w])", RegexOptions.Compiled | RegexOptions.IgnoreCase);
if (!m.Success)
//look for dd month [yy]yy
m = Regex.Match(str, @"(?:^|[^\d\w:])(?'day'\d{1,2})(?:-?st\s+|-?th\s+|-?rd\s+|-?nd\s+|-|\s+)(?'month'Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[uarychilestmbro]*(?:\s*,?\s*|-)'?(?'year'\d{2}|\d{4})(?=$|[^\d\w])", RegexOptions.Compiled | RegexOptions.IgnoreCase);
if (!m.Success)
//look for yyyy month dd
m = Regex.Match(str, @"(?:^|[^\d\w])(?'year'\d{4})\s+(?'month'Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[uarychilestmbro]*\s+(?'day'\d{1,2})(?:-?st|-?th|-?rd|-?nd)?(?=$|[^\d\w])", RegexOptions.Compiled | RegexOptions.IgnoreCase);
if (!m.Success)
//look for month dd hh:mm:ss MDT|UTC yyyy
m = Regex.Match(str, @"(?:^|[^\d\w])(?'month'Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[uarychilestmbro]*\s+(?'day'\d{1,2})\s+\d{2}\:\d{2}\:\d{2}\s+(?:MDT|UTC)\s+(?'year'\d{4})(?=$|[^\d\w])", RegexOptions.Compiled | RegexOptions.IgnoreCase);
if (!m.Success)
//look for month dd [yyyy]
m = Regex.Match(str, @"(?:^|[^\d\w])(?'month'Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[uarychilestmbro]*\s+(?'day'\d{1,2})(?:-?st|-?th|-?rd|-?nd)?(?:\s*,?\s*(?'year'\d{4}))?(?=$|[^\d\w])", RegexOptions.Compiled | RegexOptions.IgnoreCase);
if (m.Success)
{
int month = -1;
int index_of_date = m.Index;
int length_of_date = m.Length;
switch (m.Groups["month"].Value)
{
case "Jan":
case "JAN":
month = 1;
break;
case "Feb":
case "FEB":
month = 2;
break;
case "Mar":
case "MAR":
month = 3;
break;
case "Apr":
case "APR":
month = 4;
break;
case "May":
case "MAY":
month = 5;
break;
case "Jun":
case "JUN":
month = 6;
break;
case "Jul":
month = 7;
break;
case "Aug":
case "AUG":
month = 8;
break;
case "Sep":
case "SEP":
month = 9;
break;
case "Oct":
case "OCT":
month = 10;
break;
case "Nov":
case "NOV":
month = 11;
break;
case "Dec":
case "DEC":
month = 12;
break;
}
int year;
if (!string.IsNullOrEmpty(m.Groups["year"].Value))
year = int.Parse(m.Groups["year"].Value);
else
year = DefaultDate.Year;
DateTime date;
if (!convert_to_date(year, month, int.Parse(m.Groups["day"].Value), out date))
return false;
parsed_date = new ParsedDateTime(index_of_date, length_of_date, -1, -1, date);
return true;
}
return false;
}
static bool convert_to_date(int year, int month, int day, out DateTime date)
{
if (year >= 100)
{
if (year < 1000)
{
date = new DateTime(1, 1, 1);
return false;
}
}
else
if (year > 30)
year += 1900;
else
year += 2000;
try
{
date = new DateTime(year, month, day);
}
catch
{
date = new DateTime(1, 1, 1);
return false;
}
return true;
}
#endregion
}
}

View File

@@ -1,7 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net452</TargetFrameworks>
</PropertyGroup>
</Project>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

View File

@@ -1 +0,0 @@
span.multiselect-native-select{position:relative}span.multiselect-native-select select{border:0!important;clip:rect(0 0 0 0)!important;height:1px!important;margin:-1px -1px -1px -3px!important;overflow:hidden!important;padding:0!important;position:absolute!important;width:1px!important;left:50%;top:30px}.multiselect-container{position:absolute;list-style-type:none;margin:0;padding:0}.multiselect-container .input-group{margin:5px}.multiselect-container>li{padding:0}.multiselect-container>li>a.multiselect-all label{font-weight:700}.multiselect-container>li.multiselect-group label{margin:0;padding:3px 20px 3px 20px;height:100%;font-weight:700}.multiselect-container>li.multiselect-group-clickable label{cursor:pointer}.multiselect-container>li>a{padding:0}.multiselect-container>li>a>label{margin:0;height:100%;cursor:pointer;font-weight:400;padding:3px 20px 3px 40px}.multiselect-container>li>a>label.radio,.multiselect-container>li>a>label.checkbox{margin:0}.multiselect-container>li>a>label>input[type=checkbox]{margin-bottom:5px}.btn-group>.btn-group:nth-child(2)>.multiselect.btn{border-top-left-radius:4px;border-bottom-left-radius:4px}.form-inline .multiselect-container label.checkbox,.form-inline .multiselect-container label.radio{padding:3px 20px 3px 40px}.form-inline .multiselect-container li a label.checkbox input[type=checkbox],.form-inline .multiselect-container li a label.radio input[type=radio]{margin-left:-20px;margin-right:0}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -1,668 +0,0 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0" />
<meta name="mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta charset="utf-8" />
<meta name="referrer" content="no-referrer" /> <!-- Don't send referrer when loading third party ressources (E.g. Empornium banner images won't load) -->
<link rel="apple-touch-icon" href="../apple-touch-icon.png" />
<link rel="apple-touch-icon" sizes="57x57" href="../apple-touch-icon-57x57.png" />
<link rel="apple-touch-icon" sizes="72x72" href="../apple-touch-icon-72x72.png" />
<link rel="apple-touch-icon" sizes="76x76" href="../apple-touch-icon-76x76.png" />
<link rel="apple-touch-icon" sizes="114x114" href="../apple-touch-icon-114x114.png" />
<link rel="apple-touch-icon" sizes="120x120" href="../apple-touch-icon-120x120.png" />
<link rel="apple-touch-icon" sizes="144x144" href="../apple-touch-icon-144x144" />
<link rel="apple-touch-icon" sizes="152x152" href="../apple-touch-icon-152x152.png" />
<link rel="apple-touch-icon" sizes="180x180" href="../apple-touch-icon-180x180.png" />
<link rel="mask-icon" href="jackett_medium.png" color="#35c5f4">
<link rel="icon" type="image/ico" href="../favicon.ico" />
<link rel='shortcut icon' type='image/x-icon' href='../favicon.ico' />
<script type="text/javascript" src="../libs/filesize.min.js?changed=2017083001"></script>
<script type="text/javascript" src="../libs/jquery.min.js?changed=2017083001"></script>
<script type="text/javascript" src="../libs/jquery.dataTables.min.js?changed=2017083001" charset="utf8"></script>
<script type="text/javascript" src="../libs/handlebars.min.js?changed=2017083001"></script>
<script type="text/javascript" src="../libs/moment.min.js?changed=2017083001"></script>
<script type="text/javascript" src="../libs/handlebarsmoment.js?changed=2017083001"></script>
<script type="text/javascript" src="../libs/handlebarsextend.js?changed=2017083001"></script>
<script type="text/javascript" src="../bootstrap/bootstrap.min.js?changed=2017083001"></script>
<script type="text/javascript" src="../libs/bootstrap-notify.js?changed=2017083001"></script>
<script type="text/javascript" src="../libs/bootstrap-multiselect.js?changed=2017083001"></script>
<!--<script type="text/javascript" src="https://www.google.com/recaptcha/api.js?render=explicit" async defer></script>-->
<link rel="stylesheet" type="text/css" href="../bootstrap/bootstrap.min.css?changed=2017083001">
<link rel="stylesheet" type="text/css" href="../animate.css?changed=2017083001">
<link rel="stylesheet" type="text/css" href="../custom.css?changed=2017083001" media="only screen and (min-device-width: 480px)">
<link rel="stylesheet" type="text/css" href="../custom_mobile.css?changed=2017083001" media="only screen and (max-device-width: 480px)">
<link rel="stylesheet" type="text/css" href="../css/jquery.dataTables.min.css?changed=2017083001">
<link rel="stylesheet" type="text/css" href="../css/bootstrap-multiselect.css?changed=2017083001" />
<link rel="stylesheet" type="text/css" href="../css/font-awesome.min.css?changed=2017083001">
<title>Jackett</title>
</head>
<body>
<div id="page">
<img id="logo" src="../jacket_medium.png" alt="Logo" /><span id="header-title">Jackett</span>
<div class="pull-right jackett-apikey">
<span class="input-header">API Key: </span>
<input id="api-key-input" class="form-control input-right" type="text" value="" placeholder="API Key" readonly="">
</div>
<hr />
<div class="pull-right">
<button id="jackett-add-indexer" class="btn btn-success btn-sm">
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add indexer
</button>
<button id="jackett-show-search" class="btn btn-success btn-sm">
<span class="glyphicon glyphicon-search" aria-hidden="true"></span> Manual Search
</button>
<button id="jackett-show-releases" class="btn btn-primary btn-sm">
<i class="fa fa-database"></i> View cached releases
</button>
<button id="jackett-test-all" class="btn btn-warning btn-sm">
<span class="glyphicon glyphicon-screenshot" aria-hidden="true"></span> Test All
</button>
</div>
<h3>Configured Indexers</h3>
<div id="indexers"> </div>
<hr />
<div class="input-area">
<h4>Adding a Jackett indexer in Sonarr or Radarr</h4>
<ol>
<li>Go to <b>Settings > Indexers > Add > Torznab > Custom</b>.</li>
<li>Click on the indexers corresponding <button type="button" class="btn btn-xs btn-info">Copy Torznab Feed</button> button and paste it into the Sonarr/Radarr <b>URL</b> field.</li>
<li>For the <b>API key</b> use <b class="api-key-text"></b>.</li>
<li>Configure the correct category IDs via the <b>(Anime) Categories</b> options. See the Jackett indexer configuration for a list of supported categories.</li>
</ol>
<h4>Adding a Jackett indexer in CouchPotato</h4>
<ol>
<li>Go to <b>Settings > Searchers</b>.</li>
<li>Enable <b>TorrentPotato</b>.
<li>Click on the indexers corresponding <button type="button" class="btn btn-xs btn-info">Copy Potato Feed</button> button and paste it into the CouchPotato <b>host</b> field.</li>
<li>For the <b>Passkey</b> use <b class="api-key-text"></b>. Leave the <b>username</b> field blank.</li>
</ol>
<h4>Adding a Jackett indexer to RSS clients (RSS feed)</h4>
<ol>
<li>Click on the indexers corresponding <button type="button" class="btn btn-xs btn-info">Copy RSS Feed</button> button and paste it into the URL field of the RSS client.</li>
<li>You can adjust the <b>q</b> (search string) and <b>cat</b> (categories) arguments accordingly.
E.g. <b>...&cat=2030,2040&q=big+buck+bunny</b> will search for "big buck bunny" in the Movies/SD (2030) and Movies/HD (2040) categories (See the indexer configuration for available categories).</li>
</ol>
</div>
<hr />
<h3>Jackett Configuration</h3>
<div class="text-center">
<div class="btn-toolbar">
<button id="change-jackett-port" class="btn btn-primary btn-sm">
<i class="fa fa-wrench"></i> Apply server settings <span class="glyphicon glyphicon-ok-wrench" aria-hidden="true"></span>
</button>
<button id="view-jackett-logs" class="btn btn-success btn-sm">
<i class="fa fa-rss"></i> View logs <span class="glyphicon glyphicon-ok-wrench" aria-hidden="true"></span>
</button>
<button id="trigger-updater" class="btn btn-warning btn-sm">
<i class="fa fa-wrench"></i> Check for updates <span class="glyphicon glyphicon-ok-wrench" aria-hidden="true"></span>
</button>
</div>
</div>
<br />
<div class="input-area">
<span class="input-header">Admin password: </span>
<input id="jackett-adminpwd" class="form-control input-right" type="password" value="" placeholder="Blank to disable" />
<button id="change-jackett-password" class="btn btn-primary btn-sm">
<i class="fa fa-user-secret"></i> Set Password <span class="glyphicon glyphicon-ok-wrench" aria-hidden="true"></span>
</button>
<a href="Dashboard?logout=true" id="logoutBtn" style="display:none" class="btn btn-danger btn-sm">
Logout
</a>
</div>
<div class="input-area">
<span class="input-header">Base Path Override: </span>
<input id="jackett-basepathoverride" class="form-control input-right" type="text" value="" placeholder="/jackett">
</div>
<div class="input-area">
<span class="input-header">Server port: </span>
<input id="jackett-port" class="form-control input-right" type="text" value="" placeholder="9117">
</div>
<div class="input-area">
<span class="input-header">Manual download blackhole directory: </span>
<input id="jackett-savedir" class="form-control input-right" type="text" value="" placeholder="c:\torrents\">
</div>
<div class="input-area">
<span class="input-header">Proxy type: </span>
<select id="jackett-proxy-type" class="form-control input-right">
<option value="0">http</option>
<option value="1">socks4</option>
<option value="2">socks5</option>
</select>
</div>
<div class="input-area">
<span class="input-header">Proxy url: </span>
<input id="jackett-proxy-url" class="form-control input-right" type="text" value="" placeholder="Blank to disable">
</div>
<div class="input-area">
<span class="input-header">Proxy port: </span>
<input id="jackett-proxy-port" class="form-control input-right" type="text" value="" placeholder="">
</div>
<div class="input-area">
<span class="input-header">Proxy username: </span>
<input id="jackett-proxy-username" class="form-control input-right" type="text" value="" placeholder="">
</div>
<div class="input-area">
<span class="input-header">Proxy password: </span>
<input id="jackett-proxy-password" class="form-control input-right" type="text" value="" placeholder="">
</div>
<div class="input-area">
<span class="input-header">External access: </span>
<input id="jackett-allowext" class="form-control input-right" type="checkbox" />
</div>
<div class="input-area">
<span class="input-header">Disable auto update: </span>
<input id="jackett-allowupdate" class="form-control input-right" type="checkbox" />
</div>
<div class="input-area">
<span class="input-header">Update to pre-release: </span>
<input id="jackett-prerelease" class="form-control input-right" type="checkbox" />
</div>
<div class="input-area">
<span class="input-header">Enhanced logging: </span>
<input id="jackett-logging" class="form-control input-right" type="checkbox" />
</div>
<div class="input-area">
<span class="input-header">OMDB API key: </span>
<input id="jackett-omdbkey" class="form-control input-right" type="text" value="" placeholder="">
</div>
<div class="input-area">
<span class="input-header">OMDB API Url: </span>
<input id="jackett-omdburl" class="form-control input-right" type="text" value="" placeholder="Blank for default">
</div>
<hr />
<div id="footer">
<a href="https://github.com/Jackett/Jackett" target="_blank" title="Jackett on GitHub">Jackett</a> Version <span id="app-version"></span>
</div>
</div>
<div id="modals"></div>
<script id="setup-item-nonlocalrecaptcha" type="text/x-handlebars-template">
<div class="setup-item-recaptcha">
<p>This site requires you to solve a ReCaptcha. It's no longer possible to solve the captcha in Jackett. Please enter the cookie for the site manually. <a href="https://github.com/Jackett/Jackett/wiki/Finding-cookies" target="_blank">See here</a> on how get the cookies.</p>
<div class="setup-item-label">Full cookie header</div>
<input class="form-control" type="text" value="{{cookieheader}}" />
</div>
</script>
<script id="setup-item" type="text/x-handlebars-template">
<div class="setup-item form-group" data-id="{{id}}" data-value="{{value}}" data-type="{{type}}">
<div class="setup-item-label">{{name}}</div>
<div class="setup-item-value">{{{value_element}}}</div>
</div>
</script>
<script id="setup-item-inputstring" type="text/x-handlebars-template">
<div class="setup-item-inputstring">
{{#if ispassword}}
<input class="form-control" type="password" value="{{{value}}}" />
{{else}}
<input class="form-control" type="text" value="{{{value}}}" />
{{/if}}
</div>
</script>
<script id="setup-item-inputbool" type="text/x-handlebars-template">
<div class="setup-item-inputbool">
{{#if value}}
<input type="checkbox" data-id="{{id}}" class="form-control" checked />
{{else}}
<input type="checkbox" data-id="{{id}}" class="form-control" />
{{/if}}
</div>
</script>
<script id="setup-item-inputselect" type="text/x-handlebars-template">
<div class="setup-item-inputselect">
<select class="form-control" data-id="{{id}}">
{{#each options}}
{{#ifCond ../value @key}}
<option value="{{@key}}" selected>{{this}}</option>
{{else}}
<option value="{{@key}}">{{this}}</option>
{{/ifCond}}
{{/each}}
</select>
</div>
</script>
<script id="setup-item-recaptcha" type="text/x-handlebars-template">
<div class="jackettrecaptcha">
</div>
</script>
<script id="setup-item-displayimage" type="text/x-handlebars-template">
<img class="setup-item-displayimage" src="{{{value}}}" alt="No image available" />
</script>
<script id="setup-item-displayinfo" type="text/x-handlebars-template">
<div class="setup-item-displayinfo alert alert-info" role="alert">{{{value}}}</div>
</script>
<script id="setup-item-hiddendata" type="text/x-handlebars-template">
<div class="setup-item-hiddendata">
<input class="form-control" type="text" value="{{{value}}}" />
</div>
</script>
<script id="setup-item-alternativesitelinks" type="text/x-handlebars-template">
<div class="setup-item-alternativesitelinks alert alert-info" role="alert">
This indexer has multiple known URLs:
<ul>
{{#each alternativesitelinks}}
<li><a target="_blank" href="{{this}}" class="alternativesitelink">{{this}}</a></li>
{{/each}}
</ul>
Click on an URL to copy it to the Site Link field.
</div>
</script>
<script id="configured-indexer-table" type="text/x-handlebars-template">
<div class="configured-indexer-div">
<table id="configured-indexer-datatable" class="indexer-table dataTable compact cell-border hover stripe table table-responsive">
<thead>
<tr>
<th>Indexer</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{{#each indexers}}
<tr class="configured-indexer-row">
<td><a target="_blank" href="{{site_link}}" title="{{description}}">{{name}}</a> <span title="{{type}}" class="label label-{{type_label}}" style="text-transform: capitalize;">{{type}}</span></td>
<td class="fit">
<div class="indexer-buttons">
<a href="{{rss_host}}" title="{{rss_host}}" role="button" class="indexer-button-copy btn btn-xs btn-info">Copy RSS Feed</i></a>
<a href="{{torznab_host}}" title="{{torznab_host}}" role="button" class="indexer-button-copy btn btn-xs btn-info">Copy Torznab Feed</a>
<a href="{{potato_host}}" title="{{potato_host}}" role="button" class="indexer-button-copy btn btn-xs btn-info{{#unless potatoenabled}} disabled{{/unless}}">Copy Potato Feed</a>
<button title="Search" class="btn btn-success btn-xs indexer-button-search" data-id="{{id}}">
<span class="glyphicon glyphicon-search" aria-hidden="true"></span>
</button>
<button title="Configure" class="btn btn-primary btn-xs indexer-setup" data-id="{{id}}" data-link="{{site_link}}">
<span class="glyphicon glyphicon-wrench" aria-hidden="true"></span>
</button>
<button title="Delete" class="btn btn-danger btn-xs indexer-button-delete" data-id="{{id}}">
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span>
</button>
<button title="{{last_error}}" class="btn btn-warning btn-xs indexer-button-test" data-toggle="tooltip" data-id="{{id}}" data-state="{{state}}">
Test
<span class="glyphicon" aria-hidden="true"></span>
</button>
</div>
</td>
</tr>
{{/each}}
</tbody>
<tfoot>
<tr>
<td colspan="2"></td>
</tr>
</tfoot>
</table>
</div>
</script>
<script id="unconfigured-indexer-table" type="text/x-handlebars-template">
<div class="unconfigured-indexer-div">
<table id="unconfigured-indexer-datatable" class="indexer-table dataTable compact cell-border hover stripe table table-responsive">
<thead>
<tr>
<th>Indexer</th>
<th>Categories</th>
<th>Type</th>
<th>Type string</th>
<th>Language</th>
<th></th>
</tr>
</thead>
<tbody>
{{#each indexers}}
<tr class="unconfigured-indexer-row">
<td><a target="_blank" href="{{site_link}}" title="{{description}}">{{name}}</a></td>
<td>{{mains_cats}}</td>
<td class="fit"><span title="{{type}}" class="label label-{{type_label}}" style="text-transform: capitalize;">{{type}}</span></td>
<td>{{type}}</td>
<td class="fit">{{language}}</td>
<td class="fit">
<div class="indexer-buttons">
<button title="Configure" class="btn btn-primary btn-xs indexer-setup" data-id="{{id}}" data-link="{{site_link}}">
<span class="glyphicon glyphicon-wrench" aria-hidden="true"></span>
</button>
{{#if_eq type "public"}}
<button title="Add" class="btn btn-success btn-xs indexer-add" data-id="{{id}}" data-link="{{site_link}}">
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
</button>
{{/if_eq}}
</div>
</td>
</tr>
{{/each}}
</tbody>
<tfoot>
<tr>
<td colspan="6"></td>
</tr>
</tfoot>
</table>
</div>
</script>
<script id="jackett-releases" type="text/x-handlebars-template">
<div id="select-indexer-modal" class="modal fade" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-lg modal-fillwidth">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Cached Releases</h4>
</div>
<div class="modal-body">
<p>This screen shows releases which have been recently returned from Jackett. Only the last 300 releases for each tracker are returned.</p>
<table id="jackett-releases-datatable" class="dataTable compact cell-border hover stripe">
<thead>
<tr>
<th>Published</th>
<th>First Seen</th>
<th>Published</th>
<th>First Seen</th>
<th>Tracker</th>
<th>Name</th>
<th>Size</th>
<th>Size</th>
<th>Files</th>
<th>Category</th>
<th>Grabs</th>
<th>Seeds</th>
<th>Leechers</th>
<th class="fit">DL Factor</th>
<th class="fit">UL Factor</th>
<th>Download</th>
</tr>
</thead>
<tbody>
{{#each releases}}
<tr class="jackett-releases-row" data-imdb="{{Imdb}}" data-banner="{{BannerUrl}}" data-description="{{Description}}">
<td class="fit">{{PublishDate}}</td>
<td class="fit">{{FirstSeen}}</td>
<td class="fit">{{jacketTimespan PublishDate}}</td>
<td class="fit">{{jacketTimespan FirstSeen}}</td>
<td class="fit">{{Tracker}}</td>
<td class="Title"><a href="{{Comments}}">{{Title}}</a> <span class="release-labels"></span></td>
<td class="fit">{{Size}}</td>
<td class="fit">{{jacketSize Size}}</td>
<td class="fit">{{Files}}</td>
<td class="fit">{{CategoryDesc}}</td>
<td class="fit">{{Grabs}}</td>
<td class="fit">{{Seeders}}</td>
<td class="fit">{{Peers}}</td>
<td class="fit DownloadVolumeFactor">{{DownloadVolumeFactor}}</td>
<td class="fit UploadVolumeFactor">{{UploadVolumeFactor}}</td>
<td class="fit downloadcolumn">
{{#if Link}}
<a class="downloadlink" title="Download locally" href="{{Link}}"><i class="fa fa-download"></i></a>
{{/if}}
{{#if MagnetUri}}
<a class="downloadlink" title="Download locally (magnet)" href="{{MagnetUri}}"><i class="fa fa-magnet"></i></a>
{{/if}}
{{#if BlackholeLink}}
<a class="downloadlink jacketdownloadserver" title="Save to server blackhole directory" href="{{BlackholeLink}}"><i class="fa fa-upload"></i></a>
{{/if}}
</td>
</tr>
{{/each}}
</tbody>
<tfoot>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tfoot>
</table>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</script>
<script id="jackett-search" type="text/x-handlebars-template">
<div id="select-indexer-modal" class="modal fade" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-lg modal-fillwidth">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Manual search</h4>
</div>
<div class="modal-body">
<p>You can search all configured indexers from this screen.</p>
<label for="text">Query</label>
<input type="text" name="query" id="searchquery" />
<label for="tracker">Tracker</label>
<select name="tracker" id="searchTracker" multiple="multiple">
{{#each indexers}}
<option value="{{id}}" selected>{{name}}</option>
{{/each}}
</select>
<label for="category">Category</label>
<select name="category" id="searchCategory" multiple="multiple"></select>
<button id="jackett-search-perform" class="btn btn-success btn-sm"><span class="fa fa-search"></span></button>
<div id="searchResults"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</script>
<script id="jackett-search-results" type="text/x-handlebars-template">
<hr />
<p>Your search was done using:
{{#each Indexers}}{{Name}}
{{#if Error}}
(<span title="{{Error}}"><b>Error</b></span>)
{{else}}
({{Results}})
{{/if}}
, {{/each}}
</p>
<table id="jackett-search-results-datatable" class="dataTable compact cell-border hover stripe">
<thead>
<tr>
<th>Published</th>
<th>Published</th>
<th>Tracker</th>
<th>Name</th>
<th>Size</th>
<th>Size</th>
<th>Files</th>
<th>Category</th>
<th>Grabs</th>
<th>Seeds</th>
<th>Leechers</th>
<th>DL Factor</th>
<th>UL Factor</th>
<th>Download</th>
</tr>
</thead>
<tbody>
{{#each Results}}
<tr class="jackett-search-results-row" data-imdb="{{Imdb}}" data-banner="{{BannerUrl}}" data-description="{{Description}}">
<td>{{PublishDate}}</td>
<td>{{jacketTimespan PublishDate}}</td>
<td>{{Tracker}}</td>
<td class="Title"><a href="{{Comments}}" target="_blank">{{Title}}</a> <span class="release-labels"></span></td>
<td>{{Size}}</td>
<td class="fit">{{jacketSize Size}}</td>
<td>{{Files}}</td>
<td>{{CategoryDesc}}</td>
<td>{{Grabs}}</td>
<td>{{Seeders}}</td>
<td>{{Peers}}</td>
<td class="DownloadVolumeFactor">{{DownloadVolumeFactor}}</td>
<td class="UploadVolumeFactor">{{UploadVolumeFactor}}</td>
<td class="downloadcolumn">
{{#if Link}}
<a class="downloadlink" title="Download locally" href="{{Link}}"><i class="fa fa-download"></i></a>
{{/if}}
{{#if MagnetUri}}
<a class="downloadlink" title="Download locally (magnet)" href="{{MagnetUri}}"><i class="fa fa-magnet"></i></a>
{{/if}}
{{#if BlackholeLink}}
<a class="downloadlink jacketdownloadserver" title="Save to server blackhole directory" href="{{BlackholeLink}}"><i class="fa fa-upload"></i></a>
{{/if}}
</td>
</tr>
{{/each}}
</tbody>
<tfoot>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tfoot>
</table>
</script>
<script id="select-indexer" type="text/x-handlebars-template">
<div id="select-indexer-modal" class="modal fade" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Select an indexer to setup</h4>
</div>
<div class="modal-body">
<div id="unconfigured-indexers">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</script>
<script id="jackett-logs" type="text/x-handlebars-template">
<div id="select-indexer-modal" class="modal fade" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-lg modal-fillwidth">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Server Logs</h4>
</div>
<div class="modal-body">
<table class="dataTable compact cell-border hover stripe">
<thead>
<tr>
<th style="width: 200px">When</th>
<th style="width: 80px">Level</th>
<th>Message</th>
</tr>
</thead>
<tbody>
{{#each logs}}
<tr class="jackettlog{{Level}}">
<td>{{dateFormat When}}</td>
<td>{{Level}}</td>
<td><pre>{{Message}}</pre></td>
</tr>
{{/each}}
</tbody>
</table>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</script>
<script id="jackett-config-setup-modal" type="text/x-handlebars-template">
<div class="config-setup-modal modal fade" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">{{title}} - <a target="_blank" href="{{link}}">{{link}}</a></h4>
{{#if description}}
<div class="alert alert-info">{{description}}</div>
{{/if}}
</div>
<div class="modal-body">
<form class="config-setup-form"></form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary setup-indexer-go">Okay</button>
</div>
<div class="indexer-caps">
<h4>Capabilities</h4>
<table class="dataTable compact cell-border hover stripe">
<thead>
<tr>
<th>Category</th>
<th>Description</th>
</tr>
</thead>
<tbody>
{{#each caps}}
<tr>
<td>{{ID}}</td>
<td>{{Name}}</td>
</tr>
{{/each}}
</tbody>
</table>
</div>
</div>
</div>
</div>
</script>
<script id="spinner" type="text/x-handlebars-template">
<span class="spinner glyphicon glyphicon-refresh"></span>
</script>
<script id="search-button-ready" type="text/x-handlebars-template">
<span class="fa fa-search"></span>
</script>
<script type="text/javascript" src="../libs/api.js?changed=2017083001"></script>
<script type="text/javascript" src="../custom.js?changed=20180709"></script>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -1,89 +0,0 @@
var api = {
version: "2.0",
root: "/api",
key: "",
getApiPath: function(category, action) {
var path = this.root + "/v" + this.version + "/" + category;
if (action !== undefined)
path = path + "/" + action
return path;
},
getAllIndexers: function(callback) {
return $.get(this.getApiPath("indexers"), callback);
},
getServerConfig: function(callback) {
return $.get(this.getApiPath("server", "config"), callback);
},
getIndexerConfig: function(indexerId, callback) {
return $.get(this.getApiPath("indexers", indexerId + "/config"), callback);
},
updateIndexerConfig: function(indexerId, config, callback) {
return $.ajax({
url: this.getApiPath("indexers", indexerId + "/config"),
type: 'POST',
data: JSON.stringify(config),
dataType: 'json',
contentType: 'application/json',
cache: false,
success: callback
});
},
deleteIndexer: function(indexerId, callback) {
return $.ajax({
url: this.getApiPath("indexers", indexerId),
type: 'DELETE',
cache: false,
success: callback
});
},
testIndexer: function(indexerId, callback) {
return $.post(this.getApiPath("indexers", indexerId + "/test"), callback);
},
resultsForIndexer: function(indexerId, query, callback) {
return $.get(this.getApiPath("indexers", indexerId + "/results?apikey=" + this.key), query, callback);
},
getServerCache: function(callback) {
return $.get(this.getApiPath("indexers", "cache"), callback);
},
getServerLogs: function(callback) {
return $.get(this.getApiPath("server", "logs"), callback);
},
updateServerConfig: function(serverConfig, callback) {
return $.ajax({
url: this.getApiPath("server", "config"),
type: 'POST',
data: JSON.stringify(serverConfig),
dataType: 'json',
contentType: 'application/json',
cache: false,
success: callback
});
},
updateServer: function(callback) {
return $.post(this.getApiPath("server", "update"), callback);
},
updateAdminPassword: function(password, callback) {
return $.ajax({
url: this.getApiPath("server", "adminpassword"),
type: 'POST',
data: JSON.stringify(password),
dataType: 'json',
contentType: 'application/json',
cache: false,
success: callback
});
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +0,0 @@
Handlebars.registerHelper('ifCond', function (v1, v2, options) {
if(v1 === v2) {
return options.fn(this);
}
return options.inverse(this);
});

View File

@@ -1,167 +0,0 @@
/*!
DataTables 1.10.13
©2008-2016 SpryMedia Ltd - datatables.net/license
*/
(function(h){"function"===typeof define&&define.amd?define(["jquery"],function(E){return h(E,window,document)}):"object"===typeof exports?module.exports=function(E,H){E||(E=window);H||(H="undefined"!==typeof window?require("jquery"):require("jquery")(E));return h(H,E,E.document)}:h(jQuery,window,document)})(function(h,E,H,k){function Y(a){var b,c,d={};h.each(a,function(e){if((b=e.match(/^([^A-Z]+?)([A-Z])/))&&-1!=="a aa ai ao as b fn i m o s ".indexOf(b[1]+" "))c=e.replace(b[0],b[2].toLowerCase()),
d[c]=e,"o"===b[1]&&Y(a[e])});a._hungarianMap=d}function J(a,b,c){a._hungarianMap||Y(a);var d;h.each(b,function(e){d=a._hungarianMap[e];if(d!==k&&(c||b[d]===k))"o"===d.charAt(0)?(b[d]||(b[d]={}),h.extend(!0,b[d],b[e]),J(a[d],b[d],c)):b[d]=b[e]})}function Fa(a){var b=m.defaults.oLanguage,c=a.sZeroRecords;!a.sEmptyTable&&(c&&"No data available in table"===b.sEmptyTable)&&F(a,a,"sZeroRecords","sEmptyTable");!a.sLoadingRecords&&(c&&"Loading..."===b.sLoadingRecords)&&F(a,a,"sZeroRecords","sLoadingRecords");
a.sInfoThousands&&(a.sThousands=a.sInfoThousands);(a=a.sDecimal)&&fb(a)}function gb(a){A(a,"ordering","bSort");A(a,"orderMulti","bSortMulti");A(a,"orderClasses","bSortClasses");A(a,"orderCellsTop","bSortCellsTop");A(a,"order","aaSorting");A(a,"orderFixed","aaSortingFixed");A(a,"paging","bPaginate");A(a,"pagingType","sPaginationType");A(a,"pageLength","iDisplayLength");A(a,"searching","bFilter");"boolean"===typeof a.sScrollX&&(a.sScrollX=a.sScrollX?"100%":"");"boolean"===typeof a.scrollX&&(a.scrollX=
a.scrollX?"100%":"");if(a=a.aoSearchCols)for(var b=0,c=a.length;b<c;b++)a[b]&&J(m.models.oSearch,a[b])}function hb(a){A(a,"orderable","bSortable");A(a,"orderData","aDataSort");A(a,"orderSequence","asSorting");A(a,"orderDataType","sortDataType");var b=a.aDataSort;b&&!h.isArray(b)&&(a.aDataSort=[b])}function ib(a){if(!m.__browser){var b={};m.__browser=b;var c=h("<div/>").css({position:"fixed",top:0,left:-1*h(E).scrollLeft(),height:1,width:1,overflow:"hidden"}).append(h("<div/>").css({position:"absolute",
top:1,left:1,width:100,overflow:"scroll"}).append(h("<div/>").css({width:"100%",height:10}))).appendTo("body"),d=c.children(),e=d.children();b.barWidth=d[0].offsetWidth-d[0].clientWidth;b.bScrollOversize=100===e[0].offsetWidth&&100!==d[0].clientWidth;b.bScrollbarLeft=1!==Math.round(e.offset().left);b.bBounding=c[0].getBoundingClientRect().width?!0:!1;c.remove()}h.extend(a.oBrowser,m.__browser);a.oScroll.iBarWidth=m.__browser.barWidth}function jb(a,b,c,d,e,f){var g,j=!1;c!==k&&(g=c,j=!0);for(;d!==
e;)a.hasOwnProperty(d)&&(g=j?b(g,a[d],d,a):a[d],j=!0,d+=f);return g}function Ga(a,b){var c=m.defaults.column,d=a.aoColumns.length,c=h.extend({},m.models.oColumn,c,{nTh:b?b:H.createElement("th"),sTitle:c.sTitle?c.sTitle:b?b.innerHTML:"",aDataSort:c.aDataSort?c.aDataSort:[d],mData:c.mData?c.mData:d,idx:d});a.aoColumns.push(c);c=a.aoPreSearchCols;c[d]=h.extend({},m.models.oSearch,c[d]);la(a,d,h(b).data())}function la(a,b,c){var b=a.aoColumns[b],d=a.oClasses,e=h(b.nTh);if(!b.sWidthOrig){b.sWidthOrig=
e.attr("width")||null;var f=(e.attr("style")||"").match(/width:\s*(\d+[pxem%]+)/);f&&(b.sWidthOrig=f[1])}c!==k&&null!==c&&(hb(c),J(m.defaults.column,c),c.mDataProp!==k&&!c.mData&&(c.mData=c.mDataProp),c.sType&&(b._sManualType=c.sType),c.className&&!c.sClass&&(c.sClass=c.className),h.extend(b,c),F(b,c,"sWidth","sWidthOrig"),c.iDataSort!==k&&(b.aDataSort=[c.iDataSort]),F(b,c,"aDataSort"));var g=b.mData,j=R(g),i=b.mRender?R(b.mRender):null,c=function(a){return"string"===typeof a&&-1!==a.indexOf("@")};
b._bAttrSrc=h.isPlainObject(g)&&(c(g.sort)||c(g.type)||c(g.filter));b._setter=null;b.fnGetData=function(a,b,c){var d=j(a,b,k,c);return i&&b?i(d,b,a,c):d};b.fnSetData=function(a,b,c){return S(g)(a,b,c)};"number"!==typeof g&&(a._rowReadObject=!0);a.oFeatures.bSort||(b.bSortable=!1,e.addClass(d.sSortableNone));a=-1!==h.inArray("asc",b.asSorting);c=-1!==h.inArray("desc",b.asSorting);!b.bSortable||!a&&!c?(b.sSortingClass=d.sSortableNone,b.sSortingClassJUI=""):a&&!c?(b.sSortingClass=d.sSortableAsc,b.sSortingClassJUI=
d.sSortJUIAscAllowed):!a&&c?(b.sSortingClass=d.sSortableDesc,b.sSortingClassJUI=d.sSortJUIDescAllowed):(b.sSortingClass=d.sSortable,b.sSortingClassJUI=d.sSortJUI)}function Z(a){if(!1!==a.oFeatures.bAutoWidth){var b=a.aoColumns;Ha(a);for(var c=0,d=b.length;c<d;c++)b[c].nTh.style.width=b[c].sWidth}b=a.oScroll;(""!==b.sY||""!==b.sX)&&ma(a);s(a,null,"column-sizing",[a])}function $(a,b){var c=na(a,"bVisible");return"number"===typeof c[b]?c[b]:null}function aa(a,b){var c=na(a,"bVisible"),c=h.inArray(b,
c);return-1!==c?c:null}function ba(a){var b=0;h.each(a.aoColumns,function(a,d){d.bVisible&&"none"!==h(d.nTh).css("display")&&b++});return b}function na(a,b){var c=[];h.map(a.aoColumns,function(a,e){a[b]&&c.push(e)});return c}function Ia(a){var b=a.aoColumns,c=a.aoData,d=m.ext.type.detect,e,f,g,j,i,h,l,q,r;e=0;for(f=b.length;e<f;e++)if(l=b[e],r=[],!l.sType&&l._sManualType)l.sType=l._sManualType;else if(!l.sType){g=0;for(j=d.length;g<j;g++){i=0;for(h=c.length;i<h;i++){r[i]===k&&(r[i]=B(a,i,e,"type"));
q=d[g](r[i],a);if(!q&&g!==d.length-1)break;if("html"===q)break}if(q){l.sType=q;break}}l.sType||(l.sType="string")}}function kb(a,b,c,d){var e,f,g,j,i,n,l=a.aoColumns;if(b)for(e=b.length-1;0<=e;e--){n=b[e];var q=n.targets!==k?n.targets:n.aTargets;h.isArray(q)||(q=[q]);f=0;for(g=q.length;f<g;f++)if("number"===typeof q[f]&&0<=q[f]){for(;l.length<=q[f];)Ga(a);d(q[f],n)}else if("number"===typeof q[f]&&0>q[f])d(l.length+q[f],n);else if("string"===typeof q[f]){j=0;for(i=l.length;j<i;j++)("_all"==q[f]||h(l[j].nTh).hasClass(q[f]))&&
d(j,n)}}if(c){e=0;for(a=c.length;e<a;e++)d(e,c[e])}}function N(a,b,c,d){var e=a.aoData.length,f=h.extend(!0,{},m.models.oRow,{src:c?"dom":"data",idx:e});f._aData=b;a.aoData.push(f);for(var g=a.aoColumns,j=0,i=g.length;j<i;j++)g[j].sType=null;a.aiDisplayMaster.push(e);b=a.rowIdFn(b);b!==k&&(a.aIds[b]=f);(c||!a.oFeatures.bDeferRender)&&Ja(a,e,c,d);return e}function oa(a,b){var c;b instanceof h||(b=h(b));return b.map(function(b,e){c=Ka(a,e);return N(a,c.data,e,c.cells)})}function B(a,b,c,d){var e=a.iDraw,
f=a.aoColumns[c],g=a.aoData[b]._aData,j=f.sDefaultContent,i=f.fnGetData(g,d,{settings:a,row:b,col:c});if(i===k)return a.iDrawError!=e&&null===j&&(K(a,0,"Requested unknown parameter "+("function"==typeof f.mData?"{function}":"'"+f.mData+"'")+" for row "+b+", column "+c,4),a.iDrawError=e),j;if((i===g||null===i)&&null!==j&&d!==k)i=j;else if("function"===typeof i)return i.call(g);return null===i&&"display"==d?"":i}function lb(a,b,c,d){a.aoColumns[c].fnSetData(a.aoData[b]._aData,d,{settings:a,row:b,col:c})}
function La(a){return h.map(a.match(/(\\.|[^\.])+/g)||[""],function(a){return a.replace(/\\\./g,".")})}function R(a){if(h.isPlainObject(a)){var b={};h.each(a,function(a,c){c&&(b[a]=R(c))});return function(a,c,f,g){var j=b[c]||b._;return j!==k?j(a,c,f,g):a}}if(null===a)return function(a){return a};if("function"===typeof a)return function(b,c,f,g){return a(b,c,f,g)};if("string"===typeof a&&(-1!==a.indexOf(".")||-1!==a.indexOf("[")||-1!==a.indexOf("("))){var c=function(a,b,f){var g,j;if(""!==f){j=La(f);
for(var i=0,n=j.length;i<n;i++){f=j[i].match(ca);g=j[i].match(V);if(f){j[i]=j[i].replace(ca,"");""!==j[i]&&(a=a[j[i]]);g=[];j.splice(0,i+1);j=j.join(".");if(h.isArray(a)){i=0;for(n=a.length;i<n;i++)g.push(c(a[i],b,j))}a=f[0].substring(1,f[0].length-1);a=""===a?g:g.join(a);break}else if(g){j[i]=j[i].replace(V,"");a=a[j[i]]();continue}if(null===a||a[j[i]]===k)return k;a=a[j[i]]}}return a};return function(b,e){return c(b,e,a)}}return function(b){return b[a]}}function S(a){if(h.isPlainObject(a))return S(a._);
if(null===a)return function(){};if("function"===typeof a)return function(b,d,e){a(b,"set",d,e)};if("string"===typeof a&&(-1!==a.indexOf(".")||-1!==a.indexOf("[")||-1!==a.indexOf("("))){var b=function(a,d,e){var e=La(e),f;f=e[e.length-1];for(var g,j,i=0,n=e.length-1;i<n;i++){g=e[i].match(ca);j=e[i].match(V);if(g){e[i]=e[i].replace(ca,"");a[e[i]]=[];f=e.slice();f.splice(0,i+1);g=f.join(".");if(h.isArray(d)){j=0;for(n=d.length;j<n;j++)f={},b(f,d[j],g),a[e[i]].push(f)}else a[e[i]]=d;return}j&&(e[i]=e[i].replace(V,
""),a=a[e[i]](d));if(null===a[e[i]]||a[e[i]]===k)a[e[i]]={};a=a[e[i]]}if(f.match(V))a[f.replace(V,"")](d);else a[f.replace(ca,"")]=d};return function(c,d){return b(c,d,a)}}return function(b,d){b[a]=d}}function Ma(a){return D(a.aoData,"_aData")}function pa(a){a.aoData.length=0;a.aiDisplayMaster.length=0;a.aiDisplay.length=0;a.aIds={}}function qa(a,b,c){for(var d=-1,e=0,f=a.length;e<f;e++)a[e]==b?d=e:a[e]>b&&a[e]--; -1!=d&&c===k&&a.splice(d,1)}function da(a,b,c,d){var e=a.aoData[b],f,g=function(c,d){for(;c.childNodes.length;)c.removeChild(c.firstChild);
c.innerHTML=B(a,b,d,"display")};if("dom"===c||(!c||"auto"===c)&&"dom"===e.src)e._aData=Ka(a,e,d,d===k?k:e._aData).data;else{var j=e.anCells;if(j)if(d!==k)g(j[d],d);else{c=0;for(f=j.length;c<f;c++)g(j[c],c)}}e._aSortData=null;e._aFilterData=null;g=a.aoColumns;if(d!==k)g[d].sType=null;else{c=0;for(f=g.length;c<f;c++)g[c].sType=null;Na(a,e)}}function Ka(a,b,c,d){var e=[],f=b.firstChild,g,j,i=0,n,l=a.aoColumns,q=a._rowReadObject,d=d!==k?d:q?{}:[],r=function(a,b){if("string"===typeof a){var c=a.indexOf("@");
-1!==c&&(c=a.substring(c+1),S(a)(d,b.getAttribute(c)))}},m=function(a){if(c===k||c===i)j=l[i],n=h.trim(a.innerHTML),j&&j._bAttrSrc?(S(j.mData._)(d,n),r(j.mData.sort,a),r(j.mData.type,a),r(j.mData.filter,a)):q?(j._setter||(j._setter=S(j.mData)),j._setter(d,n)):d[i]=n;i++};if(f)for(;f;){g=f.nodeName.toUpperCase();if("TD"==g||"TH"==g)m(f),e.push(f);f=f.nextSibling}else{e=b.anCells;f=0;for(g=e.length;f<g;f++)m(e[f])}if(b=b.firstChild?b:b.nTr)(b=b.getAttribute("id"))&&S(a.rowId)(d,b);return{data:d,cells:e}}
function Ja(a,b,c,d){var e=a.aoData[b],f=e._aData,g=[],j,i,n,l,q;if(null===e.nTr){j=c||H.createElement("tr");e.nTr=j;e.anCells=g;j._DT_RowIndex=b;Na(a,e);l=0;for(q=a.aoColumns.length;l<q;l++){n=a.aoColumns[l];i=c?d[l]:H.createElement(n.sCellType);i._DT_CellIndex={row:b,column:l};g.push(i);if((!c||n.mRender||n.mData!==l)&&(!h.isPlainObject(n.mData)||n.mData._!==l+".display"))i.innerHTML=B(a,b,l,"display");n.sClass&&(i.className+=" "+n.sClass);n.bVisible&&!c?j.appendChild(i):!n.bVisible&&c&&i.parentNode.removeChild(i);
n.fnCreatedCell&&n.fnCreatedCell.call(a.oInstance,i,B(a,b,l),f,b,l)}s(a,"aoRowCreatedCallback",null,[j,f,b])}e.nTr.setAttribute("role","row")}function Na(a,b){var c=b.nTr,d=b._aData;if(c){var e=a.rowIdFn(d);e&&(c.id=e);d.DT_RowClass&&(e=d.DT_RowClass.split(" "),b.__rowc=b.__rowc?sa(b.__rowc.concat(e)):e,h(c).removeClass(b.__rowc.join(" ")).addClass(d.DT_RowClass));d.DT_RowAttr&&h(c).attr(d.DT_RowAttr);d.DT_RowData&&h(c).data(d.DT_RowData)}}function mb(a){var b,c,d,e,f,g=a.nTHead,j=a.nTFoot,i=0===
h("th, td",g).length,n=a.oClasses,l=a.aoColumns;i&&(e=h("<tr/>").appendTo(g));b=0;for(c=l.length;b<c;b++)f=l[b],d=h(f.nTh).addClass(f.sClass),i&&d.appendTo(e),a.oFeatures.bSort&&(d.addClass(f.sSortingClass),!1!==f.bSortable&&(d.attr("tabindex",a.iTabIndex).attr("aria-controls",a.sTableId),Oa(a,f.nTh,b))),f.sTitle!=d[0].innerHTML&&d.html(f.sTitle),Pa(a,"header")(a,d,f,n);i&&ea(a.aoHeader,g);h(g).find(">tr").attr("role","row");h(g).find(">tr>th, >tr>td").addClass(n.sHeaderTH);h(j).find(">tr>th, >tr>td").addClass(n.sFooterTH);
if(null!==j){a=a.aoFooter[0];b=0;for(c=a.length;b<c;b++)f=l[b],f.nTf=a[b].cell,f.sClass&&h(f.nTf).addClass(f.sClass)}}function fa(a,b,c){var d,e,f,g=[],j=[],i=a.aoColumns.length,n;if(b){c===k&&(c=!1);d=0;for(e=b.length;d<e;d++){g[d]=b[d].slice();g[d].nTr=b[d].nTr;for(f=i-1;0<=f;f--)!a.aoColumns[f].bVisible&&!c&&g[d].splice(f,1);j.push([])}d=0;for(e=g.length;d<e;d++){if(a=g[d].nTr)for(;f=a.firstChild;)a.removeChild(f);f=0;for(b=g[d].length;f<b;f++)if(n=i=1,j[d][f]===k){a.appendChild(g[d][f].cell);
for(j[d][f]=1;g[d+i]!==k&&g[d][f].cell==g[d+i][f].cell;)j[d+i][f]=1,i++;for(;g[d][f+n]!==k&&g[d][f].cell==g[d][f+n].cell;){for(c=0;c<i;c++)j[d+c][f+n]=1;n++}h(g[d][f].cell).attr("rowspan",i).attr("colspan",n)}}}}function O(a){var b=s(a,"aoPreDrawCallback","preDraw",[a]);if(-1!==h.inArray(!1,b))C(a,!1);else{var b=[],c=0,d=a.asStripeClasses,e=d.length,f=a.oLanguage,g=a.iInitDisplayStart,j="ssp"==y(a),i=a.aiDisplay;a.bDrawing=!0;g!==k&&-1!==g&&(a._iDisplayStart=j?g:g>=a.fnRecordsDisplay()?0:g,a.iInitDisplayStart=
-1);var g=a._iDisplayStart,n=a.fnDisplayEnd();if(a.bDeferLoading)a.bDeferLoading=!1,a.iDraw++,C(a,!1);else if(j){if(!a.bDestroying&&!nb(a))return}else a.iDraw++;if(0!==i.length){f=j?a.aoData.length:n;for(j=j?0:g;j<f;j++){var l=i[j],q=a.aoData[l];null===q.nTr&&Ja(a,l);l=q.nTr;if(0!==e){var r=d[c%e];q._sRowStripe!=r&&(h(l).removeClass(q._sRowStripe).addClass(r),q._sRowStripe=r)}s(a,"aoRowCallback",null,[l,q._aData,c,j]);b.push(l);c++}}else c=f.sZeroRecords,1==a.iDraw&&"ajax"==y(a)?c=f.sLoadingRecords:
f.sEmptyTable&&0===a.fnRecordsTotal()&&(c=f.sEmptyTable),b[0]=h("<tr/>",{"class":e?d[0]:""}).append(h("<td />",{valign:"top",colSpan:ba(a),"class":a.oClasses.sRowEmpty}).html(c))[0];s(a,"aoHeaderCallback","header",[h(a.nTHead).children("tr")[0],Ma(a),g,n,i]);s(a,"aoFooterCallback","footer",[h(a.nTFoot).children("tr")[0],Ma(a),g,n,i]);d=h(a.nTBody);d.children().detach();d.append(h(b));s(a,"aoDrawCallback","draw",[a]);a.bSorted=!1;a.bFiltered=!1;a.bDrawing=!1}}function T(a,b){var c=a.oFeatures,d=c.bFilter;
c.bSort&&ob(a);d?ga(a,a.oPreviousSearch):a.aiDisplay=a.aiDisplayMaster.slice();!0!==b&&(a._iDisplayStart=0);a._drawHold=b;O(a);a._drawHold=!1}function pb(a){var b=a.oClasses,c=h(a.nTable),c=h("<div/>").insertBefore(c),d=a.oFeatures,e=h("<div/>",{id:a.sTableId+"_wrapper","class":b.sWrapper+(a.nTFoot?"":" "+b.sNoFooter)});a.nHolding=c[0];a.nTableWrapper=e[0];a.nTableReinsertBefore=a.nTable.nextSibling;for(var f=a.sDom.split(""),g,j,i,n,l,q,k=0;k<f.length;k++){g=null;j=f[k];if("<"==j){i=h("<div/>")[0];
n=f[k+1];if("'"==n||'"'==n){l="";for(q=2;f[k+q]!=n;)l+=f[k+q],q++;"H"==l?l=b.sJUIHeader:"F"==l&&(l=b.sJUIFooter);-1!=l.indexOf(".")?(n=l.split("."),i.id=n[0].substr(1,n[0].length-1),i.className=n[1]):"#"==l.charAt(0)?i.id=l.substr(1,l.length-1):i.className=l;k+=q}e.append(i);e=h(i)}else if(">"==j)e=e.parent();else if("l"==j&&d.bPaginate&&d.bLengthChange)g=qb(a);else if("f"==j&&d.bFilter)g=rb(a);else if("r"==j&&d.bProcessing)g=sb(a);else if("t"==j)g=tb(a);else if("i"==j&&d.bInfo)g=ub(a);else if("p"==
j&&d.bPaginate)g=vb(a);else if(0!==m.ext.feature.length){i=m.ext.feature;q=0;for(n=i.length;q<n;q++)if(j==i[q].cFeature){g=i[q].fnInit(a);break}}g&&(i=a.aanFeatures,i[j]||(i[j]=[]),i[j].push(g),e.append(g))}c.replaceWith(e);a.nHolding=null}function ea(a,b){var c=h(b).children("tr"),d,e,f,g,j,i,n,l,q,k;a.splice(0,a.length);f=0;for(i=c.length;f<i;f++)a.push([]);f=0;for(i=c.length;f<i;f++){d=c[f];for(e=d.firstChild;e;){if("TD"==e.nodeName.toUpperCase()||"TH"==e.nodeName.toUpperCase()){l=1*e.getAttribute("colspan");
q=1*e.getAttribute("rowspan");l=!l||0===l||1===l?1:l;q=!q||0===q||1===q?1:q;g=0;for(j=a[f];j[g];)g++;n=g;k=1===l?!0:!1;for(j=0;j<l;j++)for(g=0;g<q;g++)a[f+g][n+j]={cell:e,unique:k},a[f+g].nTr=d}e=e.nextSibling}}}function ta(a,b,c){var d=[];c||(c=a.aoHeader,b&&(c=[],ea(c,b)));for(var b=0,e=c.length;b<e;b++)for(var f=0,g=c[b].length;f<g;f++)if(c[b][f].unique&&(!d[f]||!a.bSortCellsTop))d[f]=c[b][f].cell;return d}function ua(a,b,c){s(a,"aoServerParams","serverParams",[b]);if(b&&h.isArray(b)){var d={},
e=/(.*?)\[\]$/;h.each(b,function(a,b){var c=b.name.match(e);c?(c=c[0],d[c]||(d[c]=[]),d[c].push(b.value)):d[b.name]=b.value});b=d}var f,g=a.ajax,j=a.oInstance,i=function(b){s(a,null,"xhr",[a,b,a.jqXHR]);c(b)};if(h.isPlainObject(g)&&g.data){f=g.data;var n=h.isFunction(f)?f(b,a):f,b=h.isFunction(f)&&n?n:h.extend(!0,b,n);delete g.data}n={data:b,success:function(b){var c=b.error||b.sError;c&&K(a,0,c);a.json=b;i(b)},dataType:"json",cache:!1,type:a.sServerMethod,error:function(b,c){var d=s(a,null,"xhr",
[a,null,a.jqXHR]);-1===h.inArray(!0,d)&&("parsererror"==c?K(a,0,"Invalid JSON response",1):4===b.readyState&&K(a,0,"Ajax error",7));C(a,!1)}};a.oAjaxData=b;s(a,null,"preXhr",[a,b]);a.fnServerData?a.fnServerData.call(j,a.sAjaxSource,h.map(b,function(a,b){return{name:b,value:a}}),i,a):a.sAjaxSource||"string"===typeof g?a.jqXHR=h.ajax(h.extend(n,{url:g||a.sAjaxSource})):h.isFunction(g)?a.jqXHR=g.call(j,b,i,a):(a.jqXHR=h.ajax(h.extend(n,g)),g.data=f)}function nb(a){return a.bAjaxDataGet?(a.iDraw++,C(a,
!0),ua(a,wb(a),function(b){xb(a,b)}),!1):!0}function wb(a){var b=a.aoColumns,c=b.length,d=a.oFeatures,e=a.oPreviousSearch,f=a.aoPreSearchCols,g,j=[],i,n,l,k=W(a);g=a._iDisplayStart;i=!1!==d.bPaginate?a._iDisplayLength:-1;var r=function(a,b){j.push({name:a,value:b})};r("sEcho",a.iDraw);r("iColumns",c);r("sColumns",D(b,"sName").join(","));r("iDisplayStart",g);r("iDisplayLength",i);var ra={draw:a.iDraw,columns:[],order:[],start:g,length:i,search:{value:e.sSearch,regex:e.bRegex}};for(g=0;g<c;g++)n=b[g],
l=f[g],i="function"==typeof n.mData?"function":n.mData,ra.columns.push({data:i,name:n.sName,searchable:n.bSearchable,orderable:n.bSortable,search:{value:l.sSearch,regex:l.bRegex}}),r("mDataProp_"+g,i),d.bFilter&&(r("sSearch_"+g,l.sSearch),r("bRegex_"+g,l.bRegex),r("bSearchable_"+g,n.bSearchable)),d.bSort&&r("bSortable_"+g,n.bSortable);d.bFilter&&(r("sSearch",e.sSearch),r("bRegex",e.bRegex));d.bSort&&(h.each(k,function(a,b){ra.order.push({column:b.col,dir:b.dir});r("iSortCol_"+a,b.col);r("sSortDir_"+
a,b.dir)}),r("iSortingCols",k.length));b=m.ext.legacy.ajax;return null===b?a.sAjaxSource?j:ra:b?j:ra}function xb(a,b){var c=va(a,b),d=b.sEcho!==k?b.sEcho:b.draw,e=b.iTotalRecords!==k?b.iTotalRecords:b.recordsTotal,f=b.iTotalDisplayRecords!==k?b.iTotalDisplayRecords:b.recordsFiltered;if(d){if(1*d<a.iDraw)return;a.iDraw=1*d}pa(a);a._iRecordsTotal=parseInt(e,10);a._iRecordsDisplay=parseInt(f,10);d=0;for(e=c.length;d<e;d++)N(a,c[d]);a.aiDisplay=a.aiDisplayMaster.slice();a.bAjaxDataGet=!1;O(a);a._bInitComplete||
wa(a,b);a.bAjaxDataGet=!0;C(a,!1)}function va(a,b){var c=h.isPlainObject(a.ajax)&&a.ajax.dataSrc!==k?a.ajax.dataSrc:a.sAjaxDataProp;return"data"===c?b.aaData||b[c]:""!==c?R(c)(b):b}function rb(a){var b=a.oClasses,c=a.sTableId,d=a.oLanguage,e=a.oPreviousSearch,f=a.aanFeatures,g='<input type="search" class="'+b.sFilterInput+'"/>',j=d.sSearch,j=j.match(/_INPUT_/)?j.replace("_INPUT_",g):j+g,b=h("<div/>",{id:!f.f?c+"_filter":null,"class":b.sFilter}).append(h("<label/>").append(j)),f=function(){var b=!this.value?
"":this.value;b!=e.sSearch&&(ga(a,{sSearch:b,bRegex:e.bRegex,bSmart:e.bSmart,bCaseInsensitive:e.bCaseInsensitive}),a._iDisplayStart=0,O(a))},g=null!==a.searchDelay?a.searchDelay:"ssp"===y(a)?400:0,i=h("input",b).val(e.sSearch).attr("placeholder",d.sSearchPlaceholder).on("keyup.DT search.DT input.DT paste.DT cut.DT",g?Qa(f,g):f).on("keypress.DT",function(a){if(13==a.keyCode)return!1}).attr("aria-controls",c);h(a.nTable).on("search.dt.DT",function(b,c){if(a===c)try{i[0]!==H.activeElement&&i.val(e.sSearch)}catch(d){}});
return b[0]}function ga(a,b,c){var d=a.oPreviousSearch,e=a.aoPreSearchCols,f=function(a){d.sSearch=a.sSearch;d.bRegex=a.bRegex;d.bSmart=a.bSmart;d.bCaseInsensitive=a.bCaseInsensitive};Ia(a);if("ssp"!=y(a)){yb(a,b.sSearch,c,b.bEscapeRegex!==k?!b.bEscapeRegex:b.bRegex,b.bSmart,b.bCaseInsensitive);f(b);for(b=0;b<e.length;b++)zb(a,e[b].sSearch,b,e[b].bEscapeRegex!==k?!e[b].bEscapeRegex:e[b].bRegex,e[b].bSmart,e[b].bCaseInsensitive);Ab(a)}else f(b);a.bFiltered=!0;s(a,null,"search",[a])}function Ab(a){for(var b=
m.ext.search,c=a.aiDisplay,d,e,f=0,g=b.length;f<g;f++){for(var j=[],i=0,n=c.length;i<n;i++)e=c[i],d=a.aoData[e],b[f](a,d._aFilterData,e,d._aData,i)&&j.push(e);c.length=0;h.merge(c,j)}}function zb(a,b,c,d,e,f){if(""!==b){for(var g=[],j=a.aiDisplay,d=Ra(b,d,e,f),e=0;e<j.length;e++)b=a.aoData[j[e]]._aFilterData[c],d.test(b)&&g.push(j[e]);a.aiDisplay=g}}function yb(a,b,c,d,e,f){var d=Ra(b,d,e,f),f=a.oPreviousSearch.sSearch,g=a.aiDisplayMaster,j,e=[];0!==m.ext.search.length&&(c=!0);j=Bb(a);if(0>=b.length)a.aiDisplay=
g.slice();else{if(j||c||f.length>b.length||0!==b.indexOf(f)||a.bSorted)a.aiDisplay=g.slice();b=a.aiDisplay;for(c=0;c<b.length;c++)d.test(a.aoData[b[c]]._sFilterRow)&&e.push(b[c]);a.aiDisplay=e}}function Ra(a,b,c,d){a=b?a:Sa(a);c&&(a="^(?=.*?"+h.map(a.match(/"[^"]+"|[^ ]+/g)||[""],function(a){if('"'===a.charAt(0))var b=a.match(/^"(.*)"$/),a=b?b[1]:a;return a.replace('"',"")}).join(")(?=.*?")+").*$");return RegExp(a,d?"i":"")}function Bb(a){var b=a.aoColumns,c,d,e,f,g,j,i,h,l=m.ext.type.search;c=!1;
d=0;for(f=a.aoData.length;d<f;d++)if(h=a.aoData[d],!h._aFilterData){j=[];e=0;for(g=b.length;e<g;e++)c=b[e],c.bSearchable?(i=B(a,d,e,"filter"),l[c.sType]&&(i=l[c.sType](i)),null===i&&(i=""),"string"!==typeof i&&i.toString&&(i=i.toString())):i="",i.indexOf&&-1!==i.indexOf("&")&&(xa.innerHTML=i,i=$b?xa.textContent:xa.innerText),i.replace&&(i=i.replace(/[\r\n]/g,"")),j.push(i);h._aFilterData=j;h._sFilterRow=j.join(" ");c=!0}return c}function Cb(a){return{search:a.sSearch,smart:a.bSmart,regex:a.bRegex,
caseInsensitive:a.bCaseInsensitive}}function Db(a){return{sSearch:a.search,bSmart:a.smart,bRegex:a.regex,bCaseInsensitive:a.caseInsensitive}}function ub(a){var b=a.sTableId,c=a.aanFeatures.i,d=h("<div/>",{"class":a.oClasses.sInfo,id:!c?b+"_info":null});c||(a.aoDrawCallback.push({fn:Eb,sName:"information"}),d.attr("role","status").attr("aria-live","polite"),h(a.nTable).attr("aria-describedby",b+"_info"));return d[0]}function Eb(a){var b=a.aanFeatures.i;if(0!==b.length){var c=a.oLanguage,d=a._iDisplayStart+
1,e=a.fnDisplayEnd(),f=a.fnRecordsTotal(),g=a.fnRecordsDisplay(),j=g?c.sInfo:c.sInfoEmpty;g!==f&&(j+=" "+c.sInfoFiltered);j+=c.sInfoPostFix;j=Fb(a,j);c=c.fnInfoCallback;null!==c&&(j=c.call(a.oInstance,a,d,e,f,g,j));h(b).html(j)}}function Fb(a,b){var c=a.fnFormatNumber,d=a._iDisplayStart+1,e=a._iDisplayLength,f=a.fnRecordsDisplay(),g=-1===e;return b.replace(/_START_/g,c.call(a,d)).replace(/_END_/g,c.call(a,a.fnDisplayEnd())).replace(/_MAX_/g,c.call(a,a.fnRecordsTotal())).replace(/_TOTAL_/g,c.call(a,
f)).replace(/_PAGE_/g,c.call(a,g?1:Math.ceil(d/e))).replace(/_PAGES_/g,c.call(a,g?1:Math.ceil(f/e)))}function ha(a){var b,c,d=a.iInitDisplayStart,e=a.aoColumns,f;c=a.oFeatures;var g=a.bDeferLoading;if(a.bInitialised){pb(a);mb(a);fa(a,a.aoHeader);fa(a,a.aoFooter);C(a,!0);c.bAutoWidth&&Ha(a);b=0;for(c=e.length;b<c;b++)f=e[b],f.sWidth&&(f.nTh.style.width=v(f.sWidth));s(a,null,"preInit",[a]);T(a);e=y(a);if("ssp"!=e||g)"ajax"==e?ua(a,[],function(c){var f=va(a,c);for(b=0;b<f.length;b++)N(a,f[b]);a.iInitDisplayStart=
d;T(a);C(a,!1);wa(a,c)},a):(C(a,!1),wa(a))}else setTimeout(function(){ha(a)},200)}function wa(a,b){a._bInitComplete=!0;(b||a.oInit.aaData)&&Z(a);s(a,null,"plugin-init",[a,b]);s(a,"aoInitComplete","init",[a,b])}function Ta(a,b){var c=parseInt(b,10);a._iDisplayLength=c;Ua(a);s(a,null,"length",[a,c])}function qb(a){for(var b=a.oClasses,c=a.sTableId,d=a.aLengthMenu,e=h.isArray(d[0]),f=e?d[0]:d,d=e?d[1]:d,e=h("<select/>",{name:c+"_length","aria-controls":c,"class":b.sLengthSelect}),g=0,j=f.length;g<j;g++)e[0][g]=
new Option(d[g],f[g]);var i=h("<div><label/></div>").addClass(b.sLength);a.aanFeatures.l||(i[0].id=c+"_length");i.children().append(a.oLanguage.sLengthMenu.replace("_MENU_",e[0].outerHTML));h("select",i).val(a._iDisplayLength).on("change.DT",function(){Ta(a,h(this).val());O(a)});h(a.nTable).on("length.dt.DT",function(b,c,d){a===c&&h("select",i).val(d)});return i[0]}function vb(a){var b=a.sPaginationType,c=m.ext.pager[b],d="function"===typeof c,e=function(a){O(a)},b=h("<div/>").addClass(a.oClasses.sPaging+
b)[0],f=a.aanFeatures;d||c.fnInit(a,b,e);f.p||(b.id=a.sTableId+"_paginate",a.aoDrawCallback.push({fn:function(a){if(d){var b=a._iDisplayStart,i=a._iDisplayLength,h=a.fnRecordsDisplay(),l=-1===i,b=l?0:Math.ceil(b/i),i=l?1:Math.ceil(h/i),h=c(b,i),k,l=0;for(k=f.p.length;l<k;l++)Pa(a,"pageButton")(a,f.p[l],l,h,b,i)}else c.fnUpdate(a,e)},sName:"pagination"}));return b}function Va(a,b,c){var d=a._iDisplayStart,e=a._iDisplayLength,f=a.fnRecordsDisplay();0===f||-1===e?d=0:"number"===typeof b?(d=b*e,d>f&&
(d=0)):"first"==b?d=0:"previous"==b?(d=0<=e?d-e:0,0>d&&(d=0)):"next"==b?d+e<f&&(d+=e):"last"==b?d=Math.floor((f-1)/e)*e:K(a,0,"Unknown paging action: "+b,5);b=a._iDisplayStart!==d;a._iDisplayStart=d;b&&(s(a,null,"page",[a]),c&&O(a));return b}function sb(a){return h("<div/>",{id:!a.aanFeatures.r?a.sTableId+"_processing":null,"class":a.oClasses.sProcessing}).html(a.oLanguage.sProcessing).insertBefore(a.nTable)[0]}function C(a,b){a.oFeatures.bProcessing&&h(a.aanFeatures.r).css("display",b?"block":"none");
s(a,null,"processing",[a,b])}function tb(a){var b=h(a.nTable);b.attr("role","grid");var c=a.oScroll;if(""===c.sX&&""===c.sY)return a.nTable;var d=c.sX,e=c.sY,f=a.oClasses,g=b.children("caption"),j=g.length?g[0]._captionSide:null,i=h(b[0].cloneNode(!1)),n=h(b[0].cloneNode(!1)),l=b.children("tfoot");l.length||(l=null);i=h("<div/>",{"class":f.sScrollWrapper}).append(h("<div/>",{"class":f.sScrollHead}).css({overflow:"hidden",position:"relative",border:0,width:d?!d?null:v(d):"100%"}).append(h("<div/>",
{"class":f.sScrollHeadInner}).css({"box-sizing":"content-box",width:c.sXInner||"100%"}).append(i.removeAttr("id").css("margin-left",0).append("top"===j?g:null).append(b.children("thead"))))).append(h("<div/>",{"class":f.sScrollBody}).css({position:"relative",overflow:"auto",width:!d?null:v(d)}).append(b));l&&i.append(h("<div/>",{"class":f.sScrollFoot}).css({overflow:"hidden",border:0,width:d?!d?null:v(d):"100%"}).append(h("<div/>",{"class":f.sScrollFootInner}).append(n.removeAttr("id").css("margin-left",
0).append("bottom"===j?g:null).append(b.children("tfoot")))));var b=i.children(),k=b[0],f=b[1],r=l?b[2]:null;if(d)h(f).on("scroll.DT",function(){var a=this.scrollLeft;k.scrollLeft=a;l&&(r.scrollLeft=a)});h(f).css(e&&c.bCollapse?"max-height":"height",e);a.nScrollHead=k;a.nScrollBody=f;a.nScrollFoot=r;a.aoDrawCallback.push({fn:ma,sName:"scrolling"});return i[0]}function ma(a){var b=a.oScroll,c=b.sX,d=b.sXInner,e=b.sY,b=b.iBarWidth,f=h(a.nScrollHead),g=f[0].style,j=f.children("div"),i=j[0].style,n=j.children("table"),
j=a.nScrollBody,l=h(j),q=j.style,r=h(a.nScrollFoot).children("div"),m=r.children("table"),p=h(a.nTHead),o=h(a.nTable),u=o[0],s=u.style,t=a.nTFoot?h(a.nTFoot):null,x=a.oBrowser,U=x.bScrollOversize,ac=D(a.aoColumns,"nTh"),P,L,Q,w,Wa=[],y=[],z=[],A=[],B,C=function(a){a=a.style;a.paddingTop="0";a.paddingBottom="0";a.borderTopWidth="0";a.borderBottomWidth="0";a.height=0};L=j.scrollHeight>j.clientHeight;if(a.scrollBarVis!==L&&a.scrollBarVis!==k)a.scrollBarVis=L,Z(a);else{a.scrollBarVis=L;o.children("thead, tfoot").remove();
t&&(Q=t.clone().prependTo(o),P=t.find("tr"),Q=Q.find("tr"));w=p.clone().prependTo(o);p=p.find("tr");L=w.find("tr");w.find("th, td").removeAttr("tabindex");c||(q.width="100%",f[0].style.width="100%");h.each(ta(a,w),function(b,c){B=$(a,b);c.style.width=a.aoColumns[B].sWidth});t&&I(function(a){a.style.width=""},Q);f=o.outerWidth();if(""===c){s.width="100%";if(U&&(o.find("tbody").height()>j.offsetHeight||"scroll"==l.css("overflow-y")))s.width=v(o.outerWidth()-b);f=o.outerWidth()}else""!==d&&(s.width=
v(d),f=o.outerWidth());I(C,L);I(function(a){z.push(a.innerHTML);Wa.push(v(h(a).css("width")))},L);I(function(a,b){if(h.inArray(a,ac)!==-1)a.style.width=Wa[b]},p);h(L).height(0);t&&(I(C,Q),I(function(a){A.push(a.innerHTML);y.push(v(h(a).css("width")))},Q),I(function(a,b){a.style.width=y[b]},P),h(Q).height(0));I(function(a,b){a.innerHTML='<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+z[b]+"</div>";a.style.width=Wa[b]},L);t&&I(function(a,b){a.innerHTML='<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+
A[b]+"</div>";a.style.width=y[b]},Q);if(o.outerWidth()<f){P=j.scrollHeight>j.offsetHeight||"scroll"==l.css("overflow-y")?f+b:f;if(U&&(j.scrollHeight>j.offsetHeight||"scroll"==l.css("overflow-y")))s.width=v(P-b);(""===c||""!==d)&&K(a,1,"Possible column misalignment",6)}else P="100%";q.width=v(P);g.width=v(P);t&&(a.nScrollFoot.style.width=v(P));!e&&U&&(q.height=v(u.offsetHeight+b));c=o.outerWidth();n[0].style.width=v(c);i.width=v(c);d=o.height()>j.clientHeight||"scroll"==l.css("overflow-y");e="padding"+
(x.bScrollbarLeft?"Left":"Right");i[e]=d?b+"px":"0px";t&&(m[0].style.width=v(c),r[0].style.width=v(c),r[0].style[e]=d?b+"px":"0px");o.children("colgroup").insertBefore(o.children("thead"));l.scroll();if((a.bSorted||a.bFiltered)&&!a._drawHold)j.scrollTop=0}}function I(a,b,c){for(var d=0,e=0,f=b.length,g,j;e<f;){g=b[e].firstChild;for(j=c?c[e].firstChild:null;g;)1===g.nodeType&&(c?a(g,j,d):a(g,d),d++),g=g.nextSibling,j=c?j.nextSibling:null;e++}}function Ha(a){var b=a.nTable,c=a.aoColumns,d=a.oScroll,
e=d.sY,f=d.sX,g=d.sXInner,j=c.length,i=na(a,"bVisible"),n=h("th",a.nTHead),l=b.getAttribute("width"),k=b.parentNode,r=!1,m,p,o=a.oBrowser,d=o.bScrollOversize;(m=b.style.width)&&-1!==m.indexOf("%")&&(l=m);for(m=0;m<i.length;m++)p=c[i[m]],null!==p.sWidth&&(p.sWidth=Gb(p.sWidthOrig,k),r=!0);if(d||!r&&!f&&!e&&j==ba(a)&&j==n.length)for(m=0;m<j;m++)i=$(a,m),null!==i&&(c[i].sWidth=v(n.eq(m).width()));else{j=h(b).clone().css("visibility","hidden").removeAttr("id");j.find("tbody tr").remove();var u=h("<tr/>").appendTo(j.find("tbody"));
j.find("thead, tfoot").remove();j.append(h(a.nTHead).clone()).append(h(a.nTFoot).clone());j.find("tfoot th, tfoot td").css("width","");n=ta(a,j.find("thead")[0]);for(m=0;m<i.length;m++)p=c[i[m]],n[m].style.width=null!==p.sWidthOrig&&""!==p.sWidthOrig?v(p.sWidthOrig):"",p.sWidthOrig&&f&&h(n[m]).append(h("<div/>").css({width:p.sWidthOrig,margin:0,padding:0,border:0,height:1}));if(a.aoData.length)for(m=0;m<i.length;m++)r=i[m],p=c[r],h(Hb(a,r)).clone(!1).append(p.sContentPadding).appendTo(u);h("[name]",
j).removeAttr("name");p=h("<div/>").css(f||e?{position:"absolute",top:0,left:0,height:1,right:0,overflow:"hidden"}:{}).append(j).appendTo(k);f&&g?j.width(g):f?(j.css("width","auto"),j.removeAttr("width"),j.width()<k.clientWidth&&l&&j.width(k.clientWidth)):e?j.width(k.clientWidth):l&&j.width(l);for(m=e=0;m<i.length;m++)k=h(n[m]),g=k.outerWidth()-k.width(),k=o.bBounding?Math.ceil(n[m].getBoundingClientRect().width):k.outerWidth(),e+=k,c[i[m]].sWidth=v(k-g);b.style.width=v(e);p.remove()}l&&(b.style.width=
v(l));if((l||f)&&!a._reszEvt)b=function(){h(E).on("resize.DT-"+a.sInstance,Qa(function(){Z(a)}))},d?setTimeout(b,1E3):b(),a._reszEvt=!0}function Gb(a,b){if(!a)return 0;var c=h("<div/>").css("width",v(a)).appendTo(b||H.body),d=c[0].offsetWidth;c.remove();return d}function Hb(a,b){var c=Ib(a,b);if(0>c)return null;var d=a.aoData[c];return!d.nTr?h("<td/>").html(B(a,c,b,"display"))[0]:d.anCells[b]}function Ib(a,b){for(var c,d=-1,e=-1,f=0,g=a.aoData.length;f<g;f++)c=B(a,f,b,"display")+"",c=c.replace(bc,
""),c=c.replace(/&nbsp;/g," "),c.length>d&&(d=c.length,e=f);return e}function v(a){return null===a?"0px":"number"==typeof a?0>a?"0px":a+"px":a.match(/\d$/)?a+"px":a}function W(a){var b,c,d=[],e=a.aoColumns,f,g,j,i;b=a.aaSortingFixed;c=h.isPlainObject(b);var n=[];f=function(a){a.length&&!h.isArray(a[0])?n.push(a):h.merge(n,a)};h.isArray(b)&&f(b);c&&b.pre&&f(b.pre);f(a.aaSorting);c&&b.post&&f(b.post);for(a=0;a<n.length;a++){i=n[a][0];f=e[i].aDataSort;b=0;for(c=f.length;b<c;b++)g=f[b],j=e[g].sType||
"string",n[a]._idx===k&&(n[a]._idx=h.inArray(n[a][1],e[g].asSorting)),d.push({src:i,col:g,dir:n[a][1],index:n[a]._idx,type:j,formatter:m.ext.type.order[j+"-pre"]})}return d}function ob(a){var b,c,d=[],e=m.ext.type.order,f=a.aoData,g=0,j,i=a.aiDisplayMaster,h;Ia(a);h=W(a);b=0;for(c=h.length;b<c;b++)j=h[b],j.formatter&&g++,Jb(a,j.col);if("ssp"!=y(a)&&0!==h.length){b=0;for(c=i.length;b<c;b++)d[i[b]]=b;g===h.length?i.sort(function(a,b){var c,e,g,j,i=h.length,k=f[a]._aSortData,m=f[b]._aSortData;for(g=
0;g<i;g++)if(j=h[g],c=k[j.col],e=m[j.col],c=c<e?-1:c>e?1:0,0!==c)return"asc"===j.dir?c:-c;c=d[a];e=d[b];return c<e?-1:c>e?1:0}):i.sort(function(a,b){var c,g,j,i,k=h.length,m=f[a]._aSortData,p=f[b]._aSortData;for(j=0;j<k;j++)if(i=h[j],c=m[i.col],g=p[i.col],i=e[i.type+"-"+i.dir]||e["string-"+i.dir],c=i(c,g),0!==c)return c;c=d[a];g=d[b];return c<g?-1:c>g?1:0})}a.bSorted=!0}function Kb(a){for(var b,c,d=a.aoColumns,e=W(a),a=a.oLanguage.oAria,f=0,g=d.length;f<g;f++){c=d[f];var j=c.asSorting;b=c.sTitle.replace(/<.*?>/g,
"");var i=c.nTh;i.removeAttribute("aria-sort");c.bSortable&&(0<e.length&&e[0].col==f?(i.setAttribute("aria-sort","asc"==e[0].dir?"ascending":"descending"),c=j[e[0].index+1]||j[0]):c=j[0],b+="asc"===c?a.sSortAscending:a.sSortDescending);i.setAttribute("aria-label",b)}}function Xa(a,b,c,d){var e=a.aaSorting,f=a.aoColumns[b].asSorting,g=function(a,b){var c=a._idx;c===k&&(c=h.inArray(a[1],f));return c+1<f.length?c+1:b?null:0};"number"===typeof e[0]&&(e=a.aaSorting=[e]);c&&a.oFeatures.bSortMulti?(c=h.inArray(b,
D(e,"0")),-1!==c?(b=g(e[c],!0),null===b&&1===e.length&&(b=0),null===b?e.splice(c,1):(e[c][1]=f[b],e[c]._idx=b)):(e.push([b,f[0],0]),e[e.length-1]._idx=0)):e.length&&e[0][0]==b?(b=g(e[0]),e.length=1,e[0][1]=f[b],e[0]._idx=b):(e.length=0,e.push([b,f[0]]),e[0]._idx=0);T(a);"function"==typeof d&&d(a)}function Oa(a,b,c,d){var e=a.aoColumns[c];Ya(b,{},function(b){!1!==e.bSortable&&(a.oFeatures.bProcessing?(C(a,!0),setTimeout(function(){Xa(a,c,b.shiftKey,d);"ssp"!==y(a)&&C(a,!1)},0)):Xa(a,c,b.shiftKey,d))})}
function ya(a){var b=a.aLastSort,c=a.oClasses.sSortColumn,d=W(a),e=a.oFeatures,f,g;if(e.bSort&&e.bSortClasses){e=0;for(f=b.length;e<f;e++)g=b[e].src,h(D(a.aoData,"anCells",g)).removeClass(c+(2>e?e+1:3));e=0;for(f=d.length;e<f;e++)g=d[e].src,h(D(a.aoData,"anCells",g)).addClass(c+(2>e?e+1:3))}a.aLastSort=d}function Jb(a,b){var c=a.aoColumns[b],d=m.ext.order[c.sSortDataType],e;d&&(e=d.call(a.oInstance,a,b,aa(a,b)));for(var f,g=m.ext.type.order[c.sType+"-pre"],j=0,i=a.aoData.length;j<i;j++)if(c=a.aoData[j],
c._aSortData||(c._aSortData=[]),!c._aSortData[b]||d)f=d?e[j]:B(a,j,b,"sort"),c._aSortData[b]=g?g(f):f}function za(a){if(a.oFeatures.bStateSave&&!a.bDestroying){var b={time:+new Date,start:a._iDisplayStart,length:a._iDisplayLength,order:h.extend(!0,[],a.aaSorting),search:Cb(a.oPreviousSearch),columns:h.map(a.aoColumns,function(b,d){return{visible:b.bVisible,search:Cb(a.aoPreSearchCols[d])}})};s(a,"aoStateSaveParams","stateSaveParams",[a,b]);a.oSavedState=b;a.fnStateSaveCallback.call(a.oInstance,a,
b)}}function Lb(a,b,c){var d,e,f=a.aoColumns,b=function(b){if(b&&b.time){var i=s(a,"aoStateLoadParams","stateLoadParams",[a,g]);if(-1===h.inArray(!1,i)&&(i=a.iStateDuration,!(0<i&&b.time<+new Date-1E3*i)&&!(b.columns&&f.length!==b.columns.length))){a.oLoadedState=h.extend(!0,{},g);b.start!==k&&(a._iDisplayStart=b.start,a.iInitDisplayStart=b.start);b.length!==k&&(a._iDisplayLength=b.length);b.order!==k&&(a.aaSorting=[],h.each(b.order,function(b,c){a.aaSorting.push(c[0]>=f.length?[0,c[1]]:c)}));b.search!==
k&&h.extend(a.oPreviousSearch,Db(b.search));if(b.columns){d=0;for(e=b.columns.length;d<e;d++)i=b.columns[d],i.visible!==k&&(f[d].bVisible=i.visible),i.search!==k&&h.extend(a.aoPreSearchCols[d],Db(i.search))}s(a,"aoStateLoaded","stateLoaded",[a,g])}}c()};if(a.oFeatures.bStateSave){var g=a.fnStateLoadCallback.call(a.oInstance,a,b);g!==k&&b(g)}else c()}function Aa(a){var b=m.settings,a=h.inArray(a,D(b,"nTable"));return-1!==a?b[a]:null}function K(a,b,c,d){c="DataTables warning: "+(a?"table id="+a.sTableId+
" - ":"")+c;d&&(c+=". For more information about this error, please see http://datatables.net/tn/"+d);if(b)E.console&&console.log&&console.log(c);else if(b=m.ext,b=b.sErrMode||b.errMode,a&&s(a,null,"error",[a,d,c]),"alert"==b)alert(c);else{if("throw"==b)throw Error(c);"function"==typeof b&&b(a,d,c)}}function F(a,b,c,d){h.isArray(c)?h.each(c,function(c,d){h.isArray(d)?F(a,b,d[0],d[1]):F(a,b,d)}):(d===k&&(d=c),b[c]!==k&&(a[d]=b[c]))}function Mb(a,b,c){var d,e;for(e in b)b.hasOwnProperty(e)&&(d=b[e],
h.isPlainObject(d)?(h.isPlainObject(a[e])||(a[e]={}),h.extend(!0,a[e],d)):a[e]=c&&"data"!==e&&"aaData"!==e&&h.isArray(d)?d.slice():d);return a}function Ya(a,b,c){h(a).on("click.DT",b,function(b){a.blur();c(b)}).on("keypress.DT",b,function(a){13===a.which&&(a.preventDefault(),c(a))}).on("selectstart.DT",function(){return!1})}function z(a,b,c,d){c&&a[b].push({fn:c,sName:d})}function s(a,b,c,d){var e=[];b&&(e=h.map(a[b].slice().reverse(),function(b){return b.fn.apply(a.oInstance,d)}));null!==c&&(b=h.Event(c+
".dt"),h(a.nTable).trigger(b,d),e.push(b.result));return e}function Ua(a){var b=a._iDisplayStart,c=a.fnDisplayEnd(),d=a._iDisplayLength;b>=c&&(b=c-d);b-=b%d;if(-1===d||0>b)b=0;a._iDisplayStart=b}function Pa(a,b){var c=a.renderer,d=m.ext.renderer[b];return h.isPlainObject(c)&&c[b]?d[c[b]]||d._:"string"===typeof c?d[c]||d._:d._}function y(a){return a.oFeatures.bServerSide?"ssp":a.ajax||a.sAjaxSource?"ajax":"dom"}function ia(a,b){var c=[],c=Nb.numbers_length,d=Math.floor(c/2);b<=c?c=X(0,b):a<=d?(c=X(0,
c-2),c.push("ellipsis"),c.push(b-1)):(a>=b-1-d?c=X(b-(c-2),b):(c=X(a-d+2,a+d-1),c.push("ellipsis"),c.push(b-1)),c.splice(0,0,"ellipsis"),c.splice(0,0,0));c.DT_el="span";return c}function fb(a){h.each({num:function(b){return Ba(b,a)},"num-fmt":function(b){return Ba(b,a,Za)},"html-num":function(b){return Ba(b,a,Ca)},"html-num-fmt":function(b){return Ba(b,a,Ca,Za)}},function(b,c){x.type.order[b+a+"-pre"]=c;b.match(/^html\-/)&&(x.type.search[b+a]=x.type.search.html)})}function Ob(a){return function(){var b=
[Aa(this[m.ext.iApiIndex])].concat(Array.prototype.slice.call(arguments));return m.ext.internal[a].apply(this,b)}}var m=function(a){this.$=function(a,b){return this.api(!0).$(a,b)};this._=function(a,b){return this.api(!0).rows(a,b).data()};this.api=function(a){return a?new u(Aa(this[x.iApiIndex])):new u(this)};this.fnAddData=function(a,b){var c=this.api(!0),d=h.isArray(a)&&(h.isArray(a[0])||h.isPlainObject(a[0]))?c.rows.add(a):c.row.add(a);(b===k||b)&&c.draw();return d.flatten().toArray()};this.fnAdjustColumnSizing=
function(a){var b=this.api(!0).columns.adjust(),c=b.settings()[0],d=c.oScroll;a===k||a?b.draw(!1):(""!==d.sX||""!==d.sY)&&ma(c)};this.fnClearTable=function(a){var b=this.api(!0).clear();(a===k||a)&&b.draw()};this.fnClose=function(a){this.api(!0).row(a).child.hide()};this.fnDeleteRow=function(a,b,c){var d=this.api(!0),a=d.rows(a),e=a.settings()[0],h=e.aoData[a[0][0]];a.remove();b&&b.call(this,e,h);(c===k||c)&&d.draw();return h};this.fnDestroy=function(a){this.api(!0).destroy(a)};this.fnDraw=function(a){this.api(!0).draw(a)};
this.fnFilter=function(a,b,c,d,e,h){e=this.api(!0);null===b||b===k?e.search(a,c,d,h):e.column(b).search(a,c,d,h);e.draw()};this.fnGetData=function(a,b){var c=this.api(!0);if(a!==k){var d=a.nodeName?a.nodeName.toLowerCase():"";return b!==k||"td"==d||"th"==d?c.cell(a,b).data():c.row(a).data()||null}return c.data().toArray()};this.fnGetNodes=function(a){var b=this.api(!0);return a!==k?b.row(a).node():b.rows().nodes().flatten().toArray()};this.fnGetPosition=function(a){var b=this.api(!0),c=a.nodeName.toUpperCase();
return"TR"==c?b.row(a).index():"TD"==c||"TH"==c?(a=b.cell(a).index(),[a.row,a.columnVisible,a.column]):null};this.fnIsOpen=function(a){return this.api(!0).row(a).child.isShown()};this.fnOpen=function(a,b,c){return this.api(!0).row(a).child(b,c).show().child()[0]};this.fnPageChange=function(a,b){var c=this.api(!0).page(a);(b===k||b)&&c.draw(!1)};this.fnSetColumnVis=function(a,b,c){a=this.api(!0).column(a).visible(b);(c===k||c)&&a.columns.adjust().draw()};this.fnSettings=function(){return Aa(this[x.iApiIndex])};
this.fnSort=function(a){this.api(!0).order(a).draw()};this.fnSortListener=function(a,b,c){this.api(!0).order.listener(a,b,c)};this.fnUpdate=function(a,b,c,d,e){var h=this.api(!0);c===k||null===c?h.row(b).data(a):h.cell(b,c).data(a);(e===k||e)&&h.columns.adjust();(d===k||d)&&h.draw();return 0};this.fnVersionCheck=x.fnVersionCheck;var b=this,c=a===k,d=this.length;c&&(a={});this.oApi=this.internal=x.internal;for(var e in m.ext.internal)e&&(this[e]=Ob(e));this.each(function(){var e={},g=1<d?Mb(e,a,!0):
a,j=0,i,e=this.getAttribute("id"),n=!1,l=m.defaults,q=h(this);if("table"!=this.nodeName.toLowerCase())K(null,0,"Non-table node initialisation ("+this.nodeName+")",2);else{gb(l);hb(l.column);J(l,l,!0);J(l.column,l.column,!0);J(l,h.extend(g,q.data()));var r=m.settings,j=0;for(i=r.length;j<i;j++){var p=r[j];if(p.nTable==this||p.nTHead.parentNode==this||p.nTFoot&&p.nTFoot.parentNode==this){var u=g.bRetrieve!==k?g.bRetrieve:l.bRetrieve;if(c||u)return p.oInstance;if(g.bDestroy!==k?g.bDestroy:l.bDestroy){p.oInstance.fnDestroy();
break}else{K(p,0,"Cannot reinitialise DataTable",3);return}}if(p.sTableId==this.id){r.splice(j,1);break}}if(null===e||""===e)this.id=e="DataTables_Table_"+m.ext._unique++;var o=h.extend(!0,{},m.models.oSettings,{sDestroyWidth:q[0].style.width,sInstance:e,sTableId:e});o.nTable=this;o.oApi=b.internal;o.oInit=g;r.push(o);o.oInstance=1===b.length?b:q.dataTable();gb(g);g.oLanguage&&Fa(g.oLanguage);g.aLengthMenu&&!g.iDisplayLength&&(g.iDisplayLength=h.isArray(g.aLengthMenu[0])?g.aLengthMenu[0][0]:g.aLengthMenu[0]);
g=Mb(h.extend(!0,{},l),g);F(o.oFeatures,g,"bPaginate bLengthChange bFilter bSort bSortMulti bInfo bProcessing bAutoWidth bSortClasses bServerSide bDeferRender".split(" "));F(o,g,["asStripeClasses","ajax","fnServerData","fnFormatNumber","sServerMethod","aaSorting","aaSortingFixed","aLengthMenu","sPaginationType","sAjaxSource","sAjaxDataProp","iStateDuration","sDom","bSortCellsTop","iTabIndex","fnStateLoadCallback","fnStateSaveCallback","renderer","searchDelay","rowId",["iCookieDuration","iStateDuration"],
["oSearch","oPreviousSearch"],["aoSearchCols","aoPreSearchCols"],["iDisplayLength","_iDisplayLength"],["bJQueryUI","bJUI"]]);F(o.oScroll,g,[["sScrollX","sX"],["sScrollXInner","sXInner"],["sScrollY","sY"],["bScrollCollapse","bCollapse"]]);F(o.oLanguage,g,"fnInfoCallback");z(o,"aoDrawCallback",g.fnDrawCallback,"user");z(o,"aoServerParams",g.fnServerParams,"user");z(o,"aoStateSaveParams",g.fnStateSaveParams,"user");z(o,"aoStateLoadParams",g.fnStateLoadParams,"user");z(o,"aoStateLoaded",g.fnStateLoaded,
"user");z(o,"aoRowCallback",g.fnRowCallback,"user");z(o,"aoRowCreatedCallback",g.fnCreatedRow,"user");z(o,"aoHeaderCallback",g.fnHeaderCallback,"user");z(o,"aoFooterCallback",g.fnFooterCallback,"user");z(o,"aoInitComplete",g.fnInitComplete,"user");z(o,"aoPreDrawCallback",g.fnPreDrawCallback,"user");o.rowIdFn=R(g.rowId);ib(o);var t=o.oClasses;g.bJQueryUI?(h.extend(t,m.ext.oJUIClasses,g.oClasses),g.sDom===l.sDom&&"lfrtip"===l.sDom&&(o.sDom='<"H"lfr>t<"F"ip>'),o.renderer)?h.isPlainObject(o.renderer)&&
!o.renderer.header&&(o.renderer.header="jqueryui"):o.renderer="jqueryui":h.extend(t,m.ext.classes,g.oClasses);q.addClass(t.sTable);o.iInitDisplayStart===k&&(o.iInitDisplayStart=g.iDisplayStart,o._iDisplayStart=g.iDisplayStart);null!==g.iDeferLoading&&(o.bDeferLoading=!0,e=h.isArray(g.iDeferLoading),o._iRecordsDisplay=e?g.iDeferLoading[0]:g.iDeferLoading,o._iRecordsTotal=e?g.iDeferLoading[1]:g.iDeferLoading);var v=o.oLanguage;h.extend(!0,v,g.oLanguage);v.sUrl&&(h.ajax({dataType:"json",url:v.sUrl,success:function(a){Fa(a);
J(l.oLanguage,a);h.extend(true,v,a);ha(o)},error:function(){ha(o)}}),n=!0);null===g.asStripeClasses&&(o.asStripeClasses=[t.sStripeOdd,t.sStripeEven]);var e=o.asStripeClasses,x=q.children("tbody").find("tr").eq(0);-1!==h.inArray(!0,h.map(e,function(a){return x.hasClass(a)}))&&(h("tbody tr",this).removeClass(e.join(" ")),o.asDestroyStripes=e.slice());e=[];r=this.getElementsByTagName("thead");0!==r.length&&(ea(o.aoHeader,r[0]),e=ta(o));if(null===g.aoColumns){r=[];j=0;for(i=e.length;j<i;j++)r.push(null)}else r=
g.aoColumns;j=0;for(i=r.length;j<i;j++)Ga(o,e?e[j]:null);kb(o,g.aoColumnDefs,r,function(a,b){la(o,a,b)});if(x.length){var w=function(a,b){return a.getAttribute("data-"+b)!==null?b:null};h(x[0]).children("th, td").each(function(a,b){var c=o.aoColumns[a];if(c.mData===a){var d=w(b,"sort")||w(b,"order"),e=w(b,"filter")||w(b,"search");if(d!==null||e!==null){c.mData={_:a+".display",sort:d!==null?a+".@data-"+d:k,type:d!==null?a+".@data-"+d:k,filter:e!==null?a+".@data-"+e:k};la(o,a)}}})}var U=o.oFeatures,
e=function(){if(g.aaSorting===k){var a=o.aaSorting;j=0;for(i=a.length;j<i;j++)a[j][1]=o.aoColumns[j].asSorting[0]}ya(o);U.bSort&&z(o,"aoDrawCallback",function(){if(o.bSorted){var a=W(o),b={};h.each(a,function(a,c){b[c.src]=c.dir});s(o,null,"order",[o,a,b]);Kb(o)}});z(o,"aoDrawCallback",function(){(o.bSorted||y(o)==="ssp"||U.bDeferRender)&&ya(o)},"sc");var a=q.children("caption").each(function(){this._captionSide=h(this).css("caption-side")}),b=q.children("thead");b.length===0&&(b=h("<thead/>").appendTo(q));
o.nTHead=b[0];b=q.children("tbody");b.length===0&&(b=h("<tbody/>").appendTo(q));o.nTBody=b[0];b=q.children("tfoot");if(b.length===0&&a.length>0&&(o.oScroll.sX!==""||o.oScroll.sY!==""))b=h("<tfoot/>").appendTo(q);if(b.length===0||b.children().length===0)q.addClass(t.sNoFooter);else if(b.length>0){o.nTFoot=b[0];ea(o.aoFooter,o.nTFoot)}if(g.aaData)for(j=0;j<g.aaData.length;j++)N(o,g.aaData[j]);else(o.bDeferLoading||y(o)=="dom")&&oa(o,h(o.nTBody).children("tr"));o.aiDisplay=o.aiDisplayMaster.slice();
o.bInitialised=true;n===false&&ha(o)};g.bStateSave?(U.bStateSave=!0,z(o,"aoDrawCallback",za,"state_save"),Lb(o,g,e)):e()}});b=null;return this},x,u,p,t,$a={},Pb=/[\r\n]/g,Ca=/<.*?>/g,cc=/^\d{2,4}[\.\/\-]\d{1,2}[\.\/\-]\d{1,2}([T ]{1}\d{1,2}[:\.]\d{2}([\.:]\d{2})?)?$/,dc=RegExp("(\\/|\\.|\\*|\\+|\\?|\\||\\(|\\)|\\[|\\]|\\{|\\}|\\\\|\\$|\\^|\\-)","g"),Za=/[',$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfk]/gi,M=function(a){return!a||!0===a||"-"===a?!0:!1},Qb=function(a){var b=parseInt(a,10);return!isNaN(b)&&
isFinite(a)?b:null},Rb=function(a,b){$a[b]||($a[b]=RegExp(Sa(b),"g"));return"string"===typeof a&&"."!==b?a.replace(/\./g,"").replace($a[b],"."):a},ab=function(a,b,c){var d="string"===typeof a;if(M(a))return!0;b&&d&&(a=Rb(a,b));c&&d&&(a=a.replace(Za,""));return!isNaN(parseFloat(a))&&isFinite(a)},Sb=function(a,b,c){return M(a)?!0:!(M(a)||"string"===typeof a)?null:ab(a.replace(Ca,""),b,c)?!0:null},D=function(a,b,c){var d=[],e=0,f=a.length;if(c!==k)for(;e<f;e++)a[e]&&a[e][b]&&d.push(a[e][b][c]);else for(;e<
f;e++)a[e]&&d.push(a[e][b]);return d},ja=function(a,b,c,d){var e=[],f=0,g=b.length;if(d!==k)for(;f<g;f++)a[b[f]][c]&&e.push(a[b[f]][c][d]);else for(;f<g;f++)e.push(a[b[f]][c]);return e},X=function(a,b){var c=[],d;b===k?(b=0,d=a):(d=b,b=a);for(var e=b;e<d;e++)c.push(e);return c},Tb=function(a){for(var b=[],c=0,d=a.length;c<d;c++)a[c]&&b.push(a[c]);return b},sa=function(a){var b=[],c,d,e=a.length,f,g=0;d=0;a:for(;d<e;d++){c=a[d];for(f=0;f<g;f++)if(b[f]===c)continue a;b.push(c);g++}return b};m.util=
{throttle:function(a,b){var c=b!==k?b:200,d,e;return function(){var b=this,g=+new Date,h=arguments;d&&g<d+c?(clearTimeout(e),e=setTimeout(function(){d=k;a.apply(b,h)},c)):(d=g,a.apply(b,h))}},escapeRegex:function(a){return a.replace(dc,"\\$1")}};var A=function(a,b,c){a[b]!==k&&(a[c]=a[b])},ca=/\[.*?\]$/,V=/\(\)$/,Sa=m.util.escapeRegex,xa=h("<div>")[0],$b=xa.textContent!==k,bc=/<.*?>/g,Qa=m.util.throttle,Ub=[],w=Array.prototype,ec=function(a){var b,c,d=m.settings,e=h.map(d,function(a){return a.nTable});
if(a){if(a.nTable&&a.oApi)return[a];if(a.nodeName&&"table"===a.nodeName.toLowerCase())return b=h.inArray(a,e),-1!==b?[d[b]]:null;if(a&&"function"===typeof a.settings)return a.settings().toArray();"string"===typeof a?c=h(a):a instanceof h&&(c=a)}else return[];if(c)return c.map(function(){b=h.inArray(this,e);return-1!==b?d[b]:null}).toArray()};u=function(a,b){if(!(this instanceof u))return new u(a,b);var c=[],d=function(a){(a=ec(a))&&(c=c.concat(a))};if(h.isArray(a))for(var e=0,f=a.length;e<f;e++)d(a[e]);
else d(a);this.context=sa(c);b&&h.merge(this,b);this.selector={rows:null,cols:null,opts:null};u.extend(this,this,Ub)};m.Api=u;h.extend(u.prototype,{any:function(){return 0!==this.count()},concat:w.concat,context:[],count:function(){return this.flatten().length},each:function(a){for(var b=0,c=this.length;b<c;b++)a.call(this,this[b],b,this);return this},eq:function(a){var b=this.context;return b.length>a?new u(b[a],this[a]):null},filter:function(a){var b=[];if(w.filter)b=w.filter.call(this,a,this);
else for(var c=0,d=this.length;c<d;c++)a.call(this,this[c],c,this)&&b.push(this[c]);return new u(this.context,b)},flatten:function(){var a=[];return new u(this.context,a.concat.apply(a,this.toArray()))},join:w.join,indexOf:w.indexOf||function(a,b){for(var c=b||0,d=this.length;c<d;c++)if(this[c]===a)return c;return-1},iterator:function(a,b,c,d){var e=[],f,g,h,i,n,l=this.context,m,p,t=this.selector;"string"===typeof a&&(d=c,c=b,b=a,a=!1);g=0;for(h=l.length;g<h;g++){var s=new u(l[g]);if("table"===b)f=
c.call(s,l[g],g),f!==k&&e.push(f);else if("columns"===b||"rows"===b)f=c.call(s,l[g],this[g],g),f!==k&&e.push(f);else if("column"===b||"column-rows"===b||"row"===b||"cell"===b){p=this[g];"column-rows"===b&&(m=Da(l[g],t.opts));i=0;for(n=p.length;i<n;i++)f=p[i],f="cell"===b?c.call(s,l[g],f.row,f.column,g,i):c.call(s,l[g],f,g,i,m),f!==k&&e.push(f)}}return e.length||d?(a=new u(l,a?e.concat.apply([],e):e),b=a.selector,b.rows=t.rows,b.cols=t.cols,b.opts=t.opts,a):this},lastIndexOf:w.lastIndexOf||function(a,
b){return this.indexOf.apply(this.toArray.reverse(),arguments)},length:0,map:function(a){var b=[];if(w.map)b=w.map.call(this,a,this);else for(var c=0,d=this.length;c<d;c++)b.push(a.call(this,this[c],c));return new u(this.context,b)},pluck:function(a){return this.map(function(b){return b[a]})},pop:w.pop,push:w.push,reduce:w.reduce||function(a,b){return jb(this,a,b,0,this.length,1)},reduceRight:w.reduceRight||function(a,b){return jb(this,a,b,this.length-1,-1,-1)},reverse:w.reverse,selector:null,shift:w.shift,
sort:w.sort,splice:w.splice,toArray:function(){return w.slice.call(this)},to$:function(){return h(this)},toJQuery:function(){return h(this)},unique:function(){return new u(this.context,sa(this))},unshift:w.unshift});u.extend=function(a,b,c){if(c.length&&b&&(b instanceof u||b.__dt_wrapper)){var d,e,f,g=function(a,b,c){return function(){var d=b.apply(a,arguments);u.extend(d,d,c.methodExt);return d}};d=0;for(e=c.length;d<e;d++)f=c[d],b[f.name]="function"===typeof f.val?g(a,f.val,f):h.isPlainObject(f.val)?
{}:f.val,b[f.name].__dt_wrapper=!0,u.extend(a,b[f.name],f.propExt)}};u.register=p=function(a,b){if(h.isArray(a))for(var c=0,d=a.length;c<d;c++)u.register(a[c],b);else for(var e=a.split("."),f=Ub,g,j,c=0,d=e.length;c<d;c++){g=(j=-1!==e[c].indexOf("()"))?e[c].replace("()",""):e[c];var i;a:{i=0;for(var n=f.length;i<n;i++)if(f[i].name===g){i=f[i];break a}i=null}i||(i={name:g,val:{},methodExt:[],propExt:[]},f.push(i));c===d-1?i.val=b:f=j?i.methodExt:i.propExt}};u.registerPlural=t=function(a,b,c){u.register(a,
c);u.register(b,function(){var a=c.apply(this,arguments);return a===this?this:a instanceof u?a.length?h.isArray(a[0])?new u(a.context,a[0]):a[0]:k:a})};p("tables()",function(a){var b;if(a){b=u;var c=this.context;if("number"===typeof a)a=[c[a]];else var d=h.map(c,function(a){return a.nTable}),a=h(d).filter(a).map(function(){var a=h.inArray(this,d);return c[a]}).toArray();b=new b(a)}else b=this;return b});p("table()",function(a){var a=this.tables(a),b=a.context;return b.length?new u(b[0]):a});t("tables().nodes()",
"table().node()",function(){return this.iterator("table",function(a){return a.nTable},1)});t("tables().body()","table().body()",function(){return this.iterator("table",function(a){return a.nTBody},1)});t("tables().header()","table().header()",function(){return this.iterator("table",function(a){return a.nTHead},1)});t("tables().footer()","table().footer()",function(){return this.iterator("table",function(a){return a.nTFoot},1)});t("tables().containers()","table().container()",function(){return this.iterator("table",
function(a){return a.nTableWrapper},1)});p("draw()",function(a){return this.iterator("table",function(b){"page"===a?O(b):("string"===typeof a&&(a="full-hold"===a?!1:!0),T(b,!1===a))})});p("page()",function(a){return a===k?this.page.info().page:this.iterator("table",function(b){Va(b,a)})});p("page.info()",function(){if(0===this.context.length)return k;var a=this.context[0],b=a._iDisplayStart,c=a.oFeatures.bPaginate?a._iDisplayLength:-1,d=a.fnRecordsDisplay(),e=-1===c;return{page:e?0:Math.floor(b/c),
pages:e?1:Math.ceil(d/c),start:b,end:a.fnDisplayEnd(),length:c,recordsTotal:a.fnRecordsTotal(),recordsDisplay:d,serverSide:"ssp"===y(a)}});p("page.len()",function(a){return a===k?0!==this.context.length?this.context[0]._iDisplayLength:k:this.iterator("table",function(b){Ta(b,a)})});var Vb=function(a,b,c){if(c){var d=new u(a);d.one("draw",function(){c(d.ajax.json())})}if("ssp"==y(a))T(a,b);else{C(a,!0);var e=a.jqXHR;e&&4!==e.readyState&&e.abort();ua(a,[],function(c){pa(a);for(var c=va(a,c),d=0,e=c.length;d<
e;d++)N(a,c[d]);T(a,b);C(a,!1)})}};p("ajax.json()",function(){var a=this.context;if(0<a.length)return a[0].json});p("ajax.params()",function(){var a=this.context;if(0<a.length)return a[0].oAjaxData});p("ajax.reload()",function(a,b){return this.iterator("table",function(c){Vb(c,!1===b,a)})});p("ajax.url()",function(a){var b=this.context;if(a===k){if(0===b.length)return k;b=b[0];return b.ajax?h.isPlainObject(b.ajax)?b.ajax.url:b.ajax:b.sAjaxSource}return this.iterator("table",function(b){h.isPlainObject(b.ajax)?
b.ajax.url=a:b.ajax=a})});p("ajax.url().load()",function(a,b){return this.iterator("table",function(c){Vb(c,!1===b,a)})});var bb=function(a,b,c,d,e){var f=[],g,j,i,n,l,m;i=typeof b;if(!b||"string"===i||"function"===i||b.length===k)b=[b];i=0;for(n=b.length;i<n;i++){j=b[i]&&b[i].split&&!b[i].match(/[\[\(:]/)?b[i].split(","):[b[i]];l=0;for(m=j.length;l<m;l++)(g=c("string"===typeof j[l]?h.trim(j[l]):j[l]))&&g.length&&(f=f.concat(g))}a=x.selector[a];if(a.length){i=0;for(n=a.length;i<n;i++)f=a[i](d,e,f)}return sa(f)},
cb=function(a){a||(a={});a.filter&&a.search===k&&(a.search=a.filter);return h.extend({search:"none",order:"current",page:"all"},a)},db=function(a){for(var b=0,c=a.length;b<c;b++)if(0<a[b].length)return a[0]=a[b],a[0].length=1,a.length=1,a.context=[a.context[b]],a;a.length=0;return a},Da=function(a,b){var c,d,e,f=[],g=a.aiDisplay;c=a.aiDisplayMaster;var j=b.search;d=b.order;e=b.page;if("ssp"==y(a))return"removed"===j?[]:X(0,c.length);if("current"==e){c=a._iDisplayStart;for(d=a.fnDisplayEnd();c<d;c++)f.push(g[c])}else if("current"==
d||"applied"==d)f="none"==j?c.slice():"applied"==j?g.slice():h.map(c,function(a){return-1===h.inArray(a,g)?a:null});else if("index"==d||"original"==d){c=0;for(d=a.aoData.length;c<d;c++)"none"==j?f.push(c):(e=h.inArray(c,g),(-1===e&&"removed"==j||0<=e&&"applied"==j)&&f.push(c))}return f};p("rows()",function(a,b){a===k?a="":h.isPlainObject(a)&&(b=a,a="");var b=cb(b),c=this.iterator("table",function(c){var e=b,f;return bb("row",a,function(a){var b=Qb(a);if(b!==null&&!e)return[b];f||(f=Da(c,e));if(b!==
null&&h.inArray(b,f)!==-1)return[b];if(a===null||a===k||a==="")return f;if(typeof a==="function")return h.map(f,function(b){var e=c.aoData[b];return a(b,e._aData,e.nTr)?b:null});b=Tb(ja(c.aoData,f,"nTr"));if(a.nodeName){if(a._DT_RowIndex!==k)return[a._DT_RowIndex];if(a._DT_CellIndex)return[a._DT_CellIndex.row];b=h(a).closest("*[data-dt-row]");return b.length?[b.data("dt-row")]:[]}if(typeof a==="string"&&a.charAt(0)==="#"){var i=c.aIds[a.replace(/^#/,"")];if(i!==k)return[i.idx]}return h(b).filter(a).map(function(){return this._DT_RowIndex}).toArray()},
c,e)},1);c.selector.rows=a;c.selector.opts=b;return c});p("rows().nodes()",function(){return this.iterator("row",function(a,b){return a.aoData[b].nTr||k},1)});p("rows().data()",function(){return this.iterator(!0,"rows",function(a,b){return ja(a.aoData,b,"_aData")},1)});t("rows().cache()","row().cache()",function(a){return this.iterator("row",function(b,c){var d=b.aoData[c];return"search"===a?d._aFilterData:d._aSortData},1)});t("rows().invalidate()","row().invalidate()",function(a){return this.iterator("row",
function(b,c){da(b,c,a)})});t("rows().indexes()","row().index()",function(){return this.iterator("row",function(a,b){return b},1)});t("rows().ids()","row().id()",function(a){for(var b=[],c=this.context,d=0,e=c.length;d<e;d++)for(var f=0,g=this[d].length;f<g;f++){var h=c[d].rowIdFn(c[d].aoData[this[d][f]]._aData);b.push((!0===a?"#":"")+h)}return new u(c,b)});t("rows().remove()","row().remove()",function(){var a=this;this.iterator("row",function(b,c,d){var e=b.aoData,f=e[c],g,h,i,n,l;e.splice(c,1);
g=0;for(h=e.length;g<h;g++)if(i=e[g],l=i.anCells,null!==i.nTr&&(i.nTr._DT_RowIndex=g),null!==l){i=0;for(n=l.length;i<n;i++)l[i]._DT_CellIndex.row=g}qa(b.aiDisplayMaster,c);qa(b.aiDisplay,c);qa(a[d],c,!1);Ua(b);c=b.rowIdFn(f._aData);c!==k&&delete b.aIds[c]});this.iterator("table",function(a){for(var c=0,d=a.aoData.length;c<d;c++)a.aoData[c].idx=c});return this});p("rows.add()",function(a){var b=this.iterator("table",function(b){var c,f,g,h=[];f=0;for(g=a.length;f<g;f++)c=a[f],c.nodeName&&"TR"===c.nodeName.toUpperCase()?
h.push(oa(b,c)[0]):h.push(N(b,c));return h},1),c=this.rows(-1);c.pop();h.merge(c,b);return c});p("row()",function(a,b){return db(this.rows(a,b))});p("row().data()",function(a){var b=this.context;if(a===k)return b.length&&this.length?b[0].aoData[this[0]]._aData:k;b[0].aoData[this[0]]._aData=a;da(b[0],this[0],"data");return this});p("row().node()",function(){var a=this.context;return a.length&&this.length?a[0].aoData[this[0]].nTr||null:null});p("row.add()",function(a){a instanceof h&&a.length&&(a=a[0]);
var b=this.iterator("table",function(b){return a.nodeName&&"TR"===a.nodeName.toUpperCase()?oa(b,a)[0]:N(b,a)});return this.row(b[0])});var eb=function(a,b){var c=a.context;if(c.length&&(c=c[0].aoData[b!==k?b:a[0]])&&c._details)c._details.remove(),c._detailsShow=k,c._details=k},Wb=function(a,b){var c=a.context;if(c.length&&a.length){var d=c[0].aoData[a[0]];if(d._details){(d._detailsShow=b)?d._details.insertAfter(d.nTr):d._details.detach();var e=c[0],f=new u(e),g=e.aoData;f.off("draw.dt.DT_details column-visibility.dt.DT_details destroy.dt.DT_details");
0<D(g,"_details").length&&(f.on("draw.dt.DT_details",function(a,b){e===b&&f.rows({page:"current"}).eq(0).each(function(a){a=g[a];a._detailsShow&&a._details.insertAfter(a.nTr)})}),f.on("column-visibility.dt.DT_details",function(a,b){if(e===b)for(var c,d=ba(b),f=0,h=g.length;f<h;f++)c=g[f],c._details&&c._details.children("td[colspan]").attr("colspan",d)}),f.on("destroy.dt.DT_details",function(a,b){if(e===b)for(var c=0,d=g.length;c<d;c++)g[c]._details&&eb(f,c)}))}}};p("row().child()",function(a,b){var c=
this.context;if(a===k)return c.length&&this.length?c[0].aoData[this[0]]._details:k;if(!0===a)this.child.show();else if(!1===a)eb(this);else if(c.length&&this.length){var d=c[0],c=c[0].aoData[this[0]],e=[],f=function(a,b){if(h.isArray(a)||a instanceof h)for(var c=0,k=a.length;c<k;c++)f(a[c],b);else a.nodeName&&"tr"===a.nodeName.toLowerCase()?e.push(a):(c=h("<tr><td/></tr>").addClass(b),h("td",c).addClass(b).html(a)[0].colSpan=ba(d),e.push(c[0]))};f(a,b);c._details&&c._details.detach();c._details=h(e);
c._detailsShow&&c._details.insertAfter(c.nTr)}return this});p(["row().child.show()","row().child().show()"],function(){Wb(this,!0);return this});p(["row().child.hide()","row().child().hide()"],function(){Wb(this,!1);return this});p(["row().child.remove()","row().child().remove()"],function(){eb(this);return this});p("row().child.isShown()",function(){var a=this.context;return a.length&&this.length?a[0].aoData[this[0]]._detailsShow||!1:!1});var fc=/^([^:]+):(name|visIdx|visible)$/,Xb=function(a,b,
c,d,e){for(var c=[],d=0,f=e.length;d<f;d++)c.push(B(a,e[d],b));return c};p("columns()",function(a,b){a===k?a="":h.isPlainObject(a)&&(b=a,a="");var b=cb(b),c=this.iterator("table",function(c){var e=a,f=b,g=c.aoColumns,j=D(g,"sName"),i=D(g,"nTh");return bb("column",e,function(a){var b=Qb(a);if(a==="")return X(g.length);if(b!==null)return[b>=0?b:g.length+b];if(typeof a==="function"){var e=Da(c,f);return h.map(g,function(b,f){return a(f,Xb(c,f,0,0,e),i[f])?f:null})}var k=typeof a==="string"?a.match(fc):
"";if(k)switch(k[2]){case "visIdx":case "visible":b=parseInt(k[1],10);if(b<0){var m=h.map(g,function(a,b){return a.bVisible?b:null});return[m[m.length+b]]}return[$(c,b)];case "name":return h.map(j,function(a,b){return a===k[1]?b:null});default:return[]}if(a.nodeName&&a._DT_CellIndex)return[a._DT_CellIndex.column];b=h(i).filter(a).map(function(){return h.inArray(this,i)}).toArray();if(b.length||!a.nodeName)return b;b=h(a).closest("*[data-dt-column]");return b.length?[b.data("dt-column")]:[]},c,f)},
1);c.selector.cols=a;c.selector.opts=b;return c});t("columns().header()","column().header()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].nTh},1)});t("columns().footer()","column().footer()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].nTf},1)});t("columns().data()","column().data()",function(){return this.iterator("column-rows",Xb,1)});t("columns().dataSrc()","column().dataSrc()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].mData},
1)});t("columns().cache()","column().cache()",function(a){return this.iterator("column-rows",function(b,c,d,e,f){return ja(b.aoData,f,"search"===a?"_aFilterData":"_aSortData",c)},1)});t("columns().nodes()","column().nodes()",function(){return this.iterator("column-rows",function(a,b,c,d,e){return ja(a.aoData,e,"anCells",b)},1)});t("columns().visible()","column().visible()",function(a,b){var c=this.iterator("column",function(b,c){if(a===k)return b.aoColumns[c].bVisible;var f=b.aoColumns,g=f[c],j=b.aoData,
i,n,l;if(a!==k&&g.bVisible!==a){if(a){var m=h.inArray(!0,D(f,"bVisible"),c+1);i=0;for(n=j.length;i<n;i++)l=j[i].nTr,f=j[i].anCells,l&&l.insertBefore(f[c],f[m]||null)}else h(D(b.aoData,"anCells",c)).detach();g.bVisible=a;fa(b,b.aoHeader);fa(b,b.aoFooter);za(b)}});a!==k&&(this.iterator("column",function(c,e){s(c,null,"column-visibility",[c,e,a,b])}),(b===k||b)&&this.columns.adjust());return c});t("columns().indexes()","column().index()",function(a){return this.iterator("column",function(b,c){return"visible"===
a?aa(b,c):c},1)});p("columns.adjust()",function(){return this.iterator("table",function(a){Z(a)},1)});p("column.index()",function(a,b){if(0!==this.context.length){var c=this.context[0];if("fromVisible"===a||"toData"===a)return $(c,b);if("fromData"===a||"toVisible"===a)return aa(c,b)}});p("column()",function(a,b){return db(this.columns(a,b))});p("cells()",function(a,b,c){h.isPlainObject(a)&&(a.row===k?(c=a,a=null):(c=b,b=null));h.isPlainObject(b)&&(c=b,b=null);if(null===b||b===k)return this.iterator("table",
function(b){var d=a,e=cb(c),f=b.aoData,g=Da(b,e),i=Tb(ja(f,g,"anCells")),j=h([].concat.apply([],i)),l,n=b.aoColumns.length,m,p,t,u,s,v;return bb("cell",d,function(a){var c=typeof a==="function";if(a===null||a===k||c){m=[];p=0;for(t=g.length;p<t;p++){l=g[p];for(u=0;u<n;u++){s={row:l,column:u};if(c){v=f[l];a(s,B(b,l,u),v.anCells?v.anCells[u]:null)&&m.push(s)}else m.push(s)}}return m}if(h.isPlainObject(a))return[a];c=j.filter(a).map(function(a,b){return{row:b._DT_CellIndex.row,column:b._DT_CellIndex.column}}).toArray();
if(c.length||!a.nodeName)return c;v=h(a).closest("*[data-dt-row]");return v.length?[{row:v.data("dt-row"),column:v.data("dt-column")}]:[]},b,e)});var d=this.columns(b,c),e=this.rows(a,c),f,g,j,i,n,l=this.iterator("table",function(a,b){f=[];g=0;for(j=e[b].length;g<j;g++){i=0;for(n=d[b].length;i<n;i++)f.push({row:e[b][g],column:d[b][i]})}return f},1);h.extend(l.selector,{cols:b,rows:a,opts:c});return l});t("cells().nodes()","cell().node()",function(){return this.iterator("cell",function(a,b,c){return(a=
a.aoData[b])&&a.anCells?a.anCells[c]:k},1)});p("cells().data()",function(){return this.iterator("cell",function(a,b,c){return B(a,b,c)},1)});t("cells().cache()","cell().cache()",function(a){a="search"===a?"_aFilterData":"_aSortData";return this.iterator("cell",function(b,c,d){return b.aoData[c][a][d]},1)});t("cells().render()","cell().render()",function(a){return this.iterator("cell",function(b,c,d){return B(b,c,d,a)},1)});t("cells().indexes()","cell().index()",function(){return this.iterator("cell",
function(a,b,c){return{row:b,column:c,columnVisible:aa(a,c)}},1)});t("cells().invalidate()","cell().invalidate()",function(a){return this.iterator("cell",function(b,c,d){da(b,c,a,d)})});p("cell()",function(a,b,c){return db(this.cells(a,b,c))});p("cell().data()",function(a){var b=this.context,c=this[0];if(a===k)return b.length&&c.length?B(b[0],c[0].row,c[0].column):k;lb(b[0],c[0].row,c[0].column,a);da(b[0],c[0].row,"data",c[0].column);return this});p("order()",function(a,b){var c=this.context;if(a===
k)return 0!==c.length?c[0].aaSorting:k;"number"===typeof a?a=[[a,b]]:a.length&&!h.isArray(a[0])&&(a=Array.prototype.slice.call(arguments));return this.iterator("table",function(b){b.aaSorting=a.slice()})});p("order.listener()",function(a,b,c){return this.iterator("table",function(d){Oa(d,a,b,c)})});p("order.fixed()",function(a){if(!a){var b=this.context,b=b.length?b[0].aaSortingFixed:k;return h.isArray(b)?{pre:b}:b}return this.iterator("table",function(b){b.aaSortingFixed=h.extend(!0,{},a)})});p(["columns().order()",
"column().order()"],function(a){var b=this;return this.iterator("table",function(c,d){var e=[];h.each(b[d],function(b,c){e.push([c,a])});c.aaSorting=e})});p("search()",function(a,b,c,d){var e=this.context;return a===k?0!==e.length?e[0].oPreviousSearch.sSearch:k:this.iterator("table",function(e){e.oFeatures.bFilter&&ga(e,h.extend({},e.oPreviousSearch,{sSearch:a+"",bRegex:null===b?!1:b,bSmart:null===c?!0:c,bCaseInsensitive:null===d?!0:d}),1)})});t("columns().search()","column().search()",function(a,
b,c,d){return this.iterator("column",function(e,f){var g=e.aoPreSearchCols;if(a===k)return g[f].sSearch;e.oFeatures.bFilter&&(h.extend(g[f],{sSearch:a+"",bRegex:null===b?!1:b,bSmart:null===c?!0:c,bCaseInsensitive:null===d?!0:d}),ga(e,e.oPreviousSearch,1))})});p("state()",function(){return this.context.length?this.context[0].oSavedState:null});p("state.clear()",function(){return this.iterator("table",function(a){a.fnStateSaveCallback.call(a.oInstance,a,{})})});p("state.loaded()",function(){return this.context.length?
this.context[0].oLoadedState:null});p("state.save()",function(){return this.iterator("table",function(a){za(a)})});m.versionCheck=m.fnVersionCheck=function(a){for(var b=m.version.split("."),a=a.split("."),c,d,e=0,f=a.length;e<f;e++)if(c=parseInt(b[e],10)||0,d=parseInt(a[e],10)||0,c!==d)return c>d;return!0};m.isDataTable=m.fnIsDataTable=function(a){var b=h(a).get(0),c=!1;if(a instanceof m.Api)return!0;h.each(m.settings,function(a,e){var f=e.nScrollHead?h("table",e.nScrollHead)[0]:null,g=e.nScrollFoot?
h("table",e.nScrollFoot)[0]:null;if(e.nTable===b||f===b||g===b)c=!0});return c};m.tables=m.fnTables=function(a){var b=!1;h.isPlainObject(a)&&(b=a.api,a=a.visible);var c=h.map(m.settings,function(b){if(!a||a&&h(b.nTable).is(":visible"))return b.nTable});return b?new u(c):c};m.camelToHungarian=J;p("$()",function(a,b){var c=this.rows(b).nodes(),c=h(c);return h([].concat(c.filter(a).toArray(),c.find(a).toArray()))});h.each(["on","one","off"],function(a,b){p(b+"()",function(){var a=Array.prototype.slice.call(arguments);
a[0]=h.map(a[0].split(/\s/),function(a){return!a.match(/\.dt\b/)?a+".dt":a}).join(" ");var d=h(this.tables().nodes());d[b].apply(d,a);return this})});p("clear()",function(){return this.iterator("table",function(a){pa(a)})});p("settings()",function(){return new u(this.context,this.context)});p("init()",function(){var a=this.context;return a.length?a[0].oInit:null});p("data()",function(){return this.iterator("table",function(a){return D(a.aoData,"_aData")}).flatten()});p("destroy()",function(a){a=a||
!1;return this.iterator("table",function(b){var c=b.nTableWrapper.parentNode,d=b.oClasses,e=b.nTable,f=b.nTBody,g=b.nTHead,j=b.nTFoot,i=h(e),f=h(f),k=h(b.nTableWrapper),l=h.map(b.aoData,function(a){return a.nTr}),p;b.bDestroying=!0;s(b,"aoDestroyCallback","destroy",[b]);a||(new u(b)).columns().visible(!0);k.off(".DT").find(":not(tbody *)").off(".DT");h(E).off(".DT-"+b.sInstance);e!=g.parentNode&&(i.children("thead").detach(),i.append(g));j&&e!=j.parentNode&&(i.children("tfoot").detach(),i.append(j));
b.aaSorting=[];b.aaSortingFixed=[];ya(b);h(l).removeClass(b.asStripeClasses.join(" "));h("th, td",g).removeClass(d.sSortable+" "+d.sSortableAsc+" "+d.sSortableDesc+" "+d.sSortableNone);b.bJUI&&(h("th span."+d.sSortIcon+", td span."+d.sSortIcon,g).detach(),h("th, td",g).each(function(){var a=h("div."+d.sSortJUIWrapper,this);h(this).append(a.contents());a.detach()}));f.children().detach();f.append(l);g=a?"remove":"detach";i[g]();k[g]();!a&&c&&(c.insertBefore(e,b.nTableReinsertBefore),i.css("width",
b.sDestroyWidth).removeClass(d.sTable),(p=b.asDestroyStripes.length)&&f.children().each(function(a){h(this).addClass(b.asDestroyStripes[a%p])}));c=h.inArray(b,m.settings);-1!==c&&m.settings.splice(c,1)})});h.each(["column","row","cell"],function(a,b){p(b+"s().every()",function(a){var d=this.selector.opts,e=this;return this.iterator(b,function(f,g,h,i,m){a.call(e[b](g,"cell"===b?h:d,"cell"===b?d:k),g,h,i,m)})})});p("i18n()",function(a,b,c){var d=this.context[0],a=R(a)(d.oLanguage);a===k&&(a=b);c!==
k&&h.isPlainObject(a)&&(a=a[c]!==k?a[c]:a._);return a.replace("%d",c)});m.version="1.10.13";m.settings=[];m.models={};m.models.oSearch={bCaseInsensitive:!0,sSearch:"",bRegex:!1,bSmart:!0};m.models.oRow={nTr:null,anCells:null,_aData:[],_aSortData:null,_aFilterData:null,_sFilterRow:null,_sRowStripe:"",src:null,idx:-1};m.models.oColumn={idx:null,aDataSort:null,asSorting:null,bSearchable:null,bSortable:null,bVisible:null,_sManualType:null,_bAttrSrc:!1,fnCreatedCell:null,fnGetData:null,fnSetData:null,
mData:null,mRender:null,nTh:null,nTf:null,sClass:null,sContentPadding:null,sDefaultContent:null,sName:null,sSortDataType:"std",sSortingClass:null,sSortingClassJUI:null,sTitle:null,sType:null,sWidth:null,sWidthOrig:null};m.defaults={aaData:null,aaSorting:[[0,"asc"]],aaSortingFixed:[],ajax:null,aLengthMenu:[10,25,50,100],aoColumns:null,aoColumnDefs:null,aoSearchCols:[],asStripeClasses:null,bAutoWidth:!0,bDeferRender:!1,bDestroy:!1,bFilter:!0,bInfo:!0,bJQueryUI:!1,bLengthChange:!0,bPaginate:!0,bProcessing:!1,
bRetrieve:!1,bScrollCollapse:!1,bServerSide:!1,bSort:!0,bSortMulti:!0,bSortCellsTop:!1,bSortClasses:!0,bStateSave:!1,fnCreatedRow:null,fnDrawCallback:null,fnFooterCallback:null,fnFormatNumber:function(a){return a.toString().replace(/\B(?=(\d{3})+(?!\d))/g,this.oLanguage.sThousands)},fnHeaderCallback:null,fnInfoCallback:null,fnInitComplete:null,fnPreDrawCallback:null,fnRowCallback:null,fnServerData:null,fnServerParams:null,fnStateLoadCallback:function(a){try{return JSON.parse((-1===a.iStateDuration?
sessionStorage:localStorage).getItem("DataTables_"+a.sInstance+"_"+location.pathname))}catch(b){}},fnStateLoadParams:null,fnStateLoaded:null,fnStateSaveCallback:function(a,b){try{(-1===a.iStateDuration?sessionStorage:localStorage).setItem("DataTables_"+a.sInstance+"_"+location.pathname,JSON.stringify(b))}catch(c){}},fnStateSaveParams:null,iStateDuration:7200,iDeferLoading:null,iDisplayLength:10,iDisplayStart:0,iTabIndex:0,oClasses:{},oLanguage:{oAria:{sSortAscending:": activate to sort column ascending",
sSortDescending:": activate to sort column descending"},oPaginate:{sFirst:"First",sLast:"Last",sNext:"Next",sPrevious:"Previous"},sEmptyTable:"No data available in table",sInfo:"Showing _START_ to _END_ of _TOTAL_ entries",sInfoEmpty:"Showing 0 to 0 of 0 entries",sInfoFiltered:"(filtered from _MAX_ total entries)",sInfoPostFix:"",sDecimal:"",sThousands:",",sLengthMenu:"Show _MENU_ entries",sLoadingRecords:"Loading...",sProcessing:"Processing...",sSearch:"Search:",sSearchPlaceholder:"",sUrl:"",sZeroRecords:"No matching records found"},
oSearch:h.extend({},m.models.oSearch),sAjaxDataProp:"data",sAjaxSource:null,sDom:"lfrtip",searchDelay:null,sPaginationType:"simple_numbers",sScrollX:"",sScrollXInner:"",sScrollY:"",sServerMethod:"GET",renderer:null,rowId:"DT_RowId"};Y(m.defaults);m.defaults.column={aDataSort:null,iDataSort:-1,asSorting:["asc","desc"],bSearchable:!0,bSortable:!0,bVisible:!0,fnCreatedCell:null,mData:null,mRender:null,sCellType:"td",sClass:"",sContentPadding:"",sDefaultContent:null,sName:"",sSortDataType:"std",sTitle:null,
sType:null,sWidth:null};Y(m.defaults.column);m.models.oSettings={oFeatures:{bAutoWidth:null,bDeferRender:null,bFilter:null,bInfo:null,bLengthChange:null,bPaginate:null,bProcessing:null,bServerSide:null,bSort:null,bSortMulti:null,bSortClasses:null,bStateSave:null},oScroll:{bCollapse:null,iBarWidth:0,sX:null,sXInner:null,sY:null},oLanguage:{fnInfoCallback:null},oBrowser:{bScrollOversize:!1,bScrollbarLeft:!1,bBounding:!1,barWidth:0},ajax:null,aanFeatures:[],aoData:[],aiDisplay:[],aiDisplayMaster:[],
aIds:{},aoColumns:[],aoHeader:[],aoFooter:[],oPreviousSearch:{},aoPreSearchCols:[],aaSorting:null,aaSortingFixed:[],asStripeClasses:null,asDestroyStripes:[],sDestroyWidth:0,aoRowCallback:[],aoHeaderCallback:[],aoFooterCallback:[],aoDrawCallback:[],aoRowCreatedCallback:[],aoPreDrawCallback:[],aoInitComplete:[],aoStateSaveParams:[],aoStateLoadParams:[],aoStateLoaded:[],sTableId:"",nTable:null,nTHead:null,nTFoot:null,nTBody:null,nTableWrapper:null,bDeferLoading:!1,bInitialised:!1,aoOpenRows:[],sDom:null,
searchDelay:null,sPaginationType:"two_button",iStateDuration:0,aoStateSave:[],aoStateLoad:[],oSavedState:null,oLoadedState:null,sAjaxSource:null,sAjaxDataProp:null,bAjaxDataGet:!0,jqXHR:null,json:k,oAjaxData:k,fnServerData:null,aoServerParams:[],sServerMethod:null,fnFormatNumber:null,aLengthMenu:null,iDraw:0,bDrawing:!1,iDrawError:-1,_iDisplayLength:10,_iDisplayStart:0,_iRecordsTotal:0,_iRecordsDisplay:0,bJUI:null,oClasses:{},bFiltered:!1,bSorted:!1,bSortCellsTop:null,oInit:null,aoDestroyCallback:[],
fnRecordsTotal:function(){return"ssp"==y(this)?1*this._iRecordsTotal:this.aiDisplayMaster.length},fnRecordsDisplay:function(){return"ssp"==y(this)?1*this._iRecordsDisplay:this.aiDisplay.length},fnDisplayEnd:function(){var a=this._iDisplayLength,b=this._iDisplayStart,c=b+a,d=this.aiDisplay.length,e=this.oFeatures,f=e.bPaginate;return e.bServerSide?!1===f||-1===a?b+d:Math.min(b+a,this._iRecordsDisplay):!f||c>d||-1===a?d:c},oInstance:null,sInstance:null,iTabIndex:0,nScrollHead:null,nScrollFoot:null,
aLastSort:[],oPlugins:{},rowIdFn:null,rowId:null};m.ext=x={buttons:{},classes:{},builder:"-source-",errMode:"alert",feature:[],search:[],selector:{cell:[],column:[],row:[]},internal:{},legacy:{ajax:null},pager:{},renderer:{pageButton:{},header:{}},order:{},type:{detect:[],search:{},order:{}},_unique:0,fnVersionCheck:m.fnVersionCheck,iApiIndex:0,oJUIClasses:{},sVersion:m.version};h.extend(x,{afnFiltering:x.search,aTypes:x.type.detect,ofnSearch:x.type.search,oSort:x.type.order,afnSortData:x.order,aoFeatures:x.feature,
oApi:x.internal,oStdClasses:x.classes,oPagination:x.pager});h.extend(m.ext.classes,{sTable:"dataTable",sNoFooter:"no-footer",sPageButton:"paginate_button",sPageButtonActive:"current",sPageButtonDisabled:"disabled",sStripeOdd:"odd",sStripeEven:"even",sRowEmpty:"dataTables_empty",sWrapper:"dataTables_wrapper",sFilter:"dataTables_filter",sInfo:"dataTables_info",sPaging:"dataTables_paginate paging_",sLength:"dataTables_length",sProcessing:"dataTables_processing",sSortAsc:"sorting_asc",sSortDesc:"sorting_desc",
sSortable:"sorting",sSortableAsc:"sorting_asc_disabled",sSortableDesc:"sorting_desc_disabled",sSortableNone:"sorting_disabled",sSortColumn:"sorting_",sFilterInput:"",sLengthSelect:"",sScrollWrapper:"dataTables_scroll",sScrollHead:"dataTables_scrollHead",sScrollHeadInner:"dataTables_scrollHeadInner",sScrollBody:"dataTables_scrollBody",sScrollFoot:"dataTables_scrollFoot",sScrollFootInner:"dataTables_scrollFootInner",sHeaderTH:"",sFooterTH:"",sSortJUIAsc:"",sSortJUIDesc:"",sSortJUI:"",sSortJUIAscAllowed:"",
sSortJUIDescAllowed:"",sSortJUIWrapper:"",sSortIcon:"",sJUIHeader:"",sJUIFooter:""});var Ea="",Ea="",G=Ea+"ui-state-default",ka=Ea+"css_right ui-icon ui-icon-",Yb=Ea+"fg-toolbar ui-toolbar ui-widget-header ui-helper-clearfix";h.extend(m.ext.oJUIClasses,m.ext.classes,{sPageButton:"fg-button ui-button "+G,sPageButtonActive:"ui-state-disabled",sPageButtonDisabled:"ui-state-disabled",sPaging:"dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi ui-buttonset-multi paging_",sSortAsc:G+" sorting_asc",
sSortDesc:G+" sorting_desc",sSortable:G+" sorting",sSortableAsc:G+" sorting_asc_disabled",sSortableDesc:G+" sorting_desc_disabled",sSortableNone:G+" sorting_disabled",sSortJUIAsc:ka+"triangle-1-n",sSortJUIDesc:ka+"triangle-1-s",sSortJUI:ka+"carat-2-n-s",sSortJUIAscAllowed:ka+"carat-1-n",sSortJUIDescAllowed:ka+"carat-1-s",sSortJUIWrapper:"DataTables_sort_wrapper",sSortIcon:"DataTables_sort_icon",sScrollHead:"dataTables_scrollHead "+G,sScrollFoot:"dataTables_scrollFoot "+G,sHeaderTH:G,sFooterTH:G,sJUIHeader:Yb+
" ui-corner-tl ui-corner-tr",sJUIFooter:Yb+" ui-corner-bl ui-corner-br"});var Nb=m.ext.pager;h.extend(Nb,{simple:function(){return["previous","next"]},full:function(){return["first","previous","next","last"]},numbers:function(a,b){return[ia(a,b)]},simple_numbers:function(a,b){return["previous",ia(a,b),"next"]},full_numbers:function(a,b){return["first","previous",ia(a,b),"next","last"]},first_last_numbers:function(a,b){return["first",ia(a,b),"last"]},_numbers:ia,numbers_length:7});h.extend(!0,m.ext.renderer,
{pageButton:{_:function(a,b,c,d,e,f){var g=a.oClasses,j=a.oLanguage.oPaginate,i=a.oLanguage.oAria.paginate||{},m,l,p=0,r=function(b,d){var k,t,u,s,v=function(b){Va(a,b.data.action,true)};k=0;for(t=d.length;k<t;k++){s=d[k];if(h.isArray(s)){u=h("<"+(s.DT_el||"div")+"/>").appendTo(b);r(u,s)}else{m=null;l="";switch(s){case "ellipsis":b.append('<span class="ellipsis">&#x2026;</span>');break;case "first":m=j.sFirst;l=s+(e>0?"":" "+g.sPageButtonDisabled);break;case "previous":m=j.sPrevious;l=s+(e>0?"":" "+
g.sPageButtonDisabled);break;case "next":m=j.sNext;l=s+(e<f-1?"":" "+g.sPageButtonDisabled);break;case "last":m=j.sLast;l=s+(e<f-1?"":" "+g.sPageButtonDisabled);break;default:m=s+1;l=e===s?g.sPageButtonActive:""}if(m!==null){u=h("<a>",{"class":g.sPageButton+" "+l,"aria-controls":a.sTableId,"aria-label":i[s],"data-dt-idx":p,tabindex:a.iTabIndex,id:c===0&&typeof s==="string"?a.sTableId+"_"+s:null}).html(m).appendTo(b);Ya(u,{action:s},v);p++}}}},t;try{t=h(b).find(H.activeElement).data("dt-idx")}catch(u){}r(h(b).empty(),
d);t!==k&&h(b).find("[data-dt-idx="+t+"]").focus()}}});h.extend(m.ext.type.detect,[function(a,b){var c=b.oLanguage.sDecimal;return ab(a,c)?"num"+c:null},function(a){if(a&&!(a instanceof Date)&&!cc.test(a))return null;var b=Date.parse(a);return null!==b&&!isNaN(b)||M(a)?"date":null},function(a,b){var c=b.oLanguage.sDecimal;return ab(a,c,!0)?"num-fmt"+c:null},function(a,b){var c=b.oLanguage.sDecimal;return Sb(a,c)?"html-num"+c:null},function(a,b){var c=b.oLanguage.sDecimal;return Sb(a,c,!0)?"html-num-fmt"+
c:null},function(a){return M(a)||"string"===typeof a&&-1!==a.indexOf("<")?"html":null}]);h.extend(m.ext.type.search,{html:function(a){return M(a)?a:"string"===typeof a?a.replace(Pb," ").replace(Ca,""):""},string:function(a){return M(a)?a:"string"===typeof a?a.replace(Pb," "):a}});var Ba=function(a,b,c,d){if(0!==a&&(!a||"-"===a))return-Infinity;b&&(a=Rb(a,b));a.replace&&(c&&(a=a.replace(c,"")),d&&(a=a.replace(d,"")));return 1*a};h.extend(x.type.order,{"date-pre":function(a){return Date.parse(a)||-Infinity},
"html-pre":function(a){return M(a)?"":a.replace?a.replace(/<.*?>/g,"").toLowerCase():a+""},"string-pre":function(a){return M(a)?"":"string"===typeof a?a.toLowerCase():!a.toString?"":a.toString()},"string-asc":function(a,b){return a<b?-1:a>b?1:0},"string-desc":function(a,b){return a<b?1:a>b?-1:0}});fb("");h.extend(!0,m.ext.renderer,{header:{_:function(a,b,c,d){h(a.nTable).on("order.dt.DT",function(e,f,g,h){if(a===f){e=c.idx;b.removeClass(c.sSortingClass+" "+d.sSortAsc+" "+d.sSortDesc).addClass(h[e]==
"asc"?d.sSortAsc:h[e]=="desc"?d.sSortDesc:c.sSortingClass)}})},jqueryui:function(a,b,c,d){h("<div/>").addClass(d.sSortJUIWrapper).append(b.contents()).append(h("<span/>").addClass(d.sSortIcon+" "+c.sSortingClassJUI)).appendTo(b);h(a.nTable).on("order.dt.DT",function(e,f,g,h){if(a===f){e=c.idx;b.removeClass(d.sSortAsc+" "+d.sSortDesc).addClass(h[e]=="asc"?d.sSortAsc:h[e]=="desc"?d.sSortDesc:c.sSortingClass);b.find("span."+d.sSortIcon).removeClass(d.sSortJUIAsc+" "+d.sSortJUIDesc+" "+d.sSortJUI+" "+
d.sSortJUIAscAllowed+" "+d.sSortJUIDescAllowed).addClass(h[e]=="asc"?d.sSortJUIAsc:h[e]=="desc"?d.sSortJUIDesc:c.sSortingClassJUI)}})}}});var Zb=function(a){return"string"===typeof a?a.replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;"):a};m.render={number:function(a,b,c,d,e){return{display:function(f){if("number"!==typeof f&&"string"!==typeof f)return f;var g=0>f?"-":"",h=parseFloat(f);if(isNaN(h))return Zb(f);h=h.toFixed(c);f=Math.abs(h);h=parseInt(f,10);f=c?b+(f-h).toFixed(c).substring(2):
"";return g+(d||"")+h.toString().replace(/\B(?=(\d{3})+(?!\d))/g,a)+f+(e||"")}}},text:function(){return{display:Zb}}};h.extend(m.ext.internal,{_fnExternApiFunc:Ob,_fnBuildAjax:ua,_fnAjaxUpdate:nb,_fnAjaxParameters:wb,_fnAjaxUpdateDraw:xb,_fnAjaxDataSrc:va,_fnAddColumn:Ga,_fnColumnOptions:la,_fnAdjustColumnSizing:Z,_fnVisibleToColumnIndex:$,_fnColumnIndexToVisible:aa,_fnVisbleColumns:ba,_fnGetColumns:na,_fnColumnTypes:Ia,_fnApplyColumnDefs:kb,_fnHungarianMap:Y,_fnCamelToHungarian:J,_fnLanguageCompat:Fa,
_fnBrowserDetect:ib,_fnAddData:N,_fnAddTr:oa,_fnNodeToDataIndex:function(a,b){return b._DT_RowIndex!==k?b._DT_RowIndex:null},_fnNodeToColumnIndex:function(a,b,c){return h.inArray(c,a.aoData[b].anCells)},_fnGetCellData:B,_fnSetCellData:lb,_fnSplitObjNotation:La,_fnGetObjectDataFn:R,_fnSetObjectDataFn:S,_fnGetDataMaster:Ma,_fnClearTable:pa,_fnDeleteIndex:qa,_fnInvalidate:da,_fnGetRowElements:Ka,_fnCreateTr:Ja,_fnBuildHead:mb,_fnDrawHead:fa,_fnDraw:O,_fnReDraw:T,_fnAddOptionsHtml:pb,_fnDetectHeader:ea,
_fnGetUniqueThs:ta,_fnFeatureHtmlFilter:rb,_fnFilterComplete:ga,_fnFilterCustom:Ab,_fnFilterColumn:zb,_fnFilter:yb,_fnFilterCreateSearch:Ra,_fnEscapeRegex:Sa,_fnFilterData:Bb,_fnFeatureHtmlInfo:ub,_fnUpdateInfo:Eb,_fnInfoMacros:Fb,_fnInitialise:ha,_fnInitComplete:wa,_fnLengthChange:Ta,_fnFeatureHtmlLength:qb,_fnFeatureHtmlPaginate:vb,_fnPageChange:Va,_fnFeatureHtmlProcessing:sb,_fnProcessingDisplay:C,_fnFeatureHtmlTable:tb,_fnScrollDraw:ma,_fnApplyToChildren:I,_fnCalculateColumnWidths:Ha,_fnThrottle:Qa,
_fnConvertToWidth:Gb,_fnGetWidestNode:Hb,_fnGetMaxLenString:Ib,_fnStringToCss:v,_fnSortFlatten:W,_fnSort:ob,_fnSortAria:Kb,_fnSortListener:Xa,_fnSortAttachListener:Oa,_fnSortingClasses:ya,_fnSortData:Jb,_fnSaveState:za,_fnLoadState:Lb,_fnSettingsFromNode:Aa,_fnLog:K,_fnMap:F,_fnBindAction:Ya,_fnCallbackReg:z,_fnCallbackFire:s,_fnLengthOverflow:Ua,_fnRenderer:Pa,_fnDataSource:y,_fnRowAttributes:Na,_fnCalculateEnd:function(){}});h.fn.dataTable=m;m.$=h;h.fn.dataTableSettings=m.settings;h.fn.dataTableExt=
m.ext;h.fn.DataTable=function(a){return h(this).dataTable(a).api()};h.each(m,function(a,b){h.fn.DataTable[a]=b});return h.fn.dataTable});

File diff suppressed because one or more lines are too long

View File

@@ -1,41 +0,0 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<link rel='shortcut icon' type='image/x-icon' href='../favicon.ico' />
<script src="../libs/jquery.min.js"></script>
<script src="../libs/jquery.dataTables.min.js"></script>
<script src="../libs/handlebars.min.js"></script>
<script src="../libs/moment.min.js"></script>
<script src="../libs/handlebarsmoment.js"></script>
<script src="../bootstrap/bootstrap.min.js"></script>
<script src="../libs/bootstrap-notify.js"></script>
<link href="../bootstrap/bootstrap.min.css" rel="stylesheet">
<link href="../animate.css" rel="stylesheet">
<link href="../custom.css" rel="stylesheet">
<title>Jackett</title>
</head>
<body>
<div id="page">
<img id="logo" src="../jacket_medium.png" /><span id="header-title">Jackett</span>
<hr />
<h1>Login</h1>
<form action="Dashboard" method="post">
<div class="input-area">
<span class="input-header">Admin password</span>
<input id="password" name="password" class="form-control input-right" type="password">
</div>
<div class="input-area">
<input type="submit" value="Login" />
</div>
</form>
</div>
</body>
</html>

View File

@@ -1,198 +0,0 @@
---
site: 1337x
name: 1337x
description: "1337X is a Public torrent site that offers verified torrent downloads"
language: en-us
type: public
encoding: UTF-8
links:
- https://1337x.to
caps:
categorymappings:
#Anime
- {id: 28, cat: TV/Anime, desc: "Anime/Anime"}
- {id: 78, cat: TV/Anime, desc: "Anime/Dual Audio"}
- {id: 79, cat: TV/Anime, desc: "Anime/Dubbed"}
- {id: 80, cat: TV/Anime, desc: "Anime/Subbed"}
- {id: 81, cat: TV/Anime, desc: "Anime/Raw"}
#Audio
- {id: 22, cat: Audio/MP3, desc: "Music/MP3"}
- {id: 23, cat: Audio/Lossless, desc: "Music/Lossless"}
- {id: 24, cat: Audio, desc: "Music/DVD"}
- {id: 25, cat: Audio/Video, desc: "Music/Video"}
- {id: 26, cat: Audio, desc: "Music/Radio"}
- {id: 27, cat: Audio/Other, desc: "Music/Other"}
- {id: 53, cat: Audio, desc: "Music/Album"}
- {id: 58, cat: Audio, desc: "Music/Box set"}
- {id: 59, cat: Audio, desc: "Music/Discography"}
- {id: 60, cat: Audio, desc: "Music/Single"}
- {id: 68, cat: Audio, desc: "Music/Concerts"}
- {id: 69, cat: Audio, desc: "Music/AAC"}
#Movies
- {id: 1, cat: Movies/DVD, desc: "Movies/DVD"}
- {id: 2, cat: Movies/SD, desc: "Movies/Divx/Xvid"}
- {id: 3, cat: Movies, desc: "Movies/SVCD/VCD"}
- {id: 4, cat: Movies/Foreign, desc: "Movies/Dubs/Dual Audio"}
- {id: 9, cat: Movies, desc: "Documentaries/Documentary"}
- {id: 42, cat: Movies/HD, desc: "Movies/HD"}
- {id: 54, cat: Movies, desc: "Movies/h.264/x264"}
- {id: 55, cat: Movies, desc: "Movies/Mp4"}
- {id: 66, cat: Movies/3D, desc: "Movies/3D"}
- {id: 70, cat: Movies, desc: "Movies/HEVC/x265"}
- {id: 73, cat: Movies, desc: "Movies/Bollywood"}
- {id: 76, cat: Movies, desc: "Movies/UHD"}
#TV
- {id: 5, cat: TV, desc: "TV/DVD"}
- {id: 6, cat: TV, desc: "TV/Divx/Xvid"}
- {id: 7, cat: TV, desc: "TV/SVCD/VCD"}
- {id: 41, cat: TV/HD, desc: "TV/HD"}
- {id: 71, cat: TV, desc: "TV/HEVC/x265"}
- {id: 74, cat: TV, desc: "TV/Cartoons"}
- {id: 75, cat: TV/SD, desc: "TV/SD"}
#Apps
- {id: 18, cat: PC, desc: "Apps/PC Software"}
- {id: 19, cat: PC/Mac, desc: "Apps/Mac"}
- {id: 20, cat: PC, desc: "Apps/Linux"}
- {id: 21, cat: PC, desc: "Apps/Other"}
- {id: 56, cat: PC/Phone-Android, desc: "Apps/Android"}
- {id: 57, cat: PC/Phone-IOS, desc: "Apps/iOS"}
#Games
- {id: 10, cat: PC/Games, desc: "Games/PC Game"}
- {id: 11, cat: Console/Other, desc: "Games/PS2"}
- {id: 12, cat: Console/PSP, desc: "Games/PSP"}
- {id: 13, cat: Console/Xbox, desc: "Games/Xbox"}
- {id: 14, cat: Console/Xbox 360, desc: "Games/Xbox360"}
- {id: 15, cat: Console/Other, desc: "Games/PS1"}
- {id: 16, cat: Console/Other, desc: "Games/Dreamcast"}
- {id: 17, cat: PC/Phone-Other, desc: "Games/Other"}
- {id: 43, cat: Console/PS3, desc: "Games/PS3"}
- {id: 44, cat: Console/Wii, desc: "Games/Wii"}
- {id: 45, cat: Console/NDS, desc: "Games/DS"}
- {id: 46, cat: Console, desc: "Games/GameCube"}
- {id: 72, cat: Console/3DS, desc: "Games/3DS"}
- {id: 77, cat: Console/PS4, desc: "Games/PS4"}
- {id: 82, cat: Console/Other, desc: "Games/Switch"}
#XXX
- {id: 48, cat: XXX/DVD, desc: "XXX/Video"}
- {id: 49, cat: XXX/Imageset, desc: "XXX/Picture"}
- {id: 50, cat: XXX, desc: "XXX/Magazine"}
- {id: 51, cat: XXX, desc: "XXX/Hentai"}
- {id: 67, cat: XXX, desc: "XXX/Games"}
#Other
- {id: 33, cat: Other, desc: "Other/Emulation"}
- {id: 34, cat: Books, desc: "Other/Tutorial"}
- {id: 35, cat: Other, desc: "Other/Sounds"}
- {id: 36, cat: Books/Ebook, desc: "Other/E-books"}
- {id: 37, cat: Other, desc: "Other/Images"}
- {id: 38, cat: Other, desc: "Other/Mobile Phone"}
- {id: 39, cat: Books/Comics, desc: "Other/Comics"}
- {id: 40, cat: Other/Misc, desc: "Other/Other"}
- {id: 47, cat: Other, desc: "Other/Nulled Script"}
- {id: 52, cat: Audio/Audiobook, desc: "Other/Audiobook"}
modes:
search: [q]
tv-search: [q, season, ep]
movie-search: [q]
settings:
- name: downloadlink
type: select
label: Download link
default: "magnet:"
options:
"http://itorrents.org/" : "iTorrents.org"
"magnet:": "magnet"
download:
# the .torrent url is on the on the details page
selector: ul li a[href^="{{ .Config.downloadlink }}"]
search:
paths:
# present trending results if there are no search parms supplied
- path: "{{if .Keywords}}/search/{{ .Keywords}}/1/{{else}}/trending{{end}}"
keywordsfilters:
- name: replace # use this as a workaround till #893 is implemented
args: ["Greys Anatomy", "Grey's Anatomy"]
rows:
selector: tr:has(a[href^="/torrent/"])
fields:
title:
selector: td[class^="coll-1"] a[href^="/torrent/"]
filters:
- name: replace
args: ["Grey's Anatomy", "Greys Anatomy"]
category:
optional: true
selector: td[class^="coll-1"] a[href^="/sub/"]
attribute: href
filters:
# extract the third part
- name: split
args: ["/", 2]
details:
selector: td[class^="coll-1"] a[href^="/torrent/"]
attribute: href
download:
# .torrent link is on the details page
selector: td[class^="coll-1"] a[href^="/torrent/"]
attribute: href
# dates come in three flavours:
date:
# (within this year) 7am Sep. 14th
optional: true
selector: td[class^="coll-date"]:not(:contains(":")):not(:contains("'"))
filters:
- name: replace
args: ["st", ""]
- name: replace
args: ["nd", ""]
- name: replace
args: ["rd", ""]
- name: replace
args: ["th", ""]
- name: dateparse
args: "3pm Jan. 2"
date:
# (more than a year ago) Apr. 18th '11
optional: true
selector: td[class^="coll-date"]:contains("'")
filters:
- name: replace
args: ["'", ""]
- name: replace
args: ["st", ""]
- name: replace
args: ["nd", ""]
- name: replace
args: ["rd", ""]
- name: replace
args: ["th", ""]
- name: dateparse
args: "Jan. 2 06"
date:
# # (today) 12:25am
optional: true
selector: td[class^="coll-date"]:contains(":")
filters:
- name: dateparse
args: "3:04pm"
size:
selector: td[class^="coll-4"]
seeders:
selector: td[class^="coll-2"]
leechers:
selector: td[class^="coll-3"]
downloadvolumefactor:
text: "0"
uploadvolumefactor:
text: "1"

View File

@@ -1,148 +0,0 @@
---
site: 2fast4you
name: 2 Fast 4 You
description: "2 Fast 4 You is a FRENCH Private site for TV / MOVIES / GENERAL"
language: fr-fr
type: private
encoding: UTF-8
links:
- http://www.2f4y.me/
caps:
categorymappings:
- {id: 10, cat: TV/Anime, desc: "Animation: HD720P"}
- {id: 11, cat: TV/Anime, desc: "Animation: HD1080P"}
- {id: 56, cat: TV/Anime, desc: "Animation: DVDRip"}
- {id: 13, cat: TV/Anime, desc: "Animation: DVD"}
- {id: 18, cat: PC/0day, desc: "Applications: PC"}
- {id: 16, cat: PC/Games, desc: "Applications: Jeux"}
- {id: 19, cat: PC/Phone-Android, desc: "Applications: Android"}
- {id: 38, cat: PC/Phone-IOS, desc: "Applications: Mobile Phone"}
- {id: 17, cat: PC/0day, desc: "Applications: Autres"}
- {id: 67, cat: TV, desc: "Autres: Emission TV"}
- {id: 68, cat: TV/Sport, desc: "Autres: Sport"}
- {id: 40, cat: Other, desc: "Autres: Autres"}
- {id: 14, cat: TV/Documentary, desc: "Documentaires: DivX"}
- {id: 15, cat: TV/Documentary, desc: "Documentaires: HD"}
- {id: 76, cat: TV/Documentary, desc: "Documentaires: TVRip"}
- {id: 62, cat: Audio/Audiobook, desc: "E-Books: E-Books Audio"}
- {id: 50, cat: Books, desc: "E-Books: Manuel Français"}
- {id: 49, cat: Books, desc: "E-Books: Manuel Anglais"}
- {id: 36, cat: Books, desc: "E-Books: Livres Français"}
- {id: 53, cat: Books, desc: "E-Books: Livre Anglais"}
- {id: 52, cat: Books, desc: "E-Books: Revue - Journaux"}
- {id: 51, cat: Books, desc: "E-Books: BD"}
- {id: 66, cat: Movies, desc: "Films: VOSTFR"}
- {id: 71, cat: Movies/WEBDL, desc: "Films: WEB-DL"}
- {id: 65, cat: Movies, desc: "Films: VO"}
- {id: 72, cat: Movies/SD, desc: "Films: TVRip/HDTV"}
- {id: 70, cat: Movies/HD, desc: "Films: MHD X265"}
- {id: 57, cat: Movies/SD, desc: "Films: TS/CAM"}
- {id: 59, cat: Movies, desc: "Films: Spectacle"}
- {id: 55, cat: Movies/HD, desc: "Films: MHD 720P"}
- {id: 54, cat: Movies/HD, desc: "Films: MHD 1080P"}
- {id: 1, cat: Movies/HD, desc: "Films: HD720P"}
- {id: 2, cat: Movies/HD, desc: "Films: HD1080P"}
- {id: 90, cat: Movies/HD, desc: "Films: HD X265"}
- {id: 92, cat: Movies/HD, desc: "Films: 4K"}
- {id: 69, cat: Movies/3D, desc: "Films: Film 3D"}
- {id: 3, cat: Movies/DVD, desc: "Films: DVDRIP"}
- {id: 4, cat: Movies/DVD, desc: "Films: DVD5"}
- {id: 5, cat: Movies/DVD, desc: "Films: DVD9"}
- {id: 91, cat: Movies/HD, desc: "Films: RemuX"}
- {id: 89, cat: Movies/HD, desc: "Films: BD/BR Rip"}
- {id: 88, cat: Movies/BluRay, desc: "Films: Full BD/BR"}
- {id: 77, cat: Other, desc: "GPS: Cartes"}
- {id: 78, cat: Other, desc: "GPS: Radars"}
- {id: 79, cat: TV/Anime, desc: "Mangas: HD"}
- {id: 80, cat: TV/Anime, desc: "Mangas: HD VO"}
- {id: 81, cat: TV/Anime, desc: "Mangas: HD VOSTFR"}
- {id: 82, cat: TV/Anime, desc: "Mangas: DVDRIP"}
- {id: 83, cat: TV/Anime, desc: "Mangas: DVDRIP VO"}
- {id: 84, cat: TV/Anime, desc: "Mangas: DVDRIP VOSTFR"}
- {id: 85, cat: TV/Anime, desc: "Mangas: Web-DL"}
- {id: 86, cat: TV/Anime, desc: "Mangas: TV-RIP"}
- {id: 75, cat: Audio, desc: "Musique: Concert TVRip"}
- {id: 25, cat: Audio/MP3, desc: "Musique: Single MP3"}
- {id: 24, cat: Audio/Lossless, desc: "Musique: Single Flac"}
- {id: 22, cat: Audio/MP3, desc: "Musique: Album MP3"}
- {id: 23, cat: Audio/Lossless, desc: "Musique: Album Flac"}
- {id: 64, cat: Audio, desc: "Musique: Mégamix Maison"}
- {id: 94, cat: Audio, desc: "Musique: Podcast"}
- {id: 58, cat: Audio, desc: "Musique: Concert"}
- {id: 93, cat: TV, desc: "Serie TV: Saison VOSTFR"}
- {id: 61, cat: TV, desc: "Serie TV: Episode VOSTFR"}
- {id: 63, cat: TV, desc: "Serie TV: Episode VO"}
- {id: 12, cat: TV/Anime, desc: "Serie TV: Animation"}
- {id: 74, cat: TV, desc: "Serie TV: TVRip"}
- {id: 73, cat: TV/WEB-DL, desc: "Serie TV: WEB-DL"}
- {id: 7, cat: TV, desc: "Serie TV: Episode FR"}
- {id: 6, cat: TV, desc: "Serie TV: Saison FR"}
modes:
search: [q]
tv-search: [q, season, ep]
login:
path: account-login.php
method: post
inputs:
username: "{{ .Config.username }}"
password: "{{ .Config.password }}"
error:
- selector: form:contains("Erreur")
message:
selector: form
remove: table
test:
path: torrents-search.php
search:
paths:
- path: torrents-search.php
inputs:
$raw: "{{range .Categories}}c{{.}}=1&{{end}}"
search: "{{ .Keywords }}"
incldead: "1"
keywordsfilters:
- name: re_replace
args: ["^$", "%"] # replace empty search string with %
rows:
selector: table.ttable_headinner > tbody > tr[class^="t-row"]
fields:
download:
selector: a[href^="torrents-details.php?id="]
attribute: href
filters:
- name: replace
args: ["torrents-details.php", "download.php"]
title:
selector: a[href^="torrents-details.php?id="]
filters:
- name: replace
args: [" - (Nouveau!)", ""]
category:
selector: a[href^="torrents.php?cat="]
attribute: href
filters:
- name: querystring
args: cat
details:
selector: a[href^="torrents-details.php?id="]
attribute: href
banner:
selector: img.rounded-img
attribute: src
size:
selector: td:nth-child(5)
seeders:
selector: td:nth-child(6)
leechers:
selector: td:nth-child(7)
downloadvolumefactor:
case:
img[title="freeleech"]: "0"
"*": "1"
uploadvolumefactor:
case:
"*": "1"

View File

@@ -1,100 +0,0 @@
---
site: 3dtorrents
name: 3D Torrents
description: "3D Movie tracker"
language: en-us
type: private
encoding: UTF-8
links:
- http://www.3dtorrents.org/
caps:
categorymappings:
- {id: 14, cat: Movies, desc: "Movies XviD"}
- {id: 34, cat: Movies, desc: "Movies UltraHD"}
- {id: 15, cat: Movies, desc: "Movies DVD-R"}
- {id: 11, cat: Movies, desc: "Movies 720p"}
- {id: 13, cat: Movies, desc: "Movies 1080p"}
- {id: 16, cat: Movies, desc: "Movies 3DTV"}
- {id: 17, cat: Movies, desc: "Movies Blu-ray"}
- {id: 27, cat: Movies, desc: "Movies BD25 Encode"}
- {id: 33, cat: Movies, desc: "Movies BD9 AVCHD"}
- {id: 22, cat: Movies, desc: "Movies 2D to 3D Conv"}
- {id: 32, cat: Movies, desc: "Bluray MKV Remux"}
- {id: 23, cat: Movies, desc: "Movies Evo 3D"}
- {id: 21, cat: PC, desc: "3D Software"}
- {id: 2, cat: Audio, desc: "Music"}
- {id: 28, cat: XXX, desc: "Adult 720p"}
- {id: 29, cat: XXX, desc: "Adult 1080p"}
- {id: 30, cat: XXX, desc: "Adult Blu-ray"}
- {id: 31, cat: Other, desc: "Misc"}
- {id: 19, cat: Audio, desc: "Audio Packs"}
modes:
search: [q]
login:
path: index.php?page=login&amp;returnto=index.php
method: form
form: form
inputs:
uid: "{{ .Config.username }}"
pwd: "{{ .Config.password }}"
captcha:
type: image
selector: img.captcha
input: private_key
error:
- selector: span.errormsg
test:
path: index.php
search:
paths:
- path: index.php
inputs:
$raw: "{{range .Categories}}filter_cat[{{.}}]=1&{{end}}"
search: "{{ .Query.Keywords }}"
page: torrents
category: 0
3dformat: 0
active: 1
rows:
selector: table[cellspacing!="1"].lista > tbody > tr:has(a[href^="index.php?page=torrents&category="])
fields:
category:
selector: a[href^="index.php?page=torrents&category="]
attribute: href
filters:
- name: querystring
args: category
title:
remove: span
selector: td:nth-child(2)
download:
selector: a[href^="index.php?page=torrent-details&id="]
attribute: href
filters:
- name: replace
args: ["index.php?page=torrent-details&id=", "download.php?id="]
details:
selector: a[href^="index.php?page=torrent-details&id="]
attribute: href
size:
selector: td:nth-last-child(4)
seeders:
selector: td:nth-last-child(3)
# leechers:
# selector: td:nth-last-child(2)
date:
selector: td:nth-last-child(5)
filters:
- name: dateparse
args: "02/01/2006"
downloadvolumefactor:
case:
img[title^="You get 50% off download count on this torrent"]: "0.5"
"*": "1"
uploadvolumefactor:
case:
"*": "1"

View File

@@ -1,171 +0,0 @@
---
site: Bittorrentfiles
name: Bittorrentfiles
description: "Bittorrentfiles is a Private GERMAN tracker"
language: de-de
type: private
encoding: UTF-8
links:
- https://www.Bittorrentfiles.me/
caps:
categorymappings:
# Movie
- {id: 48, cat: Movies/HD, desc: "1080p"}
- {id: 31, cat: Movies/3D, desc: "3D"}
- {id: 21, cat: Movies/HD, desc: "720p"}
- {id: 28, cat: Movies/SD, desc: "AVI"}
- {id: 20, cat: Movies/DVD, desc: "DVD-R"}
- {id: 40, cat: Movies/HD, desc: "h264/x264"}
- {id: 30, cat: Movies/HD, desc: "HD/BD"}
- {id: 49, cat: Movies/Foreign, desc: "International"}
- {id: 78, cat: Movies/HD, desc: "UHD"}
# Serien
- {id: 79, cat: TV/HD, desc: "Staffeln HD"}
- {id: 56, cat: TV/SD, desc: "Staffeln SD"}
- {id: 54, cat: TV/HD, desc: "Folgen HD"}
- {id: 80, cat: TV/HD, desc: "Folgen HD/BD"}
- {id: 7, cat: TV/SD, desc: "Folgen SD"}
- {id: 55, cat: TV/Foreign, desc: "International"}
# Doku
- {id: 64, cat: TV/Documentary, desc: "HD"}
- {id: 36, cat: TV/Documentary, desc: "SD"}
- {id: 81, cat: TV/Documentary, desc: "3D"}
- {id: 82, cat: TV/Documentary, desc: "Packs"}
# Spiele
- {id: 4, cat: PC/Games, desc: "Windows"}
- {id: 72, cat: Console/XBox360, desc: "XBOX 360"}
- {id: 44, cat: Console/XBoxOne, desc: "XBOX One"}
- {id: 43, cat: Console/Wii, desc: "Wii"}
- {id: 69, cat: Console, desc: "PS2"}
- {id: 70, cat: Console/PS3, desc: "PS3"}
- {id: 70, cat: Console/PS4, desc: "PS4"}
- {id: 70, cat: Console/PSP, desc: "PSP"}
- {id: 42, cat: Console/Other, desc: "Misc"}
# Musik
- {id: 66, cat: Audio, desc: "Alben"}
- {id: 75, cat: Audio, desc: "Singles"}
- {id: 50, cat: Audio, desc: "Charts"}
- {id: 52, cat: Audio, desc: "Packs"}
- {id: 53, cat: Audio/Video, desc: "Video"}
- {id: 61, cat: Audio/Video, desc: "DVD-R"}
- {id: 83, cat: Audio, desc: "Flac"}
- {id: 68, cat: Audio, desc: "Live"}
- {id: 6, cat: Audio, desc: "Misc"}
- {id: 51, cat: Audio, desc: "OST"}
- {id: 67, cat: Audio, desc: "Sampler"}
# App
- {id: 22, cat: PC/0day, desc: "Windows"}
- {id: 62, cat: PC/Mac, desc: "Mac OS"}
- {id: 63, cat: PC/0day, desc: "Linux"}
- {id: 34, cat: PC, desc: "Andere"}
# Sport
- {id: 74, cat: TV/Sport, desc: "HD"}
- {id: 39, cat: TV/Sport, desc: "SD"}
# Sonstiges
- {id: 41, cat: Books/Comics, desc: "A-Book"}
- {id: 33, cat: TV/Anime, desc: "Anime"}
- {id: 35, cat: Books, desc: "e-Book"}
- {id: 65, cat: Other, desc: "E-Learning"}
- {id: 65, cat: PC, desc: "Mobile"}
- {id: 9, cat: Other, desc: "Other"}
#XXX
- {id: 58, cat: Books/Comics, desc: "HD"}
- {id: 33, cat: XXX, desc: "Hentai"}
- {id: 35, cat: XXX/Other, desc: "Other"}
- {id: 65, cat: XXX/Packs, desc: "Pack"}
- {id: 65, cat: XXX, desc: "SD"}
modes:
search: [q]
tv-search: [q, season, ep]
settings:
- name: user
type: text
label: Username
- name: pass
type: password
label: Password
login:
path: signin.php
method: form
form: form
inputs:
user: "{{ .Config.user }}"
pass: "{{ .Config.pass }}"
error:
- selector: .error
test:
path: browse.php
search:
path: browse.php
inputs:
$raw: "{{range .Categories}}c{{.}}=1&{{end}}"
search: "{{ .Query.Keywords }}"
incldead: "1"
rows:
selector: table.tableinborder > tbody > tr:has(a[href^="details.php"])
fields:
title:
selector: a[href^="details.php"]
attribute: title
category:
selector: a[href^="/browse.php?cat="]
attribute: href
filters:
- name: querystring
args: cat
details:
selector: a[href^="details.php"]
attribute: href
download:
selector: a[href^="/download.php"]
attribute: href
files:
selector: td:nth-child(7)
grabs:
selector: td:nth-child(6)
size:
selector: td:nth-child(8)
filters:
- name: replace
args: [".", ""]
- name: replace
args: [",", "."]
seeders:
selector: td:nth-child(3) > a
leechers:
selector: td:nth-child(4)
date:
selector: td:nth-child(9)
filters:
- name: split
args: ["by", 0]
- name: replace
args: ["Heute", "Today"]
- name: replace
args: ["Gestern", "Yesterday"]
- name: dateparse
args: "02.01.2006 15:04:05"
downloadvolumefactor:
case:
img[alt="OU"]: "0"
img[alt="D/2"]: "0.5"
"*": "1"
uploadvolumefactor:
case:
img[alt="2xU"]: "2"
"*": "1"

View File

@@ -1,133 +0,0 @@
---
site: acidlounge
name: Acid-Lounge
description: "Acid Lounge (A-L) is a Private Torrent Tracker for 0DAY / GENERAL"
language: en-us
type: private
encoding: UTF-8
links:
- https://www.acid-lounge.org.uk/
caps:
categorymappings:
- {id: 79, cat: PC/Phone-Android, desc: "Android"}
- {id: 61, cat: TV/Anime, desc: "Anime"}
- {id: 55, cat: PC/0day, desc: "Appz/0-Day"}
- {id: 59, cat: PC/Mac, desc: "Appz/Mac"}
- {id: 22, cat: PC, desc: "Appz/Misc"}
- {id: 32, cat: PC, desc: "Appz/PC"}
- {id: 48, cat: Audio/Audiobook, desc: "Audio/Books"}
- {id: 84, cat: Other, desc: "Damaged Torrent"}
- {id: 14, cat: Books, desc: "eBooks"}
- {id: 82, cat: Books, desc: "eBooks/Comics"}
- {id: 81, cat: Books, desc: "eBooks/Mags"}
- {id: 60, cat: PC/Mac, desc: "Games/Mac"}
- {id: 54, cat: Console/NDS, desc: "Games/NDS"}
- {id: 4, cat: PC/Games, desc: "Games/PC"}
- {id: 42, cat: Console/PS3, desc: "Games/PS3"}
- {id: 56, cat: Console/Wii, desc: "Games/Wii"}
- {id: 36, cat: Console/Xbox360, desc: "Games/xbox360"}
- {id: 69, cat: Other, desc: "Halloween"}
- {id: 80, cat: PC/Phone-IOS, desc: "iPhone / iPad"}
- {id: 46, cat: Other, desc: "Kids"}
- {id: 63, cat: PC, desc: "Linux"}
- {id: 49, cat: Other, desc: "Misc"}
- {id: 77, cat: Movies/3D, desc: "Movies/3D BLURAY"}
- {id: 73, cat: Movies/HD, desc: "Movies/Boxsets HD"}
- {id: 74, cat: Movies/SD, desc: "Movies/Boxsets SD"}
- {id: 25, cat: Movies/DVD, desc: "Movies/DVD-R"}
- {id: 51, cat: Movies/HD, desc: "Movies/HD"}
- {id: 26, cat: Movies, desc: "Movies/Retro"}
- {id: 29, cat: Movies/SD, desc: "Movies/SD"}
- {id: 52, cat: Movies/SD, desc: "Movies/WMV"}
- {id: 85, cat: Movies/HD, desc: "Movies/X265"}
- {id: 66, cat: Audio/Lossless, desc: "Music/Flac"}
- {id: 35, cat: Audio/MP3, desc: "Music/MP3"}
- {id: 31, cat: Audio/Video, desc: "Music/Videos"}
- {id: 72, cat: Movies, desc: "Sci-Fi"}
- {id: 83, cat: Movies, desc: "Tribute Packs"}
- {id: 30, cat: TV, desc: "TV"}
- {id: 50, cat: TV/HD, desc: "TV-HD/X264"}
- {id: 71, cat: TV/SD, desc: "TV-SD/X264"}
- {id: 75, cat: TV/HD, desc: "TV/Boxsets HD"}
- {id: 76, cat: TV/SD, desc: "TV/Boxsets SD"}
- {id: 37, cat: XXX, desc: "XXX"}
- {id: 78, cat: XXX, desc: "XXX/3D"}
modes:
search: [q]
tv-search: [q, season, ep]
movie-search: [q]
login:
path: Main/?act=Login
method: form
form: form#login
captcha:
type: image
selector: img[alt="Security code"]
input: code
inputs:
username: "{{ .Config.username }}"
password: "{{ .Config.password }}"
error:
- selector: div.errorWrap
test:
path: browse.php
search:
paths:
- path: browse.php
inputs:
$raw: "{{range .Categories}}cid[]={{.}}&{{end}}"
search: "{{ .Keywords }}"
search_type: "title"
rows:
selector: table#browse_torrents_table > tbody > tr[id^="torrent_row_"]
fields:
title:
selector: a.torrent_name
attribute: title
description:
selector: span.torrent_small_desc
category:
selector: td.torrent_table_type > a
attribute: href
filters:
- name: querystring
args: cat[]
details:
selector: a.torrent_name
attribute: href
download:
selector: a[href^="download.php?"]
attribute: href
size:
selector: td.torrent_table_size
files:
selector: td.torrent_table_files
seeders:
selector: td.torrent_table_seeders
leechers:
selector: td.torrent_table_leechers
grabs:
selector: td.torrent_table_snatched
filters:
- name: regexp
args: ([\d\.]+)
downloadvolumefactor:
case:
":root div#notice_ratioBoostingMadness": "0"
"*": "1"
uploadvolumefactor:
case:
"*": "1"
date:
selector: td.torrent_table_dateAdded
filters:
- name: append
args: " +01:00"
- name: dateparse
args: "2006-01-02 15:04:05 -07:00"

View File

@@ -1,87 +0,0 @@
---
site: anidex
name: Anidex
description: "Anidex is a Public torrent tracker and indexer, primarily for English fansub groups of anime"
language: en-us
encoding: UTF-8
type: public
links:
- https://anidex.info/
caps:
categorymappings:
- {id: 1, cat: TV/Anime, desc: "Anime - Sub"}
- {id: 2, cat: TV/Anime, desc: "Anime - Raw"}
- {id: 3, cat: TV/Anime, desc: "Anime - Dub"}
- {id: 4, cat: TV/Anime, desc: "LA - Sub"}
- {id: 5, cat: TV/Anime, desc: "LA - Raw"}
- {id: 6, cat: TV/Anime, desc: "Light Novel"}
- {id: 7, cat: TV/Anime, desc: "Manga - TLed"}
- {id: 8, cat: TV/Anime, desc: "Manga - Raw"}
- {id: 9, cat: TV/Anime, desc: "♫ - Lossy"}
- {id: 10, cat: TV/Anime, desc: "♫ - Lossless"}
- {id: 11, cat: TV/Anime, desc: "♫ - Video"}
- {id: 12, cat: TV/Anime, desc: "Games"}
- {id: 13, cat: TV/Anime, desc: "Applications"}
- {id: 14, cat: TV/Anime, desc: "Pictures"}
- {id: 15, cat: TV/Anime, desc: "Adult Video"}
- {id: 16, cat: TV/Anime, desc: "Other"}
modes:
search: [q]
tv-search: [q, season, ep]
settings:
- name: cat-id
type: text
label: Category Id
- name: info
type: info
label: Category Id Note
default: "You can filter your searches by using any of the following category numbers (comma delimited):<br>1 :Anime - Sub<br>2 :Anime - Raw<br>3 :Anime - Dub<br>4 :LA - Sub<br>5 :LA - Raw<br>6 :Light Novel<br>7 :Manga - TLed<br>8 :Manga - Raw<br>9 :♫ - Lossy<br>10 :♫ - Lossless<br>11 :♫ - Video<br>12 :Games<br>13 :Applications<br>14 :Pictures<br>15 :Adult Video<br>16 :Other"
- name: lang-id
type: text
label: Language Id
search:
paths:
- path: "?{{if .Config.cat-id}}id={{.Config.cat-id }}&{{else}}{{end}}{{if .Config.lang-id}}lang_id={{.Config.lang-id}}&{{else}}{{end}}q={{if .Keywords}}{{.Keywords}}{{else}}{{end}}"
rows:
selector: div.table-responsive > table > tbody > tr
fields:
category:
selector: a[href^="/?id="]
attribute: href
filters:
- name: querystring
args: id
title:
selector: td:nth-child(3) > a.torrent > span.span-1440
details:
selector: td:nth-child(3) > a.torrent
attribute: href
download:
selector: td:nth-child(5) > a
attribute: href
magnet:
selector: a[href^="magnet:?"]
attribute: href
size:
selector: td:nth-child(7)
date:
selector: td:nth-child(8)
attribute: title
filters:
- name: replace
args: ["UTC", "+00:00"]
- name: dateparse
args: "2006-01-02 15:04:05 -07:00"
seeders:
selector: td:nth-child(9)
leechers:
selector: td:nth-child(10)
grabs:
selector: td:nth-child(11)
downloadvolumefactor:
text: "0"
uploadvolumefactor:
text: "1"

View File

@@ -1,78 +0,0 @@
---
site: aniRena
name: AniRena
description: "AniRena is a Public torrent tracker for the latest anime and Japanese related torrents"
language: en-us
type: public
encoding: UTF-8
links:
- https://www.anirena.com/
settings: []
caps:
categorymappings:
# Anime
- {id: 1, cat: TV/Anime, desc: "Raw Animes"}
- {id: 2, cat: TV/Anime, desc: "Anime"}
- {id: 3, cat: TV/Anime, desc: "Hentai"}
- {id: 4, cat: TV/Anime, desc: "Drama"}
- {id: 9, cat: TV/Anime, desc: "Anime Music Videos"}
- {id: 10, cat: TV/Anime, desc: "Non-English"}
# Software
- {id: 5, cat: PC/ISO, desc: "DVD/ISO"}
- {id: 6, cat: PC, desc: "Hentai-Game"}
# Literature
- {id: 7, cat: Books, desc: "Manga"}
# Audio
- {id: 8, cat: Audio, desc: "Audio"}
# Other
- {id: 11, cat: Other, desc: "Other"}
modes:
search: [q]
tv-search: [q, season, ep]
search:
paths:
- path: "/{{if .Keywords}}?s={{ .Keywords}}{{else}}{{end}}"
rows:
selector: table tbody tr:has(td.torrents_small_type_data1)
fields:
title:
selector: .torrents_small_info_data1 div
download:
selector: .torrents_small_info_data2 a[title="Download Torrent"]
attribute: href
magnet:
selector: .torrents_small_info_data2 a[title="Magnet Link"]
attribute: href
date:
text: now
size:
selector: .torrents_small_size_data1
seeders:
selector: .torrents_small_seeders_data1 b big
leechers:
selector: .torrents_small_leechers_data1 b big
grabs:
selector: .torrents_small_downloads_data1
category:
selector: .torrents_small_type_data1 img
attribute: src
case:
"[src=\"./styles/tracker/imageset/cat_raw_small.png\"]": "1"
"[src=\"./styles/tracker/imageset/cat_anime_small.png\"]": "2"
"[src=\"./styles/tracker/imageset/cat_hentai_small.png\"]": "3"
"[src=\"./styles/tracker/imageset/cat_drama_small.png\"]": "4"
"[src=\"./styles/tracker/imageset/cat_dvd_small.png\"]": "5"
"[src=\"./styles/tracker/imageset/cat_hgame2_small.png\"]": "6"
"[src=\"./styles/tracker/imageset/cat_manga_small.png\"]": "7"
"[src=\"./styles/tracker/imageset/cat_music_small.png\"]": "8"
"[src=\"./styles/tracker/imageset/cat_musicvid_small.png\"]": "9"
"[src=\"./styles/tracker/imageset/cat_noneng_small.png\"]": "10"
"[src=\"./styles/tracker/imageset/cat_other_small.png\"]": "11"
downloadvolumefactor:
text: "0"
uploadvolumefactor:
text: "1"

View File

@@ -1,106 +0,0 @@
---
site: aox
name: AOX
description: "AOX (Chippu) is a Private Torrent Tracker for ASIAN MOVIES / TV"
language: en-us
type: private
encoding: UTF-8
links:
- https://aox.to/
caps:
categorymappings:
- {id: 13, cat: Movies, desc: "Movie"}
- {id: 11, cat: TV, desc: "TV-Show"}
- {id: 5, cat: TV/Other, desc: "Variety Show"}
- {id: 24, cat: XXX, desc: "Adult"}
modes:
search: [q]
tv-search: [q, season, ep]
login:
path: index.php?page=login
method: post
inputs:
uid: "{{ .Config.username }}"
pwd: "{{ .Config.password }}"
error:
- selector: body[onLoad^="makeAlert('"]
message:
selector: body[onLoad^="makeAlert('"]
attribute: onLoad
filters:
- name: replace
args: ["makeAlert('Error' , '", ""]
- name: replace
args: ["');", ""]
test:
path: index.php
search:
paths:
- path: index.php
inputs:
search: "{{ .Query.Keywords }}"
page: "torrents"
category: "{{range .Categories}}{{.}};{{end}}"
options: "0"
active: "0"
rows:
selector: table.table.table-bordered > tbody > tr:has(a[href^="index.php?page=torrent-details&id="])
fields:
download:
selector: a[href^="download.php"]
attribute: href
title:
selector: a[title][href^="index.php?page=torrent-details&id="]
banner:
selector: img[src^="torrentimg/"]
attribute: src
category:
selector: a[href^="index.php?page=torrents&category="]
attribute: href
filters:
- name: querystring
args: category
details:
selector: a[title][href^="index.php?page=torrent-details&id="]
attribute: href
size:
selector: p:has(b:contains("Size:"))
remove: b
date:
selector: p:has(b:contains("Added:"))
remove: b
filters:
- name: replace
args: ["@ ", ""]
- name: append
args: " +01:00"
- name: dateparse
args: "01/02/2006 15:04:05 -07:00"
seeders:
selector: b:contains("Seeds:") + a
leechers:
selector: b:contains("Leechers:") + a
grabs:
selector: p:has(b:contains("Complete:"))
remove: b, a[href^="index.php?page=peers"]
filters:
- name: replace
args: ["---", "0"]
downloadvolumefactor:
case:
i.fa-star: "0"
i.fa-star-half-o: "0.5"
i.fa-star-o: "0.75"
"*": "1"
uploadvolumefactor:
case:
span[title="2x Upload Multiplier"]: "2"
"*": "1"
description:
selector: p:has(b:contains("Language:"))

View File

@@ -1,166 +0,0 @@
---
site: arabafenice
name: ArabaFenice
description: "Araba Fenice (Phoenix) is an ITALIAN Private site for TV / MOVIES / GENERAL"
language: it-it
type: private
encoding: UTF-8
links:
- http://www.arabafenice.me/
caps:
categorymappings:
# HRS
- {id: 34, cat: Movies/HD, desc: "1080p HRS x264"}
- {id: 47, cat: Movies/HD, desc: "2160p 4k UltraHD HRS"}
- {id: 35, cat: TV, desc: "Serie TV HRS"}
- {id: 36, cat: Movies/SD, desc: "DVDRip HRS"}
- {id: 41, cat: Movies/SD, desc: "BDRip 576p HRS"}
- {id: 39, cat: Movies/HD, desc: "1080p HRS x265 HEVC"}
# VIDEO
- {id: 1, cat: Movies, desc: "News Cinema"}
- {id: 2, cat: Movies/SD, desc: "BD-DVDRip"}
- {id: 3, cat: Movies/DVD, desc: "DVD 5"}
- {id: 5, cat: Movies/DVD, desc: "DVD 9"}
- {id: 6, cat: Movies/BluRay, desc: "BluRay Full"}
- {id: 4, cat: Movies/HD, desc: "1080p 3D x264"}
- {id: 7, cat: Movies/HD, desc: "1080p x264"}
- {id: 46, cat: Movies/HD, desc: "1080p Video Untouch"}
- {id: 44, cat: Movies/HD, desc: "1080p x265"}
- {id: 9, cat: TV/Anime, desc: "Cartoons"}
- {id: 8, cat: TV/Anime, desc: "720p x264"}
- {id: 12, cat: TV, desc: "He concluded seasons"}
- {id: 13, cat: TV, desc: "Seasons in Onda"}
- {id: 14, cat: TV, desc: "TV Show"}
- {id: 42, cat: TV, desc: "Serie Tv Sub Ita"}
- {id: 15, cat: TV/Documentary, desc: "documentaries"}
- {id: 33, cat: TV, desc: "mp4"}
- {id: 40, cat: TV/HD, desc: "2160p 4K UltraHD"}
- {id: 38, cat: XXX, desc: "xXx"}
- {id: 43, cat: Other, desc: "Arabic for social"}
# MUSICA
- {id: 17, cat: Audio, desc: "Italian music"}
- {id: 45, cat: Audio, desc: "Discography"}
- {id: 18, cat: Audio, desc: "MusicaInternazionale"}
- {id: 19, cat: Audio, desc: "Compilation"}
# PDF
- {id: 21, cat: Books, desc: "Ebook"}
- {id: 22, cat: Books/Comics, desc: "Comics"}
- {id: 23, cat: Books, desc: "Newsstand"}
# GAMES
- {id: 25, cat: Console/PS4, desc: "Sony Games"}
- {id: 26, cat: Console/Xbox, desc: "XboX Games"}
- {id: 27, cat: Console/Other, desc: "Nintendo Games"}
- {id: 28, cat: PC/Games, desc: "PC Games"}
# SOFTWARE
- {id: 30, cat: PC/ISO, desc: "Windows APP"}
- {id: 31, cat: PC/Phone-IOS, desc: "Apple APP"}
- {id: 32, cat: PC/Phone-Android, desc: "Android APP"}
modes:
search: [q]
tv-search: [q, season, ep, imdbid]
movie-search: [q, imdbid]
login:
path: index.php?page=login
method: post
inputs:
uid: "{{ .Config.username }}"
pwd: "{{ .Config.password }}"
error:
- selector: body[onLoad^="makeAlert('"]
message:
selector: body[onLoad^="makeAlert('"]
attribute: onLoad
filters:
- name: replace
args: ["makeAlert('Error' , '", ""]
- name: replace
args: ["');", ""]
test:
path: index.php
download:
before:
path: "thanks.php"
method: "post"
inputs:
infohash: "{{ .DownloadUri.Query.id }}"
thanks: "1"
rndval: "1487013827343"
selector: a[href^="download.php?id="]
search:
paths:
- path: index.php
inputs:
search: "{{if .Query.IMDBID}}{{ .Query.IMDBIDShort }}{{else}}{{ .Keywords }}{{end}}"
page: "torrents"
category: "{{range .Categories}}{{.}};{{end}}"
options: "{{ if .Query.IMDBID }}4{{else}}0{{end}}"
active: "0"
rows:
selector: table > tbody > tr > td > table.lista > tbody > tr:has(a[href^="index.php?page=torrent-details&id="])
fields:
download:
selector: a[href^="index.php?page=downloadcheck&id="]
attribute: href
title:
selector: a[onmouseover][href^="index.php?page=torrent-details&id="]
banner:
selector: a[onmouseover][href^="index.php?page=torrent-details&id="]
attribute: onmouseover
filters:
- name: regexp
args: "src=(.*?) "
category:
selector: a[href^="index.php?page=torrents&category="]
attribute: href
filters:
- name: querystring
args: category
details:
selector: a[onmouseover][href^="index.php?page=torrent-details&id="]
attribute: href
size:
selector: td:nth-last-child(4)
date:
selector: td:nth-last-child(9)
filters:
- name: append
args: " +01:00"
- name: dateparse
args: "02/01/2006 -07:00"
grabs:
selector: td:nth-last-child(6)
filters:
- name: replace
args: ["---", "0"]
seeders:
selector: td:nth-last-child(8)
leechers:
selector: td:nth-last-child(7)
downloadvolumefactor:
case:
img[alt="Gold 100% Free"]: "0"
img[alt="Silver 50% Free"]: "0.5"
img[alt="Bronze 25% Free"]: "0.75"
"*": "1"
uploadvolumefactor:
case:
img[alt="2x Upload Multiplier"]: "2"
img[alt="3x Upload Multiplier"]: "3"
img[alt="4x Upload Multiplier"]: "4"
img[alt="5x Upload Multiplier"]: "5"
img[alt="6x Upload Multiplier"]: "6"
img[alt="7x Upload Multiplier"]: "7"
img[alt="8x Upload Multiplier"]: "8"
img[alt="9x Upload Multiplier"]: "9"
img[alt="10x Upload Multiplier"]: "10"
"*": "1"

View File

@@ -1,143 +0,0 @@
---
site: archetorrent
name: ArcheTorrent
description: "ArcheTorrent is a FRENCH Private Torrent Tracker"
language: fr-fr
type: private
encoding: UTF-8
links:
- https://archetorrent.com
caps:
categorymappings:
- {id: 18, cat: PC, desc: "Applications: PC"}
- {id: 19, cat: PC/Mac, desc: "Applications: Mac"}
- {id: 54, cat: PC, desc: "Applications: linux"}
- {id: 56, cat: XXX/Other, desc: "Autres: ebook xxx"}
- {id: 36, cat: Books, desc: "Autres: E-Books"}
- {id: 37, cat: Other, desc: "Autres: Images"}
- {id: 38, cat: PC/Phone-Other, desc: "Autres: Telephone-mobile"}
- {id: 47, cat: Movies, desc: "Films: Animé"}
- {id: 1, cat: Movies/DVD, desc: "Films: DVD"}
- {id: 2, cat: Movies/SD, desc: "Films: Dvdrip"}
- {id: 68, cat: Movies, desc: "Films: TAT Releases"}
- {id: 70, cat: Movies/HD, desc: "Films: UHD 4K"}
- {id: 69, cat: Movies, desc: "Films: Retro"}
- {id: 3, cat: Movies/HD, desc: "Films: HD1080"}
- {id: 42, cat: Movies/HD, desc: "Films: HD720"}
- {id: 4, cat: Movies, desc: "Films: Cam/Ts"}
- {id: 22, cat: Movies/BluRay, desc: "Films: bluray"}
- {id: 23, cat: Movies/3D, desc: "Films: 3D"}
- {id: 24, cat: Movies/Foreign, desc: "Films: VOSTFR"}
- {id: 25, cat: XXX, desc: "Films: Adulte"}
- {id: 48, cat: TV/Documentary, desc: "Films: Documentaire"}
- {id: 49, cat: Movies/Other, desc: "Films: Spectacle"}
- {id: 51, cat: Movies/SD, desc: "Films: R5"}
- {id: 52, cat: Movies/SD, desc: "Films: bdrip"}
- {id: 53, cat: Movies/SD, desc: "Films: brrip"}
- {id: 55, cat: Movies/DVD, desc: "Films: dvd-pack"}
- {id: 57, cat: Movies, desc: "Films: manga"}
- {id: 59, cat: Movies/WEBDL, desc: "Films: Webrip"}
- {id: 63, cat: Movies/SD, desc: "Films: M-HD"}
- {id: 10, cat: PC/Games, desc: "Jeux: PC"}
- {id: 11, cat: Console/Other, desc: "Jeux: PS2"}
- {id: 43, cat: Console/PS3, desc: "Jeux: PS3"}
- {id: 12, cat: Console/PSP, desc: "Jeux: PSP"}
- {id: 14, cat: Console/Xbox 360, desc: "Jeux: Xbox360"}
- {id: 44, cat: Console/Wii, desc: "Jeux: Wii"}
- {id: 45, cat: Console/NDS, desc: "Jeux: DS"}
- {id: 27, cat: Audio/Video, desc: "Musique: Clip Video"}
- {id: 62, cat: TV/SD, desc: "Serie tv: TV BDRip"}
- {id: 5, cat: TV/SD, desc: "Serie tv: Dvdrip"}
- {id: 41, cat: TV/HD, desc: "Serie tv: Hd"}
- {id: 60, cat: TV/SD, desc: "Serie tv: pack série tv"}
- {id: 64, cat: TV/FOREIGN, desc: "Serie tv: vostfr"}
- {id: 65, cat: TV/HD, desc: "Serie tv: Série tv 720P"}
- {id: 66, cat: TV/HD, desc: "Serie tv: Série tv 1080P"}
- {id: 67, cat: TV/HD, desc: "Serie tv: Série tv PackHD"}
- {id: 73, cat: TV/Anime, desc: "Serie tv: Anime "}
- {id: 72, cat: TV/Sport, desc: "Sport: sport"}
- {id: 61, cat: TV/SD, desc: "Tv: DVDRip"}
modes:
search: [q]
tv-search: [q, season, ep]
login:
path: account-login.php
method: post
inputs:
username: "{{ .Config.username }}"
password: "{{ .Config.password }}"
error:
- selector: form:contains("Erreur")
message:
selector: form
remove: table
test:
path: torrents-search.php
search:
keywordsfilters:
- name: replace
args: ["-", " "] # remove special search character (negative search)
- name: replace
args: ["+", " "] # remove special search character (positive search)
- name: re_replace
args: ["(\\w+)", " +$1"] # prepend + to each word
paths:
- path: torrents-search.php
inputs:
$raw: "{{range .Categories}}c{{.}}=1&{{end}}"
search: "{{ .Keywords }}"
incldead: "1"
rows:
selector: table.ttable_headinner > tbody > tr[class^="t-row"]
fields:
download:
selector: a[href^="torrents-details.php?id="]
attribute: href
filters:
- name: replace
args: ["torrents-details.php", "download.php"]
date:
selector: td:nth-child(3) a
attribute: onmouseover
filters:
- name: regexp
args: "Poster le: </b>(.*?)<br />"
- name: dateparse
args: "02-01-2006"
title:
selector: a[href^="torrents-details.php?id="]
filters:
- name: replace
args: [" - (Nouveau!)", ""]
category:
selector: a[href^="torrents.php?cat="]
attribute: href
filters:
- name: querystring
args: cat
details:
selector: a[href^="torrents-details.php?id="]
attribute: href
banner:
selector: img.rounded-img
attribute: src
size:
selector: td:nth-child(6)
grabs:
selector: td:nth-child(9) font b
seeders:
selector: td:nth-child(7) font b
leechers:
selector: td:nth-child(8) font b
downloadvolumefactor:
case:
img[title="freeleech"]: "0"
"*": "1"
uploadvolumefactor:
case:
"*": "1"

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