mirror of https://github.com/Jackett/Jackett
Fix: Redhat/NSS based libcurl not being able to access certain indexers
This commit is contained in:
parent
1606e3379f
commit
796bb70421
|
@ -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;
|
||||
|
@ -293,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;
|
||||
|
||||
|
@ -368,17 +355,6 @@ namespace CurlSharp
|
|||
}
|
||||
}
|
||||
|
||||
public object SslCtxData
|
||||
{
|
||||
get { return _sslContextData; }
|
||||
set
|
||||
{
|
||||
_sslContextData = value;
|
||||
#if !USE_LIBCURLSHIM
|
||||
setSslCtxData(value);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public object IoctlData
|
||||
{
|
||||
|
@ -538,11 +514,6 @@ namespace CurlSharp
|
|||
set { setFunctionOptions(CurlOption.IoctlFunction, value); }
|
||||
}
|
||||
|
||||
public CurlSslContextCallback SslContextFunction
|
||||
{
|
||||
get { return _pfCurlSslContext; }
|
||||
set { setFunctionOptions(CurlOption.SslCtxFunction, value); }
|
||||
}
|
||||
|
||||
public string LastErrorDescription
|
||||
{
|
||||
|
@ -1262,7 +1233,6 @@ namespace CurlSharp
|
|||
freeHandle(ref _curlProgressData);
|
||||
freeHandle(ref _curlHeaderData);
|
||||
freeHandle(ref _curlIoctlData);
|
||||
freeHandle(ref _curlSslCtxData);
|
||||
#endif
|
||||
NativeMethods.curl_easy_cleanup(_pCurl);
|
||||
|
||||
|
@ -1439,9 +1409,6 @@ namespace CurlSharp
|
|||
case CurlOption.HeaderData:
|
||||
_headerData = parameter;
|
||||
break;
|
||||
case CurlOption.SslCtxData:
|
||||
_sslContextData = parameter;
|
||||
break;
|
||||
case CurlOption.IoctlData:
|
||||
_ioctlData = parameter;
|
||||
break;
|
||||
|
@ -1593,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:
|
||||
{
|
||||
|
@ -1949,7 +1908,6 @@ namespace CurlSharp
|
|||
_pcbProgress = _curlProgressCallback;
|
||||
_pcbDebug = _curlDebugCallback;
|
||||
_pcbHeader = _curlHeaderCallback;
|
||||
_pcbSslCtx = _curlSslCtxCallback;
|
||||
_pcbIoctl = _curlIoctlCallback;
|
||||
|
||||
setLastError(NativeMethods.curl_easy_setopt_cb(_pCurl, CurlOption.WriteFunction, _pcbWrite),
|
||||
|
@ -1962,8 +1920,6 @@ namespace CurlSharp
|
|||
CurlOption.HeaderFunction);
|
||||
setLastError(NativeMethods.curl_easy_setopt_cb(_pCurl, CurlOption.DebugFunction, _pcbDebug),
|
||||
CurlOption.DebugFunction);
|
||||
setLastError(NativeMethods.curl_easy_setopt_cb(_pCurl, CurlOption.SslCtxFunction, _pcbSslCtx),
|
||||
CurlOption.SslCtxFunction);
|
||||
setLastError(NativeMethods.curl_easy_setopt_cb(_pCurl, CurlOption.IoctlFunction, _pcbIoctl),
|
||||
CurlOption.IoctlFunction);
|
||||
setLastError(NativeMethods.curl_easy_setopt(_pCurl, CurlOption.NoProgress, (IntPtr) 0),
|
||||
|
@ -1974,7 +1930,6 @@ namespace CurlSharp
|
|||
setHeaderData(null);
|
||||
setProgressData(null);
|
||||
setDebugData(null);
|
||||
setSslCtxData(null);
|
||||
setIoctlData(null);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -78,6 +78,7 @@
|
|||
<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.
|
||||
|
|
|
@ -1075,32 +1075,6 @@ namespace CurlSharp
|
|||
/// </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
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CurlSharp
|
||||
{
|
||||
public class SSLFix
|
||||
{
|
||||
public const string CipherList = "rsa_aes_128_sha,ecdhe_rsa_aes_256_sha,ecdhe_ecdsa_aes_128_sha";
|
||||
}
|
||||
}
|
|
@ -24,7 +24,7 @@ namespace Jackett.Console
|
|||
[Option('t', "Tracing", HelpText = "Enable tracing")]
|
||||
public bool Tracing { get; set; }
|
||||
|
||||
[Option('c', "UseClient", HelpText = "Override web client selection. Automatic(Default)/libcurl/safecurl/httpclient ")]
|
||||
[Option('c', "UseClient", HelpText = "Override web client selection. [automatic(Default)/libcurl/safecurl/httpclient]")]
|
||||
public string Client { get; set; }
|
||||
|
||||
[Option('s', "Start", HelpText = "Start the Jacket Windows service (Must be admin)")]
|
||||
|
@ -33,7 +33,7 @@ namespace Jackett.Console
|
|||
[Option('k', "Stop", HelpText = "Stop the Jacket Windows service (Must be admin)")]
|
||||
public bool StopService { get; set; }
|
||||
|
||||
[Option('x', "ListenPublic", HelpText = "Listen publicly")]
|
||||
[Option('x', "ListenPublic", HelpText = "Listen publicly [true/false]")]
|
||||
public bool? ListenPublic { get; set; }
|
||||
|
||||
[Option('h', "Help", HelpText = "Show Help")]
|
||||
|
@ -47,5 +47,8 @@ namespace Jackett.Console
|
|||
|
||||
[Option('m', "MigrateSettings", HelpText = "Migrate settings manually (Must be admin on Windows)")]
|
||||
public bool MigrateSettings { get; set; }
|
||||
|
||||
[Option('f', "SSLFix", HelpText = "Linux Libcurl NSS Missing ECC Ciphers workaround (Use if you can't access some trackers) [true/false].")]
|
||||
public bool? SSLFix { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,11 +35,11 @@ namespace JackettConsole
|
|||
}
|
||||
else
|
||||
{
|
||||
|
||||
|
||||
|
||||
/* ====== Options ===== */
|
||||
|
||||
// SSL Fix
|
||||
Startup.DoSSLFix = options.SSLFix;
|
||||
|
||||
// Use curl
|
||||
if (options.Client!=null)
|
||||
Startup.ClientOverride = options.Client.ToLowerInvariant();
|
||||
|
@ -60,6 +60,10 @@ namespace JackettConsole
|
|||
if (options.Tracing)
|
||||
Engine.Logger.Info("Tracing enabled.");
|
||||
|
||||
if (options.SSLFix == true)
|
||||
Engine.Logger.Info("SSL ECC workaround enabled.");
|
||||
else if (options.SSLFix == false)
|
||||
Engine.Logger.Info("SSL ECC workaround has been disabled.");
|
||||
/* ====== Actions ===== */
|
||||
|
||||
// Install service
|
||||
|
|
|
@ -5,6 +5,7 @@ using Jackett.Services;
|
|||
using Jackett.Utils;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NLog;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
@ -34,8 +35,9 @@ namespace Jackett.Controllers
|
|||
private ISecuityService securityService;
|
||||
private IProcessService processService;
|
||||
private ICacheService cacheService;
|
||||
private Logger logger;
|
||||
|
||||
public AdminController(IConfigurationService config, IIndexerManagerService i, IServerService ss, ISecuityService s, IProcessService p, ICacheService c)
|
||||
public AdminController(IConfigurationService config, IIndexerManagerService i, IServerService ss, ISecuityService s, IProcessService p, ICacheService c, Logger l)
|
||||
{
|
||||
this.config = config;
|
||||
indexerService = i;
|
||||
|
@ -43,6 +45,7 @@ namespace Jackett.Controllers
|
|||
securityService = s;
|
||||
processService = p;
|
||||
cacheService = c;
|
||||
logger = l;
|
||||
}
|
||||
|
||||
private async Task<JToken> ReadPostDataJson()
|
||||
|
@ -130,6 +133,7 @@ namespace Jackett.Controllers
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Error(ex, "Exception in SetAdminPassword");
|
||||
jsonReply["result"] = "error";
|
||||
jsonReply["error"] = ex.Message;
|
||||
}
|
||||
|
@ -153,6 +157,7 @@ namespace Jackett.Controllers
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Error(ex, "Exception in GetConfigForm");
|
||||
jsonReply["result"] = "error";
|
||||
jsonReply["error"] = ex.Message;
|
||||
}
|
||||
|
@ -185,6 +190,9 @@ namespace Jackett.Controllers
|
|||
if (ex is ExceptionWithConfigData)
|
||||
{
|
||||
jsonReply["config"] = ((ExceptionWithConfigData)ex).ConfigData.ToJson();
|
||||
} else
|
||||
{
|
||||
logger.Error(ex, "Exception in Configure");
|
||||
}
|
||||
}
|
||||
return Json(jsonReply);
|
||||
|
@ -214,6 +222,7 @@ namespace Jackett.Controllers
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Error(ex, "Exception in get_indexers");
|
||||
jsonReply["result"] = "error";
|
||||
jsonReply["error"] = ex.Message;
|
||||
}
|
||||
|
@ -235,6 +244,7 @@ namespace Jackett.Controllers
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Error(ex, "Exception in test_indexer");
|
||||
jsonReply["result"] = "error";
|
||||
jsonReply["error"] = ex.Message;
|
||||
}
|
||||
|
@ -254,6 +264,7 @@ namespace Jackett.Controllers
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Error(ex, "Exception in delete_indexer");
|
||||
jsonReply["result"] = "error";
|
||||
jsonReply["error"] = ex.Message;
|
||||
}
|
||||
|
@ -276,14 +287,9 @@ namespace Jackett.Controllers
|
|||
jsonReply["config"] = cfg;
|
||||
jsonReply["app_version"] = config.GetVersion();
|
||||
jsonReply["result"] = "success";
|
||||
}
|
||||
catch (CustomException ex)
|
||||
{
|
||||
jsonReply["result"] = "error";
|
||||
jsonReply["error"] = ex.Message;
|
||||
}
|
||||
catch (Exception ex)
|
||||
}catch (Exception ex)
|
||||
{
|
||||
logger.Error(ex, "Exception in get_jackett_config");
|
||||
jsonReply["result"] = "error";
|
||||
jsonReply["error"] = ex.Message;
|
||||
}
|
||||
|
@ -357,6 +363,7 @@ namespace Jackett.Controllers
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Error(ex, "Exception in set_port");
|
||||
jsonReply["result"] = "error";
|
||||
jsonReply["error"] = ex.Message;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ using System.Threading.Tasks;
|
|||
using System.Net.Http.Headers;
|
||||
using Jackett.Utils;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
|
||||
namespace Jackett
|
||||
{
|
||||
|
@ -18,15 +19,10 @@ namespace Jackett
|
|||
|
||||
public class CurlRequest
|
||||
{
|
||||
|
||||
public string Url { get; private set; }
|
||||
|
||||
public string Cookies { get; private set; }
|
||||
|
||||
public string Referer { get; private set; }
|
||||
|
||||
public HttpMethod Method { get; private set; }
|
||||
|
||||
public Dictionary<string, string> PostData { get; set; }
|
||||
|
||||
public CurlRequest(HttpMethod method, string url, string cookies = null, string referer = null)
|
||||
|
@ -40,49 +36,17 @@ namespace Jackett
|
|||
|
||||
public class CurlResponse
|
||||
{
|
||||
public Dictionary<string, string> Headers { get; private set; }
|
||||
public List<string[]> HeaderList { get; private set; }
|
||||
public byte[] Content { get; private set; }
|
||||
public HttpStatusCode Status { get; private set;}
|
||||
public Dictionary<string, string> Cookies { get; private set; }
|
||||
public List<string> CookiesFlat { get { return Cookies.Select(c => c.Key + "=" + c.Value).ToList(); } }
|
||||
public string CookieHeader { get { return string.Join("; ", CookiesFlat); } }
|
||||
public string Cookies { set; get; }
|
||||
|
||||
public CurlResponse(List<string[]> headers, byte[] content, HttpStatusCode s)
|
||||
public CurlResponse(List<string[]> headers, byte[] content, HttpStatusCode s, string cookies)
|
||||
{
|
||||
Headers = new Dictionary<string, string>();
|
||||
Cookies = new Dictionary<string, string>();
|
||||
HeaderList = headers;
|
||||
Content = content;
|
||||
Status = s;
|
||||
foreach (var h in headers)
|
||||
{
|
||||
Headers[h[0]] = h[1];
|
||||
}
|
||||
}
|
||||
|
||||
public void AddCookiesFromHeaderValue(string cookieHeaderValue)
|
||||
{
|
||||
var rawCookies = cookieHeaderValue.Split(';');
|
||||
foreach (var rawCookie in rawCookies)
|
||||
{
|
||||
var parts = rawCookie.Split(new char[] { '=' }, 2, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (parts.Length == 1)
|
||||
Cookies[rawCookie.Trim()] = string.Empty;
|
||||
else
|
||||
Cookies[parts[0].Trim()] = parts[1].Trim();
|
||||
}
|
||||
}
|
||||
|
||||
public void AddCookiesFromHeaders(List<string[]> headers)
|
||||
{
|
||||
foreach (var h in headers)
|
||||
{
|
||||
if (h[0] == "set-cookie")
|
||||
{
|
||||
AddCookiesFromHeaderValue(h[1]);
|
||||
}
|
||||
}
|
||||
Cookies = cookies;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,36 +65,14 @@ namespace Jackett
|
|||
return result;
|
||||
}
|
||||
|
||||
private static async Task<CurlResponse> FollowRedirect(string url, CurlResponse response)
|
||||
{
|
||||
var uri = new Uri(url);
|
||||
string redirect;
|
||||
if (response.Headers.TryGetValue("location", out redirect))
|
||||
{
|
||||
string cookie = response.CookieHeader;
|
||||
if (!redirect.StartsWith("http://") && !redirect.StartsWith("https://"))
|
||||
{
|
||||
if (redirect.StartsWith("/"))
|
||||
redirect = string.Format("{0}://{1}{2}", uri.Scheme, uri.Host, redirect);
|
||||
else
|
||||
redirect = string.Format("{0}://{1}/{2}", uri.Scheme, uri.Host, redirect);
|
||||
}
|
||||
var newRedirect = await GetAsync(redirect, cookie);
|
||||
foreach (var c in response.Cookies)
|
||||
newRedirect.Cookies[c.Key] = c.Value;
|
||||
newRedirect.AddCookiesFromHeaders(response.HeaderList);
|
||||
return newRedirect;
|
||||
}
|
||||
else
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
public static async Task<CurlResponse> PerformCurlAsync(CurlRequest curlRequest)
|
||||
{
|
||||
return await Task.Run(() => PerformCurl(curlRequest));
|
||||
}
|
||||
|
||||
public delegate void ErrorMessage(string s);
|
||||
public static ErrorMessage OnErrorMessage;
|
||||
|
||||
public static CurlResponse PerformCurl(CurlRequest curlRequest)
|
||||
{
|
||||
lock (instance)
|
||||
|
@ -145,11 +87,13 @@ namespace Jackett
|
|||
easy.UserAgent = BrowserUtil.ChromeUserAgent;
|
||||
easy.FollowLocation = false;
|
||||
easy.ConnectTimeout = 20;
|
||||
|
||||
easy.WriteFunction = (byte[] buf, int size, int nmemb, object data) =>
|
||||
{
|
||||
contentBuffers.Add(buf);
|
||||
return size * nmemb;
|
||||
};
|
||||
|
||||
easy.HeaderFunction = (byte[] buf, int size, int nmemb, object extraData) =>
|
||||
{
|
||||
headerBuffers.Add(buf);
|
||||
|
@ -170,7 +114,25 @@ namespace Jackett
|
|||
easy.PostFieldSize = Encoding.UTF8.GetByteCount(postString);
|
||||
}
|
||||
|
||||
if (Startup.DoSSLFix == true)
|
||||
{
|
||||
// http://stackoverflow.com/questions/31107851/how-to-fix-curl-35-cannot-communicate-securely-with-peer-no-common-encryptio
|
||||
// https://git.fedorahosted.org/cgit/mod_nss.git/plain/docs/mod_nss.html
|
||||
easy.SslCipherList = SSLFix.CipherList;
|
||||
easy.FreshConnect = true;
|
||||
easy.ForbidReuse = true;
|
||||
}
|
||||
|
||||
easy.Perform();
|
||||
|
||||
if(easy.LastErrorCode != CurlCode.Ok)
|
||||
{
|
||||
var message = "Error " + easy.LastErrorCode.ToString() + " " + easy.LastErrorDescription;
|
||||
if (null != OnErrorMessage)
|
||||
OnErrorMessage(message);
|
||||
else
|
||||
Console.WriteLine(message);
|
||||
}
|
||||
}
|
||||
|
||||
var headerBytes = Combine(headerBuffers.ToArray());
|
||||
|
@ -179,10 +141,14 @@ namespace Jackett
|
|||
var headers = new List<string[]>();
|
||||
var headerCount = 0;
|
||||
HttpStatusCode status = HttpStatusCode.InternalServerError;
|
||||
var cookieBuilder = new StringBuilder();
|
||||
foreach (var headerPart in headerParts)
|
||||
{
|
||||
if (headerCount == 0)
|
||||
{
|
||||
var split = headerPart.Split(' ');
|
||||
if (split.Length < 2)
|
||||
throw new Exception("HTTP Header missing");
|
||||
var responseCode = int.Parse(headerPart.Split(' ')[1]);
|
||||
status = (HttpStatusCode)responseCode;
|
||||
}
|
||||
|
@ -191,7 +157,17 @@ namespace Jackett
|
|||
var keyVal = headerPart.Split(new char[] { ':' }, 2);
|
||||
if (keyVal.Length > 1)
|
||||
{
|
||||
headers.Add(new[] { keyVal[0].ToLower().Trim(), keyVal[1].Trim() });
|
||||
var key = keyVal[0].ToLower().Trim();
|
||||
var value = keyVal[1].Trim();
|
||||
|
||||
if (key == "set-cookie")
|
||||
{
|
||||
cookieBuilder.AppendFormat("{0} ", value.Substring(0, value.IndexOf(';') + 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
headers.Add(new[] { key, value });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,12 +175,7 @@ namespace Jackett
|
|||
}
|
||||
|
||||
var contentBytes = Combine(contentBuffers.ToArray());
|
||||
|
||||
var curlResponse = new CurlResponse(headers, contentBytes, status);
|
||||
if (!string.IsNullOrEmpty(curlRequest.Cookies))
|
||||
curlResponse.AddCookiesFromHeaderValue(curlRequest.Cookies);
|
||||
curlResponse.AddCookiesFromHeaders(headers);
|
||||
|
||||
var curlResponse = new CurlResponse(headers, contentBytes, status, cookieBuilder.ToString().TrimEnd());
|
||||
return curlResponse;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -119,7 +119,7 @@ namespace Jackett
|
|||
logFile.FileName = Path.Combine(ConfigurationService.GetAppDataFolderStatic(), "log.txt");
|
||||
logFile.ArchiveFileName = "log.{#####}.txt";
|
||||
logFile.ArchiveAboveSize = 500000;
|
||||
logFile.MaxArchiveFiles = 1;
|
||||
logFile.MaxArchiveFiles = 5;
|
||||
logFile.KeepFileOpen = false;
|
||||
logFile.ArchiveNumbering = ArchiveNumberingMode.DateAndSequence;
|
||||
var logFileRule = new LoggingRule("*", logLevel, logFile);
|
||||
|
|
|
@ -18,11 +18,4 @@ namespace Jackett
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
public class CustomException : Exception
|
||||
{
|
||||
public CustomException(string message)
|
||||
: base(message)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,8 +47,10 @@ namespace Jackett.Indexers
|
|||
{ "submit", "come on in" }
|
||||
};
|
||||
|
||||
var result = await RequestLoginAndFollowRedirect(LoginUrl, pairs, null, true, SiteLink, LoginUrl);
|
||||
ConfigureIfOK(result.Cookies, result.Content != null && result.Content.Contains("nav_profile"), () =>
|
||||
var loginPage = await RequestStringWithCookies(LoginUrl, string.Empty);
|
||||
|
||||
var result = await RequestLoginAndFollowRedirect(LoginUrl, pairs, loginPage.Cookies, true, SiteLink, LoginUrl);
|
||||
ConfigureIfOK(result.Cookies + " " + loginPage.Cookies, result.Content != null && result.Content.Contains("nav_profile"), () =>
|
||||
{
|
||||
CQ dom = result.Content;
|
||||
var messageEl = dom["#login_box_desc"];
|
||||
|
|
|
@ -120,15 +120,12 @@ namespace Jackett.Indexers
|
|||
// 15 results per page - really don't want to call the server twice but only 15 results per page is a bit crap!
|
||||
await ProcessPage(releases, searchUrl);
|
||||
await ProcessPage(releases, searchUrl + "&page=1");
|
||||
|
||||
return releases;
|
||||
}
|
||||
|
||||
private async Task ProcessPage(List<ReleaseInfo> releases, string searchUrl)
|
||||
{
|
||||
|
||||
var response = await RequestStringWithCookiesAndRetry(searchUrl, null, BrowseUrl);
|
||||
|
||||
var results = response.Content;
|
||||
try
|
||||
{
|
||||
|
|
|
@ -40,6 +40,12 @@ namespace Jackett
|
|||
set;
|
||||
}
|
||||
|
||||
public static bool? DoSSLFix
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public void Configuration(IAppBuilder appBuilder)
|
||||
{
|
||||
// Configure Web API for self-host.
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace Jackett.Utils.Clients
|
|||
{
|
||||
logger.Debug(string.Format("WindowsWebClient:GetBytes(Url:{0})", request.Url));
|
||||
var result = await Run(request);
|
||||
logger.Debug(string.Format("WindowsWebClient: Returning", result.Status));
|
||||
logger.Debug(string.Format("WindowsWebClient: Returning {0} => {1} bytes", result.Status, (result.Content == null ? "<NULL>" : result.Content.Length.ToString())));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ namespace Jackett.Utils.Clients
|
|||
{
|
||||
logger.Debug(string.Format("WindowsWebClient:GetString(Url:{0})", request.Url));
|
||||
var result = await Run(request);
|
||||
logger.Debug(string.Format("WindowsWebClient: Returning", result.Status));
|
||||
logger.Debug(string.Format("WindowsWebClient: Returning {0} => {1}", result.Status, (result.Content == null ? "<NULL>" : Encoding.UTF8.GetString(result.Content))));
|
||||
return Mapper.Map<WebClientStringResult>(result);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace Jackett.Utils.Clients
|
|||
{
|
||||
logger.Debug(string.Format("UnixLibCurlWebClient:GetBytes(Url:{0})", request.Url));
|
||||
var result = await Run(request);
|
||||
logger.Debug(string.Format("UnixLibCurlWebClient: Returning", result.Status));
|
||||
logger.Debug(string.Format("UnixLibCurlWebClient:GetBytes Returning {0} => {1} bytes", result.Status, (result.Content==null?"<NULL>":result.Content.Length.ToString())));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -35,14 +35,35 @@ namespace Jackett.Utils.Clients
|
|||
{
|
||||
logger.Debug(string.Format("UnixLibCurlWebClient:GetString(Url:{0})", request.Url));
|
||||
var result = await Run(request);
|
||||
logger.Debug(string.Format("UnixLibCurlWebClient: Returning", result.Status));
|
||||
logger.Debug(string.Format("UnixLibCurlWebClient:GetString Returning {0} => {1}", result.Status, (result.Content== null?"<NULL>": Encoding.UTF8.GetString(result.Content))));
|
||||
return Mapper.Map<WebClientStringResult>(result);
|
||||
}
|
||||
|
||||
public void Init()
|
||||
{
|
||||
Engine.Logger.Info("LibCurl init " + Curl.GlobalInit(CurlInitFlag.All).ToString());
|
||||
Engine.Logger.Info("LibCurl version " + Curl.Version);
|
||||
try {
|
||||
Engine.Logger.Info("LibCurl init " + Curl.GlobalInit(CurlInitFlag.All).ToString());
|
||||
CurlHelper.OnErrorMessage += (msg) =>
|
||||
{
|
||||
Engine.Logger.Error(msg);
|
||||
};
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Engine.Logger.Warn("Libcurl failed to initalize. Did you install it?");
|
||||
Engine.Logger.Warn("Debian: apt-get install libcurl4-openssl-dev");
|
||||
Engine.Logger.Warn("Redhat: yum install libcurl-devel");
|
||||
throw e;
|
||||
}
|
||||
|
||||
var version = Curl.Version;
|
||||
Engine.Logger.Info("LibCurl version " + version);
|
||||
|
||||
if (!Startup.DoSSLFix.HasValue && version.IndexOf("NSS")>-1)
|
||||
{
|
||||
Engine.Logger.Info("NSS Detected SSL ECC workaround enabled.");
|
||||
Startup.DoSSLFix = true;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<WebClientByteResult> Run(WebRequest request)
|
||||
|
@ -54,23 +75,30 @@ namespace Jackett.Utils.Clients
|
|||
}
|
||||
else
|
||||
{
|
||||
if (request.PostData != null && request.PostData.Count > 0)
|
||||
{
|
||||
logger.Debug("UnixLibCurlWebClient: Posting " + new FormUrlEncodedContent(request.PostData).ReadAsStringAsync().Result);
|
||||
}
|
||||
|
||||
response = await CurlHelper.PostAsync(request.Url, request.PostData, request.Cookies, request.Referer);
|
||||
}
|
||||
|
||||
var result = new WebClientByteResult()
|
||||
{
|
||||
Content = response.Content,
|
||||
Cookies = response.CookieHeader,
|
||||
Cookies = response.Cookies,
|
||||
Status = response.Status
|
||||
};
|
||||
|
||||
if (response.Headers != null)
|
||||
if (response.HeaderList != null)
|
||||
{
|
||||
foreach (var header in response.Headers)
|
||||
foreach (var header in response.HeaderList)
|
||||
{
|
||||
if (string.Equals(header.Key, "location", StringComparison.InvariantCultureIgnoreCase) && header.Value != null)
|
||||
switch (header[0].ToLowerInvariant())
|
||||
{
|
||||
result.RedirectingTo = header.Value;
|
||||
case "location":
|
||||
result.RedirectingTo = header[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using AutoMapper;
|
||||
using CurlSharp;
|
||||
using Jackett.Models;
|
||||
using Jackett.Services;
|
||||
using NLog;
|
||||
|
@ -32,7 +33,7 @@ namespace Jackett.Utils.Clients
|
|||
{
|
||||
logger.Debug(string.Format("UnixSafeCurlWebClient:GetBytes(Url:{0})", request.Url));
|
||||
var result = await Run(request);
|
||||
logger.Debug(string.Format("UnixSafeCurlWebClient: Returning", result.Status));
|
||||
logger.Debug(string.Format("UnixSafeCurlWebClient: Returning {0} => {1} bytes", result.Status, (result.Content == null ? "<NULL>" : result.Content.Length.ToString())));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -40,7 +41,7 @@ namespace Jackett.Utils.Clients
|
|||
{
|
||||
logger.Debug(string.Format("UnixSafeCurlWebClient:GetString(Url:{0})", request.Url));
|
||||
var result = await Run(request);
|
||||
logger.Debug(string.Format("UnixSafeCurlWebClient: Returning", result.Status));
|
||||
logger.Debug(string.Format("UnixSafeCurlWebClient: Returning {0} => {1}", result.Status, (result.Content == null ? "<NULL>" : Encoding.UTF8.GetString(result.Content))));
|
||||
return Mapper.Map<WebClientStringResult>(result);
|
||||
}
|
||||
|
||||
|
@ -69,6 +70,13 @@ namespace Jackett.Utils.Clients
|
|||
var tempFile = Path.GetTempFileName();
|
||||
args.AppendFormat("--output \"{0}\" ", tempFile);
|
||||
|
||||
if (Startup.DoSSLFix == true)
|
||||
{
|
||||
// http://stackoverflow.com/questions/31107851/how-to-fix-curl-35-cannot-communicate-securely-with-peer-no-common-encryptio
|
||||
// https://git.fedorahosted.org/cgit/mod_nss.git/plain/docs/mod_nss.html
|
||||
args.Append("--cipher " + SSLFix.CipherList);
|
||||
}
|
||||
|
||||
string stdout = null;
|
||||
await Task.Run(() =>
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue