Added: Radarr now stores cookies for PTP beyond restarts. Should limit active sessions correctly. (#2643)

Fixes #2626
pull/2642/head^2
Leonardo Galli 7 years ago committed by GitHub
parent a2fa8c4594
commit 6eb678cd92
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

796
package-lock.json generated

@ -422,6 +422,7 @@
"requires": { "requires": {
"anymatch": "1.3.2", "anymatch": "1.3.2",
"async-each": "1.0.1", "async-each": "1.0.1",
"fsevents": "1.1.3",
"glob-parent": "2.0.0", "glob-parent": "2.0.0",
"inherits": "2.0.3", "inherits": "2.0.3",
"is-binary-path": "1.0.1", "is-binary-path": "1.0.1",
@ -1034,6 +1035,795 @@
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
}, },
"fsevents": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz",
"integrity": "sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==",
"optional": true,
"requires": {
"nan": "2.10.0",
"node-pre-gyp": "0.6.39"
},
"dependencies": {
"abbrev": {
"version": "1.1.0",
"bundled": true,
"optional": true
},
"ajv": {
"version": "4.11.8",
"bundled": true,
"optional": true,
"requires": {
"co": "4.6.0",
"json-stable-stringify": "1.0.1"
}
},
"ansi-regex": {
"version": "2.1.1",
"bundled": true
},
"aproba": {
"version": "1.1.1",
"bundled": true,
"optional": true
},
"are-we-there-yet": {
"version": "1.1.4",
"bundled": true,
"optional": true,
"requires": {
"delegates": "1.0.0",
"readable-stream": "2.2.9"
}
},
"asn1": {
"version": "0.2.3",
"bundled": true,
"optional": true
},
"assert-plus": {
"version": "0.2.0",
"bundled": true,
"optional": true
},
"asynckit": {
"version": "0.4.0",
"bundled": true,
"optional": true
},
"aws-sign2": {
"version": "0.6.0",
"bundled": true,
"optional": true
},
"aws4": {
"version": "1.6.0",
"bundled": true,
"optional": true
},
"balanced-match": {
"version": "0.4.2",
"bundled": true
},
"bcrypt-pbkdf": {
"version": "1.0.1",
"bundled": true,
"optional": true,
"requires": {
"tweetnacl": "0.14.5"
}
},
"block-stream": {
"version": "0.0.9",
"bundled": true,
"requires": {
"inherits": "2.0.3"
}
},
"boom": {
"version": "2.10.1",
"bundled": true,
"requires": {
"hoek": "2.16.3"
}
},
"brace-expansion": {
"version": "1.1.7",
"bundled": true,
"requires": {
"balanced-match": "0.4.2",
"concat-map": "0.0.1"
}
},
"buffer-shims": {
"version": "1.0.0",
"bundled": true
},
"caseless": {
"version": "0.12.0",
"bundled": true,
"optional": true
},
"co": {
"version": "4.6.0",
"bundled": true,
"optional": true
},
"code-point-at": {
"version": "1.1.0",
"bundled": true
},
"combined-stream": {
"version": "1.0.5",
"bundled": true,
"requires": {
"delayed-stream": "1.0.0"
}
},
"concat-map": {
"version": "0.0.1",
"bundled": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true
},
"core-util-is": {
"version": "1.0.2",
"bundled": true
},
"cryptiles": {
"version": "2.0.5",
"bundled": true,
"requires": {
"boom": "2.10.1"
}
},
"dashdash": {
"version": "1.14.1",
"bundled": true,
"optional": true,
"requires": {
"assert-plus": "1.0.0"
},
"dependencies": {
"assert-plus": {
"version": "1.0.0",
"bundled": true,
"optional": true
}
}
},
"debug": {
"version": "2.6.8",
"bundled": true,
"optional": true,
"requires": {
"ms": "2.0.0"
}
},
"deep-extend": {
"version": "0.4.2",
"bundled": true,
"optional": true
},
"delayed-stream": {
"version": "1.0.0",
"bundled": true
},
"delegates": {
"version": "1.0.0",
"bundled": true,
"optional": true
},
"detect-libc": {
"version": "1.0.2",
"bundled": true,
"optional": true
},
"ecc-jsbn": {
"version": "0.1.1",
"bundled": true,
"optional": true,
"requires": {
"jsbn": "0.1.1"
}
},
"extend": {
"version": "3.0.1",
"bundled": true,
"optional": true
},
"extsprintf": {
"version": "1.0.2",
"bundled": true
},
"forever-agent": {
"version": "0.6.1",
"bundled": true,
"optional": true
},
"form-data": {
"version": "2.1.4",
"bundled": true,
"optional": true,
"requires": {
"asynckit": "0.4.0",
"combined-stream": "1.0.5",
"mime-types": "2.1.15"
}
},
"fs.realpath": {
"version": "1.0.0",
"bundled": true
},
"fstream": {
"version": "1.0.11",
"bundled": true,
"requires": {
"graceful-fs": "4.1.11",
"inherits": "2.0.3",
"mkdirp": "0.5.1",
"rimraf": "2.6.1"
}
},
"fstream-ignore": {
"version": "1.0.5",
"bundled": true,
"optional": true,
"requires": {
"fstream": "1.0.11",
"inherits": "2.0.3",
"minimatch": "3.0.4"
}
},
"gauge": {
"version": "2.7.4",
"bundled": true,
"optional": true,
"requires": {
"aproba": "1.1.1",
"console-control-strings": "1.1.0",
"has-unicode": "2.0.1",
"object-assign": "4.1.1",
"signal-exit": "3.0.2",
"string-width": "1.0.2",
"strip-ansi": "3.0.1",
"wide-align": "1.1.2"
}
},
"getpass": {
"version": "0.1.7",
"bundled": true,
"optional": true,
"requires": {
"assert-plus": "1.0.0"
},
"dependencies": {
"assert-plus": {
"version": "1.0.0",
"bundled": true,
"optional": true
}
}
},
"glob": {
"version": "7.1.2",
"bundled": true,
"requires": {
"fs.realpath": "1.0.0",
"inflight": "1.0.6",
"inherits": "2.0.3",
"minimatch": "3.0.4",
"once": "1.4.0",
"path-is-absolute": "1.0.1"
}
},
"graceful-fs": {
"version": "4.1.11",
"bundled": true
},
"har-schema": {
"version": "1.0.5",
"bundled": true,
"optional": true
},
"har-validator": {
"version": "4.2.1",
"bundled": true,
"optional": true,
"requires": {
"ajv": "4.11.8",
"har-schema": "1.0.5"
}
},
"has-unicode": {
"version": "2.0.1",
"bundled": true,
"optional": true
},
"hawk": {
"version": "3.1.3",
"bundled": true,
"requires": {
"boom": "2.10.1",
"cryptiles": "2.0.5",
"hoek": "2.16.3",
"sntp": "1.0.9"
}
},
"hoek": {
"version": "2.16.3",
"bundled": true
},
"http-signature": {
"version": "1.1.1",
"bundled": true,
"optional": true,
"requires": {
"assert-plus": "0.2.0",
"jsprim": "1.4.0",
"sshpk": "1.13.0"
}
},
"inflight": {
"version": "1.0.6",
"bundled": true,
"requires": {
"once": "1.4.0",
"wrappy": "1.0.2"
}
},
"inherits": {
"version": "2.0.3",
"bundled": true
},
"ini": {
"version": "1.3.4",
"bundled": true,
"optional": true
},
"is-fullwidth-code-point": {
"version": "1.0.0",
"bundled": true,
"requires": {
"number-is-nan": "1.0.1"
}
},
"is-typedarray": {
"version": "1.0.0",
"bundled": true,
"optional": true
},
"isarray": {
"version": "1.0.0",
"bundled": true
},
"isstream": {
"version": "0.1.2",
"bundled": true,
"optional": true
},
"jodid25519": {
"version": "1.0.2",
"bundled": true,
"optional": true,
"requires": {
"jsbn": "0.1.1"
}
},
"jsbn": {
"version": "0.1.1",
"bundled": true,
"optional": true
},
"json-schema": {
"version": "0.2.3",
"bundled": true,
"optional": true
},
"json-stable-stringify": {
"version": "1.0.1",
"bundled": true,
"optional": true,
"requires": {
"jsonify": "0.0.0"
}
},
"json-stringify-safe": {
"version": "5.0.1",
"bundled": true,
"optional": true
},
"jsonify": {
"version": "0.0.0",
"bundled": true,
"optional": true
},
"jsprim": {
"version": "1.4.0",
"bundled": true,
"optional": true,
"requires": {
"assert-plus": "1.0.0",
"extsprintf": "1.0.2",
"json-schema": "0.2.3",
"verror": "1.3.6"
},
"dependencies": {
"assert-plus": {
"version": "1.0.0",
"bundled": true,
"optional": true
}
}
},
"mime-db": {
"version": "1.27.0",
"bundled": true
},
"mime-types": {
"version": "2.1.15",
"bundled": true,
"requires": {
"mime-db": "1.27.0"
}
},
"minimatch": {
"version": "3.0.4",
"bundled": true,
"requires": {
"brace-expansion": "1.1.7"
}
},
"minimist": {
"version": "0.0.8",
"bundled": true
},
"mkdirp": {
"version": "0.5.1",
"bundled": true,
"requires": {
"minimist": "0.0.8"
}
},
"ms": {
"version": "2.0.0",
"bundled": true,
"optional": true
},
"node-pre-gyp": {
"version": "0.6.39",
"bundled": true,
"optional": true,
"requires": {
"detect-libc": "1.0.2",
"hawk": "3.1.3",
"mkdirp": "0.5.1",
"nopt": "4.0.1",
"npmlog": "4.1.0",
"rc": "1.2.1",
"request": "2.81.0",
"rimraf": "2.6.1",
"semver": "5.3.0",
"tar": "2.2.1",
"tar-pack": "3.4.0"
}
},
"nopt": {
"version": "4.0.1",
"bundled": true,
"optional": true,
"requires": {
"abbrev": "1.1.0",
"osenv": "0.1.4"
}
},
"npmlog": {
"version": "4.1.0",
"bundled": true,
"optional": true,
"requires": {
"are-we-there-yet": "1.1.4",
"console-control-strings": "1.1.0",
"gauge": "2.7.4",
"set-blocking": "2.0.0"
}
},
"number-is-nan": {
"version": "1.0.1",
"bundled": true
},
"oauth-sign": {
"version": "0.8.2",
"bundled": true,
"optional": true
},
"object-assign": {
"version": "4.1.1",
"bundled": true,
"optional": true
},
"once": {
"version": "1.4.0",
"bundled": true,
"requires": {
"wrappy": "1.0.2"
}
},
"os-homedir": {
"version": "1.0.2",
"bundled": true,
"optional": true
},
"os-tmpdir": {
"version": "1.0.2",
"bundled": true,
"optional": true
},
"osenv": {
"version": "0.1.4",
"bundled": true,
"optional": true,
"requires": {
"os-homedir": "1.0.2",
"os-tmpdir": "1.0.2"
}
},
"path-is-absolute": {
"version": "1.0.1",
"bundled": true
},
"performance-now": {
"version": "0.2.0",
"bundled": true,
"optional": true
},
"process-nextick-args": {
"version": "1.0.7",
"bundled": true
},
"punycode": {
"version": "1.4.1",
"bundled": true,
"optional": true
},
"qs": {
"version": "6.4.0",
"bundled": true,
"optional": true
},
"rc": {
"version": "1.2.1",
"bundled": true,
"optional": true,
"requires": {
"deep-extend": "0.4.2",
"ini": "1.3.4",
"minimist": "1.2.0",
"strip-json-comments": "2.0.1"
},
"dependencies": {
"minimist": {
"version": "1.2.0",
"bundled": true,
"optional": true
}
}
},
"readable-stream": {
"version": "2.2.9",
"bundled": true,
"requires": {
"buffer-shims": "1.0.0",
"core-util-is": "1.0.2",
"inherits": "2.0.3",
"isarray": "1.0.0",
"process-nextick-args": "1.0.7",
"string_decoder": "1.0.1",
"util-deprecate": "1.0.2"
}
},
"request": {
"version": "2.81.0",
"bundled": true,
"optional": true,
"requires": {
"aws-sign2": "0.6.0",
"aws4": "1.6.0",
"caseless": "0.12.0",
"combined-stream": "1.0.5",
"extend": "3.0.1",
"forever-agent": "0.6.1",
"form-data": "2.1.4",
"har-validator": "4.2.1",
"hawk": "3.1.3",
"http-signature": "1.1.1",
"is-typedarray": "1.0.0",
"isstream": "0.1.2",
"json-stringify-safe": "5.0.1",
"mime-types": "2.1.15",
"oauth-sign": "0.8.2",
"performance-now": "0.2.0",
"qs": "6.4.0",
"safe-buffer": "5.0.1",
"stringstream": "0.0.5",
"tough-cookie": "2.3.2",
"tunnel-agent": "0.6.0",
"uuid": "3.0.1"
}
},
"rimraf": {
"version": "2.6.1",
"bundled": true,
"requires": {
"glob": "7.1.2"
}
},
"safe-buffer": {
"version": "5.0.1",
"bundled": true
},
"semver": {
"version": "5.3.0",
"bundled": true,
"optional": true
},
"set-blocking": {
"version": "2.0.0",
"bundled": true,
"optional": true
},
"signal-exit": {
"version": "3.0.2",
"bundled": true,
"optional": true
},
"sntp": {
"version": "1.0.9",
"bundled": true,
"requires": {
"hoek": "2.16.3"
}
},
"sshpk": {
"version": "1.13.0",
"bundled": true,
"optional": true,
"requires": {
"asn1": "0.2.3",
"assert-plus": "1.0.0",
"bcrypt-pbkdf": "1.0.1",
"dashdash": "1.14.1",
"ecc-jsbn": "0.1.1",
"getpass": "0.1.7",
"jodid25519": "1.0.2",
"jsbn": "0.1.1",
"tweetnacl": "0.14.5"
},
"dependencies": {
"assert-plus": {
"version": "1.0.0",
"bundled": true,
"optional": true
}
}
},
"string_decoder": {
"version": "1.0.1",
"bundled": true,
"requires": {
"safe-buffer": "5.0.1"
}
},
"string-width": {
"version": "1.0.2",
"bundled": true,
"requires": {
"code-point-at": "1.1.0",
"is-fullwidth-code-point": "1.0.0",
"strip-ansi": "3.0.1"
}
},
"stringstream": {
"version": "0.0.5",
"bundled": true,
"optional": true
},
"strip-ansi": {
"version": "3.0.1",
"bundled": true,
"requires": {
"ansi-regex": "2.1.1"
}
},
"strip-json-comments": {
"version": "2.0.1",
"bundled": true,
"optional": true
},
"tar": {
"version": "2.2.1",
"bundled": true,
"requires": {
"block-stream": "0.0.9",
"fstream": "1.0.11",
"inherits": "2.0.3"
}
},
"tar-pack": {
"version": "3.4.0",
"bundled": true,
"optional": true,
"requires": {
"debug": "2.6.8",
"fstream": "1.0.11",
"fstream-ignore": "1.0.5",
"once": "1.4.0",
"readable-stream": "2.2.9",
"rimraf": "2.6.1",
"tar": "2.2.1",
"uid-number": "0.0.6"
}
},
"tough-cookie": {
"version": "2.3.2",
"bundled": true,
"optional": true,
"requires": {
"punycode": "1.4.1"
}
},
"tunnel-agent": {
"version": "0.6.0",
"bundled": true,
"optional": true,
"requires": {
"safe-buffer": "5.0.1"
}
},
"tweetnacl": {
"version": "0.14.5",
"bundled": true,
"optional": true
},
"uid-number": {
"version": "0.0.6",
"bundled": true,
"optional": true
},
"util-deprecate": {
"version": "1.0.2",
"bundled": true
},
"uuid": {
"version": "3.0.1",
"bundled": true,
"optional": true
},
"verror": {
"version": "1.3.6",
"bundled": true,
"optional": true,
"requires": {
"extsprintf": "1.0.2"
}
},
"wide-align": {
"version": "1.1.2",
"bundled": true,
"optional": true,
"requires": {
"string-width": "1.0.2"
}
},
"wrappy": {
"version": "1.0.2",
"bundled": true
}
}
},
"fstream": { "fstream": {
"version": "0.1.31", "version": "0.1.31",
"resolved": "https://registry.npmjs.org/fstream/-/fstream-0.1.31.tgz", "resolved": "https://registry.npmjs.org/fstream/-/fstream-0.1.31.tgz",
@ -2783,6 +3573,12 @@
"duplexer2": "0.0.2" "duplexer2": "0.0.2"
} }
}, },
"nan": {
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz",
"integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==",
"optional": true
},
"natives": { "natives": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/natives/-/natives-1.1.0.tgz", "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.0.tgz",

@ -1,24 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="ContentModelStore"> <component name="ContentModelStore">
<e p="E:\C++ Projects\Sonarr\_output" t="ExcludeRecursive"> <e p="$PROJECT_DIR$/../_output" t="ExcludeRecursive">
<e p="NzbDrone.Update" t="ExcludeRecursive" /> <e p="NzbDrone.Update" t="ExcludeRecursive" />
</e> </e>
<e p="E:\C++ Projects\Sonarr\Logo\1024.png" t="Include" /> <e p="$PROJECT_DIR$/../Logo/1024.png" t="Include" />
<e p="E:\C++ Projects\Sonarr\Logo\64.png" t="Include" /> <e p="$PROJECT_DIR$/../Logo/64.png" t="Include" />
<e p="E:\C++ Projects\Sonarr\src" t="IncludeFlat"> <e p="$PROJECT_DIR$" t="IncludeFlat">
<e p=".nuget" t="Include"> <e p=".nuget" t="Include">
<e p="NuGet.exe" t="Include" /> <e p="NuGet.exe" t="Include" />
</e> </e>
<e p="_ReSharper.Caches\ReSharperHost11.NzbDrone.00" t="ExcludeRecursive" /> <e p="_ReSharper.Caches/ReSharperHost12.NzbDrone.00" t="ExcludeRecursive" />
<e p="Common" t="Include"> <e p="Common/CommonAssemblyInfo.cs" t="Include" />
<e p="CodeAnalysisDictionary.xml" t="Include" /> <e p="Common/CommonVersionInfo.cs" t="Include" />
<e p="CommonAssemblyInfo.cs" t="Include" /> <e p="Common/GlobalSuppressions.cs" t="Include" />
<e p="CommonVersionInfo.cs" t="Include" />
<e p="GlobalSuppressions.cs" t="Include" />
</e>
<e p="External" t="Include" /> <e p="External" t="Include" />
<e p="ExternalModules\CurlSharp\CurlSharp" t="IncludeRecursive"> <e p="ExternalModules/CurlSharp/CurlSharp" t="IncludeRecursive">
<e p="bin" t="ExcludeRecursive" /> <e p="bin" t="ExcludeRecursive" />
<e p="Callbacks" t="Include"> <e p="Callbacks" t="Include">
<e p="CurlEasyCallbacks.cs" t="Include" /> <e p="CurlEasyCallbacks.cs" t="Include" />
@ -70,10 +67,10 @@
</e> </e>
</e> </e>
<e p="Host" t="Include" /> <e p="Host" t="Include" />
<e p="Libraries\MediaInfo\libmediainfo.0.dylib" t="Include" /> <e p="Libraries/MediaInfo/libmediainfo.0.dylib" t="Include" />
<e p="Libraries\MediaInfo\MediaInfo.dll" t="Include" /> <e p="Libraries/MediaInfo/MediaInfo.dll" t="Include" />
<e p="Libraries\Sqlite\libsqlite3.0.dylib" t="Include" /> <e p="Libraries/Sqlite/libsqlite3.0.dylib" t="Include" />
<e p="Libraries\Sqlite\sqlite3.dll" t="Include" /> <e p="Libraries/Sqlite/sqlite3.dll" t="Include" />
<e p="LogentriesCore" t="IncludeRecursive"> <e p="LogentriesCore" t="IncludeRecursive">
<e p="AsyncLogger.cs" t="Include" /> <e p="AsyncLogger.cs" t="Include" />
<e p="bin" t="ExcludeRecursive" /> <e p="bin" t="ExcludeRecursive" />
@ -1332,6 +1329,7 @@
<e p="141_fix_duplicate_alt_titles.cs" t="Include" /> <e p="141_fix_duplicate_alt_titles.cs" t="Include" />
<e p="142_movie_extras.cs" t="Include" /> <e p="142_movie_extras.cs" t="Include" />
<e p="143_clean_core_tv.cs" t="Include" /> <e p="143_clean_core_tv.cs" t="Include" />
<e p="144_add_cookies_to_indexer_status.cs" t="Include" />
<e p="Framework" t="Include"> <e p="Framework" t="Include">
<e p="MigrationContext.cs" t="Include" /> <e p="MigrationContext.cs" t="Include" />
<e p="MigrationController.cs" t="Include" /> <e p="MigrationController.cs" t="Include" />
@ -3282,7 +3280,7 @@
</e> </e>
<e p="packages" t="ExcludeRecursive" /> <e p="packages" t="ExcludeRecursive" />
<e p="Platform" t="Include" /> <e p="Platform" t="Include" />
<e p="ServiceHelpers\ServiceInstall" t="IncludeRecursive"> <e p="ServiceHelpers/ServiceInstall" t="IncludeRecursive">
<e p="app.config" t="Include" /> <e p="app.config" t="Include" />
<e p="app.manifest" t="Include" /> <e p="app.manifest" t="Include" />
<e p="green_puzzle.ico" t="Include" /> <e p="green_puzzle.ico" t="Include" />
@ -3294,7 +3292,7 @@
<e p="ServiceHelper.cs" t="Include" /> <e p="ServiceHelper.cs" t="Include" />
<e p="ServiceInstall.csproj" t="IncludeRecursive" /> <e p="ServiceInstall.csproj" t="IncludeRecursive" />
</e> </e>
<e p="ServiceHelpers\ServiceUninstall" t="IncludeRecursive"> <e p="ServiceHelpers/ServiceUninstall" t="IncludeRecursive">
<e p="app.config" t="Include" /> <e p="app.config" t="Include" />
<e p="app.manifest" t="Include" /> <e p="app.manifest" t="Include" />
<e p="obj" t="ExcludeRecursive" /> <e p="obj" t="ExcludeRecursive" />

@ -1,103 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<module type="RIDER_MODULE" version="4"> <module type="RIDER_MODULE" version="4">
<component name="NewModuleRootManager"> <component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$/../../../Logo/1024.png"> <content url="file://$MODULE_DIR$/../../../Logo/1024.png" />
<sourceFolder url="file://$MODULE_DIR$/../../../Logo/1024.png" isTestSource="false" /> <content url="file://$MODULE_DIR$/../../../Logo/64.png" />
</content> <content url="file://$MODULE_DIR$/../.." />
<content url="file://$MODULE_DIR$/../../../Logo/64.png">
<sourceFolder url="file://$MODULE_DIR$/../../../Logo/64.png" isTestSource="false" />
</content>
<content url="file://$MODULE_DIR$/../..">
<sourceFolder url="file://$MODULE_DIR$/../../.nuget/NuGet.exe" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../Common/CommonAssemblyInfo.cs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../Common/CommonVersionInfo.cs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../Common/GlobalSuppressions.cs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../ExternalModules/CurlSharp/CurlSharp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../Libraries/MediaInfo/libmediainfo.0.dylib" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../Libraries/MediaInfo/MediaInfo.dll" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../Libraries/Sqlite/libsqlite3.0.dylib" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../Libraries/Sqlite/sqlite3.dll" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../LogentriesCore" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../LogentriesNLog" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../Marr.Data" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../Microsoft.AspNet.SignalR.Core" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../Microsoft.AspNet.SignalR.Owin" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../MonoTorrent" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Api" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Api.Test" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.App.Test" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Automation.Test" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Common" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Common.Test" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Console" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Core" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Core.Test" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Host" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Integration.Test" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Libraries.Test" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Mono" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Mono.Test" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.SignalR" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Test.Common" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Test.Dummy" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Update" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Update.Test" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Windows" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Windows.Test" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../ServiceHelpers/ServiceInstall" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../ServiceHelpers/ServiceUninstall" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/../../ExternalModules/CurlSharp/CurlSharp/bin" />
<excludeFolder url="file://$MODULE_DIR$/../../ExternalModules/CurlSharp/CurlSharp/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../LogentriesCore/bin" />
<excludeFolder url="file://$MODULE_DIR$/../../LogentriesCore/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../LogentriesNLog/bin" />
<excludeFolder url="file://$MODULE_DIR$/../../LogentriesNLog/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../Marr.Data/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../Microsoft.AspNet.SignalR.Core/bin" />
<excludeFolder url="file://$MODULE_DIR$/../../Microsoft.AspNet.SignalR.Core/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../Microsoft.AspNet.SignalR.Owin/bin" />
<excludeFolder url="file://$MODULE_DIR$/../../Microsoft.AspNet.SignalR.Owin/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../MonoTorrent/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Api.Test/bin" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Api.Test/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Api/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.App.Test/bin" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.App.Test/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Automation.Test/bin" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Automation.Test/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Common.Test/bin" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Common.Test/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Common/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Console/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Core.Test/bin" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Core.Test/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Core/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Host/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Integration.Test/bin" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Integration.Test/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Libraries.Test/bin" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Libraries.Test/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Mono.Test/bin" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Mono.Test/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Mono/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.SignalR/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Test.Common/bin" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Test.Common/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Test.Dummy/bin" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Test.Dummy/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Update.Test/bin" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Update.Test/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Update/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Windows.Test/bin" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Windows.Test/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Windows/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../ServiceHelpers/ServiceInstall/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../ServiceHelpers/ServiceUninstall/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../_ReSharper.Caches/ReSharperHost8.NzbDrone.00" />
<excludeFolder url="file://$MODULE_DIR$/../../packages" />
</content>
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
</component> </component>
</module> </module>

@ -273,19 +273,74 @@ namespace NzbDrone.Common.Test.Http
response.Resource.Headers.Should().NotContainKey("Cookie"); response.Resource.Headers.Should().NotContainKey("Cookie");
} }
[Test]
public void should_not_store_request_cookie()
{
var requestGet = new HttpRequest($"http://{_httpBinHost}/get");
requestGet.Cookies.Add("my", "cookie");
requestGet.AllowAutoRedirect = false;
requestGet.StoreRequestCookie = false;
requestGet.StoreResponseCookie = false;
var responseGet = Subject.Get<HttpBinResource>(requestGet);
var requestCookies = new HttpRequest($"http://{_httpBinHost}/cookies");
requestCookies.AllowAutoRedirect = false;
var responseCookies = Subject.Get<HttpCookieResource>(requestCookies);
responseCookies.Resource.Cookies.Should().BeEmpty();
ExceptionVerification.IgnoreErrors();
}
[Test]
public void should_store_request_cookie()
{
var requestGet = new HttpRequest($"http://{_httpBinHost}/get");
requestGet.Cookies.Add("my", "cookie");
requestGet.AllowAutoRedirect = false;
requestGet.StoreRequestCookie.Should().BeTrue();
requestGet.StoreResponseCookie = false;
var responseGet = Subject.Get<HttpBinResource>(requestGet);
var requestCookies = new HttpRequest($"http://{_httpBinHost}/cookies");
requestCookies.AllowAutoRedirect = false;
var responseCookies = Subject.Get<HttpCookieResource>(requestCookies);
responseCookies.Resource.Cookies.Should().HaveCount(1).And.Contain("my", "cookie");
ExceptionVerification.IgnoreErrors();
}
[Test]
public void should_delete_request_cookie()
{
var requestDelete = new HttpRequest($"http://{_httpBinHost}/cookies/delete?my");
requestDelete.Cookies.Add("my", "cookie");
requestDelete.AllowAutoRedirect = true;
requestDelete.StoreRequestCookie = false;
requestDelete.StoreResponseCookie = false;
// Delete and redirect since that's the only way to check the internal temporary cookie container
var responseCookies = Subject.Get<HttpCookieResource>(requestDelete);
responseCookies.Resource.Cookies.Should().BeEmpty();
}
[Test] [Test]
public void should_not_store_response_cookie() public void should_not_store_response_cookie()
{ {
var requestSet = new HttpRequest(string.Format("http://{0}/cookies/set?my=cookie", _httpBinHost)); var requestSet = new HttpRequest(string.Format("http://{0}/cookies/set?my=cookie", _httpBinHost));
requestSet.AllowAutoRedirect = false; requestSet.AllowAutoRedirect = false;
requestSet.StoreRequestCookie = false;
requestSet.StoreResponseCookie.Should().BeFalse();
var responseSet = Subject.Get(requestSet); var responseSet = Subject.Get(requestSet);
var request = new HttpRequest(string.Format("http://{0}/get", _httpBinHost)); var requestCookies = new HttpRequest($"http://{_httpBinHost}/cookies");
var response = Subject.Get<HttpBinResource>(request); var responseCookies = Subject.Get<HttpCookieResource>(requestCookies);
response.Resource.Headers.Should().NotContainKey("Cookie"); responseCookies.Resource.Cookies.Should().BeEmpty();
ExceptionVerification.IgnoreErrors(); ExceptionVerification.IgnoreErrors();
} }
@ -295,19 +350,31 @@ namespace NzbDrone.Common.Test.Http
{ {
var requestSet = new HttpRequest(string.Format("http://{0}/cookies/set?my=cookie", _httpBinHost)); var requestSet = new HttpRequest(string.Format("http://{0}/cookies/set?my=cookie", _httpBinHost));
requestSet.AllowAutoRedirect = false; requestSet.AllowAutoRedirect = false;
requestSet.StoreRequestCookie = false;
requestSet.StoreResponseCookie = true; requestSet.StoreResponseCookie = true;
var responseSet = Subject.Get(requestSet); var responseSet = Subject.Get(requestSet);
var request = new HttpRequest(string.Format("http://{0}/get", _httpBinHost)); var requestCookies = new HttpRequest($"http://{_httpBinHost}/cookies");
var response = Subject.Get<HttpBinResource>(request); var responseCookies = Subject.Get<HttpCookieResource>(requestCookies);
response.Resource.Headers.Should().ContainKey("Cookie"); responseCookies.Resource.Cookies.Should().HaveCount(1).And.Contain("my", "cookie");
var cookie = response.Resource.Headers["Cookie"].ToString(); ExceptionVerification.IgnoreErrors();
}
cookie.Should().Contain("my=cookie"); [Test]
public void should_temp_store_response_cookie()
{
var requestSet = new HttpRequest($"http://{_httpBinHost}/cookies/set?my=cookie");
requestSet.AllowAutoRedirect = true;
requestSet.StoreRequestCookie = false;
requestSet.StoreResponseCookie.Should().BeFalse();
var responseSet = Subject.Get<HttpCookieResource>(requestSet);
// Set and redirect since that's the only way to check the internal temporary cookie container
responseSet.Resource.Cookies.Should().HaveCount(1).And.Contain("my", "cookie");
ExceptionVerification.IgnoreErrors(); ExceptionVerification.IgnoreErrors();
} }
@ -315,26 +382,148 @@ namespace NzbDrone.Common.Test.Http
[Test] [Test]
public void should_overwrite_response_cookie() public void should_overwrite_response_cookie()
{ {
var requestSet = new HttpRequest(string.Format("http://{0}/cookies/set?my=cookie", _httpBinHost)); var requestSet = new HttpRequest($"http://{_httpBinHost}/cookies/set?my=cookie");
requestSet.Cookies.Add("my", "oldcookie");
requestSet.AllowAutoRedirect = false; requestSet.AllowAutoRedirect = false;
requestSet.StoreRequestCookie = false;
requestSet.StoreResponseCookie = true; requestSet.StoreResponseCookie = true;
requestSet.Cookies["my"] = "oldcookie";
var responseSet = Subject.Get(requestSet); var responseSet = Subject.Get(requestSet);
var request = new HttpRequest(string.Format("http://{0}/get", _httpBinHost)); var requestCookies = new HttpRequest($"http://{_httpBinHost}/cookies");
var response = Subject.Get<HttpBinResource>(request); var responseCookies = Subject.Get<HttpCookieResource>(requestCookies);
response.Resource.Headers.Should().ContainKey("Cookie"); responseCookies.Resource.Cookies.Should().HaveCount(1).And.Contain("my", "cookie");
var cookie = response.Resource.Headers["Cookie"].ToString(); ExceptionVerification.IgnoreErrors();
}
cookie.Should().Contain("my=cookie"); [Test]
public void should_overwrite_temp_response_cookie()
{
var requestSet = new HttpRequest($"http://{_httpBinHost}/cookies/set?my=cookie");
requestSet.Cookies.Add("my", "oldcookie");
requestSet.AllowAutoRedirect = true;
requestSet.StoreRequestCookie = true;
requestSet.StoreResponseCookie = false;
var responseSet = Subject.Get<HttpCookieResource>(requestSet);
responseSet.Resource.Cookies.Should().HaveCount(1).And.Contain("my", "cookie");
var requestCookies = new HttpRequest($"http://{_httpBinHost}/cookies");
var responseCookies = Subject.Get<HttpCookieResource>(requestCookies);
responseCookies.Resource.Cookies.Should().HaveCount(1).And.Contain("my", "oldcookie");
ExceptionVerification.IgnoreErrors();
}
[Test]
public void should_not_delete_response_cookie()
{
var requestCookies = new HttpRequest($"http://{_httpBinHost}/cookies");
requestCookies.Cookies.Add("my", "cookie");
requestCookies.AllowAutoRedirect = false;
requestCookies.StoreRequestCookie = true;
requestCookies.StoreResponseCookie = false;
var responseCookies = Subject.Get<HttpCookieResource>(requestCookies);
responseCookies.Resource.Cookies.Should().HaveCount(1).And.Contain("my", "cookie");
var requestDelete = new HttpRequest($"http://{_httpBinHost}/cookies/delete?my");
requestDelete.AllowAutoRedirect = false;
requestDelete.StoreRequestCookie = false;
requestDelete.StoreResponseCookie = false;
var responseDelete = Subject.Get(requestDelete);
requestCookies = new HttpRequest($"http://{_httpBinHost}/cookies");
requestCookies.StoreRequestCookie = false;
requestCookies.StoreResponseCookie = false;
responseCookies = Subject.Get<HttpCookieResource>(requestCookies);
responseCookies.Resource.Cookies.Should().HaveCount(1).And.Contain("my", "cookie");
ExceptionVerification.IgnoreErrors(); ExceptionVerification.IgnoreErrors();
} }
[Test]
public void should_delete_response_cookie()
{
var requestCookies = new HttpRequest($"http://{_httpBinHost}/cookies");
requestCookies.Cookies.Add("my", "cookie");
requestCookies.AllowAutoRedirect = false;
requestCookies.StoreRequestCookie = true;
requestCookies.StoreResponseCookie = false;
var responseCookies = Subject.Get<HttpCookieResource>(requestCookies);
responseCookies.Resource.Cookies.Should().HaveCount(1).And.Contain("my", "cookie");
var requestDelete = new HttpRequest($"http://{_httpBinHost}/cookies/delete?my");
requestDelete.AllowAutoRedirect = false;
requestDelete.StoreRequestCookie = false;
requestDelete.StoreResponseCookie = true;
var responseDelete = Subject.Get(requestDelete);
requestCookies = new HttpRequest($"http://{_httpBinHost}/cookies");
requestCookies.StoreRequestCookie = false;
requestCookies.StoreResponseCookie = false;
responseCookies = Subject.Get<HttpCookieResource>(requestCookies);
responseCookies.Resource.Cookies.Should().BeEmpty();
ExceptionVerification.IgnoreErrors();
}
[Test]
public void should_delete_temp_response_cookie()
{
var requestCookies = new HttpRequest($"http://{_httpBinHost}/cookies");
requestCookies.Cookies.Add("my", "cookie");
requestCookies.AllowAutoRedirect = false;
requestCookies.StoreRequestCookie = true;
requestCookies.StoreResponseCookie = false;
var responseCookies = Subject.Get<HttpCookieResource>(requestCookies);
responseCookies.Resource.Cookies.Should().HaveCount(1).And.Contain("my", "cookie");
var requestDelete = new HttpRequest($"http://{_httpBinHost}/cookies/delete?my");
requestDelete.AllowAutoRedirect = true;
requestDelete.StoreRequestCookie = false;
requestDelete.StoreResponseCookie = false;
var responseDelete = Subject.Get<HttpCookieResource>(requestDelete);
responseDelete.Resource.Cookies.Should().BeEmpty();
requestCookies = new HttpRequest($"http://{_httpBinHost}/cookies");
requestCookies.StoreRequestCookie = false;
requestCookies.StoreResponseCookie = false;
responseCookies.Resource.Cookies.Should().HaveCount(1).And.Contain("my", "cookie");
ExceptionVerification.IgnoreErrors();
}
[Test]
public void should_not_send_old_cookie()
{
GivenOldCookie();
var requestCookies = new HttpRequest($"http://{_httpBinHost}/cookies");
requestCookies.IgnorePersistentCookies = true;
requestCookies.StoreRequestCookie = false;
requestCookies.StoreResponseCookie = false;
var responseCookies = Subject.Get<HttpCookieResource>(requestCookies);
responseCookies.Resource.Cookies.Should().BeEmpty();
}
[Test] [Test]
public void should_throw_on_http429_too_many_requests() public void should_throw_on_http429_too_many_requests()
{ {
@ -442,4 +631,9 @@ namespace NzbDrone.Common.Test.Http
public string Url { get; set; } public string Url { get; set; }
public string Data { get; set; } public string Data { get; set; }
} }
public class HttpCookieResource
{
public Dictionary<string, string> Cookies { get; set; }
}
} }

@ -45,7 +45,9 @@ namespace NzbDrone.Common.Http
public HttpResponse Execute(HttpRequest request) public HttpResponse Execute(HttpRequest request)
{ {
var response = ExecuteRequest(request); var cookieContainer = InitializeRequestCookies(request);
var response = ExecuteRequest(request, cookieContainer);
if (request.AllowAutoRedirect && response.HasHttpRedirect) if (request.AllowAutoRedirect && response.HasHttpRedirect)
{ {
@ -64,7 +66,7 @@ namespace NzbDrone.Common.Http
throw new WebException($"Too many automatic redirections were attempted for {string.Join(" -> ", autoRedirectChain)}", WebExceptionStatus.ProtocolError); throw new WebException($"Too many automatic redirections were attempted for {string.Join(" -> ", autoRedirectChain)}", WebExceptionStatus.ProtocolError);
} }
response = ExecuteRequest(request); response = ExecuteRequest(request, cookieContainer);
} }
while (response.HasHttpRedirect); while (response.HasHttpRedirect);
} }
@ -91,7 +93,7 @@ namespace NzbDrone.Common.Http
return response; return response;
} }
private HttpResponse ExecuteRequest(HttpRequest request) private HttpResponse ExecuteRequest(HttpRequest request, CookieContainer cookieContainer)
{ {
foreach (var interceptor in _requestInterceptors) foreach (var interceptor in _requestInterceptors)
{ {
@ -107,11 +109,11 @@ namespace NzbDrone.Common.Http
var stopWatch = Stopwatch.StartNew(); var stopWatch = Stopwatch.StartNew();
var cookies = PrepareRequestCookies(request); PrepareRequestCookies(request, cookieContainer);
var response = _httpDispatcher.GetResponse(request, cookies); var response = _httpDispatcher.GetResponse(request, cookieContainer);
HandleResponseCookies(request, cookies); HandleResponseCookies(response, cookieContainer);
stopWatch.Stop(); stopWatch.Stop();
@ -130,49 +132,84 @@ namespace NzbDrone.Common.Http
return response; return response;
} }
private CookieContainer PrepareRequestCookies(HttpRequest request) private CookieContainer InitializeRequestCookies(HttpRequest request)
{ {
lock (_cookieContainerCache) lock (_cookieContainerCache)
{ {
var persistentCookieContainer = _cookieContainerCache.Get("container", () => new CookieContainer()); var sourceContainer = new CookieContainer();
var presistentContainer = _cookieContainerCache.Get("container", () => new CookieContainer());
if (!request.IgnorePersistentCookies)
{
var persistentCookies = presistentContainer.GetCookies((Uri)request.Url);
sourceContainer.Add(persistentCookies);
}
if (request.Cookies.Count != 0) if (request.Cookies.Count != 0)
{ {
foreach (var pair in request.Cookies) foreach (var pair in request.Cookies)
{ {
persistentCookieContainer.Add(new Cookie(pair.Key, pair.Value, "/", request.Url.Host) var cookie = new Cookie(pair.Key, pair.Value, "/")
{ {
// Use Now rather than UtcNow to work around Mono cookie expiry bug. // Use Now rather than UtcNow to work around Mono cookie expiry bug.
// See https://gist.github.com/ta264/7822b1424f72e5b4c961 // See https://gist.github.com/ta264/7822b1424f72e5b4c961
Expires = DateTime.Now.AddHours(1) Expires = DateTime.Now.AddHours(1)
}); };
sourceContainer.Add((Uri)request.Url, cookie);
if (request.StoreRequestCookie)
{
presistentContainer.Add((Uri)request.Url, cookie);
}
} }
} }
var requestCookies = persistentCookieContainer.GetCookies((Uri)request.Url); return sourceContainer;
}
var cookieContainer = new CookieContainer(); }
cookieContainer.Add(requestCookies); private void PrepareRequestCookies(HttpRequest request, CookieContainer cookieContainer)
{
// Don't collect persistnet cookies for intermediate/redirected urls.
/*lock (_cookieContainerCache)
{
var presistentContainer = _cookieContainerCache.Get("container", () => new CookieContainer());
var persistentCookies = presistentContainer.GetCookies((Uri)request.Url);
var existingCookies = cookieContainer.GetCookies((Uri)request.Url);
return cookieContainer; cookieContainer.Add(persistentCookies);
} cookieContainer.Add(existingCookies);
}*/
} }
private void HandleResponseCookies(HttpRequest request, CookieContainer cookieContainer) private void HandleResponseCookies(HttpResponse response, CookieContainer cookieContainer)
{ {
if (!request.StoreResponseCookie) var cookieHeaders = response.GetCookieHeaders();
if (cookieHeaders.Empty())
{ {
return; return;
} }
lock (_cookieContainerCache) if (response.Request.StoreResponseCookie)
{ {
var persistentCookieContainer = _cookieContainerCache.Get("container", () => new CookieContainer()); lock (_cookieContainerCache)
{
var cookies = cookieContainer.GetCookies((Uri)request.Url); var persistentCookieContainer = _cookieContainerCache.Get("container", () => new CookieContainer());
persistentCookieContainer.Add(cookies); foreach (var cookieHeader in cookieHeaders)
{
try
{
persistentCookieContainer.SetCookies((Uri)response.Request.Url, cookieHeader);
}
catch (Exception ex)
{
_logger.Debug(ex, "Invalid cookie in {0}", response.Request.Url);
}
}
}
} }
} }

@ -13,6 +13,8 @@ namespace NzbDrone.Common.Http
Url = new HttpUri(url); Url = new HttpUri(url);
Headers = new HttpHeader(); Headers = new HttpHeader();
AllowAutoRedirect = true; AllowAutoRedirect = true;
StoreRequestCookie = true;
IgnorePersistentCookies = false;
Cookies = new Dictionary<string, string>(); Cookies = new Dictionary<string, string>();
if (!RuntimeInfoBase.IsProduction) if (!RuntimeInfoBase.IsProduction)
@ -37,6 +39,8 @@ namespace NzbDrone.Common.Http
public bool ConnectionKeepAlive { get; set; } public bool ConnectionKeepAlive { get; set; }
public bool LogResponseContent { get; set; } public bool LogResponseContent { get; set; }
public Dictionary<string, string> Cookies { get; private set; } public Dictionary<string, string> Cookies { get; private set; }
public bool IgnorePersistentCookies { get; set; }
public bool StoreRequestCookie { get; set; }
public bool StoreResponseCookie { get; set; } public bool StoreResponseCookie { get; set; }
public TimeSpan RequestTimeout { get; set; } public TimeSpan RequestTimeout { get; set; }
public TimeSpan RateLimit { get; set; } public TimeSpan RateLimit { get; set; }

@ -55,20 +55,22 @@ namespace NzbDrone.Common.Http
StatusCode == HttpStatusCode.MovedPermanently || StatusCode == HttpStatusCode.MovedPermanently ||
StatusCode == HttpStatusCode.Found; StatusCode == HttpStatusCode.Found;
public string[] GetCookieHeaders()
{
return Headers.GetValues("Set-Cookie") ?? new string[0];
}
public Dictionary<string, string> GetCookies() public Dictionary<string, string> GetCookies()
{ {
var result = new Dictionary<string, string>(); var result = new Dictionary<string, string>();
var setCookieHeaders = Headers.GetValues("Set-Cookie"); var setCookieHeaders = GetCookieHeaders();
if (setCookieHeaders != null) foreach (var cookie in setCookieHeaders)
{ {
foreach (var cookie in setCookieHeaders) var match = RegexSetCookie.Match(cookie);
if (match.Success)
{ {
var match = RegexSetCookie.Match(cookie); result[match.Groups[1].Value] = match.Groups[2].Value;
if (match.Success)
{
result[match.Groups[1].Value] = match.Groups[2].Value;
}
} }
} }

@ -0,0 +1,16 @@
using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(144)]
public class add_cookies_to_indexer_status : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Alter.Table("IndexerStatus").AddColumn("Cookies").AsString().Nullable()
.AddColumn("CookiesExpirationDate").AsDateTime().Nullable();
}
}
}

@ -146,6 +146,7 @@ namespace NzbDrone.Core.Datastore
MapRepository.Instance.RegisterTypeConverter(typeof(List<ProfileQualityItem>), new EmbeddedDocumentConverter(new QualityIntConverter())); MapRepository.Instance.RegisterTypeConverter(typeof(List<ProfileQualityItem>), new EmbeddedDocumentConverter(new QualityIntConverter()));
MapRepository.Instance.RegisterTypeConverter(typeof(QualityModel), new EmbeddedDocumentConverter(new QualityIntConverter())); MapRepository.Instance.RegisterTypeConverter(typeof(QualityModel), new EmbeddedDocumentConverter(new QualityIntConverter()));
MapRepository.Instance.RegisterTypeConverter(typeof(Dictionary<string, string>), new EmbeddedDocumentConverter()); MapRepository.Instance.RegisterTypeConverter(typeof(Dictionary<string, string>), new EmbeddedDocumentConverter());
MapRepository.Instance.RegisterTypeConverter(typeof(IDictionary<string, string>), new EmbeddedDocumentConverter());
MapRepository.Instance.RegisterTypeConverter(typeof(List<int>), new EmbeddedDocumentConverter()); MapRepository.Instance.RegisterTypeConverter(typeof(List<int>), new EmbeddedDocumentConverter());
MapRepository.Instance.RegisterTypeConverter(typeof(List<string>), new EmbeddedDocumentConverter()); MapRepository.Instance.RegisterTypeConverter(typeof(List<string>), new EmbeddedDocumentConverter());
MapRepository.Instance.RegisterTypeConverter(typeof(ParsedMovieInfo), new EmbeddedDocumentConverter()); MapRepository.Instance.RegisterTypeConverter(typeof(ParsedMovieInfo), new EmbeddedDocumentConverter());

@ -25,6 +25,9 @@ namespace NzbDrone.Core.Indexers.AwesomeHD
return pageableRequests; return pageableRequests;
} }
public Func<IDictionary<string, string>> GetCookies { get; set; }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
private IEnumerable<IndexerRequest> GetRequest(string searchParameters) private IEnumerable<IndexerRequest> GetRequest(string searchParameters)
{ {
if (searchParameters != null) if (searchParameters != null)

@ -106,6 +106,8 @@ namespace NzbDrone.Core.Indexers.AwesomeHD
return torrentInfos.OrderByDescending(o => ((dynamic)o).Seeders).ToArray(); return torrentInfos.OrderByDescending(o => ((dynamic)o).Seeders).ToArray();
} }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
private string GetDownloadUrl(string torrentId, string authKey, string passKey) private string GetDownloadUrl(string torrentId, string authKey, string passKey)
{ {
var url = new HttpUri(_settings.BaseUrl) var url = new HttpUri(_settings.BaseUrl)

@ -1,4 +1,5 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.Net; using System.Net;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
@ -85,6 +86,8 @@ namespace NzbDrone.Core.Indexers.HDBits
return torrentInfos.ToArray(); return torrentInfos.ToArray();
} }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
private string GetDownloadUrl(string torrentId) private string GetDownloadUrl(string torrentId)
{ {
var url = new HttpUri(_settings.BaseUrl) var url = new HttpUri(_settings.BaseUrl)

@ -1,3 +1,4 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
@ -45,6 +46,9 @@ namespace NzbDrone.Core.Indexers.HDBits
return false; return false;
} }
public Func<IDictionary<string, string>> GetCookies { get; set; }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
private IEnumerable<IndexerRequest> GetRequest(TorrentQuery query) private IEnumerable<IndexerRequest> GetRequest(TorrentQuery query)
{ {
var request = new HttpRequestBuilder(Settings.BaseUrl) var request = new HttpRequestBuilder(Settings.BaseUrl)

@ -46,9 +46,7 @@ namespace NzbDrone.Core.Indexers
return new List<ReleaseInfo>(); return new List<ReleaseInfo>();
} }
var generator = GetRequestGenerator(); return FetchReleases(GetRequestChain(), true);
return FetchReleases(generator.GetRecentRequests(), true);
} }
public override IList<ReleaseInfo> Fetch(MovieSearchCriteria searchCriteria) public override IList<ReleaseInfo> Fetch(MovieSearchCriteria searchCriteria)
@ -58,17 +56,48 @@ namespace NzbDrone.Core.Indexers
return new List<ReleaseInfo>(); return new List<ReleaseInfo>();
} }
return FetchReleases(GetRequestChain(searchCriteria));
}
protected IndexerPageableRequestChain GetRequestChain(SearchCriteriaBase searchCriteria = null)
{
var generator = GetRequestGenerator(); var generator = GetRequestGenerator();
return FetchReleases(generator.GetSearchRequests(searchCriteria)); //A func ensures cookies are always updated to the latest. This way, the first page could update the cookies and then can be reused by the second page.
generator.GetCookies = () =>
{
var cookies = _indexerStatusService.GetIndexerCookies(Definition.Id);
var expiration = _indexerStatusService.GetIndexerCookiesExpirationDate(Definition.Id);
if (expiration < DateTime.Now)
{
cookies = null;
}
return cookies;
};
var requests = searchCriteria == null ? generator.GetRecentRequests() : generator.GetSearchRequests(searchCriteria as MovieSearchCriteria);
generator.CookiesUpdater = (cookies, expiration) =>
{
_indexerStatusService.UpdateCookies(Definition.Id, cookies, expiration);
};
return requests;
} }
protected virtual IList<ReleaseInfo> FetchReleases(IndexerPageableRequestChain pageableRequestChain, bool isRecent = false) protected virtual IList<ReleaseInfo> FetchReleases(IndexerPageableRequestChain pageableRequestChain, bool isRecent = false)
{ {
var releases = new List<ReleaseInfo>(); var releases = new List<ReleaseInfo>();
var url = string.Empty; var url = string.Empty;
var parser = GetParser(); var parser = GetParser();
parser.CookiesUpdater = (cookies, expiration) =>
{
_indexerStatusService.UpdateCookies(Definition.Id, cookies, expiration);
};
try try
{ {
@ -261,8 +290,11 @@ namespace NzbDrone.Core.Indexers
try try
{ {
var parser = GetParser(); var parser = GetParser();
var generator = GetRequestGenerator(); parser.CookiesUpdater = (cookies, expiration) =>
var releases = FetchPage(generator.GetRecentRequests().GetAllTiers().First().First(), parser); {
_indexerStatusService.UpdateCookies(Definition.Id, cookies, expiration);
};
var releases = FetchPage(GetRequestChain().GetAllTiers().First().First(), parser);
if (releases.Empty()) if (releases.Empty())
{ {

@ -1,3 +1,5 @@
using System;
using System.Collections.Generic;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
namespace NzbDrone.Core.Indexers namespace NzbDrone.Core.Indexers
@ -6,5 +8,7 @@ namespace NzbDrone.Core.Indexers
{ {
IndexerPageableRequestChain GetRecentRequests(); IndexerPageableRequestChain GetRecentRequests();
IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria); IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria);
Func<IDictionary<string, string>> GetCookies { get; set; }
Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
} }

@ -27,5 +27,8 @@ namespace NzbDrone.Core.Indexers.IPTorrents
{ {
yield return new IndexerRequest(Settings.BaseUrl, HttpAccept.Rss); yield return new IndexerRequest(Settings.BaseUrl, HttpAccept.Rss);
} }
public Func<IDictionary<string, string>> GetCookies { get; set; }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
} }

@ -1,4 +1,5 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.Indexers namespace NzbDrone.Core.Indexers
@ -6,5 +7,6 @@ namespace NzbDrone.Core.Indexers
public interface IParseIndexerResponse public interface IParseIndexerResponse
{ {
IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse); IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse);
Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
} }

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using NzbDrone.Core.Datastore; using NzbDrone.Core.Datastore;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
@ -15,6 +16,9 @@ namespace NzbDrone.Core.Indexers
public ReleaseInfo LastRssSyncReleaseInfo { get; set; } public ReleaseInfo LastRssSyncReleaseInfo { get; set; }
public IDictionary<string, string> Cookies { get; set; }
public DateTime? CookiesExpirationDate { get; set; }
public bool IsDisabled() public bool IsDisabled()
{ {
return DisabledTill.HasValue && DisabledTill.Value > DateTime.UtcNow; return DisabledTill.HasValue && DisabledTill.Value > DateTime.UtcNow;

@ -12,11 +12,14 @@ namespace NzbDrone.Core.Indexers
{ {
List<IndexerStatus> GetBlockedIndexers(); List<IndexerStatus> GetBlockedIndexers();
ReleaseInfo GetLastRssSyncReleaseInfo(int indexerId); ReleaseInfo GetLastRssSyncReleaseInfo(int indexerId);
IDictionary<string, string> GetIndexerCookies(int indexerId);
DateTime GetIndexerCookiesExpirationDate(int indexerId);
void RecordSuccess(int indexerId); void RecordSuccess(int indexerId);
void RecordFailure(int indexerId, TimeSpan minimumBackOff = default(TimeSpan)); void RecordFailure(int indexerId, TimeSpan minimumBackOff = default(TimeSpan));
void RecordConnectionFailure(int indexerId); void RecordConnectionFailure(int indexerId);
void UpdateRssSyncStatus(int indexerId, ReleaseInfo releaseInfo); void UpdateRssSyncStatus(int indexerId, ReleaseInfo releaseInfo);
void UpdateCookies(int indexerId, IDictionary<string, string> cookies, DateTime? expiration);
} }
public class IndexerStatusService : IIndexerStatusService, IHandleAsync<ProviderDeletedEvent<IIndexer>> public class IndexerStatusService : IIndexerStatusService, IHandleAsync<ProviderDeletedEvent<IIndexer>>
@ -55,6 +58,16 @@ namespace NzbDrone.Core.Indexers
return GetIndexerStatus(indexerId).LastRssSyncReleaseInfo; return GetIndexerStatus(indexerId).LastRssSyncReleaseInfo;
} }
public IDictionary<string, string> GetIndexerCookies(int indexerId)
{
return GetIndexerStatus(indexerId).Cookies;
}
public DateTime GetIndexerCookiesExpirationDate(int indexerId)
{
return GetIndexerStatus(indexerId).CookiesExpirationDate ?? DateTime.Now + TimeSpan.FromDays(12);
}
private IndexerStatus GetIndexerStatus(int indexerId) private IndexerStatus GetIndexerStatus(int indexerId)
{ {
return _indexerStatusRepository.FindByIndexerId(indexerId) ?? new IndexerStatus { IndexerId = indexerId }; return _indexerStatusRepository.FindByIndexerId(indexerId) ?? new IndexerStatus { IndexerId = indexerId };
@ -141,6 +154,17 @@ namespace NzbDrone.Core.Indexers
} }
} }
public void UpdateCookies(int indexerId, IDictionary<string, string> cookies, DateTime? expiration)
{
lock (_syncRoot)
{
var status = GetIndexerStatus(indexerId);
status.Cookies = cookies;
status.CookiesExpirationDate = expiration;
_indexerStatusRepository.Upsert(status);
}
}
public void HandleAsync(ProviderDeletedEvent<IIndexer> message) public void HandleAsync(ProviderDeletedEvent<IIndexer> message)
{ {
var indexerStatus = _indexerStatusRepository.FindByIndexerId(message.ProviderId); var indexerStatus = _indexerStatusRepository.FindByIndexerId(message.ProviderId);

@ -109,5 +109,8 @@ namespace NzbDrone.Core.Indexers.Newznab
} }
} }
} }
public Func<IDictionary<string, string>> GetCookies { get; set; }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
} }

@ -60,5 +60,8 @@ namespace NzbDrone.Core.Indexers.Nyaa
{ {
return new IndexerPageableRequestChain(); return new IndexerPageableRequestChain();
} }
public Func<IDictionary<string, string>> GetCookies { get; set; }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
} }

@ -49,5 +49,8 @@ namespace NzbDrone.Core.Indexers.Omgwtfnzbs
return pageableRequests; return pageableRequests;
} }
public Func<IDictionary<string, string>> GetCookies { get; set; }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
} }

@ -15,8 +15,8 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
public override bool SupportsSearch => true; public override bool SupportsSearch => true;
public override int PageSize => 50; public override int PageSize => 50;
private readonly ICached<Dictionary<string, string>> _authCookieCache;
private readonly IHttpClient _httpClient; private readonly IHttpClient _httpClient;
private readonly IIndexerStatusService _indexerStatusService;
private readonly Logger _logger; private readonly Logger _logger;
public PassThePopcorn(IHttpClient httpClient, ICacheManager cacheManager, IIndexerStatusService indexerStatusService, public PassThePopcorn(IHttpClient httpClient, ICacheManager cacheManager, IIndexerStatusService indexerStatusService,
@ -25,7 +25,7 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
{ {
_httpClient = httpClient; _httpClient = httpClient;
_logger = logger; _logger = logger;
_authCookieCache = cacheManager.GetCache<Dictionary<string, string>>(GetType(), "authCookies"); _indexerStatusService = indexerStatusService;
} }
public override IIndexerRequestGenerator GetRequestGenerator() public override IIndexerRequestGenerator GetRequestGenerator()
@ -35,7 +35,6 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
Settings = Settings, Settings = Settings,
HttpClient = _httpClient, HttpClient = _httpClient,
Logger = _logger, Logger = _logger,
AuthCookieCache = _authCookieCache
}; };
} }
@ -43,5 +42,20 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
{ {
return new PassThePopcornParser(Settings); return new PassThePopcornParser(Settings);
} }
/*protected override IndexerResponse FetchIndexerResponse(IndexerRequest request)
{
_logger.Debug("Downloading Feed " + request.HttpRequest.ToString(false));
if (request.HttpRequest.RateLimit < RateLimit)
{
request.HttpRequest.RateLimit = RateLimit;
}
//Potentially dangerous though if ptp moves domains!
request.HttpRequest.AllowAutoRedirect = false;
return new IndexerResponse(request, _httpClient.Execute(request.HttpRequest));
}*/
} }
} }

@ -1,3 +1,4 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net; using System.Net;
using Newtonsoft.Json; using Newtonsoft.Json;
@ -13,8 +14,6 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
public class PassThePopcornParser : IParseIndexerResponse public class PassThePopcornParser : IParseIndexerResponse
{ {
private readonly PassThePopcornSettings _settings; private readonly PassThePopcornSettings _settings;
public ICached<Dictionary<string, string>> AuthCookieCache { get; set; }
public PassThePopcornParser(PassThePopcornSettings settings) public PassThePopcornParser(PassThePopcornSettings settings)
{ {
_settings = settings; _settings = settings;
@ -27,16 +26,23 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
if (indexerResponse.HttpResponse.StatusCode != HttpStatusCode.OK) if (indexerResponse.HttpResponse.StatusCode != HttpStatusCode.OK)
{ {
// Remove cookie cache // Remove cookie cache
AuthCookieCache.Remove(_settings.BaseUrl.Trim().TrimEnd('/')); if (indexerResponse.HttpResponse.HasHttpRedirect && indexerResponse.HttpResponse.Headers["Location"]
.ContainsIgnoreCase("login.php"))
{
CookiesUpdater(null, null);
throw new IndexerException(indexerResponse, "We are being redirected to the PTP login page. Most likely your session expired or was killed. Try testing the indexer in the settings.");
}
throw new IndexerException(indexerResponse, $"Unexpected response status {indexerResponse.HttpResponse.StatusCode} code from API request"); throw new IndexerException(indexerResponse, $"Unexpected response status {indexerResponse.HttpResponse.StatusCode} code from API request");
} }
if (indexerResponse.HttpResponse.Headers.ContentType != HttpAccept.Json.Value) if (indexerResponse.HttpResponse.Headers.ContentType != HttpAccept.Json.Value)
{ {
if (indexerResponse.HttpResponse.Request.Url.Path.ContainsIgnoreCase("login.php"))
{
CookiesUpdater(null, null);
throw new IndexerException(indexerResponse, "We are currently on the login page. Most likely your session expired or was killed. Try testing the indexer in the settings.");
}
// Remove cookie cache // Remove cookie cache
AuthCookieCache.Remove(_settings.BaseUrl.Trim().TrimEnd('/'));
throw new IndexerException(indexerResponse, $"Unexpected response header {indexerResponse.HttpResponse.Headers.ContentType} from API request, expected {HttpAccept.Json.Value}"); throw new IndexerException(indexerResponse, $"Unexpected response header {indexerResponse.HttpResponse.Headers.ContentType} from API request, expected {HttpAccept.Json.Value}");
} }
@ -97,6 +103,8 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
} }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
private string GetDownloadUrl(int torrentId, string authKey, string passKey) private string GetDownloadUrl(int torrentId, string authKey, string passKey)
{ {
var url = new HttpUri(_settings.BaseUrl) var url = new HttpUri(_settings.BaseUrl)

@ -13,7 +13,8 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
public PassThePopcornSettings Settings { get; set; } public PassThePopcornSettings Settings { get; set; }
public ICached<Dictionary<string, string>> AuthCookieCache { get; set; } public IDictionary<string, string> Cookies { get; set; }
public IHttpClient HttpClient { get; set; } public IHttpClient HttpClient { get; set; }
public Logger Logger { get; set; } public Logger Logger { get; set; }
@ -33,62 +34,62 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
return pageableRequests; return pageableRequests;
} }
public Func<IDictionary<string, string>> GetCookies { get; set; }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
private IEnumerable<IndexerRequest> GetRequest(string searchParameters) private IEnumerable<IndexerRequest> GetRequest(string searchParameters)
{ {
Authenticate(); Cookies = GetCookies();
var filter = ""; Authenticate();
if (searchParameters == null)
{
}
var request = var request =
new IndexerRequest( new IndexerRequest(
$"{Settings.BaseUrl.Trim().TrimEnd('/')}/torrents.php?action=advanced&json=noredirect&searchstr={searchParameters}{filter}", $"{Settings.BaseUrl.Trim().TrimEnd('/')}/torrents.php?action=advanced&json=noredirect&searchstr={searchParameters}",
HttpAccept.Json); HttpAccept.Json);
var cookies = AuthCookieCache.Find(Settings.BaseUrl.Trim().TrimEnd('/')); foreach (var cookie in Cookies)
foreach (var cookie in cookies)
{ {
request.HttpRequest.Cookies[cookie.Key] = cookie.Value; request.HttpRequest.Cookies[cookie.Key] = cookie.Value;
} }
CookiesUpdater(Cookies, DateTime.Now + TimeSpan.FromDays(30));
yield return request; yield return request;
} }
private void Authenticate() private void Authenticate()
{ {
var requestBuilder = new HttpRequestBuilder($"{Settings.BaseUrl.Trim().TrimEnd('/')}") if (Cookies == null)
{ {
LogResponseContent = true var requestBuilder = new HttpRequestBuilder($"{Settings.BaseUrl.Trim().TrimEnd('/')}")
}; {
LogResponseContent = true
requestBuilder.Method = HttpMethod.POST; };
requestBuilder.Resource("ajax.php?action=login");
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
var authKey = Settings.BaseUrl.Trim().TrimEnd('/'); requestBuilder.Method = HttpMethod.POST;
var cookies = AuthCookieCache.Find(authKey); requestBuilder.Resource("ajax.php?action=login");
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
if (cookies == null)
{
AuthCookieCache.Remove(authKey);
var authLoginRequest = requestBuilder var authLoginRequest = requestBuilder
.AddFormParameter("username", Settings.Username) .AddFormParameter("username", Settings.Username)
.AddFormParameter("password", Settings.Password) .AddFormParameter("password", Settings.Password)
.AddFormParameter("passkey", Settings.Passkey) .AddFormParameter("passkey", Settings.Passkey)
.AddFormParameter("keeplogged", "1") .AddFormParameter("keeplogged", "1")
.AddFormParameter("login", "Log In!")
.SetHeader("Content-Type", "multipart/form-data") .SetHeader("Content-Type", "multipart/form-data")
.Accept(HttpAccept.Json) .Accept(HttpAccept.Json)
.Build(); .Build();
authLoginRequest.AllowAutoRedirect = true;
// We want clean cookies for the auth request.
authLoginRequest.StoreRequestCookie = false;
authLoginRequest.StoreResponseCookie = false;
authLoginRequest.Cookies.Clear();
authLoginRequest.IgnorePersistentCookies = true;
var response = HttpClient.Execute(authLoginRequest); var response = HttpClient.Execute(authLoginRequest);
var result = Json.Deserialize<PassThePopcornAuthResponse>(response.Content); var result = Json.Deserialize<PassThePopcornAuthResponse>(response.Content);
if (result.Result != "Ok" || string.IsNullOrWhiteSpace(result.Result)) if (result?.Result != "Ok" || string.IsNullOrWhiteSpace(result.Result))
{ {
Logger.Debug("PassThePopcorn authentication failed."); Logger.Debug("PassThePopcorn authentication failed.");
throw new Exception("Failed to authenticate with PassThePopcorn."); throw new Exception("Failed to authenticate with PassThePopcorn.");
@ -96,13 +97,8 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
Logger.Debug("PassThePopcorn authentication succeeded."); Logger.Debug("PassThePopcorn authentication succeeded.");
cookies = response.GetCookies(); Cookies = response.GetCookies();
AuthCookieCache.Set(authKey, cookies, new TimeSpan(7, 0, 0, 0, 0)); // re-auth every 7 days requestBuilder.SetCookies(Cookies);
requestBuilder.SetCookies(cookies);
}
else
{
requestBuilder.SetCookies(cookies);
} }
} }
} }

@ -1,3 +1,4 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net; using System.Net;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
@ -76,6 +77,8 @@ namespace NzbDrone.Core.Indexers.Rarbg
return results; return results;
} }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
private string GetGuid(RarbgTorrent torrent) private string GetGuid(RarbgTorrent torrent)
{ {
var match = RegexGuid.Match(torrent.download); var match = RegexGuid.Match(torrent.download);

@ -1,3 +1,4 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
@ -105,5 +106,8 @@ namespace NzbDrone.Core.Indexers.Rarbg
yield return new IndexerRequest(requestBuilder.Build()); yield return new IndexerRequest(requestBuilder.Build());
} }
public Func<IDictionary<string, string>> GetCookies { get; set; }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
} }

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
@ -27,5 +28,8 @@ namespace NzbDrone.Core.Indexers
{ {
return new IndexerPageableRequestChain(); return new IndexerPageableRequestChain();
} }
public Func<IDictionary<string, string>> GetCookies { get; set; }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
} }

@ -73,6 +73,8 @@ namespace NzbDrone.Core.Indexers
return releases; return releases;
} }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
protected virtual XDocument LoadXmlDocument(IndexerResponse indexerResponse) protected virtual XDocument LoadXmlDocument(IndexerResponse indexerResponse)
{ {
try try

@ -48,6 +48,8 @@ namespace NzbDrone.Core.Indexers.TorrentPotato
return results; return results;
} }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
private string GetGuid(Result torrent) private string GetGuid(Result torrent)
{ {
var match = RegexGuid.Match(torrent.download_url); var match = RegexGuid.Match(torrent.download_url);

@ -79,5 +79,8 @@ namespace NzbDrone.Core.Indexers.TorrentPotato
pageableRequests.Add(GetMovieRequest(searchCriteria)); pageableRequests.Add(GetMovieRequest(searchCriteria));
return pageableRequests; return pageableRequests;
} }
public Func<IDictionary<string, string>> GetCookies { get; set; }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
} }

@ -38,5 +38,8 @@ namespace NzbDrone.Core.Indexers.TorrentRss
yield return request; yield return request;
} }
public Func<IDictionary<string, string>> GetCookies { get; set; }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
} }

@ -128,6 +128,7 @@
<Compile Include="Datastore\Migration\142_movie_extras.cs" /> <Compile Include="Datastore\Migration\142_movie_extras.cs" />
<Compile Include="Datastore\Migration\140_add_alternative_titles_table.cs" /> <Compile Include="Datastore\Migration\140_add_alternative_titles_table.cs" />
<Compile Include="Datastore\Migration\141_fix_duplicate_alt_titles.cs" /> <Compile Include="Datastore\Migration\141_fix_duplicate_alt_titles.cs" />
<Compile Include="Datastore\Migration\144_add_cookies_to_indexer_status.cs" />
<Compile Include="DecisionEngine\Specifications\MaximumSizeSpecification.cs" /> <Compile Include="DecisionEngine\Specifications\MaximumSizeSpecification.cs" />
<Compile Include="DecisionEngine\Specifications\RequiredIndexerFlagsSpecification.cs" /> <Compile Include="DecisionEngine\Specifications\RequiredIndexerFlagsSpecification.cs" />
<Compile Include="Housekeeping\Housekeepers\CleanupOrphanedAlternativeTitles.cs" /> <Compile Include="Housekeeping\Housekeepers\CleanupOrphanedAlternativeTitles.cs" />

Loading…
Cancel
Save