mirror of https://github.com/Jackett/Jackett
MoreThanTv now working on mono with libcurl
This commit is contained in:
parent
0530bed226
commit
bf3759020a
|
@ -0,0 +1,239 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Called when cURL has debug information for the client.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// For usage, see the sample <c>Upload.cs</c>.
|
||||
/// Arguments passed to the recipient include:
|
||||
/// <list type="table">
|
||||
/// <listheader>
|
||||
/// <term>Argument</term>
|
||||
/// <description>Description</description>
|
||||
/// </listheader>
|
||||
/// <item>
|
||||
/// <term>infoType</term>
|
||||
/// <description>
|
||||
/// Type of debug information, see
|
||||
/// <see cref="CurlInfoType" />.
|
||||
/// </description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>message</term>
|
||||
/// <description>Debug information as a string.</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>extraData</term>
|
||||
/// <description>Client-provided extra data.</description>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// </remarks>
|
||||
public delegate void CurlDebugCallback(CurlInfoType infoType, String message, Object extraData);
|
||||
|
||||
/// <summary>
|
||||
/// Called when cURL has header data for the client.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// For usage, see the sample <c>Headers.cs</c>.
|
||||
/// Arguments passed to the recipient include:
|
||||
/// <list type="table">
|
||||
/// <listheader>
|
||||
/// <term>Argument</term>
|
||||
/// <description>Description</description>
|
||||
/// </listheader>
|
||||
/// <item>
|
||||
/// <term>buf</term>
|
||||
/// <description>Header data from cURL to the client.</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>size</term>
|
||||
/// <description>Size of a character, in bytes.</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>nmemb</term>
|
||||
/// <description>Number of characters.</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>extraData</term>
|
||||
/// <description>Client-provided extra data.</description>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// Your implementation should return the number of bytes (not
|
||||
/// characters) processed. Usually this is <c>size * nmemb</c>.
|
||||
/// Return -1 to abort the transfer.
|
||||
/// </remarks>
|
||||
public delegate int CurlHeaderCallback(byte[] buf, int size, int nmemb, Object extraData);
|
||||
|
||||
/// <summary>
|
||||
/// Called when cURL needs for the client to perform an
|
||||
/// IOCTL operation. An example might be when an FTP
|
||||
/// upload requires rewinding of the input file to deal
|
||||
/// with a resend occasioned by an error.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <list type="table">
|
||||
/// <listheader>
|
||||
/// <term>Argument</term>
|
||||
/// <description>Description</description>
|
||||
/// </listheader>
|
||||
/// <item>
|
||||
/// <term>cmd</term>
|
||||
/// <description>
|
||||
/// A <see cref="CurlIoCommand" />; for now, only
|
||||
/// <c>RestartRead</c> should be passed.
|
||||
/// </description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>extraData</term>
|
||||
/// <description>
|
||||
/// Client-provided extra data; in the
|
||||
/// case of an FTP upload, it might be a
|
||||
/// <c>FileStream</c> object.
|
||||
/// </description>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// Your implementation should return a <see cref="CurlIoError" />,
|
||||
/// which should be <see cref="CurlIoError.Ok" /> if everything
|
||||
/// is okay.
|
||||
/// </remarks>
|
||||
public delegate CurlIoError CurlIoctlCallback(CurlIoCommand cmd, Object extraData);
|
||||
|
||||
/// <summary>
|
||||
/// Called when cURL wants to report progress.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// For usage, see the sample <c>Upload.cs</c>.
|
||||
/// Arguments passed to the recipient include:
|
||||
/// <list type="table">
|
||||
/// <listheader>
|
||||
/// <term>Argument</term>
|
||||
/// <description>Description</description>
|
||||
/// </listheader>
|
||||
/// <item>
|
||||
/// <term>extraData</term>
|
||||
/// <description>Client-provided extra data.</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>dlTotal</term>
|
||||
/// <description>Number of bytes to download.</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>dlNow</term>
|
||||
/// <description>Number of bytes downloaded so far.</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>ulTotal</term>
|
||||
/// <description>Number of bytes to upload.</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>ulNow</term>
|
||||
/// <description>Number of bytes uploaded so far.</description>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// Your implementation should return 0 to continue, or a non-zero
|
||||
/// value to abort the transfer.
|
||||
/// </remarks>
|
||||
public delegate int CurlProgressCallback(Object extraData, double dlTotal, double dlNow,
|
||||
double ulTotal, double ulNow);
|
||||
|
||||
/// <summary>
|
||||
/// Called when cURL wants to read data from the client.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// For usage, see the sample <c>Upload.cs</c>.
|
||||
/// Arguments passed to the recipient include:
|
||||
/// <list type="table">
|
||||
/// <listheader>
|
||||
/// <term>Argument</term>
|
||||
/// <description>Description</description>
|
||||
/// </listheader>
|
||||
/// <item>
|
||||
/// <term>buf</term>
|
||||
/// <description>
|
||||
/// Buffer into which your client should write data
|
||||
/// for cURL.
|
||||
/// </description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>size</term>
|
||||
/// <description>Size of a character, usually 1.</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>nmemb</term>
|
||||
/// <description>Number of characters.</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>extraData</term>
|
||||
/// <description>Client-provided extra data.</description>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// Your implementation should return the number of bytes (not
|
||||
/// characters) written to <c>buf</c>. Return 0 to abort the transfer.
|
||||
/// </remarks>
|
||||
public delegate int CurlReadCallback([Out] byte[] buf, int size, int nmemb, Object extraData);
|
||||
|
||||
/// <summary>
|
||||
/// Called when cURL wants to report an Ssl event.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// For usage, see the sample <c>SSLGet.cs</c>.
|
||||
/// Arguments passed to the recipient include:
|
||||
/// <list type="table">
|
||||
/// <listheader>
|
||||
/// <term>Argument</term>
|
||||
/// <description>Description</description>
|
||||
/// </listheader>
|
||||
/// <item>
|
||||
/// <term>ctx</term>
|
||||
/// <description>
|
||||
/// An <see cref="CurlSslContext" /> object that wraps an
|
||||
/// OpenSSL <c>SSL_CTX</c> pointer.
|
||||
/// </description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>extraData</term>
|
||||
/// <description>Client-provided extra data.</description>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// Your implementation should return a <see cref="CurlCode" />,
|
||||
/// which should be <see cref="CurlCode.Ok" /> if everything
|
||||
/// is okay.
|
||||
/// </remarks>
|
||||
public delegate CurlCode CurlSslContextCallback(CurlSslContext ctx, Object extraData);
|
||||
|
||||
/// <summary>
|
||||
/// Called when cURL has data for the client.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// For usage, see the example <c>EasyGet.cs</c>.
|
||||
/// Arguments passed to the delegate implementation include:
|
||||
/// <list type="table">
|
||||
/// <listheader>
|
||||
/// <term>Argument</term>
|
||||
/// <description>Description</description>
|
||||
/// </listheader>
|
||||
/// <item>
|
||||
/// <term>buf</term>
|
||||
/// <description>Data cURL is providing to the client.</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>size</term>
|
||||
/// <description>Size of a character, usually 1.</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>nmemb</term>
|
||||
/// <description>Number of characters.</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>extraData</term>
|
||||
/// <description>Client-provided extra data.</description>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// Your implementation should return the number of bytes (not
|
||||
/// characters) processed. Return 0 to abort the transfer.
|
||||
/// </remarks>
|
||||
public delegate int CurlWriteCallback(byte[] buf, int size, int nmemb, Object extraData);
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
using System;
|
||||
|
||||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Called when <c>cURL</c> wants to lock a shared resource.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// For a usage example, refer to the <c>ShareDemo.cs</c> sample.
|
||||
/// Arguments passed to your delegate implementation include:
|
||||
/// <list type="table">
|
||||
/// <listheader>
|
||||
/// <term>Argument</term>
|
||||
/// <term>Description</term>
|
||||
/// </listheader>
|
||||
/// <item>
|
||||
/// <term>data</term>
|
||||
/// <term>
|
||||
/// Type of data to lock; one of the values in the
|
||||
/// <see cref="CurlLockData" /> enumeration.
|
||||
/// </term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>access</term>
|
||||
/// <term>
|
||||
/// Lock access requested; one of the values in the
|
||||
/// <see cref="CurlLockAccess" /> enumeration.
|
||||
/// </term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>userData</term>
|
||||
/// <term>
|
||||
/// Client-provided data that is not touched internally by
|
||||
/// <c>cURL</c>. This is set via
|
||||
/// <see cref="CurlShareOption.UserData" /> when calling the
|
||||
/// <see cref="CurlShare.SetOpt" /> member of the <see cref="CurlShare" />
|
||||
/// class.
|
||||
/// </term>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// </remarks>
|
||||
public delegate void CurlShareLockCallback(CurlLockData data, CurlLockAccess access, Object userData);
|
||||
|
||||
/// <summary>
|
||||
/// Called when <c>cURL</c> wants to unlock a shared resource.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// For a usage example, refer to the <c>ShareDemo.cs</c> sample.
|
||||
/// Arguments passed to your delegate implementation include:
|
||||
/// <list type="table">
|
||||
/// <listheader>
|
||||
/// <term>Argument</term>
|
||||
/// <term>Description</term>
|
||||
/// </listheader>
|
||||
/// <item>
|
||||
/// <term>data</term>
|
||||
/// <term>
|
||||
/// Type of data to unlock; one of the values in the
|
||||
/// <see cref="CurlLockData" /> enumeration.
|
||||
/// </term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>userData</term>
|
||||
/// <term>
|
||||
/// Client-provided data that is not touched internally by
|
||||
/// <c>cURL</c>. This is set via
|
||||
/// <see cref="CurlShareOption.UserData" /> when calling the
|
||||
/// <see cref="CurlShare.SetOpt" /> member of the <see cref="CurlShare" />
|
||||
/// class.
|
||||
/// </term>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// </remarks>
|
||||
public delegate void CurlShareUnlockCallback(CurlLockData data, Object userData);
|
||||
}
|
|
@ -0,0 +1,170 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* CurlS#arp
|
||||
*
|
||||
* Copyright (c) 2013 Dr. Masroor Ehsan (masroore@gmail.com)
|
||||
* Portions copyright (c) 2004, 2005 Jeff Phillips (jeff@jeffp.net)
|
||||
*
|
||||
* This software is licensed as described in the file LICENSE, which you
|
||||
* should have received as part of this distribution.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of this Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the LICENSE file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
|
||||
* ANY KIND, either express or implied.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Top-level class for initialization and cleanup.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// It also implements static methods for capabilities that don't
|
||||
/// logically belong in a class.
|
||||
/// </remarks>
|
||||
public static class Curl
|
||||
{
|
||||
// for state management
|
||||
private static CurlCode _initCode;
|
||||
|
||||
/// <summary>
|
||||
/// Class constructor - initialize global status.
|
||||
/// </summary>
|
||||
static Curl()
|
||||
{
|
||||
_initCode = CurlCode.FailedInit;
|
||||
}
|
||||
|
||||
// hidden instance stuff
|
||||
|
||||
/// <summary>
|
||||
/// Get the underlying cURL version as a string, example "7.12.2".
|
||||
/// </summary>
|
||||
/// <exception cref="System.InvalidOperationException">
|
||||
/// Thrown if cURL isn't properly initialized.
|
||||
/// </exception>
|
||||
public static string Version
|
||||
{
|
||||
get
|
||||
{
|
||||
EnsureCurl();
|
||||
return Marshal.PtrToStringAnsi(NativeMethods.curl_version());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process-wide initialization -- call only once per process.
|
||||
/// </summary>
|
||||
/// <param name="flags">
|
||||
/// An or'd combination of
|
||||
/// <see cref="CurlInitFlag" /> members.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="CurlCode" />, hopefully
|
||||
/// <c>CurlCode.Ok</c>.
|
||||
/// </returns>
|
||||
public static CurlCode GlobalInit(CurlInitFlag flags)
|
||||
{
|
||||
_initCode = NativeMethods.curl_global_init((int)flags);
|
||||
#if USE_LIBCURLSHIM
|
||||
if (_initCode == CurlCode.Ok)
|
||||
NativeMethods.curl_shim_initialize();
|
||||
#endif
|
||||
return _initCode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process-wide cleanup -- call just before exiting process.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// While it's not necessary that your program call this method
|
||||
/// before exiting, doing so will prevent leaks of native cURL resources.
|
||||
/// </remarks>
|
||||
public static void GlobalCleanup()
|
||||
{
|
||||
if (_initCode == CurlCode.Ok)
|
||||
{
|
||||
#if USE_LIBCURLSHIM
|
||||
NativeMethods.curl_shim_cleanup();
|
||||
#endif
|
||||
NativeMethods.curl_global_cleanup();
|
||||
_initCode = CurlCode.FailedInit;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// URL encode a String.
|
||||
/// </summary>
|
||||
/// <param name="url">The string to URL encode.</param>
|
||||
/// <param name="length">
|
||||
/// Input string length;
|
||||
/// use 0 for cURL to determine.
|
||||
/// </param>
|
||||
/// <returns>A new URL encoded string.</returns>
|
||||
/// <exception cref="System.InvalidOperationException">
|
||||
/// Thrown if cURL isn't properly initialized.
|
||||
/// </exception>
|
||||
public static string Escape(string url, int length)
|
||||
{
|
||||
EnsureCurl();
|
||||
var p = NativeMethods.curl_escape(url, length);
|
||||
var s = Marshal.PtrToStringAnsi(p);
|
||||
NativeMethods.curl_free(p);
|
||||
return s;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// URL decode a String.
|
||||
/// </summary>
|
||||
/// <param name="url">The string to URL decode.</param>
|
||||
/// <param name="length">
|
||||
/// Input string length;
|
||||
/// use 0 for cURL to determine.
|
||||
/// </param>
|
||||
/// <returns>A new URL decoded string.</returns>
|
||||
/// <exception cref="System.InvalidOperationException">
|
||||
/// Thrown if cURL isn't properly initialized.
|
||||
/// </exception>
|
||||
public static string Unescape(string url, int length)
|
||||
{
|
||||
EnsureCurl();
|
||||
var p = NativeMethods.curl_unescape(url, length);
|
||||
var s = Marshal.PtrToStringAnsi(p);
|
||||
NativeMethods.curl_free(p);
|
||||
return s;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a <see cref="CurlVersionInfoData" /> object.
|
||||
/// </summary>
|
||||
/// <param name="ver">
|
||||
/// Specify a <see cref="CurlVersion" />, such as
|
||||
/// <c>CurlVersion.Now</c>.
|
||||
/// </param>
|
||||
/// <returns>A <see cref="CurlVersionInfoData" /> object.</returns>
|
||||
/// <exception cref="System.InvalidOperationException">
|
||||
/// Thrown if cURL isn't properly initialized.
|
||||
/// </exception>
|
||||
public static CurlVersionInfoData GetVersionInfo(CurlVersion ver)
|
||||
{
|
||||
EnsureCurl();
|
||||
return new CurlVersionInfoData(ver);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by other classes to ensure valid cURL state.
|
||||
/// </summary>
|
||||
internal static void EnsureCurl()
|
||||
{
|
||||
if (_initCode != CurlCode.Ok)
|
||||
throw new InvalidOperationException("cURL not initialized");
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,388 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* CurlS#arp
|
||||
*
|
||||
* Copyright (c) 2014 Dr. Masroor Ehsan (masroore@gmail.com)
|
||||
* Portions copyright (c) 2004, 2005 Jeff Phillips (jeff@jeffp.net)
|
||||
*
|
||||
* This software is licensed as described in the file LICENSE, which you
|
||||
* should have received as part of this distribution.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of this Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the LICENSE file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
|
||||
* ANY KIND, either express or implied.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This trivial class wraps the internal <c>curl_forms</c> struct.
|
||||
/// </summary>
|
||||
public sealed class CurlForms
|
||||
{
|
||||
/// <summary>The <see cref="CurlFormOption" />.</summary>
|
||||
public CurlFormOption Option;
|
||||
|
||||
/// <summary>Value for the option.</summary>
|
||||
public Object Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps a section of multipart form data to be submitted via the
|
||||
/// <see cref="CurlOption.HttpPost" /> option in the
|
||||
/// <see cref="CurlEasy.SetOpt" /> member of the <see cref="CurlEasy" /> class.
|
||||
/// </summary>
|
||||
public class CurlHttpMultiPartForm : IDisposable
|
||||
{
|
||||
// the two curlform pointers
|
||||
private readonly IntPtr[] _pItems;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <exception cref="System.InvalidOperationException">
|
||||
/// This is thrown
|
||||
/// if <see cref="Curl" /> hasn't bee properly initialized.
|
||||
/// </exception>
|
||||
public CurlHttpMultiPartForm()
|
||||
{
|
||||
Curl.EnsureCurl();
|
||||
_pItems = new IntPtr[2];
|
||||
_pItems[0] = IntPtr.Zero;
|
||||
_pItems[1] = IntPtr.Zero;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Free unmanaged resources.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destructor
|
||||
/// </summary>
|
||||
~CurlHttpMultiPartForm()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
// for CurlEasy.SetOpt()
|
||||
internal IntPtr GetHandle()
|
||||
{
|
||||
return _pItems[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a multi-part form section.
|
||||
/// </summary>
|
||||
/// <param name="args">
|
||||
/// Argument list, as described in the remarks.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="CurlFormCode" />, hopefully
|
||||
/// <c>CurlFormCode.Ok</c>.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// This is definitely the workhorse method for this class. It
|
||||
/// should be called in roughly the same manner as
|
||||
/// <c>curl_formadd()</c>, except you would omit the first two
|
||||
/// <c>struct curl_httppost**</c> arguments (<c>firstitem</c> and
|
||||
/// <c>lastitem</c>), which are wrapped in this class. So you should
|
||||
/// pass arguments in the following sequence:
|
||||
/// <para>
|
||||
/// <c>
|
||||
/// CurlHttpMultiPartForm.AddSection(option1, value1, ..., optionX, valueX,
|
||||
/// CurlFormOption.End)
|
||||
/// </c>
|
||||
/// ;
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// For a complete list of possible options, see the documentation for
|
||||
/// the <see cref="CurlFormOption" /> enumeration.
|
||||
/// </para>
|
||||
/// <note>
|
||||
/// The pointer options (<c>PtrName</c>, etc.) make an
|
||||
/// internal copy of the passed <c>byte</c> array. Therefore, any
|
||||
/// changes you make to the client copy of this array AFTER calling
|
||||
/// this method, won't be reflected internally with <c>cURL</c>. The
|
||||
/// purpose of providing the pointer options is to support the
|
||||
/// posting of non-string binary data.
|
||||
/// </note>
|
||||
/// </remarks>
|
||||
public CurlFormCode AddSection(params object[] args)
|
||||
{
|
||||
var nCount = args.Length;
|
||||
var nRealCount = nCount;
|
||||
var retCode = CurlFormCode.Ok;
|
||||
CurlForms[] aForms = null;
|
||||
|
||||
// one arg or even number of args is an error
|
||||
if ((nCount == 1) || (nCount%2 == 0))
|
||||
return CurlFormCode.Incomplete;
|
||||
|
||||
// ensure the last argument is End
|
||||
var iCode = (CurlFormOption)
|
||||
Convert.ToInt32(args.GetValue(nCount - 1));
|
||||
if (iCode != CurlFormOption.End)
|
||||
return CurlFormCode.Incomplete;
|
||||
|
||||
// walk through any passed arrays to get the true number of
|
||||
// items and ensure the child arrays are properly (and not
|
||||
// prematurely) terminated with End
|
||||
for (var i = 0; i < nCount; i += 2)
|
||||
{
|
||||
iCode = (CurlFormOption) Convert.ToInt32(args.GetValue(i));
|
||||
switch (iCode)
|
||||
{
|
||||
case CurlFormOption.Array:
|
||||
{
|
||||
aForms = args.GetValue(i + 1) as CurlForms[];
|
||||
if (aForms == null)
|
||||
return CurlFormCode.Incomplete;
|
||||
var nFormsCount = aForms.Length;
|
||||
for (var j = 0; j < nFormsCount; j++)
|
||||
{
|
||||
var pcf = aForms.GetValue(j) as CurlForms;
|
||||
if (pcf == null)
|
||||
return CurlFormCode.Incomplete;
|
||||
if (j == nFormsCount - 1)
|
||||
{
|
||||
if (pcf.Option != CurlFormOption.End)
|
||||
return CurlFormCode.Incomplete;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pcf.Option == CurlFormOption.End)
|
||||
return CurlFormCode.Incomplete;
|
||||
}
|
||||
}
|
||||
// -2 accounts for the fact that we're a) not
|
||||
// including the item with End and b) not
|
||||
// including Array in what we pass to cURL
|
||||
nRealCount += 2*(nFormsCount - 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// allocate the IntPtr array for the data
|
||||
var aPointers = new IntPtr[nRealCount];
|
||||
for (var i = 0; i < nRealCount - 1; i++)
|
||||
aPointers[i] = IntPtr.Zero;
|
||||
aPointers[nRealCount - 1] = (IntPtr) CurlFormOption.End;
|
||||
|
||||
// now we go through the args
|
||||
aForms = null;
|
||||
var formArrayPos = 0;
|
||||
var argArrayPos = 0;
|
||||
var ptrArrayPos = 0;
|
||||
Object obj = null;
|
||||
|
||||
while ((retCode == CurlFormCode.Ok) &&
|
||||
(ptrArrayPos < nRealCount))
|
||||
{
|
||||
if (aForms != null)
|
||||
{
|
||||
var pcf = aForms.GetValue(formArrayPos++)
|
||||
as CurlForms;
|
||||
if (pcf == null)
|
||||
{
|
||||
retCode = CurlFormCode.UnknownOption;
|
||||
break;
|
||||
}
|
||||
iCode = pcf.Option;
|
||||
obj = pcf.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
iCode = (CurlFormOption) Convert.ToInt32(
|
||||
args.GetValue(argArrayPos++));
|
||||
obj = (iCode == CurlFormOption.End)
|
||||
? null
|
||||
: args.GetValue(argArrayPos++);
|
||||
}
|
||||
|
||||
switch (iCode)
|
||||
{
|
||||
// handle byte-array pointer-related items
|
||||
case CurlFormOption.PtrName:
|
||||
case CurlFormOption.PtrContents:
|
||||
case CurlFormOption.BufferPtr:
|
||||
{
|
||||
var bytes = obj as byte[];
|
||||
if (bytes == null)
|
||||
retCode = CurlFormCode.UnknownOption;
|
||||
else
|
||||
{
|
||||
var nLen = bytes.Length;
|
||||
var ptr = Marshal.AllocHGlobal(nLen);
|
||||
if (ptr != IntPtr.Zero)
|
||||
{
|
||||
aPointers[ptrArrayPos++] = (IntPtr) iCode;
|
||||
// copy bytes to unmanaged buffer
|
||||
for (var j = 0; j < nLen; j++)
|
||||
Marshal.WriteByte(ptr, bytes[j]);
|
||||
aPointers[ptrArrayPos++] = ptr;
|
||||
}
|
||||
else
|
||||
retCode = CurlFormCode.Memory;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// length values
|
||||
case CurlFormOption.NameLength:
|
||||
case CurlFormOption.ContentsLength:
|
||||
case CurlFormOption.BufferLength:
|
||||
aPointers[ptrArrayPos++] = (IntPtr) iCode;
|
||||
aPointers[ptrArrayPos++] = (IntPtr)
|
||||
Convert.ToInt32(obj);
|
||||
break;
|
||||
|
||||
// strings
|
||||
case CurlFormOption.CopyName:
|
||||
case CurlFormOption.CopyContents:
|
||||
case CurlFormOption.FileContent:
|
||||
case CurlFormOption.File:
|
||||
case CurlFormOption.ContentType:
|
||||
case CurlFormOption.Filename:
|
||||
case CurlFormOption.Buffer:
|
||||
{
|
||||
aPointers[ptrArrayPos++] = (IntPtr) iCode;
|
||||
var s = obj as String;
|
||||
if (s == null)
|
||||
retCode = CurlFormCode.UnknownOption;
|
||||
else
|
||||
{
|
||||
var p = Marshal.StringToHGlobalAnsi(s);
|
||||
if (p != IntPtr.Zero)
|
||||
aPointers[ptrArrayPos++] = p;
|
||||
else
|
||||
retCode = CurlFormCode.Memory;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// array case: already handled
|
||||
case CurlFormOption.Array:
|
||||
if (aForms != null)
|
||||
retCode = CurlFormCode.IllegalArray;
|
||||
else
|
||||
{
|
||||
aForms = obj as CurlForms[];
|
||||
if (aForms == null)
|
||||
retCode = CurlFormCode.UnknownOption;
|
||||
}
|
||||
break;
|
||||
|
||||
// slist
|
||||
case CurlFormOption.ContentHeader:
|
||||
{
|
||||
aPointers[ptrArrayPos++] = (IntPtr) iCode;
|
||||
var s = obj as CurlSlist;
|
||||
if (s == null)
|
||||
retCode = CurlFormCode.UnknownOption;
|
||||
else
|
||||
aPointers[ptrArrayPos++] = s.Handle;
|
||||
break;
|
||||
}
|
||||
|
||||
// erroneous stuff
|
||||
case CurlFormOption.Nothing:
|
||||
retCode = CurlFormCode.Incomplete;
|
||||
break;
|
||||
|
||||
// end
|
||||
case CurlFormOption.End:
|
||||
if (aForms != null) // end of form
|
||||
{
|
||||
aForms = null;
|
||||
formArrayPos = 0;
|
||||
}
|
||||
else
|
||||
aPointers[ptrArrayPos++] = (IntPtr) iCode;
|
||||
break;
|
||||
|
||||
// default is unknown
|
||||
default:
|
||||
retCode = CurlFormCode.UnknownOption;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ensure we didn't come up short on parameters
|
||||
if (ptrArrayPos != nRealCount)
|
||||
retCode = CurlFormCode.Incomplete;
|
||||
|
||||
// if we're OK here, call into curl
|
||||
if (retCode == CurlFormCode.Ok)
|
||||
{
|
||||
#if USE_LIBCURLSHIM
|
||||
retCode = (CurlFormCode) NativeMethods.curl_shim_formadd(_pItems, aPointers, nRealCount);
|
||||
#else
|
||||
retCode = (CurlFormCode) NativeMethods.curl_formadd(ref _pItems[0], ref _pItems[1],
|
||||
(int) aPointers[0], aPointers[1],
|
||||
(int) aPointers[2], aPointers[3],
|
||||
(int) aPointers[4]);
|
||||
#endif
|
||||
}
|
||||
|
||||
// unmarshal native allocations
|
||||
for (var i = 0; i < nRealCount - 1; i += 2)
|
||||
{
|
||||
iCode = (CurlFormOption) (int) aPointers[i];
|
||||
switch (iCode)
|
||||
{
|
||||
case CurlFormOption.CopyName:
|
||||
case CurlFormOption.CopyContents:
|
||||
case CurlFormOption.FileContent:
|
||||
case CurlFormOption.File:
|
||||
case CurlFormOption.ContentType:
|
||||
case CurlFormOption.Filename:
|
||||
case CurlFormOption.Buffer:
|
||||
// byte buffer cases
|
||||
case CurlFormOption.PtrName:
|
||||
case CurlFormOption.PtrContents:
|
||||
case CurlFormOption.BufferPtr:
|
||||
{
|
||||
if (aPointers[i + 1] != IntPtr.Zero)
|
||||
Marshal.FreeHGlobal(aPointers[i + 1]);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return retCode;
|
||||
}
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
// clean up managed objects
|
||||
}
|
||||
|
||||
// clean up native objects
|
||||
if (_pItems[0] != IntPtr.Zero)
|
||||
NativeMethods.curl_formfree(_pItems[0]);
|
||||
_pItems[0] = IntPtr.Zero;
|
||||
_pItems[1] = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,302 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* CurlS#arp
|
||||
*
|
||||
* Copyright (c) 2014 Dr. Masroor Ehsan (masroore@gmail.com)
|
||||
* Portions copyright (c) 2004, 2005 Jeff Phillips (jeff@jeffp.net)
|
||||
*
|
||||
* This software is licensed as described in the file LICENSE, which you
|
||||
* should have received as part of this distribution.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of this Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the LICENSE file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
|
||||
* ANY KIND, either express or implied.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements the <c>curl_multi_xxx</c> API.
|
||||
/// </summary>
|
||||
public class CurlMulti : IDisposable
|
||||
{
|
||||
// private members
|
||||
private readonly Hashtable _htEasy;
|
||||
private int _maxFd;
|
||||
private CurlMultiInfo[] _multiInfo;
|
||||
private bool _bGotMultiInfo;
|
||||
#if USE_LIBCURLSHIM
|
||||
private IntPtr _fdSets;
|
||||
#else
|
||||
private NativeMethods.fd_set _fd_read, _fd_write, _fd_except;
|
||||
#endif
|
||||
private IntPtr _pMulti;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <exception cref="System.InvalidOperationException">
|
||||
/// This is thrown
|
||||
/// if <see cref="Curl" /> hasn't bee properly initialized.
|
||||
/// </exception>
|
||||
/// <exception cref="System.NullReferenceException">
|
||||
/// This is thrown if the native <c>CurlMulti</c> handle wasn't
|
||||
/// created successfully.
|
||||
/// </exception>
|
||||
public CurlMulti()
|
||||
{
|
||||
Curl.EnsureCurl();
|
||||
_pMulti = NativeMethods.curl_multi_init();
|
||||
ensureHandle();
|
||||
_maxFd = 0;
|
||||
#if USE_LIBCURLSHIM
|
||||
_fdSets = IntPtr.Zero;
|
||||
_fdSets = NativeMethods.curl_shim_alloc_fd_sets();
|
||||
#else
|
||||
_fd_read = NativeMethods.fd_set.Create();
|
||||
_fd_read = NativeMethods.fd_set.Create();
|
||||
_fd_write = NativeMethods.fd_set.Create();
|
||||
_fd_except = NativeMethods.fd_set.Create();
|
||||
#endif
|
||||
_multiInfo = null;
|
||||
_bGotMultiInfo = false;
|
||||
_htEasy = new Hashtable();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Max file descriptor
|
||||
/// </summary>
|
||||
public int MaxFd
|
||||
{
|
||||
get { return _maxFd; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleanup unmanaged resources.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destructor
|
||||
/// </summary>
|
||||
~CurlMulti()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
// if (disposing) // managed member cleanup
|
||||
// unmanaged cleanup
|
||||
if (_pMulti != IntPtr.Zero)
|
||||
{
|
||||
NativeMethods.curl_multi_cleanup(_pMulti);
|
||||
_pMulti = IntPtr.Zero;
|
||||
}
|
||||
|
||||
#if USE_LIBCURLSHIM
|
||||
if (_fdSets != IntPtr.Zero)
|
||||
{
|
||||
NativeMethods.curl_shim_free_fd_sets(_fdSets);
|
||||
_fdSets = IntPtr.Zero;
|
||||
}
|
||||
#else
|
||||
_fd_read.Cleanup();
|
||||
_fd_write.Cleanup();
|
||||
_fd_except.Cleanup();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureHandle()
|
||||
{
|
||||
if (_pMulti == IntPtr.Zero)
|
||||
throw new NullReferenceException("No internal multi handle");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add an CurlEasy object.
|
||||
/// </summary>
|
||||
/// <param name="curlEasy">
|
||||
/// <see cref="CurlEasy" /> object to add.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="CurlMultiCode" />, hopefully <c>CurlMultiCode.Ok</c>
|
||||
/// </returns>
|
||||
/// <exception cref="System.NullReferenceException">
|
||||
/// This is thrown if the native <c>CurlMulti</c> handle wasn't
|
||||
/// created successfully.
|
||||
/// </exception>
|
||||
public CurlMultiCode AddHandle(CurlEasy curlEasy)
|
||||
{
|
||||
ensureHandle();
|
||||
var p = curlEasy.Handle;
|
||||
_htEasy.Add(p, curlEasy);
|
||||
return NativeMethods.curl_multi_add_handle(_pMulti, p);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove an CurlEasy object.
|
||||
/// </summary>
|
||||
/// <param name="curlEasy">
|
||||
/// <see cref="CurlEasy" /> object to remove.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="CurlMultiCode" />, hopefully <c>CurlMultiCode.Ok</c>
|
||||
/// </returns>
|
||||
/// <exception cref="System.NullReferenceException">
|
||||
/// This is thrown if the native <c>CurlMulti</c> handle wasn't
|
||||
/// created successfully.
|
||||
/// </exception>
|
||||
public CurlMultiCode RemoveHandle(CurlEasy curlEasy)
|
||||
{
|
||||
ensureHandle();
|
||||
var p = curlEasy.Handle;
|
||||
_htEasy.Remove(p);
|
||||
return NativeMethods.curl_multi_remove_handle(_pMulti, curlEasy.Handle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a string description of an error code.
|
||||
/// </summary>
|
||||
/// <param name="errorNum">
|
||||
/// The <see cref="CurlMultiCode" /> for which to obtain the error
|
||||
/// string description.
|
||||
/// </param>
|
||||
/// <returns>The string description.</returns>
|
||||
public String StrError(CurlMultiCode errorNum)
|
||||
{
|
||||
return Marshal.PtrToStringAnsi(NativeMethods.curl_multi_strerror(errorNum));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read/write data to/from each CurlEasy object.
|
||||
/// </summary>
|
||||
/// <param name="runningObjects">
|
||||
/// The number of <see cref="CurlEasy" /> objects still in process is
|
||||
/// written by this function to this reference parameter.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="CurlMultiCode" />, hopefully <c>CurlMultiCode.Ok</c>
|
||||
/// </returns>
|
||||
/// <exception cref="System.NullReferenceException">
|
||||
/// This is thrown if the native <c>CurlMulti</c> handle wasn't
|
||||
/// created successfully.
|
||||
/// </exception>
|
||||
public CurlMultiCode Perform(ref int runningObjects)
|
||||
{
|
||||
ensureHandle();
|
||||
return NativeMethods.curl_multi_perform(_pMulti, ref runningObjects);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set internal file desriptor information before calling Select.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="CurlMultiCode" />, hopefully <c>CurlMultiCode.Ok</c>
|
||||
/// </returns>
|
||||
/// <exception cref="System.NullReferenceException">
|
||||
/// This is thrown if the native <c>CurlMulti</c> handle wasn't
|
||||
/// created successfully.
|
||||
/// </exception>
|
||||
public CurlMultiCode FdSet()
|
||||
{
|
||||
ensureHandle();
|
||||
#if USE_LIBCURLSHIM
|
||||
return NativeMethods.curl_shim_multi_fdset(_pMulti, _fdSets, ref _maxFd);
|
||||
#else
|
||||
NativeMethods.FD_ZERO(_fd_read);
|
||||
NativeMethods.FD_ZERO(_fd_write);
|
||||
NativeMethods.FD_ZERO(_fd_except);
|
||||
return NativeMethods.curl_multi_fdset(_pMulti, ref _fd_read, ref _fd_write, ref _fd_except, ref _maxFd);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call <c>select()</c> on the CurlEasy objects.
|
||||
/// </summary>
|
||||
/// <param name="timeoutMillis">
|
||||
/// The timeout for the internal <c>select()</c> call,
|
||||
/// in milliseconds.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// Number or <see cref="CurlEasy" /> objects with pending reads.
|
||||
/// </returns>
|
||||
/// <exception cref="System.NullReferenceException">
|
||||
/// This is thrown if the native <c>CurlMulti</c> handle wasn't
|
||||
/// created successfully.
|
||||
/// </exception>
|
||||
public int Select(int timeoutMillis)
|
||||
{
|
||||
ensureHandle();
|
||||
#if USE_LIBCURLSHIM
|
||||
return NativeMethods.curl_shim_select(_maxFd + 1, _fdSets, timeoutMillis);
|
||||
#else
|
||||
var timeout = NativeMethods.timeval.Create(timeoutMillis);
|
||||
return NativeMethods.select(_maxFd + 1, ref _fd_read, ref _fd_write, ref _fd_except, ref timeout);
|
||||
//return NativeMethods.select2(_maxFd + 1, _fd_read, _fd_write, _fd_except, timeout);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Obtain status information for a CurlMulti transfer. Requires
|
||||
/// CurlSharp be compiled with the libcurlshim helper.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// An array of <see cref="CurlMultiInfo" /> objects, one for each
|
||||
/// <see cref="CurlEasy" /> object child.
|
||||
/// </returns>
|
||||
/// <exception cref="System.NullReferenceException">
|
||||
/// This is thrown if the native <c>CurlMulti</c> handle wasn't
|
||||
/// created successfully.
|
||||
/// </exception>
|
||||
public CurlMultiInfo[] InfoRead()
|
||||
{
|
||||
if (_bGotMultiInfo)
|
||||
return _multiInfo;
|
||||
|
||||
_bGotMultiInfo = true;
|
||||
|
||||
#if USE_LIBCURLSHIM
|
||||
var nMsgs = 0;
|
||||
var pInfo = NativeMethods.curl_shim_multi_info_read(_pMulti, ref nMsgs);
|
||||
if (pInfo != IntPtr.Zero)
|
||||
{
|
||||
_multiInfo = new CurlMultiInfo[nMsgs];
|
||||
for (var i = 0; i < nMsgs; i++)
|
||||
{
|
||||
var msg = (CurlMessage) Marshal.ReadInt32(pInfo, i*12);
|
||||
var pEasy = Marshal.ReadIntPtr(pInfo, i*12 + 4);
|
||||
var code = (CurlCode) Marshal.ReadInt32(pInfo, i*12 + 8);
|
||||
_multiInfo[i] = new CurlMultiInfo(msg, (CurlEasy) _htEasy[pEasy], code);
|
||||
}
|
||||
NativeMethods.curl_shim_multi_info_free(pInfo);
|
||||
}
|
||||
|
||||
return _multiInfo;
|
||||
|
||||
#else
|
||||
|
||||
throw new NotImplementedException(
|
||||
"Sorry, CurlMulti.InfoRead is not implemented on this system."
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* CurlS#arp
|
||||
*
|
||||
* Copyright (c) 2013 Dr. Masroor Ehsan (masroore@gmail.com)
|
||||
* Portions copyright (c) 2004, 2005 Jeff Phillips (jeff@jeffp.net)
|
||||
*
|
||||
* This software is licensed as described in the file LICENSE, which you
|
||||
* should have received as part of this distribution.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of this Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the LICENSE file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
|
||||
* ANY KIND, either express or implied.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Wraps the <c>cURL</c> struct <c>CURLMsg</c>. This class provides
|
||||
/// status information following a <see cref="CurlMulti" /> transfer.
|
||||
/// </summary>
|
||||
public sealed class CurlMultiInfo
|
||||
{
|
||||
// private members
|
||||
private readonly CurlEasy _mCurlEasy;
|
||||
private readonly CurlMessage _msg;
|
||||
private readonly CurlCode _result;
|
||||
|
||||
internal CurlMultiInfo(CurlMessage msg, CurlEasy curlEasy, CurlCode result)
|
||||
{
|
||||
_msg = msg;
|
||||
_mCurlEasy = curlEasy;
|
||||
_result = result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the status code from the <see cref="CurlMessage" /> enumeration.
|
||||
/// </summary>
|
||||
public CurlMessage Msg
|
||||
{
|
||||
get { return _msg; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the <see cref="CurlEasy" /> object for this child.
|
||||
/// </summary>
|
||||
public CurlEasy CurlEasyHandle
|
||||
{
|
||||
get { return _mCurlEasy; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the return code for the transfer, as a
|
||||
/// <see cref="CurlCode" />.
|
||||
/// </summary>
|
||||
public CurlCode Result
|
||||
{
|
||||
get { return _result; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,276 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* CurlS#arp
|
||||
*
|
||||
* Copyright (c) 2013 Dr. Masroor Ehsan (masroore@gmail.com)
|
||||
* Portions copyright (c) 2004, 2005 Jeff Phillips (jeff@jeffp.net)
|
||||
*
|
||||
* This software is licensed as described in the file LICENSE, which you
|
||||
* should have received as part of this distribution.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of this Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the LICENSE file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
|
||||
* ANY KIND, either express or implied.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This class provides an infrastructure for serializing access to data
|
||||
/// shared by multiple <see cref="CurlEasy" /> objects, including cookie data
|
||||
/// and Dns hosts. It implements the <c>curl_share_xxx</c> API.
|
||||
/// </summary>
|
||||
public class CurlShare : IDisposable
|
||||
{
|
||||
// private members
|
||||
private GCHandle _hThis; // for handle extraction
|
||||
private CurlShareCode _lastErrorCode;
|
||||
private string _lastErrorDescription;
|
||||
#if USE_LIBCURLSHIM
|
||||
private NativeMethods._ShimLockCallback _pDelLock; // lock delegate
|
||||
private NativeMethods._ShimUnlockCallback _pDelUnlock; // unlock delegate
|
||||
#endif
|
||||
private IntPtr _pShare; // share handle
|
||||
private CurlShareLockCallback _pfLock; // client lock delegate
|
||||
private CurlShareUnlockCallback _pfUnlock; // client unlock delegate
|
||||
private IntPtr _ptrThis; // numeric handle
|
||||
private Object _userData; // user data for delegates
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <exception cref="System.InvalidOperationException">
|
||||
/// This is thrown
|
||||
/// if <see cref="Curl" /> hasn't bee properly initialized.
|
||||
/// </exception>
|
||||
/// <exception cref="System.NullReferenceException">
|
||||
/// This is thrown if
|
||||
/// the native <c>share</c> handle wasn't created successfully.
|
||||
/// </exception>
|
||||
public CurlShare()
|
||||
{
|
||||
Curl.EnsureCurl();
|
||||
_pShare = NativeMethods.curl_share_init();
|
||||
EnsureHandle();
|
||||
LockFunction = null;
|
||||
UnlockFunction = null;
|
||||
UserData = null;
|
||||
installDelegates();
|
||||
}
|
||||
|
||||
public object UserData
|
||||
{
|
||||
get { return _userData; }
|
||||
set { _userData = value; }
|
||||
}
|
||||
|
||||
public CurlShareUnlockCallback UnlockFunction
|
||||
{
|
||||
get { return _pfUnlock; }
|
||||
set { _pfUnlock = value; }
|
||||
}
|
||||
|
||||
public CurlShareLockCallback LockFunction
|
||||
{
|
||||
get { return _pfLock; }
|
||||
set { _pfLock = value; }
|
||||
}
|
||||
|
||||
public CurlLockData Share
|
||||
{
|
||||
set { setShareOption(CurlShareOption.Share, value); }
|
||||
}
|
||||
|
||||
public CurlLockData Unshare
|
||||
{
|
||||
set { setShareOption(CurlShareOption.Unshare, value); }
|
||||
}
|
||||
|
||||
public CurlShareCode LastErrorCode
|
||||
{
|
||||
get { return _lastErrorCode; }
|
||||
}
|
||||
|
||||
public string LastErrorDescription
|
||||
{
|
||||
get { return _lastErrorDescription; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleanup unmanaged resources.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destructor
|
||||
/// </summary>
|
||||
~CurlShare()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set options for this object.
|
||||
/// </summary>
|
||||
/// <param name="option">
|
||||
/// One of the values in the <see cref="CurlShareOption" />
|
||||
/// enumeration.
|
||||
/// </param>
|
||||
/// <param name="parameter">
|
||||
/// An appropriate object based on the value passed in the
|
||||
/// <c>option</c> argument. See <see cref="CurlShareOption" />
|
||||
/// for more information about the appropriate parameter type.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="CurlShareCode" />, hopefully
|
||||
/// <c>CurlShareCode.Ok</c>.
|
||||
/// </returns>
|
||||
/// <exception cref="System.NullReferenceException">
|
||||
/// This is thrown if
|
||||
/// the native <c>share</c> handle wasn't created successfully.
|
||||
/// </exception>
|
||||
public CurlShareCode SetOpt(CurlShareOption option, Object parameter)
|
||||
{
|
||||
EnsureHandle();
|
||||
var retCode = CurlShareCode.Ok;
|
||||
|
||||
switch (option)
|
||||
{
|
||||
case CurlShareOption.LockFunction:
|
||||
var lf = parameter as CurlShareLockCallback;
|
||||
if (lf == null)
|
||||
return CurlShareCode.BadOption;
|
||||
_pfLock = lf;
|
||||
break;
|
||||
|
||||
case CurlShareOption.UnlockFunction:
|
||||
var ulf = parameter as CurlShareUnlockCallback;
|
||||
if (ulf == null)
|
||||
return CurlShareCode.BadOption;
|
||||
_pfUnlock = ulf;
|
||||
break;
|
||||
|
||||
case CurlShareOption.Share:
|
||||
case CurlShareOption.Unshare:
|
||||
{
|
||||
var opt = (CurlLockData) Convert.ToInt32(parameter);
|
||||
retCode = setShareOption(option, opt);
|
||||
break;
|
||||
}
|
||||
|
||||
case CurlShareOption.UserData:
|
||||
_userData = parameter;
|
||||
break;
|
||||
|
||||
default:
|
||||
retCode = CurlShareCode.BadOption;
|
||||
break;
|
||||
}
|
||||
return retCode;
|
||||
}
|
||||
|
||||
private void setLastError(CurlShareCode code, CurlShareOption opt)
|
||||
{
|
||||
if (_lastErrorCode == CurlShareCode.Ok && code != CurlShareCode.Ok)
|
||||
{
|
||||
_lastErrorCode = code;
|
||||
_lastErrorDescription = string.Format("Error: {0} setting option {1}", StrError(code), opt);
|
||||
}
|
||||
}
|
||||
|
||||
private CurlShareCode setShareOption(CurlShareOption option, CurlLockData value)
|
||||
{
|
||||
var retCode = (value != CurlLockData.Cookie) && (value != CurlLockData.Dns)
|
||||
? CurlShareCode.BadOption
|
||||
: NativeMethods.curl_share_setopt(_pShare, option, (IntPtr) value);
|
||||
setLastError(retCode, option);
|
||||
return retCode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a String description of an error code.
|
||||
/// </summary>
|
||||
/// <param name="errorNum">
|
||||
/// The <see cref="CurlShareCode" /> for which to obtain the error
|
||||
/// string description.
|
||||
/// </param>
|
||||
/// <returns>The string description.</returns>
|
||||
public String StrError(CurlShareCode errorNum)
|
||||
{
|
||||
return Marshal.PtrToStringAnsi(NativeMethods.curl_share_strerror(errorNum));
|
||||
}
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
// if (disposing) cleanup managed objects
|
||||
if (_pShare != IntPtr.Zero)
|
||||
{
|
||||
#if USE_LIBCURLSHIM
|
||||
NativeMethods.curl_shim_cleanup_share_delegates(_pShare);
|
||||
#endif
|
||||
NativeMethods.curl_share_cleanup(_pShare);
|
||||
_hThis.Free();
|
||||
_ptrThis = IntPtr.Zero;
|
||||
_pShare = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal IntPtr GetHandle()
|
||||
{
|
||||
return _pShare;
|
||||
}
|
||||
|
||||
private void EnsureHandle()
|
||||
{
|
||||
if (_pShare == IntPtr.Zero)
|
||||
throw new NullReferenceException("No internal share handle");
|
||||
}
|
||||
|
||||
private void installDelegates()
|
||||
{
|
||||
_hThis = GCHandle.Alloc(this);
|
||||
_ptrThis = (IntPtr)_hThis;
|
||||
#if USE_LIBCURLSHIM
|
||||
_pDelLock = LockDelegate;
|
||||
_pDelUnlock = UnlockDelegate;
|
||||
NativeMethods.curl_shim_install_share_delegates(_pShare, _ptrThis, _pDelLock, _pDelUnlock);
|
||||
#endif
|
||||
}
|
||||
|
||||
internal static void LockDelegate(int data, int access, IntPtr userPtr)
|
||||
{
|
||||
var gch = (GCHandle) userPtr;
|
||||
var share = (CurlShare) gch.Target;
|
||||
if (share == null)
|
||||
return;
|
||||
if (share.LockFunction == null)
|
||||
return;
|
||||
share.LockFunction((CurlLockData) data, (CurlLockAccess) access, share.UserData);
|
||||
}
|
||||
|
||||
internal static void UnlockDelegate(int data, IntPtr userPtr)
|
||||
{
|
||||
var gch = (GCHandle) userPtr;
|
||||
var share = (CurlShare) gch.Target;
|
||||
if (share == null)
|
||||
return;
|
||||
if (share.UnlockFunction == null)
|
||||
return;
|
||||
share.UnlockFunction((CurlLockData) data, share.UserData);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{74420A79-CC16-442C-8B1E-7C1B913844F0}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>CurlSharp</RootNamespace>
|
||||
<AssemblyName>CurlSharp</AssemblyName>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProductVersion>12.0.0</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug</OutputPath>
|
||||
<DefineConstants>DEBUG;LINUX</DefineConstants>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<ConsolePause>false</ConsolePause>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release</OutputPath>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<ConsolePause>false</ConsolePause>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Curl.cs" />
|
||||
<Compile Include="CurlEasy.cs" />
|
||||
<Compile Include="CurlHttpMultiPartForm.cs" />
|
||||
<Compile Include="CurlMulti.cs" />
|
||||
<Compile Include="CurlMultiInfo.cs" />
|
||||
<Compile Include="CurlShare.cs" />
|
||||
<Compile Include="CurlSlist.cs" />
|
||||
<Compile Include="CurlSslContext.cs" />
|
||||
<Compile Include="CurlVersionInfoData.cs" />
|
||||
<Compile Include="NativeMethods.cs" />
|
||||
<Compile Include="Enums\CurlClosePolicy.cs" />
|
||||
<Compile Include="Enums\CurlCode.cs" />
|
||||
<Compile Include="Enums\CurlFormCode.cs" />
|
||||
<Compile Include="Enums\CurlFormOption.cs" />
|
||||
<Compile Include="Enums\CurlFtpAuth.cs" />
|
||||
<Compile Include="Enums\CurlFtpSsl.cs" />
|
||||
<Compile Include="Enums\CurlHttpAuth.cs" />
|
||||
<Compile Include="Enums\CurlHttpVersion.cs" />
|
||||
<Compile Include="Enums\CurlInfo.cs" />
|
||||
<Compile Include="Enums\CurlInfoType.cs" />
|
||||
<Compile Include="Enums\CurlInitFlag.cs" />
|
||||
<Compile Include="Enums\CurlIoCommand.cs" />
|
||||
<Compile Include="Enums\CurlIoError.cs" />
|
||||
<Compile Include="Enums\CurlIpResolve.cs" />
|
||||
<Compile Include="Enums\CurlLockAccess.cs" />
|
||||
<Compile Include="Enums\CurlLockData.cs" />
|
||||
<Compile Include="Enums\CurlMessage.cs" />
|
||||
<Compile Include="Enums\CurlMultiCode.cs" />
|
||||
<Compile Include="Enums\CurlNetrcOption.cs" />
|
||||
<Compile Include="Enums\CurlOption.cs" />
|
||||
<Compile Include="Enums\CurlProxyType.cs" />
|
||||
<Compile Include="Enums\CurlShareCode.cs" />
|
||||
<Compile Include="Enums\CurlShareOption.cs" />
|
||||
<Compile Include="Enums\CurlSslVersion.cs" />
|
||||
<Compile Include="Enums\CurlTimeCond.cs" />
|
||||
<Compile Include="Enums\CurlVersion.cs" />
|
||||
<Compile Include="Enums\CurlVersionFeatureBitmask.cs" />
|
||||
<Compile Include="Callbacks\CurlEasyCallbacks.cs" />
|
||||
<Compile Include="Callbacks\CurlShareCallbacks.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
<ItemGroup />
|
||||
</Project>
|
|
@ -0,0 +1,144 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* CurlS#arp
|
||||
*
|
||||
* Copyright (c) 2013 Dr. Masroor Ehsan (masroore@gmail.com)
|
||||
* Portions copyright (c) 2004, 2005 Jeff Phillips (jeff@jeffp.net)
|
||||
*
|
||||
* This software is licensed as described in the file LICENSE, which you
|
||||
* should have received as part of this distribution.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of this Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the LICENSE file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
|
||||
* ANY KIND, either express or implied.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This class wraps a linked list of strings used in <c>cURL</c>. Use it
|
||||
/// to build string lists where they're required, such as when calling
|
||||
/// <see cref="CurlEasy.SetOpt" /> with <see cref="CurlOption.Quote" />
|
||||
/// as the option.
|
||||
/// </summary>
|
||||
public class CurlSlist : IDisposable
|
||||
{
|
||||
#if !USE_LIBCURLSHIM
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private class curl_slist
|
||||
{
|
||||
/// char*
|
||||
[MarshalAs(UnmanagedType.LPStr)] public string data;
|
||||
|
||||
/// curl_slist*
|
||||
public IntPtr next;
|
||||
}
|
||||
#endif
|
||||
private IntPtr _handle;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <exception cref="System.InvalidOperationException">
|
||||
/// This is thrown
|
||||
/// if <see cref="Curl" /> hasn't bee properly initialized.
|
||||
/// </exception>
|
||||
public CurlSlist()
|
||||
{
|
||||
Curl.EnsureCurl();
|
||||
_handle = IntPtr.Zero;
|
||||
}
|
||||
|
||||
public CurlSlist(IntPtr handle)
|
||||
{
|
||||
_handle = handle;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read-only copy of the strings stored in the SList
|
||||
/// </summary>
|
||||
public List<string> Strings
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_handle == IntPtr.Zero)
|
||||
return null;
|
||||
var strings = new List<string>();
|
||||
|
||||
#if !USE_LIBCURLSHIM
|
||||
var slist = new curl_slist();
|
||||
Marshal.PtrToStructure(_handle, slist);
|
||||
|
||||
while (true)
|
||||
{
|
||||
strings.Add(slist.data);
|
||||
if (slist.next != IntPtr.Zero)
|
||||
Marshal.PtrToStructure(slist.next, slist);
|
||||
else
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
return strings;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destructor
|
||||
/// </summary>
|
||||
~CurlSlist()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Append a string to the list.
|
||||
/// </summary>
|
||||
/// <param name="str">The <c>string</c> to append.</param>
|
||||
public void Append(string str)
|
||||
{
|
||||
#if USE_LIBCURLSHIM
|
||||
_handle = NativeMethods.curl_shim_add_string_to_slist(_handle, str);
|
||||
#else
|
||||
_handle = NativeMethods.curl_slist_append(_handle, str);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Free all internal strings.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
Dispose(true);
|
||||
}
|
||||
|
||||
internal IntPtr Handle
|
||||
{
|
||||
get { return _handle; }
|
||||
}
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (_handle != IntPtr.Zero)
|
||||
{
|
||||
#if USE_LIBCURLSHIM
|
||||
NativeMethods.curl_shim_free_slist(_handle);
|
||||
#else
|
||||
NativeMethods.curl_slist_free_all(_handle);
|
||||
#endif
|
||||
_handle = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* CurlS#arp
|
||||
*
|
||||
* Copyright (c) 2013 Dr. Masroor Ehsan (masroore@gmail.com)
|
||||
* Portions copyright (c) 2004, 2005 Jeff Phillips (jeff@jeffp.net)
|
||||
*
|
||||
* This software is licensed as described in the file LICENSE, which you
|
||||
* should have received as part of this distribution.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of this Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the LICENSE file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
|
||||
* ANY KIND, either express or implied.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
using System;
|
||||
|
||||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// An instance of this class is passed to the delegate
|
||||
/// <see cref="CurlSslContextCallback" />, if it's implemented.
|
||||
/// Within that delegate, the code will have to make native calls to
|
||||
/// the <c>OpenSSL</c> library with the value returned from the
|
||||
/// <see cref="CurlSslContext.Context" /> property cast to an
|
||||
/// <c>SSL_CTX</c> pointer.
|
||||
/// </summary>
|
||||
public sealed class CurlSslContext
|
||||
{
|
||||
private readonly IntPtr _pvContext;
|
||||
|
||||
internal CurlSslContext(IntPtr pvContext)
|
||||
{
|
||||
_pvContext = pvContext;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the underlying OpenSSL context.
|
||||
/// </summary>
|
||||
public IntPtr Context
|
||||
{
|
||||
get { return _pvContext; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,207 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* CurlS#arp
|
||||
*
|
||||
* Copyright (c) 2013 Dr. Masroor Ehsan (masroore@gmail.com)
|
||||
* Portions copyright (c) 2004, 2005 Jeff Phillips (jeff@jeffp.net)
|
||||
*
|
||||
* This software is licensed as described in the file LICENSE, which you
|
||||
* should have received as part of this distribution.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of this Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the LICENSE file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
|
||||
* ANY KIND, either express or implied.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This class wraps a <c>curl_version_info_data</c> struct. An instance is
|
||||
/// obtained by calling <see cref="Curl.GetVersionInfo" />.
|
||||
/// </summary>
|
||||
public sealed class CurlVersionInfoData
|
||||
{
|
||||
private const int OFFSET_AGE = 0;
|
||||
private const int OFFSET_VERSION = 4;
|
||||
private const int OFFSET_VERSION_NUM = 8;
|
||||
private const int OFFSET_HOST = 12;
|
||||
private const int OFFSET_FEATURES = 16;
|
||||
private const int OFFSET_SSL_VERSION = 20;
|
||||
private const int OFFSET_SSL_VERSION_NUM = 24;
|
||||
private const int OFFSET_LIBZ_VERSION = 28;
|
||||
private const int OFFSET_PROTOCOLS = 32;
|
||||
private const int OFFSET_ARES_VERSION = 36;
|
||||
private const int OFFSET_ARES_VERSION_NUM = 40;
|
||||
private const int OFFSET_LIBIDN_VERSION = 44;
|
||||
|
||||
private readonly IntPtr m_pVersionInfoData;
|
||||
|
||||
internal CurlVersionInfoData(CurlVersion ver)
|
||||
{
|
||||
m_pVersionInfoData = NativeMethods.curl_version_info(ver);
|
||||
}
|
||||
#if USE_LIBCURLSHIM
|
||||
/// <summary>
|
||||
/// Age of this struct, depending on how recent the linked-in
|
||||
/// <c>libcurl</c> is, as a <see cref="CurlVersion" />.
|
||||
/// </summary>
|
||||
public CurlVersion Age
|
||||
{
|
||||
get { return (CurlVersion) NativeMethods.curl_shim_get_version_int_value(m_pVersionInfoData, OFFSET_AGE); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the internal cURL version, as a <c>string</c>.
|
||||
/// </summary>
|
||||
public string Version
|
||||
{
|
||||
get
|
||||
{
|
||||
return Marshal.PtrToStringAnsi(
|
||||
NativeMethods.curl_shim_get_version_char_ptr(m_pVersionInfoData, OFFSET_VERSION));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the internal cURL version number, a A 24-bit number created
|
||||
/// like this: [8 bits major number] | [8 bits minor number] | [8
|
||||
/// bits patch number]. For example, Version 7.12.2 is <c>0x070C02</c>.
|
||||
/// </summary>
|
||||
public int VersionNum
|
||||
{
|
||||
get { return NativeMethods.curl_shim_get_version_int_value(m_pVersionInfoData, OFFSET_VERSION_NUM); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the host information on which the underlying cURL was built.
|
||||
/// </summary>
|
||||
public string Host
|
||||
{
|
||||
get
|
||||
{
|
||||
return
|
||||
Marshal.PtrToStringAnsi(NativeMethods.curl_shim_get_version_char_ptr(m_pVersionInfoData, OFFSET_HOST));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a bitmask of features, containing bits or'd from the
|
||||
/// <see cref="CurlVersionFeatureBitmask" /> enumeration.
|
||||
/// </summary>
|
||||
public int Features
|
||||
{
|
||||
get { return NativeMethods.curl_shim_get_version_int_value(m_pVersionInfoData, OFFSET_FEATURES); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the Ssl version, if it's linked in.
|
||||
/// </summary>
|
||||
public string SslVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
return
|
||||
Marshal.PtrToStringAnsi(NativeMethods.curl_shim_get_version_char_ptr(m_pVersionInfoData,
|
||||
OFFSET_SSL_VERSION));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the Ssl version number, if Ssl is linked in.
|
||||
/// </summary>
|
||||
public int SSLVersionNum
|
||||
{
|
||||
get { return NativeMethods.curl_shim_get_version_int_value(m_pVersionInfoData, OFFSET_SSL_VERSION_NUM); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the libz version, if libz is linked in.
|
||||
/// </summary>
|
||||
public string LibZVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
return
|
||||
Marshal.PtrToStringAnsi(NativeMethods.curl_shim_get_version_char_ptr(m_pVersionInfoData,
|
||||
OFFSET_LIBZ_VERSION));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the names of the supported protocols.
|
||||
/// </summary>
|
||||
public string[] Protocols
|
||||
{
|
||||
get
|
||||
{
|
||||
var nProts = NativeMethods.curl_shim_get_number_of_protocols(
|
||||
m_pVersionInfoData, OFFSET_PROTOCOLS);
|
||||
var aProts = new String[nProts];
|
||||
for (var i = 0; i < nProts; i++)
|
||||
{
|
||||
aProts[i] =
|
||||
Marshal.PtrToStringAnsi(NativeMethods.curl_shim_get_protocol_string(m_pVersionInfoData,
|
||||
OFFSET_PROTOCOLS, i));
|
||||
}
|
||||
return aProts;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the ARes version, if ARes is linked in.
|
||||
/// </summary>
|
||||
public string ARes
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Age > CurlVersion.First)
|
||||
{
|
||||
return
|
||||
Marshal.PtrToStringAnsi(NativeMethods.curl_shim_get_version_char_ptr(m_pVersionInfoData,
|
||||
OFFSET_ARES_VERSION));
|
||||
}
|
||||
return "n.a.";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the ARes version number, if ARes is linked in.
|
||||
/// </summary>
|
||||
public int AResNum
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Age > CurlVersion.First)
|
||||
{
|
||||
return NativeMethods.curl_shim_get_version_int_value(m_pVersionInfoData, OFFSET_ARES_VERSION_NUM);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the libidn version, if libidn is linked in.
|
||||
/// </summary>
|
||||
public string LibIdn
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Age > CurlVersion.Second)
|
||||
{
|
||||
return
|
||||
Marshal.PtrToStringAnsi(NativeMethods.curl_shim_get_version_char_ptr(m_pVersionInfoData,
|
||||
OFFSET_LIBIDN_VERSION));
|
||||
}
|
||||
return "n.a.";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains values used to specify the order in which cached connections
|
||||
/// are closed. One of these is passed as the
|
||||
/// <see cref="CurlOption.ClosePolicy" /> option in a call
|
||||
/// to <see cref="CurlEasy.SetOpt" />
|
||||
/// </summary>
|
||||
public enum CurlClosePolicy
|
||||
{
|
||||
/// <summary>
|
||||
/// No close policy. Never use this.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Close the oldest cached connections first.
|
||||
/// </summary>
|
||||
Oldest = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Close the least recently used connections first.
|
||||
/// </summary>
|
||||
LeastRecentlyUsed = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Close the connections with the least traffic first.
|
||||
/// </summary>
|
||||
LeastTraffic = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Close the slowest connections first.
|
||||
/// </summary>
|
||||
Slowest = 4,
|
||||
|
||||
/// <summary>
|
||||
/// Currently unimplemented.
|
||||
/// </summary>
|
||||
Callback = 5,
|
||||
|
||||
/// <summary>
|
||||
/// End-of-enumeration marker; do not use in application code.
|
||||
/// </summary>
|
||||
Last = 6
|
||||
};
|
||||
}
|
|
@ -0,0 +1,403 @@
|
|||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Status code returned from <see cref="CurlEasy" /> functions.
|
||||
/// </summary>
|
||||
public enum CurlCode
|
||||
{
|
||||
/// <summary>
|
||||
/// All fine. Proceed as usual.
|
||||
/// </summary>
|
||||
Ok = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Aborted by callback. An internal callback returned "abort"
|
||||
/// to libcurl.
|
||||
/// </summary>
|
||||
AbortedByCallback = 42,
|
||||
|
||||
/// <summary>
|
||||
/// Internal error. A function was called in a bad order.
|
||||
/// </summary>
|
||||
BadCallingOrder = 44,
|
||||
|
||||
/// <summary>
|
||||
/// Unrecognized transfer encoding.
|
||||
/// </summary>
|
||||
BadContentEncoding = 61,
|
||||
|
||||
/// <summary>
|
||||
/// Attempting FTP resume beyond file size.
|
||||
/// </summary>
|
||||
BadDownloadResume = 36,
|
||||
|
||||
/// <summary>
|
||||
/// Internal error. A function was called with a bad parameter.
|
||||
/// </summary>
|
||||
BadFunctionArgument = 43,
|
||||
|
||||
/// <summary>
|
||||
/// Bad password entered. An error was signaled when the password was
|
||||
/// entered. This can also be the result of a "bad password" returned
|
||||
/// from a specified password callback.
|
||||
/// </summary>
|
||||
BadPasswordEntered = 46,
|
||||
|
||||
/// <summary>
|
||||
/// Failed to connect to host or proxy.
|
||||
/// </summary>
|
||||
CouldntConnect = 7,
|
||||
|
||||
/// <summary>
|
||||
/// Couldn't resolve host. The given remote host was not resolved.
|
||||
/// </summary>
|
||||
CouldntResolveHost = 6,
|
||||
|
||||
/// <summary>
|
||||
/// Couldn't resolve proxy. The given proxy host could not be resolved.
|
||||
/// </summary>
|
||||
CouldntResolveProxy = 5,
|
||||
|
||||
/// <summary>
|
||||
/// Very early initialization code failed. This is likely to be an
|
||||
/// internal error or problem.
|
||||
/// </summary>
|
||||
FailedInit = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Maximum file size exceeded.
|
||||
/// </summary>
|
||||
FilesizeExceeded = 63,
|
||||
|
||||
/// <summary>
|
||||
/// A file given with FILE:// couldn't be opened. Most likely
|
||||
/// because the file path doesn't identify an existing file. Did
|
||||
/// you check file permissions?
|
||||
/// </summary>
|
||||
FileCouldntReadFile = 37,
|
||||
|
||||
/// <summary>
|
||||
/// We were denied access when trying to login to an FTP server or
|
||||
/// when trying to change working directory to the one given in the URL.
|
||||
/// </summary>
|
||||
FtpAccessDenied = 9,
|
||||
|
||||
/// <summary>
|
||||
/// An internal failure to lookup the host used for the new
|
||||
/// connection.
|
||||
/// </summary>
|
||||
FtpCantGetHost = 15,
|
||||
|
||||
/// <summary>
|
||||
/// A bad return code on either PASV or EPSV was sent by the FTP
|
||||
/// server, preventing libcurl from being able to continue.
|
||||
/// </summary>
|
||||
FtpCantReconnect = 16,
|
||||
|
||||
/// <summary>
|
||||
/// The FTP SIZE command returned error. SIZE is not a kosher FTP
|
||||
/// command, it is an extension and not all servers support it. This
|
||||
/// is not a surprising error.
|
||||
/// </summary>
|
||||
FtpCouldntGetSize = 32,
|
||||
|
||||
/// <summary>
|
||||
/// This was either a weird reply to a 'RETR' command or a zero byte
|
||||
/// transfer complete.
|
||||
/// </summary>
|
||||
FtpCouldntRetrFile = 19,
|
||||
|
||||
/// <summary>
|
||||
/// libcurl failed to set ASCII transfer type (TYPE A).
|
||||
/// </summary>
|
||||
FtpCouldntSetAscii = 29,
|
||||
|
||||
/// <summary>
|
||||
/// Received an error when trying to set the transfer mode to binary.
|
||||
/// </summary>
|
||||
FtpCouldntSetBinary = 17,
|
||||
|
||||
/// <summary>
|
||||
/// FTP couldn't STOR file. The server denied the STOR operation.
|
||||
/// The error buffer usually contains the server's explanation to this.
|
||||
/// </summary>
|
||||
FtpCouldntStorFile = 25,
|
||||
|
||||
/// <summary>
|
||||
/// The FTP REST command returned error. This should never happen
|
||||
/// if the server is sane.
|
||||
/// </summary>
|
||||
FtpCouldntUseRest = 31,
|
||||
|
||||
/// <summary>
|
||||
/// The FTP PORT command returned error. This mostly happen when
|
||||
/// you haven't specified a good enough address for libcurl to use.
|
||||
/// See <see cref="CurlOption.FtpPort" />.
|
||||
/// </summary>
|
||||
FtpPortFailed = 30,
|
||||
|
||||
/// <summary>
|
||||
/// When sending custom "QUOTE" commands to the remote server, one
|
||||
/// of the commands returned an error code that was 400 or higher.
|
||||
/// </summary>
|
||||
FtpQuoteError = 21,
|
||||
|
||||
/// <summary>
|
||||
/// Requested FTP Ssl level failed.
|
||||
/// </summary>
|
||||
FtpSslFailed = 64,
|
||||
|
||||
/// <summary>
|
||||
/// The FTP server rejected access to the server after the password
|
||||
/// was sent to it. It might be because the username and/or the
|
||||
/// password were incorrect or just that the server is not allowing
|
||||
/// you access for the moment etc.
|
||||
/// </summary>
|
||||
FtpUserPasswordIncorrect = 10,
|
||||
|
||||
/// <summary>
|
||||
/// FTP servers return a 227-line as a response to a PASV command.
|
||||
/// If libcurl fails to parse that line, this return code is
|
||||
/// passed back.
|
||||
/// </summary>
|
||||
FtpWeird227Format = 14,
|
||||
|
||||
/// <summary>
|
||||
/// After having sent the FTP password to the server, libcurl expects
|
||||
/// a proper reply. This error code indicates that an unexpected code
|
||||
/// was returned.
|
||||
/// </summary>
|
||||
FtpWeirdPassReply = 11,
|
||||
|
||||
/// <summary>
|
||||
/// libcurl failed to get a sensible result back from the server as
|
||||
/// a response to either a PASV or a EPSV command. The server is flawed.
|
||||
/// </summary>
|
||||
FtpWeirdPasvReply = 13,
|
||||
|
||||
/// <summary>
|
||||
/// After connecting to an FTP server, libcurl expects to get a
|
||||
/// certain reply back. This error code implies that it got a strange
|
||||
/// or bad reply. The given remote server is probably not an
|
||||
/// OK FTP server.
|
||||
/// </summary>
|
||||
FtpWeirdServerReply = 8,
|
||||
|
||||
/// <summary>
|
||||
/// After having sent user name to the FTP server, libcurl expects a
|
||||
/// proper reply. This error code indicates that an unexpected code
|
||||
/// was returned.
|
||||
/// </summary>
|
||||
FtpWeirdUserReply = 12,
|
||||
|
||||
/// <summary>
|
||||
/// After a completed file transfer, the FTP server did not respond a
|
||||
/// proper "transfer successful" code.
|
||||
/// </summary>
|
||||
FtpWriteError = 20,
|
||||
|
||||
/// <summary>
|
||||
/// Function not found. A required LDAP function was not found.
|
||||
/// </summary>
|
||||
FunctionNotFound = 41,
|
||||
|
||||
/// <summary>
|
||||
/// Nothing was returned from the server, and under the circumstances,
|
||||
/// getting nothing is considered an error.
|
||||
/// </summary>
|
||||
GotNothing = 52,
|
||||
|
||||
/// <summary>
|
||||
/// This is an odd error that mainly occurs due to internal confusion.
|
||||
/// </summary>
|
||||
HttpPostError = 34,
|
||||
|
||||
/// <summary>
|
||||
/// The HTTP server does not support or accept range requests.
|
||||
/// </summary>
|
||||
HttpRangeError = 33,
|
||||
|
||||
/// <summary>
|
||||
/// This is returned if <see cref="CurlOption.FailOnError" />
|
||||
/// is set TRUE and the HTTP server returns an error code that
|
||||
/// is >= 400.
|
||||
/// </summary>
|
||||
HttpReturnedError = 22,
|
||||
|
||||
/// <summary>
|
||||
/// Interface error. A specified outgoing interface could not be
|
||||
/// used. Set which interface to use for outgoing connections'
|
||||
/// source IP address with <see cref="CurlOption.Interface" />.
|
||||
/// </summary>
|
||||
InterfaceFailed = 45,
|
||||
|
||||
/// <summary>
|
||||
/// End-of-enumeration marker; do not use in client applications.
|
||||
/// </summary>
|
||||
Last = 67,
|
||||
|
||||
/// <summary>
|
||||
/// LDAP cannot bind. LDAP bind operation failed.
|
||||
/// </summary>
|
||||
LdapCannotBind = 38,
|
||||
|
||||
/// <summary>
|
||||
/// Invalid LDAP URL.
|
||||
/// </summary>
|
||||
LdapInvalidUrl = 62,
|
||||
|
||||
/// <summary>
|
||||
/// LDAP search failed.
|
||||
/// </summary>
|
||||
LdapSearchFailed = 39,
|
||||
|
||||
/// <summary>
|
||||
/// Library not found. The LDAP library was not found.
|
||||
/// </summary>
|
||||
LibraryNotFound = 40,
|
||||
|
||||
/// <summary>
|
||||
/// Malformat user. User name badly specified. *Not currently used*
|
||||
/// </summary>
|
||||
MalformatUser = 24,
|
||||
|
||||
/// <summary>
|
||||
/// This is not an error. This used to be another error code in an
|
||||
/// old libcurl version and is currently unused.
|
||||
/// </summary>
|
||||
Obsolete = 50,
|
||||
|
||||
/// <summary>
|
||||
/// Operation timeout. The specified time-out period was reached
|
||||
/// according to the conditions.
|
||||
/// </summary>
|
||||
OperationTimeouted = 28,
|
||||
|
||||
/// <summary>
|
||||
/// Out of memory. A memory allocation request failed. This is serious
|
||||
/// badness and things are severely messed up if this ever occurs.
|
||||
/// </summary>
|
||||
OutOfMemory = 27,
|
||||
|
||||
/// <summary>
|
||||
/// A file transfer was shorter or larger than expected. This
|
||||
/// happens when the server first reports an expected transfer size,
|
||||
/// and then delivers data that doesn't match the previously
|
||||
/// given size.
|
||||
/// </summary>
|
||||
PartialFile = 18,
|
||||
|
||||
/// <summary>
|
||||
/// There was a problem reading a local file or an error returned by
|
||||
/// the read callback.
|
||||
/// </summary>
|
||||
ReadError = 26,
|
||||
|
||||
/// <summary>
|
||||
/// Failure with receiving network data.
|
||||
/// </summary>
|
||||
RecvError = 56,
|
||||
|
||||
/// <summary>
|
||||
/// Failed sending network data.
|
||||
/// </summary>
|
||||
SendError = 55,
|
||||
|
||||
/// <summary>
|
||||
/// Sending the data requires a rewind that failed.
|
||||
/// </summary>
|
||||
SendFailRewind = 65,
|
||||
|
||||
/// <summary>
|
||||
/// CurlShare is in use.
|
||||
/// </summary>
|
||||
ShareInUse = 57,
|
||||
|
||||
/// <summary>
|
||||
/// Problem with the CA cert (path? access rights?)
|
||||
/// </summary>
|
||||
SslCaCert = 60,
|
||||
|
||||
/// <summary>
|
||||
/// There's a problem with the local client certificate.
|
||||
/// </summary>
|
||||
SslCertProblem = 58,
|
||||
|
||||
/// <summary>
|
||||
/// Couldn't use specified cipher.
|
||||
/// </summary>
|
||||
SslCipher = 59,
|
||||
|
||||
/// <summary>
|
||||
/// A problem occurred somewhere in the Ssl/TLS handshake. You really
|
||||
/// want to use the <see cref="CurlEasy.CurlDebugCallback" /> delegate and read
|
||||
/// the message there as it pinpoints the problem slightly more. It
|
||||
/// could be certificates (file formats, paths, permissions),
|
||||
/// passwords, and others.
|
||||
/// </summary>
|
||||
SslConnectError = 35,
|
||||
|
||||
/// <summary>
|
||||
/// Failed to initialize Ssl engine.
|
||||
/// </summary>
|
||||
SslEngineInitFailed = 66,
|
||||
|
||||
/// <summary>
|
||||
/// The specified crypto engine wasn't found.
|
||||
/// </summary>
|
||||
SslEngineNotFound = 53,
|
||||
|
||||
/// <summary>
|
||||
/// Failed setting the selected Ssl crypto engine as default!
|
||||
/// </summary>
|
||||
SslEngineSetFailed = 54,
|
||||
|
||||
/// <summary>
|
||||
/// The remote server's Ssl certificate was deemed not OK.
|
||||
/// </summary>
|
||||
SslPeerCertificate = 51,
|
||||
|
||||
/// <summary>
|
||||
/// A telnet option string was improperly formatted.
|
||||
/// </summary>
|
||||
TelnetOptionSyntax = 49,
|
||||
|
||||
/// <summary>
|
||||
/// Too many redirects. When following redirects, libcurl hit the
|
||||
/// maximum amount. Set your limit with
|
||||
/// <see cref="CurlOption.MaxRedirs" />.
|
||||
/// </summary>
|
||||
TooManyRedirects = 47,
|
||||
|
||||
/// <summary>
|
||||
/// An option set with <see cref="CurlOption.TelnetOptions" />
|
||||
/// was not recognized/known. Refer to the appropriate documentation.
|
||||
/// </summary>
|
||||
UnknownTelnetOption = 48,
|
||||
|
||||
/// <summary>
|
||||
/// The URL you passed to libcurl used a protocol that this libcurl
|
||||
/// does not support. The support might be a compile-time option that
|
||||
/// wasn't used, it can be a misspelled protocol string or just a
|
||||
/// protocol libcurl has no code for.
|
||||
/// </summary>
|
||||
UnsupportedProtocol = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The URL was not properly formatted.
|
||||
/// </summary>
|
||||
UrlMalformat = 3,
|
||||
|
||||
/// <summary>
|
||||
/// URL user malformatted. The user-part of the URL syntax was not
|
||||
/// correct.
|
||||
/// </summary>
|
||||
UrlMalformatUser = 4,
|
||||
|
||||
/// <summary>
|
||||
/// An error occurred when writing received data to a local file,
|
||||
/// or an error was returned to libcurl from a write callback.
|
||||
/// </summary>
|
||||
WriteError = 23,
|
||||
};
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Project: libcurl.NET
|
||||
*
|
||||
* Copyright (c) 2004, 2005 Jeff Phillips (jeff@jeffp.net)
|
||||
*
|
||||
* This software is licensed as described in the file LICENSE, which you
|
||||
* should have received as part of this distribution.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of this Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the LICENSE file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
|
||||
* ANY KIND, either express or implied.
|
||||
*
|
||||
* $Id: Enums.cs,v 1.1 2005/02/17 22:47:25 jeffreyphillips Exp $
|
||||
**************************************************************************/
|
||||
|
||||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// One of these is returned by <see cref="CurlHttpMultiPartForm.AddSection" />.
|
||||
/// </summary>
|
||||
public enum CurlFormCode
|
||||
{
|
||||
/// <summary>
|
||||
/// The section was added properly.
|
||||
/// </summary>
|
||||
Ok = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Out-of-memory when adding the section.
|
||||
/// </summary>
|
||||
Memory = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Invalid attempt to add the same option more than once to a
|
||||
/// section.
|
||||
/// </summary>
|
||||
OptionTwice = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Invalid attempt to pass a <c>null</c> string or byte array in
|
||||
/// one of the arguments.
|
||||
/// </summary>
|
||||
Null = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Invalid attempt to pass an unrecognized option in one of the
|
||||
/// arguments.
|
||||
/// </summary>
|
||||
UnknownOption = 4,
|
||||
|
||||
/// <summary>
|
||||
/// Incomplete argument lists.
|
||||
/// </summary>
|
||||
Incomplete = 5,
|
||||
|
||||
/// <summary>
|
||||
/// Invalid attempt to provide a nested <c>Array</c>.
|
||||
/// </summary>
|
||||
IllegalArray = 6,
|
||||
|
||||
/// <summary>
|
||||
/// This will not be returned so long as HTTP is enabled, which
|
||||
/// it always is in libcurl.NET.
|
||||
/// </summary>
|
||||
Disabled = 7,
|
||||
|
||||
/// <summary>
|
||||
/// End-of-enumeration marker; do not use in application code.
|
||||
/// </summary>
|
||||
Last = 8
|
||||
};
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// These are options available to build a multi-part form section
|
||||
/// in a call to <see cref="CurlHttpMultiPartForm.AddSection" />
|
||||
/// </summary>
|
||||
public enum CurlFormOption
|
||||
{
|
||||
/// <summary>
|
||||
/// Another possibility to send options to
|
||||
/// <see cref="CurlHttpMultiPartForm.AddSection" /> is this option, that
|
||||
/// passes a <see cref="CurlForms" /> array reference as its value.
|
||||
/// Each <see cref="CurlForms" /> array element has a
|
||||
/// <see cref="CurlFormOption" /> and a <c>string</c>. All available
|
||||
/// options can be used in an array, except the <c>Array</c>
|
||||
/// option itself! The last argument in such an array must always be
|
||||
/// <c>End</c>.
|
||||
/// </summary>
|
||||
Array = 8,
|
||||
|
||||
/// <summary>
|
||||
/// Followed by a <c>string</c>, tells libcurl that a buffer is to be
|
||||
/// used to upload data instead of using a file.
|
||||
/// </summary>
|
||||
Buffer = 11,
|
||||
|
||||
/// <summary>
|
||||
/// Followed by an <c>int</c> with the size of the
|
||||
/// <c>BufferPtr</c> byte array, tells libcurl the length of
|
||||
/// the data to upload.
|
||||
/// </summary>
|
||||
BufferLength = 13,
|
||||
|
||||
/// <summary>
|
||||
/// Followed by a <c>byte[]</c> array, tells libcurl the address of
|
||||
/// the buffer containing data to upload (as indicated with
|
||||
/// <c>Buffer</c>). You must also use
|
||||
/// <c>BufferLength</c> to set the length of the buffer area.
|
||||
/// </summary>
|
||||
BufferPtr = 12,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies extra headers for the form POST section. This takes an
|
||||
/// <see cref="CurlSlist" /> prepared in the usual way using
|
||||
/// <see cref="CurlSlist.Append" /> and appends the list of headers to
|
||||
/// those libcurl automatically generates.
|
||||
/// </summary>
|
||||
ContentHeader = 15,
|
||||
|
||||
/// <summary>
|
||||
/// Followed by an <c>int</c> setting the length of the contents.
|
||||
/// </summary>
|
||||
ContentsLength = 6,
|
||||
|
||||
/// <summary>
|
||||
/// Followed by a <c>string</c> with a content-type will make cURL
|
||||
/// use this given content-type for this file upload part, possibly
|
||||
/// instead of an internally chosen one.
|
||||
/// </summary>
|
||||
ContentType = 14,
|
||||
|
||||
/// <summary>
|
||||
/// Followed by a <c>string</c> is used for the contents of this part, the
|
||||
/// actual data to send away. If you'd like it to contain zero bytes,
|
||||
/// you need to set the length of the name with
|
||||
/// <c>ContentsLength</c>.
|
||||
/// </summary>
|
||||
CopyContents = 4,
|
||||
|
||||
/// <summary>
|
||||
/// Followed by a <c>string</c> used to set the name of this part.
|
||||
/// If you'd like it to contain zero bytes, you need to set the
|
||||
/// length of the name with <c>NameLength</c>.
|
||||
/// </summary>
|
||||
CopyName = 1,
|
||||
|
||||
/// <summary>
|
||||
/// This should be the last argument to a call to
|
||||
/// <see cref="CurlHttpMultiPartForm.AddSection" />.
|
||||
/// </summary>
|
||||
End = 17,
|
||||
|
||||
/// <summary>
|
||||
/// Followed by a file name, makes this part a file upload part. It
|
||||
/// sets the file name field to the actual file name used here,
|
||||
/// it gets the contents of the file and passes as data and sets the
|
||||
/// content-type if the given file match one of the new internally
|
||||
/// known file extension. For <c>File</c> the user may send
|
||||
/// one or more files in one part by providing multiple <c>File</c>
|
||||
/// arguments each followed by the filename (and each <c>File</c>
|
||||
/// is allowed to have a <c>ContentType</c>).
|
||||
/// </summary>
|
||||
File = 10,
|
||||
|
||||
/// <summary>
|
||||
/// Followed by a file name, and does the file read: the contents
|
||||
/// will be used in as data in this part.
|
||||
/// </summary>
|
||||
FileContent = 7,
|
||||
|
||||
/// <summary>
|
||||
/// Followed by a <c>string</c> file name, will make libcurl use the
|
||||
/// given name in the file upload part, instead of the actual file
|
||||
/// name given to <c>File</c>.
|
||||
/// </summary>
|
||||
Filename = 16,
|
||||
|
||||
/// <summary>
|
||||
/// Followed by an <c>int</c> setting the length of the name.
|
||||
/// </summary>
|
||||
NameLength = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Not used.
|
||||
/// </summary>
|
||||
Nothing = 0,
|
||||
|
||||
/// <summary>
|
||||
/// No longer used.
|
||||
/// </summary>
|
||||
Obsolete = 9,
|
||||
|
||||
/// <summary>
|
||||
/// No longer used.
|
||||
/// </summary>
|
||||
Obsolete2 = 18,
|
||||
|
||||
/// <summary>
|
||||
/// Followed by a <c>byte[]</c> used for the contents of this part.
|
||||
/// If you'd like it to contain zero bytes, you need to set the
|
||||
/// length of the name with <c>ContentsLength</c>.
|
||||
/// </summary>
|
||||
PtrContents = 5,
|
||||
|
||||
/// <summary>
|
||||
/// Followed by a <c>byte[]</c> used for the name of this part.
|
||||
/// If you'd like it to contain zero bytes, you need to set the
|
||||
/// length of the name with <c>NameLength</c>.
|
||||
/// </summary>
|
||||
PtrName = 2
|
||||
};
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This enumeration contains values used to specify the FTP Ssl
|
||||
/// authorization level using the
|
||||
/// <see cref="CurlOption.FtpSslAuth" /> option when calling
|
||||
/// <see cref="CurlEasy.SetOpt" />
|
||||
/// </summary>
|
||||
public enum CurlFtpAuth
|
||||
{
|
||||
/// <summary>
|
||||
/// Let <c>libcurl</c> decide on the authorization scheme.
|
||||
/// </summary>
|
||||
Default = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Use "AUTH Ssl".
|
||||
/// </summary>
|
||||
SSL = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Use "AUTH TLS".
|
||||
/// </summary>
|
||||
TLS = 2,
|
||||
|
||||
/// <summary>
|
||||
/// End-of-enumeration marker. Do not use in a client application.
|
||||
/// </summary>
|
||||
Last = 3
|
||||
};
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This enumeration contains values used to specify the FTP Ssl level
|
||||
/// using the <see cref="CurlOption.FtpSsl" /> option when calling
|
||||
/// <see cref="CurlEasy.SetOpt" />
|
||||
/// </summary>
|
||||
public enum CurlFtpSsl
|
||||
{
|
||||
/// <summary>
|
||||
/// Don't attempt to use Ssl.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Try using Ssl, proceed as normal otherwise.
|
||||
/// </summary>
|
||||
Try = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Require Ssl for the control connection or fail with
|
||||
/// <see cref="CurlCode.FtpSslFailed" />.
|
||||
/// </summary>
|
||||
Control = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Require Ssl for all communication or fail with
|
||||
/// <see cref="CurlCode.FtpSslFailed" />.
|
||||
/// </summary>
|
||||
All = 3,
|
||||
|
||||
/// <summary>
|
||||
/// End-of-enumeration marker. Do not use in a client application.
|
||||
/// </summary>
|
||||
Last = 4
|
||||
};
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This enumeration contains values used to specify the HTTP authentication
|
||||
/// when using the <see cref="CurlOption.HttpAuth" /> option when
|
||||
/// calling <see cref="CurlEasy.SetOpt" />
|
||||
/// </summary>
|
||||
public enum CurlHttpAuth
|
||||
{
|
||||
/// <summary>
|
||||
/// No authentication.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// HTTP Basic authentication. This is the default choice, and the
|
||||
/// only method that is in wide-spread use and supported virtually
|
||||
/// everywhere. This is sending the user name and password over the
|
||||
/// network in plain text, easily captured by others.
|
||||
/// </summary>
|
||||
Basic = 1,
|
||||
|
||||
/// <summary>
|
||||
/// HTTP Digest authentication. Digest authentication is defined
|
||||
/// in RFC2617 and is a more secure way to do authentication over
|
||||
/// public networks than the regular old-fashioned Basic method.
|
||||
/// </summary>
|
||||
Digest = 2,
|
||||
|
||||
/// <summary>
|
||||
/// HTTP GSS-Negotiate authentication. The GSS-Negotiate (also known
|
||||
/// as plain "Negotiate") method was designed by Microsoft and is
|
||||
/// used in their web applications. It is primarily meant as a
|
||||
/// support for Kerberos5 authentication but may be also used along
|
||||
/// with another authentication methods. For more information see IETF
|
||||
/// draft draft-brezak-spnego-http-04.txt.
|
||||
/// <note>
|
||||
/// You need to use a version of libcurl.NET built with a suitable
|
||||
/// GSS-API library for this to work. This is not currently standard.
|
||||
/// </note>
|
||||
/// </summary>
|
||||
GssNegotiate = 4,
|
||||
|
||||
/// <summary>
|
||||
/// HTTP Ntlm authentication. A proprietary protocol invented and
|
||||
/// used by Microsoft. It uses a challenge-response and hash concept
|
||||
/// similar to Digest, to prevent the password from being eavesdropped.
|
||||
/// </summary>
|
||||
Ntlm = 8,
|
||||
|
||||
/// <summary>
|
||||
/// This is a convenience macro that sets all bits and thus makes
|
||||
/// libcurl pick any it finds suitable. libcurl will automatically
|
||||
/// select the one it finds most secure.
|
||||
/// </summary>
|
||||
Any = 15, // ~0
|
||||
|
||||
/// <summary>
|
||||
/// This is a convenience macro that sets all bits except Basic
|
||||
/// and thus makes libcurl pick any it finds suitable. libcurl
|
||||
/// will automatically select the one it finds most secure.
|
||||
/// </summary>
|
||||
AnySafe = 14 // ~Basic
|
||||
};
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains values used to specify the HTTP version level when using
|
||||
/// the <see cref="CurlOption.HttpVersion" /> option in a call
|
||||
/// to <see cref="CurlEasy.SetOpt" />
|
||||
/// </summary>
|
||||
public enum CurlHttpVersion
|
||||
{
|
||||
/// <summary>
|
||||
/// We don't care about what version the library uses. libcurl will
|
||||
/// use whatever it thinks fit.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Enforce HTTP 1.0 requests.
|
||||
/// </summary>
|
||||
Http1_0 = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Enforce HTTP 1.1 requests.
|
||||
/// </summary>
|
||||
Http1_1 = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Last entry in enumeration; do not use in application code.
|
||||
/// </summary>
|
||||
Last = 3
|
||||
};
|
||||
}
|
|
@ -0,0 +1,222 @@
|
|||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This enumeration is used to extract information associated with an
|
||||
/// <see cref="CurlEasy" /> transfer. Specifically, a member of this
|
||||
/// enumeration is passed as the first argument to
|
||||
/// CurlEasy.GetInfo specifying the item to retrieve in the
|
||||
/// second argument, which is a reference to an <c>int</c>, a
|
||||
/// <c>double</c>, a <c>string</c>, a <c>DateTime</c> or an <c>object</c>.
|
||||
/// </summary>
|
||||
public enum CurlInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// The second argument receives the elapsed time, as a <c>double</c>,
|
||||
/// in seconds, from the start until the connect to the remote host
|
||||
/// (or proxy) was completed.
|
||||
/// </summary>
|
||||
ConnectTime = 0x300005,
|
||||
|
||||
/// <summary>
|
||||
/// The second argument receives, as a <c>double</c>, the content-length
|
||||
/// of the download. This is the value read from the Content-Length: field.
|
||||
/// </summary>
|
||||
ContentLengthDownload = 0x30000F,
|
||||
|
||||
/// <summary>
|
||||
/// The second argument receives, as a <c>double</c>, the specified size
|
||||
/// of the upload.
|
||||
/// </summary>
|
||||
ContentLengthUpload = 0x300010,
|
||||
|
||||
/// <summary>
|
||||
/// The second argument receives, as a <c>string</c>, the content-type of
|
||||
/// the downloaded object. This is the value read from the Content-Type:
|
||||
/// field. If you get <c>null</c>, it means that the server didn't
|
||||
/// send a valid Content-Type header or that the protocol used
|
||||
/// doesn't support this.
|
||||
/// </summary>
|
||||
ContentType = 0x100012,
|
||||
|
||||
/// <summary>
|
||||
/// The second argument receives, as a <c>string</c>, the last
|
||||
/// used effective URL.
|
||||
/// </summary>
|
||||
EffectiveUrl = 0x100001,
|
||||
|
||||
/// <summary>
|
||||
/// The second argument receives, as a <c>long</c>, the remote time
|
||||
/// of the retrieved document. You should construct a <c>DateTime</c>
|
||||
/// from this value, as shown in the <c>InfoDemo</c> sample. If you
|
||||
/// get a date in the distant
|
||||
/// past, it can be because of many reasons (unknown, the server
|
||||
/// hides it or the server doesn't support the command that tells
|
||||
/// document time etc) and the time of the document is unknown. Note
|
||||
/// that you must tell the server to collect this information before
|
||||
/// the transfer is made, by using the
|
||||
/// <see cref="CurlOption.Filetime" /> option to
|
||||
/// <see cref="CurlEasy.SetOpt" />. (Added in 7.5)
|
||||
/// </summary>
|
||||
Filetime = 0x20000E,
|
||||
|
||||
/// <summary>
|
||||
/// The second argument receives an <c>int</c> specifying the total size
|
||||
/// of all the headers received.
|
||||
/// </summary>
|
||||
HeaderSize = 0x20000B,
|
||||
|
||||
/// <summary>
|
||||
/// The second argument receives, as an <c>int</c>, a bitmask indicating
|
||||
/// the authentication method(s) available. The meaning of the bits is
|
||||
/// explained in the documentation of
|
||||
/// <see cref="CurlOption.HttpAuth" />. (Added in 7.10.8)
|
||||
/// </summary>
|
||||
HttpAuthAvail = 0x200017,
|
||||
|
||||
/// <summary>
|
||||
/// The second argument receives an <c>int</c> indicating the numeric
|
||||
/// connect code for the HTTP request.
|
||||
/// </summary>
|
||||
HttpConnectCode = 0x200016,
|
||||
|
||||
/// <summary>
|
||||
/// End-of-enumeration marker; do not use in client applications.
|
||||
/// </summary>
|
||||
LastOne = 0x1C,
|
||||
|
||||
/// <summary>
|
||||
/// The second argument receives, as a <c>double</c>, the time, in
|
||||
/// seconds it took from the start until the name resolving was
|
||||
/// completed.
|
||||
/// </summary>
|
||||
NameLookupTime = 0x300004,
|
||||
|
||||
/// <summary>
|
||||
/// Never used.
|
||||
/// </summary>
|
||||
None = 0x0,
|
||||
|
||||
/// <summary>
|
||||
/// The second argument receives an <c>int</c> indicating the
|
||||
/// number of current connections. (Added in 7.13.0)
|
||||
/// </summary>
|
||||
NumConnects = 0x20001A,
|
||||
|
||||
/// <summary>
|
||||
/// The second argument receives an <c>int</c> indicating the operating
|
||||
/// system error number: <c>_errro</c> or <c>GetLastError()</c>,
|
||||
/// depending on the platform. (Added in 7.12.2)
|
||||
/// </summary>
|
||||
OsErrno = 0x200019,
|
||||
|
||||
/// <summary>
|
||||
/// The second argument receives, as a <c>double</c>, the time, in
|
||||
/// seconds, it took from the start until the file transfer is just about
|
||||
/// to begin. This includes all pre-transfer commands and negotiations
|
||||
/// that are specific to the particular protocol(s) involved.
|
||||
/// </summary>
|
||||
PreTransferTime = 0x300006,
|
||||
|
||||
/// <summary>
|
||||
/// The second argument receives a reference to the private data
|
||||
/// associated with the <see cref="CurlEasy" /> object (set with the
|
||||
/// <see cref="CurlOption.Private" /> option to
|
||||
/// <see cref="CurlEasy.SetOpt" />. (Added in 7.10.3)
|
||||
/// </summary>
|
||||
Private = 0x100015,
|
||||
|
||||
/// <summary>
|
||||
/// The second argument receives, as an <c>int</c>, a bitmask
|
||||
/// indicating the authentication method(s) available for your
|
||||
/// proxy authentication. This will be a bitmask of
|
||||
/// <see cref="CurlHttpAuth" /> enumeration constants.
|
||||
/// (Added in 7.10.8)
|
||||
/// </summary>
|
||||
ProxyAuthAvail = 0x200018,
|
||||
|
||||
/// <summary>
|
||||
/// The second argument receives an <c>int</c> indicating the total
|
||||
/// number of redirections that were actually followed. (Added in 7.9.7)
|
||||
/// </summary>
|
||||
RedirectCount = 0x200014,
|
||||
|
||||
/// <summary>
|
||||
/// The second argument receives, as a <c>double</c>, the total time, in
|
||||
/// seconds, for all redirection steps include name lookup, connect,
|
||||
/// pretransfer and transfer before final transaction was started.
|
||||
/// <c>RedirectTime</c> contains the complete execution
|
||||
/// time for multiple redirections. (Added in 7.9.7)
|
||||
/// </summary>
|
||||
RedirectTime = 0x300013,
|
||||
|
||||
/// <summary>
|
||||
/// The second argument receives an <c>int</c> containing the total size
|
||||
/// of the issued requests. This is so far only for HTTP requests. Note
|
||||
/// that this may be more than one request if
|
||||
/// <see cref="CurlOption.FollowLocation" /> is <c>true</c>.
|
||||
/// </summary>
|
||||
RequestSize = 0x20000C,
|
||||
|
||||
/// <summary>
|
||||
/// The second argument receives an <c>int</c> with the last received HTTP
|
||||
/// or FTP code. This option was known as <c>CURLINFO_HTTP_CODE</c> in
|
||||
/// libcurl 7.10.7 and earlier.
|
||||
/// </summary>
|
||||
ResponseCode = 0x200002,
|
||||
|
||||
/// <summary>
|
||||
/// The second argument receives a <c>double</c> with the total amount of
|
||||
/// bytes that were downloaded. The amount is only for the latest transfer
|
||||
/// and will be reset again for each new transfer.
|
||||
/// </summary>
|
||||
SizeDownload = 0x300008,
|
||||
|
||||
/// <summary>
|
||||
/// The second argument receives a <c>double</c> with the total amount
|
||||
/// of bytes that were uploaded.
|
||||
/// </summary>
|
||||
SizeUpload = 0x300007,
|
||||
|
||||
/// <summary>
|
||||
/// The second argument receives a <c>double</c> with the average
|
||||
/// download speed that cURL measured for the complete download.
|
||||
/// </summary>
|
||||
SpeedDownload = 0x300009,
|
||||
|
||||
/// <summary>
|
||||
/// The second argument receives a <c>double</c> with the average
|
||||
/// upload speed that libcurl measured for the complete upload.
|
||||
/// </summary>
|
||||
SpeedUpload = 0x30000A,
|
||||
|
||||
/// <summary>
|
||||
/// The second argument receives an <see cref="CurlSlist" /> containing
|
||||
/// the names of the available Ssl engines.
|
||||
/// </summary>
|
||||
SslEngines = 0x40001B,
|
||||
|
||||
/// <summary>
|
||||
/// The second argument receives an <c>int</c> with the result of
|
||||
/// the certificate verification that was requested (using the
|
||||
/// <see cref="CurlOption.SslVerifyPeer" /> option in
|
||||
/// <see cref="CurlEasy.SetOpt" />.
|
||||
/// </summary>
|
||||
SslVerifyResult = 0x20000D,
|
||||
|
||||
/// <summary>
|
||||
/// The second argument receives a <c>double</c> specifying the time,
|
||||
/// in seconds, from the start until the first byte is just about to be
|
||||
/// transferred. This includes <c>PreTransferTime</c> and
|
||||
/// also the time the server needs to calculate the result.
|
||||
/// </summary>
|
||||
StartTransferTime = 0x300011,
|
||||
|
||||
/// <summary>
|
||||
/// The second argument receives a <c>double</c> indicating the total transaction
|
||||
/// time in seconds for the previous transfer. This time does not include
|
||||
/// the connect time, so if you want the complete operation time,
|
||||
/// you should add the <c>ConnectTime</c>.
|
||||
/// </summary>
|
||||
TotalTime = 0x300003,
|
||||
};
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// A member of this enumeration is passed as the first parameter to the
|
||||
/// <see cref="CurlEasy.CurlDebugCallback" /> delegate to which libcurl passes
|
||||
/// debug messages.
|
||||
/// </summary>
|
||||
public enum CurlInfoType
|
||||
{
|
||||
/// <summary>
|
||||
/// The data is informational text.
|
||||
/// </summary>
|
||||
Text = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The data is header (or header-like) data received from the peer.
|
||||
/// </summary>
|
||||
HeaderIn = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The data is header (or header-like) data sent to the peer.
|
||||
/// </summary>
|
||||
HeaderOut = 2,
|
||||
|
||||
/// <summary>
|
||||
/// The data is protocol data received from the peer.
|
||||
/// </summary>
|
||||
DataIn = 3,
|
||||
|
||||
/// <summary>
|
||||
/// The data is protocol data sent to the peer.
|
||||
/// </summary>
|
||||
DataOut = 4,
|
||||
|
||||
/// <summary>
|
||||
/// The data is Ssl-related data sent to the peer.
|
||||
/// </summary>
|
||||
SslDataIn = 5,
|
||||
|
||||
/// <summary>
|
||||
/// The data is Ssl-related data received from the peer.
|
||||
/// </summary>
|
||||
SslDataOut = 6,
|
||||
|
||||
/// <summary>
|
||||
/// End of enumeration marker, don't use in a client application.
|
||||
/// </summary>
|
||||
End = 7
|
||||
};
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains values used to initialize libcurl internally. One of
|
||||
/// these is passed in the call to <see cref="Curl.GlobalInit" />.
|
||||
/// </summary>
|
||||
public enum CurlInitFlag
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialise nothing extra. This sets no bit.
|
||||
/// </summary>
|
||||
Nothing = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Initialize Ssl.
|
||||
/// </summary>
|
||||
Ssl = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the Win32 socket libraries.
|
||||
/// </summary>
|
||||
Win32 = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Initialize everything possible. This sets all known bits.
|
||||
/// </summary>
|
||||
All = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Equivalent to <c>All</c>.
|
||||
/// </summary>
|
||||
Default = All
|
||||
};
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Your handler for the <see cref="CurlEasy.CurlIoctlCallback" />
|
||||
/// delegate is passed one of these values as its first parameter.
|
||||
/// Right now, the only supported value is
|
||||
/// <code>RestartRead</code>.
|
||||
/// </summary>
|
||||
public enum CurlIoCommand
|
||||
{
|
||||
/// <summary>
|
||||
/// No IOCTL operation; we should never see this.
|
||||
/// </summary>
|
||||
Nop = 0,
|
||||
|
||||
/// <summary>
|
||||
/// When this is sent, your callback may need to, for example,
|
||||
/// rewind a local file that is being sent via FTP.
|
||||
/// </summary>
|
||||
RestartRead = 1,
|
||||
|
||||
/// <summary>
|
||||
/// End of enumeration marker, don't use in a client application.
|
||||
/// </summary>
|
||||
Last = 2
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Your handler for the <see cref="CurlEasy.CurlIoctlCallback" /> delegate
|
||||
/// should return a member of this enumeration.
|
||||
/// </summary>
|
||||
public enum CurlIoError
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicate that the callback processed everything okay.
|
||||
/// </summary>
|
||||
Ok = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Unknown command sent to callback. Right now, only
|
||||
/// <code>RestartRead</code> is supported.
|
||||
/// </summary>
|
||||
UnknownCommand = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate to libcurl that a restart failed.
|
||||
/// </summary>
|
||||
FailRestart = 2,
|
||||
|
||||
/// <summary>
|
||||
/// End of enumeration marker, don't use in a client application.
|
||||
/// </summary>
|
||||
Last = 3
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This enumeration contains values used to specify the IP resolution
|
||||
/// method when using the <see cref="CurlOption.IpResolve" />
|
||||
/// option in a call to <see cref="CurlEasy.SetOpt" />
|
||||
/// </summary>
|
||||
public enum CurlIpResolve
|
||||
{
|
||||
/// <summary>
|
||||
/// Default, resolves addresses to all IP versions that your system
|
||||
/// allows.
|
||||
/// </summary>
|
||||
Whatever = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Resolve to ipv4 addresses.
|
||||
/// </summary>
|
||||
V4 = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Resolve to ipv6 addresses.
|
||||
/// </summary>
|
||||
V6 = 2
|
||||
};
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Values containing the type of shared access requested when libcurl
|
||||
/// calls the <see cref="CurlShare.CurlShareLockCallback" /> delegate.
|
||||
/// </summary>
|
||||
public enum CurlLockAccess
|
||||
{
|
||||
/// <summary>
|
||||
/// Unspecified action; the delegate should never receive this.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The delegate receives this call when libcurl is requesting
|
||||
/// read access to the shared resource.
|
||||
/// </summary>
|
||||
Shared = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The delegate receives this call when libcurl is requesting
|
||||
/// write access to the shared resource.
|
||||
/// </summary>
|
||||
Single = 2,
|
||||
|
||||
/// <summary>
|
||||
/// End-of-enumeration marker; do not use in application code.
|
||||
/// </summary>
|
||||
Last = 3
|
||||
};
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Members of this enumeration should be passed to
|
||||
/// <see cref="CurlShare.SetOpt" /> when it is called with the
|
||||
/// <c>CurlShare</c> or <c>Unshare</c> options
|
||||
/// provided in the <see cref="CurlShareOption" /> enumeration.
|
||||
/// </summary>
|
||||
public enum CurlLockData
|
||||
{
|
||||
/// <summary>
|
||||
/// Not used.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Used internally by libcurl.
|
||||
/// </summary>
|
||||
Share = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Cookie data will be shared across the <see cref="CurlEasy" /> objects
|
||||
/// using this shared object.
|
||||
/// </summary>
|
||||
Cookie = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Cached Dns hosts will be shared across the <see cref="CurlEasy" />
|
||||
/// objects using this shared object.
|
||||
/// </summary>
|
||||
Dns = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Not supported yet.
|
||||
/// </summary>
|
||||
SslSession = 4,
|
||||
|
||||
/// <summary>
|
||||
/// Not supported yet.
|
||||
/// </summary>
|
||||
Connect = 5,
|
||||
|
||||
/// <summary>
|
||||
/// End-of-enumeration marker; do not use in application code.
|
||||
/// </summary>
|
||||
Last = 6
|
||||
};
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// The status code associated with an <see cref="CurlEasy" /> object in a
|
||||
/// <see cref="CurlMulti" /> operation. One of these is returned in response
|
||||
/// to reading the <see cref="CurlMultiInfo.Msg" /> property.
|
||||
/// </summary>
|
||||
public enum CurlMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// First entry in the enumeration, not used.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The associated <see cref="CurlEasy" /> object completed.
|
||||
/// </summary>
|
||||
Done = 1,
|
||||
|
||||
/// <summary>
|
||||
/// End-of-enumeration marker, not used.
|
||||
/// </summary>
|
||||
Last = 2
|
||||
};
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains return codes for many of the functions in the
|
||||
/// <see cref="CurlMulti" /> class.
|
||||
/// </summary>
|
||||
public enum CurlMultiCode
|
||||
{
|
||||
/// <summary>
|
||||
/// You should call <see cref="CurlMulti.Perform" /> again before calling
|
||||
/// <see cref="CurlMulti.Select" />.
|
||||
/// </summary>
|
||||
CallMultiPerform = -1,
|
||||
|
||||
/// <summary>
|
||||
/// The function succeded.
|
||||
/// </summary>
|
||||
Ok = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The internal <see cref="CurlMulti" /> is bad.
|
||||
/// </summary>
|
||||
BadHandle = 1,
|
||||
|
||||
/// <summary>
|
||||
/// One of the <see cref="CurlEasy" /> handles associated with the
|
||||
/// <see cref="CurlMulti" /> object is bad.
|
||||
/// </summary>
|
||||
BadEasyHandle = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Out of memory. This is a severe problem.
|
||||
/// </summary>
|
||||
OutOfMemory = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Internal error deep within the libcurl library.
|
||||
/// </summary>
|
||||
InternalError = 4,
|
||||
|
||||
/// <summary>
|
||||
/// End-of-enumeration marker, not used.
|
||||
/// </summary>
|
||||
Last = 5
|
||||
};
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains values used to specify the preference of libcurl between
|
||||
/// using user names and passwords from your ~/.netrc file, relative to
|
||||
/// user names and passwords in the URL supplied with
|
||||
/// <see cref="CurlOption.Url" />. This is passed when using
|
||||
/// the <see cref="CurlOption.Netrc" /> option in a call
|
||||
/// to <see cref="CurlEasy.SetOpt" />
|
||||
/// </summary>
|
||||
public enum CurlNetrcOption
|
||||
{
|
||||
/// <summary>
|
||||
/// The library will ignore the file and use only the information
|
||||
/// in the URL. This is the default.
|
||||
/// </summary>
|
||||
Ignored = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The use of your ~/.netrc file is optional, and information in the
|
||||
/// URL is to be preferred. The file will be scanned with the host
|
||||
/// and user name (to find the password only) or with the host only,
|
||||
/// to find the first user name and password after that machine,
|
||||
/// which ever information is not specified in the URL.
|
||||
/// <para>
|
||||
/// Undefined values of the option will have this effect.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
Optional = 1,
|
||||
|
||||
/// <summary>
|
||||
/// This value tells the library that use of the file is required,
|
||||
/// to ignore the information in the URL, and to search the file
|
||||
/// with the host only.
|
||||
/// </summary>
|
||||
Required = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Last entry in enumeration; do not use in application code.
|
||||
/// </summary>
|
||||
Last = 3
|
||||
};
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,27 @@
|
|||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This enumeration contains values used to specify the proxy type when
|
||||
/// using the <see cref="CurlOption.Proxy" /> option when calling
|
||||
/// <see cref="CurlEasy.SetOpt" />
|
||||
/// </summary>
|
||||
public enum CurlProxyType
|
||||
{
|
||||
/// <summary>
|
||||
/// Ordinary HTTP proxy.
|
||||
/// </summary>
|
||||
Http = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Use if the proxy supports SOCKS4 user authentication. If you're
|
||||
/// unfamiliar with this, consult your network administrator.
|
||||
/// </summary>
|
||||
Socks4 = 4,
|
||||
|
||||
/// <summary>
|
||||
/// Use if the proxy supports SOCKS5 user authentication. If you're
|
||||
/// unfamiliar with this, consult your network administrator.
|
||||
/// </summary>
|
||||
Socks5 = 5
|
||||
};
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains return codes from many of the functions in the
|
||||
/// <see cref="CurlShare" /> class.
|
||||
/// </summary>
|
||||
public enum CurlShareCode
|
||||
{
|
||||
/// <summary>
|
||||
/// The function succeeded.
|
||||
/// </summary>
|
||||
Ok = 0,
|
||||
|
||||
/// <summary>
|
||||
/// A bad option was passed to <see cref="CurlShare.SetOpt" />.
|
||||
/// </summary>
|
||||
BadOption = 1,
|
||||
|
||||
/// <summary>
|
||||
/// An attempt was made to pass an option to
|
||||
/// <see cref="CurlShare.SetOpt" /> while the CurlShare object is in use.
|
||||
/// </summary>
|
||||
InUse = 2,
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="CurlShare" /> object's internal handle is invalid.
|
||||
/// </summary>
|
||||
Invalid = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Out of memory. This is a severe problem.
|
||||
/// </summary>
|
||||
NoMem = 4,
|
||||
|
||||
/// <summary>
|
||||
/// End-of-enumeration marker; do not use in application code.
|
||||
/// </summary>
|
||||
Last = 5
|
||||
};
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// A member of this enumeration is passed to the function
|
||||
/// <see cref="CurlShare.SetOpt" /> to configure a <see cref="CurlShare" />
|
||||
/// transfer.
|
||||
/// </summary>
|
||||
public enum CurlShareOption
|
||||
{
|
||||
/// <summary>
|
||||
/// Start-of-enumeration; do not use in application code.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The parameter, which should be a member of the
|
||||
/// <see cref="CurlLockData" /> enumeration, specifies a type of
|
||||
/// data that should be shared.
|
||||
/// </summary>
|
||||
Share = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The parameter, which should be a member of the
|
||||
/// <see cref="CurlLockData" /> enumeration, specifies a type of
|
||||
/// data that should be unshared.
|
||||
/// </summary>
|
||||
Unshare = 2,
|
||||
|
||||
/// <summary>
|
||||
/// The parameter should be a reference to a
|
||||
/// <see cref="CurlShare.CurlShareLockCallback" /> delegate.
|
||||
/// </summary>
|
||||
LockFunction = 3,
|
||||
|
||||
/// <summary>
|
||||
/// The parameter should be a reference to a
|
||||
/// <see cref="CurlShare.CurlShareUnlockCallback" /> delegate.
|
||||
/// </summary>
|
||||
UnlockFunction = 4,
|
||||
|
||||
/// <summary>
|
||||
/// The parameter allows you to specify an object reference that
|
||||
/// will passed to the <see cref="CurlShare.CurlShareLockCallback" /> delegate and
|
||||
/// the <see cref="CurlShare.CurlShareUnlockCallback" /> delegate.
|
||||
/// </summary>
|
||||
UserData = 5,
|
||||
|
||||
/// <summary>
|
||||
/// End-of-enumeration; do not use in application code.
|
||||
/// </summary>
|
||||
Last = 6
|
||||
};
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains values used to specify the Ssl version level when using
|
||||
/// the <see cref="CurlOption.SslVersion" /> option in a call
|
||||
/// to <see cref="CurlEasy.SetOpt" />
|
||||
/// </summary>
|
||||
public enum CurlSslVersion
|
||||
{
|
||||
/// <summary>
|
||||
/// Use whatever version the Ssl library selects.
|
||||
/// </summary>
|
||||
Default = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Use TLS version 1.
|
||||
/// </summary>
|
||||
Tlsv1 = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Use Ssl version 2. This is not a good option unless it's the
|
||||
/// only version supported by the remote server.
|
||||
/// </summary>
|
||||
Sslv2 = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Use Ssl version 3. This is a preferred option.
|
||||
/// </summary>
|
||||
Sslv3 = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Last entry in enumeration; do not use in application code.
|
||||
/// </summary>
|
||||
Last = 4
|
||||
};
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains values used to specify the time condition when using
|
||||
/// the <see cref="CurlOption.TimeCondition" /> option in a call
|
||||
/// to <see cref="CurlEasy.SetOpt" />
|
||||
/// </summary>
|
||||
public enum CurlTimeCond
|
||||
{
|
||||
/// <summary>
|
||||
/// Use no time condition.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The time condition is true if the resource has been modified
|
||||
/// since the date/time passed in
|
||||
/// <see cref="CurlOption.TimeValue" />.
|
||||
/// </summary>
|
||||
IfModSince = 1,
|
||||
|
||||
/// <summary>
|
||||
/// True if the resource has not been modified since the date/time
|
||||
/// passed in <see cref="CurlOption.TimeValue" />.
|
||||
/// </summary>
|
||||
IfUnmodSince = 2,
|
||||
|
||||
/// <summary>
|
||||
/// True if the resource's last modification date/time equals that
|
||||
/// passed in <see cref="CurlOption.TimeValue" />.
|
||||
/// </summary>
|
||||
LastMod = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Last entry in enumeration; do not use in application code.
|
||||
/// </summary>
|
||||
Last = 4
|
||||
};
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// A member of this enumeration is passed to the function
|
||||
/// <see cref="Curl.GetVersionInfo" />
|
||||
/// </summary>
|
||||
public enum CurlVersion
|
||||
{
|
||||
/// <summary>
|
||||
/// Capabilities associated with the initial version of libcurl.
|
||||
/// </summary>
|
||||
First = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Capabilities associated with the second version of libcurl.
|
||||
/// </summary>
|
||||
Second = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Capabilities associated with the third version of libcurl.
|
||||
/// </summary>
|
||||
Third = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Same as <c>Third</c>.
|
||||
/// </summary>
|
||||
Now = Third,
|
||||
|
||||
/// <summary>
|
||||
/// End-of-enumeration marker; do not use in application code.
|
||||
/// </summary>
|
||||
Last = 3
|
||||
};
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// A bitmask of libcurl features OR'd together as the value of the
|
||||
/// property <see cref="CurlVersionInfoData.Features" />. The feature
|
||||
/// bits are summarized in the table below.
|
||||
/// </summary>
|
||||
public enum CurlVersionFeatureBitmask
|
||||
{
|
||||
/// <summary>
|
||||
/// Supports Ipv6.
|
||||
/// </summary>
|
||||
Ipv6 = 0x01,
|
||||
|
||||
/// <summary>
|
||||
/// Supports kerberos4 (when using FTP).
|
||||
/// </summary>
|
||||
Kerberos64 = 0x02,
|
||||
|
||||
/// <summary>
|
||||
/// Supports Ssl (HTTPS/FTPS).
|
||||
/// </summary>
|
||||
Ssl = 0x04,
|
||||
|
||||
/// <summary>
|
||||
/// Supports HTTP deflate using libz.
|
||||
/// </summary>
|
||||
LibZ = 0x08,
|
||||
|
||||
/// <summary>
|
||||
/// Supports HTTP Ntlm (added in 7.10.6).
|
||||
/// </summary>
|
||||
Ntlm = 0x10,
|
||||
|
||||
/// <summary>
|
||||
/// Supports HTTP GSS-Negotiate (added in 7.10.6).
|
||||
/// </summary>
|
||||
GssNegotiate = 0x20,
|
||||
|
||||
/// <summary>
|
||||
/// libcurl was built with extra debug capabilities built-in. This
|
||||
/// is mainly of interest for libcurl hackers. (added in 7.10.6)
|
||||
/// </summary>
|
||||
Debug = 0x40,
|
||||
|
||||
/// <summary>
|
||||
/// libcurl was built with support for asynchronous name lookups,
|
||||
/// which allows more exact timeouts (even on Windows) and less
|
||||
/// blocking when using the multi interface. (added in 7.10.7)
|
||||
/// </summary>
|
||||
AsynchDns = 0x80,
|
||||
|
||||
/// <summary>
|
||||
/// libcurl was built with support for Spnego authentication
|
||||
/// (Simple and Protected GSS-API Negotiation Mechanism, defined
|
||||
/// in RFC 2478.) (added in 7.10.8)
|
||||
/// </summary>
|
||||
Spnego = 0x100,
|
||||
|
||||
/// <summary>
|
||||
/// libcurl was built with support for large files.
|
||||
/// </summary>
|
||||
LargeFile = 0x200,
|
||||
|
||||
/// <summary>
|
||||
/// libcurl was built with support for IDNA, domain names with
|
||||
/// international letters.
|
||||
/// </summary>
|
||||
Idn = 0x400
|
||||
};
|
||||
}
|
|
@ -0,0 +1,393 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* CurlS#arp
|
||||
*
|
||||
* Copyright (c) 2014 Dr. Masroor Ehsan (masroore@gmail.com)
|
||||
* Portions copyright (c) 2004, 2005 Jeff Phillips (jeff@jeffp.net)
|
||||
*
|
||||
* This software is licensed as described in the file LICENSE, which you
|
||||
* should have received as part of this distribution.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of this Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the LICENSE file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
|
||||
* ANY KIND, either express or implied.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
//#define USE_LIBCURLSHIM
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// P/Invoke signatures.
|
||||
/// </summary>
|
||||
internal static unsafe class NativeMethods
|
||||
{
|
||||
#if WIN64
|
||||
private const string CURL_LIB = "libcurl64.dll";
|
||||
|
||||
|
||||
#if USE_LIBCURLSHIM
|
||||
private const string CURLSHIM_LIB = "libcurlshim64.dll";
|
||||
#endif
|
||||
|
||||
#else
|
||||
#if LINUX
|
||||
private const string CURL_LIB = "libcurl";
|
||||
#else
|
||||
private const string CURL_LIB = "libcurl.dll";
|
||||
|
||||
|
||||
#if USE_LIBCURLSHIM
|
||||
private const string CURLSHIM_LIB = "libcurlshim.dll";
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#if !USE_LIBCURLSHIM
|
||||
#if LINUX
|
||||
private const string WINSOCK_LIB = "libc";
|
||||
#else
|
||||
private const string WINSOCK_LIB = "ws2_32.dll";
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// internal delegates from cURL
|
||||
|
||||
// libcurl imports
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern CurlCode curl_global_init (int flags);
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern void curl_global_cleanup ();
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
internal static extern IntPtr curl_escape (String url, int length);
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
internal static extern IntPtr curl_unescape (String url, int length);
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern void curl_free (IntPtr p);
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern IntPtr curl_version ();
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern IntPtr curl_easy_init ();
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern void curl_easy_cleanup (IntPtr pCurl);
|
||||
|
||||
[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
|
||||
internal delegate int _CurlGenericCallback (IntPtr ptr, int sz, int nmemb, IntPtr userdata);
|
||||
|
||||
[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
|
||||
internal delegate int _CurlProgressCallback (
|
||||
IntPtr extraData, double dlTotal, double dlNow, double ulTotal, double ulNow);
|
||||
|
||||
[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
|
||||
internal delegate int _CurlDebugCallback (
|
||||
IntPtr ptrCurl, CurlInfoType infoType, string message, int size, IntPtr ptrUserData);
|
||||
|
||||
[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
|
||||
internal delegate int _CurlSslCtxCallback (IntPtr ctx, IntPtr parm);
|
||||
|
||||
[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
|
||||
internal delegate CurlIoError _CurlIoctlCallback (CurlIoCommand cmd, IntPtr parm);
|
||||
|
||||
// curl_easy_setopt() overloads
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern CurlCode curl_easy_setopt (IntPtr pCurl, CurlOption opt, IntPtr parm);
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern CurlCode curl_easy_setopt (IntPtr pCurl, CurlOption opt, string parm);
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern CurlCode curl_easy_setopt (IntPtr pCurl, CurlOption opt, byte[] parm);
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern CurlCode curl_easy_setopt (IntPtr pCurl, CurlOption opt, long parm);
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern CurlCode curl_easy_setopt (IntPtr pCurl, CurlOption opt, bool parm);
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "curl_easy_setopt")]
|
||||
internal static extern CurlCode curl_easy_setopt_cb (IntPtr pCurl, CurlOption opt, _CurlGenericCallback parm);
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "curl_easy_setopt")]
|
||||
internal static extern CurlCode curl_easy_setopt_cb (IntPtr pCurl, CurlOption opt, _CurlProgressCallback parm);
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "curl_easy_setopt")]
|
||||
internal static extern CurlCode curl_easy_setopt_cb (IntPtr pCurl, CurlOption opt, _CurlDebugCallback parm);
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "curl_easy_setopt")]
|
||||
internal static extern CurlCode curl_easy_setopt_cb (IntPtr pCurl, CurlOption opt, _CurlSslCtxCallback parm);
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "curl_easy_setopt")]
|
||||
internal static extern CurlCode curl_easy_setopt_cb (IntPtr pCurl, CurlOption opt, _CurlIoctlCallback parm);
|
||||
|
||||
#if !USE_LIBCURLSHIM
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern CurlMultiCode curl_multi_fdset (IntPtr pmulti,
|
||||
[In, Out] ref fd_set read_fd_set,
|
||||
[In, Out] ref fd_set write_fd_set,
|
||||
[In, Out] ref fd_set exc_fd_set,
|
||||
[In, Out] ref int max_fd);
|
||||
|
||||
[StructLayout (LayoutKind.Sequential)]
|
||||
internal struct fd_set
|
||||
{
|
||||
internal uint fd_count;
|
||||
//[MarshalAs(UnmanagedType.ByValArray, SizeConst = FD_SETSIZE)] internal IntPtr[] fd_array;
|
||||
internal fixed uint fd_array[FD_SETSIZE];
|
||||
|
||||
internal const int FD_SETSIZE = 64;
|
||||
|
||||
internal void Cleanup ()
|
||||
{
|
||||
//fd_array = null;
|
||||
}
|
||||
|
||||
internal static fd_set Create ()
|
||||
{
|
||||
return new fd_set {
|
||||
//fd_array = new IntPtr[FD_SETSIZE],
|
||||
fd_count = 0
|
||||
};
|
||||
}
|
||||
|
||||
internal static fd_set Create (IntPtr socket)
|
||||
{
|
||||
var handle = Create ();
|
||||
handle.fd_count = 1;
|
||||
handle.fd_array [0] = (uint)socket;
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void FD_ZERO (fd_set fds)
|
||||
{
|
||||
for (var i = 0; i < fd_set.FD_SETSIZE; i++) {
|
||||
//fds.fd_array[i] = (IntPtr) 0;
|
||||
fds.fd_array [i] = 0;
|
||||
}
|
||||
fds.fd_count = 0;
|
||||
}
|
||||
|
||||
[StructLayout (LayoutKind.Sequential)]
|
||||
internal struct timeval
|
||||
{
|
||||
/// <summary>
|
||||
/// Time interval, in seconds.
|
||||
/// </summary>
|
||||
internal int tv_sec;
|
||||
|
||||
/// <summary>
|
||||
/// Time interval, in microseconds.
|
||||
/// </summary>
|
||||
internal int tv_usec;
|
||||
|
||||
internal static timeval Create (int milliseconds)
|
||||
{
|
||||
return new timeval {
|
||||
tv_sec = milliseconds / 1000,
|
||||
tv_usec = (milliseconds % 1000) * 1000
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
[DllImport (WINSOCK_LIB, EntryPoint = "select")]
|
||||
internal static extern int select (
|
||||
int nfds, // number of sockets, (ignored in winsock)
|
||||
[In, Out] ref fd_set readfds, // read sockets to watch
|
||||
[In, Out] ref fd_set writefds, // write sockets to watch
|
||||
[In, Out] ref fd_set exceptfds, // error sockets to watch
|
||||
ref timeval timeout);
|
||||
|
||||
//[DllImport(WINSOCK_LIB, EntryPoint = "select")]
|
||||
//internal static extern int select(int ndfs, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, timeval* timeout);
|
||||
#endif
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern CurlCode curl_easy_perform (IntPtr pCurl);
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern IntPtr curl_easy_duphandle (IntPtr pCurl);
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern IntPtr curl_easy_strerror (CurlCode err);
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern CurlCode curl_easy_getinfo (IntPtr pCurl, CurlInfo info, ref IntPtr pInfo);
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern CurlCode curl_easy_getinfo (IntPtr pCurl, CurlInfo info, ref double dblVal);
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern void curl_easy_reset (IntPtr pCurl);
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern IntPtr curl_multi_init ();
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern CurlMultiCode curl_multi_cleanup (IntPtr pmulti);
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern CurlMultiCode curl_multi_add_handle (IntPtr pmulti, IntPtr peasy);
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern CurlMultiCode curl_multi_remove_handle (IntPtr pmulti, IntPtr peasy);
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern IntPtr curl_multi_strerror (CurlMultiCode errorNum);
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern CurlMultiCode curl_multi_perform (IntPtr pmulti, ref int runningHandles);
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern void curl_formfree (IntPtr pForm);
|
||||
|
||||
#if !USE_LIBCURLSHIM
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern int curl_formadd (ref IntPtr pHttppost, ref IntPtr pLastPost,
|
||||
int codeFirst, IntPtr bufFirst,
|
||||
int codeNext, IntPtr bufNext,
|
||||
int codeLast);
|
||||
#endif
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern IntPtr curl_share_init ();
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern CurlShareCode curl_share_cleanup (IntPtr pShare);
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern IntPtr curl_share_strerror (CurlShareCode errorCode);
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern CurlShareCode curl_share_setopt (IntPtr pShare, CurlShareOption optCode, IntPtr option);
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
internal static extern IntPtr curl_slist_append (IntPtr slist, string data);
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern CurlShareCode curl_slist_free_all (IntPtr pList);
|
||||
|
||||
[DllImport (CURL_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern IntPtr curl_version_info (CurlVersion ver);
|
||||
|
||||
#if USE_LIBCURLSHIM
|
||||
|
||||
// libcurlshim imports
|
||||
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern void curl_shim_initialize();
|
||||
|
||||
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern void curl_shim_cleanup();
|
||||
|
||||
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern IntPtr curl_shim_alloc_strings();
|
||||
|
||||
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl,
|
||||
CharSet = CharSet.Ansi)]
|
||||
internal static extern IntPtr curl_shim_add_string_to_slist(
|
||||
IntPtr pStrings, String str);
|
||||
|
||||
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl,
|
||||
CharSet = CharSet.Ansi)]
|
||||
internal static extern IntPtr curl_shim_get_string_from_slist(
|
||||
IntPtr pSlist, ref IntPtr pStr);
|
||||
|
||||
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl,
|
||||
CharSet = CharSet.Ansi)]
|
||||
internal static extern IntPtr curl_shim_add_string(IntPtr pStrings, String str);
|
||||
|
||||
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern void curl_shim_free_strings(IntPtr pStrings);
|
||||
|
||||
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern int curl_shim_install_delegates(IntPtr pCurl, IntPtr pThis,
|
||||
_ShimWriteCallback pWrite, _ShimReadCallback pRead,
|
||||
_ShimProgressCallback pProgress, _ShimDebugCallback pDebug,
|
||||
_ShimHeaderCallback pHeader, _ShimSslCtxCallback pCtx,
|
||||
_ShimIoctlCallback pIoctl);
|
||||
|
||||
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern void curl_shim_cleanup_delegates(IntPtr pThis);
|
||||
|
||||
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern void curl_shim_get_file_time(int unixTime,
|
||||
ref int yy, ref int mm, ref int dd, ref int hh, ref int mn, ref int ss);
|
||||
|
||||
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern void curl_shim_free_slist(IntPtr p);
|
||||
|
||||
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern IntPtr curl_shim_alloc_fd_sets();
|
||||
|
||||
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern void curl_shim_free_fd_sets(IntPtr fdsets);
|
||||
|
||||
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern CurlMultiCode curl_shim_multi_fdset(IntPtr multi,
|
||||
IntPtr fdsets, ref int maxFD);
|
||||
|
||||
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern int curl_shim_select(int maxFD, IntPtr fdsets,
|
||||
int milliseconds);
|
||||
|
||||
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern IntPtr curl_shim_multi_info_read(IntPtr multi,
|
||||
ref int nMsgs);
|
||||
|
||||
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern void curl_shim_multi_info_free(IntPtr multiInfo);
|
||||
|
||||
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern int curl_shim_formadd(IntPtr[] ppForms, IntPtr[] pParams, int nParams);
|
||||
|
||||
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern int curl_shim_install_share_delegates(IntPtr pShare,
|
||||
IntPtr pThis, _ShimLockCallback pLock, _ShimUnlockCallback pUnlock);
|
||||
|
||||
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern void curl_shim_cleanup_share_delegates(IntPtr pShare);
|
||||
|
||||
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern int curl_shim_get_version_int_value(IntPtr p, int offset);
|
||||
|
||||
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern IntPtr curl_shim_get_version_char_ptr(IntPtr p, int offset);
|
||||
|
||||
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern int curl_shim_get_number_of_protocols(IntPtr p, int offset);
|
||||
|
||||
[DllImport(CURLSHIM_LIB, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern IntPtr curl_shim_get_protocol_string(IntPtr p, int offset, int index);
|
||||
|
||||
internal delegate void _ShimLockCallback(int data, int access, IntPtr userPtr);
|
||||
|
||||
internal delegate void _ShimUnlockCallback(int data, IntPtr userPtr);
|
||||
|
||||
internal delegate int _ShimDebugCallback(CurlInfoType infoType, IntPtr msgBuf, int msgBufSize, IntPtr parm);
|
||||
|
||||
internal delegate int _ShimHeaderCallback(IntPtr buf, int sz, int nmemb, IntPtr stream);
|
||||
|
||||
internal delegate CurlIoError _ShimIoctlCallback(CurlIoCommand cmd, IntPtr parm);
|
||||
|
||||
internal delegate int _ShimProgressCallback(IntPtr parm, double dlTotal, double dlNow, double ulTotal, double ulNow);
|
||||
|
||||
internal delegate int _ShimReadCallback(IntPtr buf, int sz, int nmemb, IntPtr parm);
|
||||
|
||||
internal delegate int _ShimSslCtxCallback(IntPtr ctx, IntPtr parm);
|
||||
|
||||
internal delegate int _ShimWriteCallback(IntPtr buf, int sz, int nmemb, IntPtr parm);
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
// Information about this assembly is defined by the following attributes.
|
||||
// Change them to the values specific to your project.
|
||||
[assembly: AssemblyTitle ("CurlSharp")]
|
||||
[assembly: AssemblyDescription ("")]
|
||||
[assembly: AssemblyConfiguration ("")]
|
||||
[assembly: AssemblyCompany ("")]
|
||||
[assembly: AssemblyProduct ("")]
|
||||
[assembly: AssemblyCopyright ("max")]
|
||||
[assembly: AssemblyTrademark ("")]
|
||||
[assembly: AssemblyCulture ("")]
|
||||
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
|
||||
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
|
||||
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
|
||||
[assembly: AssemblyVersion ("1.0.*")]
|
||||
// The following attributes are used to specify the signing key for the assembly,
|
||||
// if desired. See the Mono documentation for more information about signing.
|
||||
//[assembly: AssemblyDelaySign(false)]
|
||||
//[assembly: AssemblyKeyFile("")]
|
||||
|
|
@ -1,10 +1,11 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2013
|
||||
VisualStudioVersion = 12.0.31101.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jackett", "Jackett\Jackett.csproj", "{E636D5F8-68B4-4903-B4ED-CCFD9C9E899F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CurlSharp", "CurlSharp\CurlSharp.csproj", "{74420A79-CC16-442C-8B1E-7C1B913844F0}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -15,6 +16,10 @@ Global
|
|||
{E636D5F8-68B4-4903-B4ED-CCFD9C9E899F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E636D5F8-68B4-4903-B4ED-CCFD9C9E899F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E636D5F8-68B4-4903-B4ED-CCFD9C9E899F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{74420A79-CC16-442C-8B1E-7C1B913844F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{74420A79-CC16-442C-8B1E-7C1B913844F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{74420A79-CC16-442C-8B1E-7C1B913844F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{74420A79-CC16-442C-8B1E-7C1B913844F0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
@ -8,15 +8,26 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace Jackett
|
||||
{
|
||||
public static class CookieContainerExtensions
|
||||
{
|
||||
public static void FillFromJson(this CookieContainer cookies, Uri uri, JArray json)
|
||||
{
|
||||
foreach (var cookie in json)
|
||||
{
|
||||
var w = ((string)cookie).Split(':');
|
||||
cookies.Add(uri, new Cookie(w[0], w[1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
public static class CookieContainerExtensions
|
||||
{
|
||||
public static void FillFromJson (this CookieContainer cookies, Uri uri, JArray json)
|
||||
{
|
||||
foreach (string cookie in json) {
|
||||
|
||||
var w = cookie.Split ('=');
|
||||
if (w.Length == 1)
|
||||
cookies.Add (uri, new Cookie{ Name = cookie.Trim () });
|
||||
else
|
||||
cookies.Add (uri, new Cookie (w [0].Trim (), w [1].Trim ()));
|
||||
}
|
||||
}
|
||||
|
||||
public static JArray ToJson (this CookieContainer cookies, Uri baseUrl)
|
||||
{
|
||||
return new JArray ((
|
||||
from cookie in cookies.GetCookies (baseUrl).Cast<Cookie> ()
|
||||
select cookie.Name.Trim () + "=" + cookie.Value.Trim ()
|
||||
).ToArray ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
using CurlSharp;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Jackett
|
||||
{
|
||||
public class CurlHelper
|
||||
{
|
||||
private const string ChromeUserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36";
|
||||
|
||||
public static CurlHelper Shared = new CurlHelper();
|
||||
|
||||
private BlockingCollection<CurlRequest> curlRequests;
|
||||
|
||||
public bool IsSupported { get; private set; }
|
||||
|
||||
private class CurlRequest
|
||||
{
|
||||
public TaskCompletionSource<string> TaskCompletion { get; private set; }
|
||||
|
||||
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 string PostData { get; set; }
|
||||
|
||||
public CurlRequest(HttpMethod method, string url, string cookies = null, string referer = null)
|
||||
{
|
||||
TaskCompletion = new TaskCompletionSource<string>();
|
||||
Method = method;
|
||||
Url = url;
|
||||
Cookies = cookies;
|
||||
Referer = referer;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<string> GetStringAsync(string url, string cookies = null, string referer = null)
|
||||
{
|
||||
var curlRequest = new CurlRequest(HttpMethod.Get, url, cookies, referer);
|
||||
curlRequests.Add(curlRequest);
|
||||
var result = await curlRequest.TaskCompletion.Task;
|
||||
return result;
|
||||
}
|
||||
|
||||
public CurlHelper()
|
||||
{
|
||||
try
|
||||
{
|
||||
Curl.GlobalInit(CurlInitFlag.All);
|
||||
IsSupported = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
IsSupported = false;
|
||||
}
|
||||
Task.Run((Action)CurlServicer);
|
||||
}
|
||||
|
||||
private void CurlServicer()
|
||||
{
|
||||
curlRequests = new BlockingCollection<CurlRequest>();
|
||||
foreach (var curlRequest in curlRequests.GetConsumingEnumerable())
|
||||
{
|
||||
PerformCurl(curlRequest);
|
||||
}
|
||||
}
|
||||
|
||||
private void PerformCurl(CurlRequest curlRequest)
|
||||
{
|
||||
var headerBuffers = new List<byte[]>();
|
||||
var contentBuffers = new List<byte[]>();
|
||||
try
|
||||
{
|
||||
using (var easy = new CurlEasy())
|
||||
{
|
||||
easy.Url = curlRequest.Url;
|
||||
easy.BufferSize = 64 * 1024;
|
||||
//easy.Encoding = "UTF8";
|
||||
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);
|
||||
return size * nmemb;
|
||||
};
|
||||
|
||||
if (!string.IsNullOrEmpty(curlRequest.Cookies))
|
||||
easy.Cookie = curlRequest.Cookies;
|
||||
|
||||
if (curlRequest.Method == HttpMethod.Post)
|
||||
{
|
||||
easy.Post = true;
|
||||
easy.PostFields = curlRequest.PostData;
|
||||
easy.PostFieldSize = Encoding.UTF8.GetByteCount(curlRequest.PostData);
|
||||
}
|
||||
|
||||
easy.Perform();
|
||||
}
|
||||
|
||||
var headerBytes = Combine(headerBuffers.ToArray());
|
||||
var headerString = Encoding.UTF8.GetString(headerBytes);
|
||||
|
||||
var contentBytes = Combine(contentBuffers.ToArray());
|
||||
var result = Encoding.UTF8.GetString(contentBytes);
|
||||
curlRequest.TaskCompletion.SetResult(result);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
curlRequest.TaskCompletion.TrySetException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] Combine(params byte[][] arrays)
|
||||
{
|
||||
byte[] ret = new byte[arrays.Sum(x => x.Length)];
|
||||
int offset = 0;
|
||||
foreach (byte[] data in arrays)
|
||||
{
|
||||
Buffer.BlockCopy(data, 0, ret, offset, data.Length);
|
||||
offset += data.Length;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,152 +12,139 @@ using System.Web;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class BitHdtv : IndexerInterface
|
||||
{
|
||||
public string DisplayName
|
||||
{
|
||||
get { return "BIT-HDTV"; }
|
||||
}
|
||||
public class BitHdtv : IndexerInterface
|
||||
{
|
||||
public string DisplayName {
|
||||
get { return "BIT-HDTV"; }
|
||||
}
|
||||
|
||||
public string DisplayDescription
|
||||
{
|
||||
get { return "Home of high definition invites"; }
|
||||
}
|
||||
public string DisplayDescription {
|
||||
get { return "Home of high definition invites"; }
|
||||
}
|
||||
|
||||
public Uri SiteLink
|
||||
{
|
||||
get { return new Uri(BaseUrl); }
|
||||
}
|
||||
public Uri SiteLink {
|
||||
get { return new Uri (BaseUrl); }
|
||||
}
|
||||
|
||||
static string BaseUrl = "https://www.bit-hdtv.com";
|
||||
static string LoginUrl = BaseUrl + "/takelogin.php";
|
||||
static string SearchUrl = BaseUrl + "/torrents.php?cat=0&search=";
|
||||
static string DownloadUrl = BaseUrl + "/download.php?/{0}/dl.torrent";
|
||||
static string BaseUrl = "https://www.bit-hdtv.com";
|
||||
static string LoginUrl = BaseUrl + "/takelogin.php";
|
||||
static string SearchUrl = BaseUrl + "/torrents.php?cat=0&search=";
|
||||
static string DownloadUrl = BaseUrl + "/download.php?/{0}/dl.torrent";
|
||||
|
||||
CookieContainer cookies;
|
||||
HttpClientHandler handler;
|
||||
HttpClient client;
|
||||
CookieContainer cookies;
|
||||
HttpClientHandler handler;
|
||||
HttpClient client;
|
||||
|
||||
public BitHdtv()
|
||||
{
|
||||
IsConfigured = false;
|
||||
cookies = new CookieContainer();
|
||||
handler = new HttpClientHandler
|
||||
{
|
||||
CookieContainer = cookies,
|
||||
AllowAutoRedirect = true,
|
||||
UseCookies = true,
|
||||
};
|
||||
client = new HttpClient(handler);
|
||||
}
|
||||
public BitHdtv ()
|
||||
{
|
||||
IsConfigured = false;
|
||||
cookies = new CookieContainer ();
|
||||
handler = new HttpClientHandler {
|
||||
CookieContainer = cookies,
|
||||
AllowAutoRedirect = true,
|
||||
UseCookies = true,
|
||||
};
|
||||
client = new HttpClient (handler);
|
||||
}
|
||||
|
||||
public Task<ConfigurationData> GetConfigurationForSetup()
|
||||
{
|
||||
var config = new ConfigurationDataBasicLogin();
|
||||
return Task.FromResult<ConfigurationData>(config);
|
||||
}
|
||||
public Task<ConfigurationData> GetConfigurationForSetup ()
|
||||
{
|
||||
var config = new ConfigurationDataBasicLogin ();
|
||||
return Task.FromResult<ConfigurationData> (config);
|
||||
}
|
||||
|
||||
public async Task ApplyConfiguration(JToken configJson)
|
||||
{
|
||||
var config = new ConfigurationDataBasicLogin();
|
||||
config.LoadValuesFromJson(configJson);
|
||||
public async Task ApplyConfiguration (JToken configJson)
|
||||
{
|
||||
var config = new ConfigurationDataBasicLogin ();
|
||||
config.LoadValuesFromJson (configJson);
|
||||
|
||||
var pairs = new Dictionary<string, string>
|
||||
{
|
||||
{ "username", config.Username.Value},
|
||||
{ "password", config.Password.Value}
|
||||
};
|
||||
var pairs = new Dictionary<string, string> {
|
||||
{ "username", config.Username.Value },
|
||||
{ "password", config.Password.Value }
|
||||
};
|
||||
|
||||
var content = new FormUrlEncodedContent(pairs);
|
||||
var content = new FormUrlEncodedContent (pairs);
|
||||
|
||||
var response = await client.PostAsync(LoginUrl, content);
|
||||
var responseContent = await response.Content.ReadAsStringAsync();
|
||||
var response = await client.PostAsync (LoginUrl, content);
|
||||
var responseContent = await response.Content.ReadAsStringAsync ();
|
||||
|
||||
if (!responseContent.Contains("logout.php"))
|
||||
{
|
||||
CQ dom = responseContent;
|
||||
var messageEl = dom["table.detail td.text"].Last();
|
||||
messageEl.Children("a").Remove();
|
||||
messageEl.Children("style").Remove();
|
||||
var errorMessage = messageEl.Text().Trim();
|
||||
throw new ExceptionWithConfigData(errorMessage, (ConfigurationData)config);
|
||||
}
|
||||
else
|
||||
{
|
||||
var configSaveData = new JObject();
|
||||
configSaveData["cookies"] = new JArray((
|
||||
from cookie in cookies.GetCookies(new Uri(BaseUrl)).Cast<Cookie>()
|
||||
select cookie.Name + ":" + cookie.Value
|
||||
).ToArray());
|
||||
if (!responseContent.Contains ("logout.php")) {
|
||||
CQ dom = responseContent;
|
||||
var messageEl = dom ["table.detail td.text"].Last ();
|
||||
messageEl.Children ("a").Remove ();
|
||||
messageEl.Children ("style").Remove ();
|
||||
var errorMessage = messageEl.Text ().Trim ();
|
||||
throw new ExceptionWithConfigData (errorMessage, (ConfigurationData)config);
|
||||
} else {
|
||||
var configSaveData = new JObject ();
|
||||
configSaveData ["cookies"] = cookies.ToJson (SiteLink);
|
||||
|
||||
if (OnSaveConfigurationRequested != null)
|
||||
OnSaveConfigurationRequested(this, configSaveData);
|
||||
if (OnSaveConfigurationRequested != null)
|
||||
OnSaveConfigurationRequested (this, configSaveData);
|
||||
|
||||
IsConfigured = true;
|
||||
}
|
||||
}
|
||||
IsConfigured = true;
|
||||
}
|
||||
}
|
||||
|
||||
public event Action<IndexerInterface, JToken> OnSaveConfigurationRequested;
|
||||
public event Action<IndexerInterface, JToken> OnSaveConfigurationRequested;
|
||||
|
||||
public bool IsConfigured { get; private set; }
|
||||
public bool IsConfigured { get; private set; }
|
||||
|
||||
public void LoadFromSavedConfiguration(JToken jsonConfig)
|
||||
{
|
||||
cookies.FillFromJson(new Uri(BaseUrl), (JArray)jsonConfig["cookies"]);
|
||||
IsConfigured = true;
|
||||
}
|
||||
public void LoadFromSavedConfiguration (JToken jsonConfig)
|
||||
{
|
||||
cookies.FillFromJson (new Uri (BaseUrl), (JArray)jsonConfig ["cookies"]);
|
||||
IsConfigured = true;
|
||||
}
|
||||
|
||||
public async Task<ReleaseInfo[]> PerformQuery(TorznabQuery query)
|
||||
{
|
||||
List<ReleaseInfo> releases = new List<ReleaseInfo>();
|
||||
public async Task<ReleaseInfo[]> PerformQuery (TorznabQuery query)
|
||||
{
|
||||
List<ReleaseInfo> releases = new List<ReleaseInfo> ();
|
||||
|
||||
|
||||
foreach (var title in query.ShowTitles ?? new string[] { string.Empty })
|
||||
{
|
||||
var searchString = title + " " + query.GetEpisodeSearchString();
|
||||
var episodeSearchUrl = SearchUrl + HttpUtility.UrlEncode(searchString);
|
||||
var results = await client.GetStringAsync(episodeSearchUrl);
|
||||
CQ dom = results;
|
||||
dom["#needseed"].Remove();
|
||||
var rows = dom["table[width='750'] > tbody"].Children();
|
||||
foreach (var row in rows.Skip(1))
|
||||
{
|
||||
foreach (var title in query.ShowTitles ?? new string[] { string.Empty }) {
|
||||
var searchString = title + " " + query.GetEpisodeSearchString ();
|
||||
var episodeSearchUrl = SearchUrl + HttpUtility.UrlEncode (searchString);
|
||||
var results = await client.GetStringAsync (episodeSearchUrl);
|
||||
CQ dom = results;
|
||||
dom ["#needseed"].Remove ();
|
||||
var rows = dom ["table[width='750'] > tbody"].Children ();
|
||||
foreach (var row in rows.Skip(1)) {
|
||||
|
||||
var release = new ReleaseInfo();
|
||||
var release = new ReleaseInfo ();
|
||||
|
||||
var qRow = row.Cq();
|
||||
var qLink = qRow.Children().ElementAt(2).Cq().Children("a").First();
|
||||
var qRow = row.Cq ();
|
||||
var qLink = qRow.Children ().ElementAt (2).Cq ().Children ("a").First ();
|
||||
|
||||
release.MinimumRatio = 1;
|
||||
release.MinimumSeedTime = 172800;
|
||||
release.Title = qLink.Attr("title");
|
||||
release.Description = release.Title;
|
||||
release.Guid = new Uri(BaseUrl + qLink.Attr("href"));
|
||||
release.Comments = release.Guid;
|
||||
release.Link = new Uri(string.Format(DownloadUrl, qLink.Attr("href").Split('=')[1]));
|
||||
release.MinimumRatio = 1;
|
||||
release.MinimumSeedTime = 172800;
|
||||
release.Title = qLink.Attr ("title");
|
||||
release.Description = release.Title;
|
||||
release.Guid = new Uri (BaseUrl + qLink.Attr ("href"));
|
||||
release.Comments = release.Guid;
|
||||
release.Link = new Uri (string.Format (DownloadUrl, qLink.Attr ("href").Split ('=') [1]));
|
||||
|
||||
var dateString = qRow.Children().ElementAt(5).Cq().Text().Trim();
|
||||
var pubDate = DateTime.ParseExact(dateString, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
|
||||
release.PublishDate = pubDate;
|
||||
var dateString = qRow.Children ().ElementAt (5).Cq ().Text ().Trim ();
|
||||
var pubDate = DateTime.ParseExact (dateString, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
|
||||
release.PublishDate = pubDate;
|
||||
|
||||
var sizeCol = qRow.Children().ElementAt(6);
|
||||
var sizeVal = sizeCol.ChildNodes[0].NodeValue;
|
||||
var sizeUnit = sizeCol.ChildNodes[2].NodeValue;
|
||||
release.Size = ReleaseInfo.GetBytes(sizeUnit, float.Parse(sizeVal));
|
||||
var sizeCol = qRow.Children ().ElementAt (6);
|
||||
var sizeVal = sizeCol.ChildNodes [0].NodeValue;
|
||||
var sizeUnit = sizeCol.ChildNodes [2].NodeValue;
|
||||
release.Size = ReleaseInfo.GetBytes (sizeUnit, float.Parse (sizeVal));
|
||||
|
||||
release.Seeders = int.Parse(qRow.Children().ElementAt(8).Cq().Text().Trim());
|
||||
release.Peers = int.Parse(qRow.Children().ElementAt(9).Cq().Text().Trim()) + release.Seeders;
|
||||
release.Seeders = int.Parse (qRow.Children ().ElementAt (8).Cq ().Text ().Trim ());
|
||||
release.Peers = int.Parse (qRow.Children ().ElementAt (9).Cq ().Text ().Trim ()) + release.Seeders;
|
||||
|
||||
releases.Add(release);
|
||||
}
|
||||
}
|
||||
releases.Add (release);
|
||||
}
|
||||
}
|
||||
|
||||
return releases.ToArray();
|
||||
}
|
||||
return releases.ToArray ();
|
||||
}
|
||||
|
||||
public Task<byte[]> Download(Uri link)
|
||||
{
|
||||
return client.GetByteArrayAsync(link);
|
||||
}
|
||||
}
|
||||
public Task<byte[]> Download (Uri link)
|
||||
{
|
||||
return client.GetByteArrayAsync (link);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,175 +13,170 @@ using System.Web;
|
|||
|
||||
namespace Jackett
|
||||
{
|
||||
public class BitMeTV : IndexerInterface
|
||||
{
|
||||
class BmtvConfig : ConfigurationData
|
||||
{
|
||||
public StringItem Username { get; private set; }
|
||||
public StringItem Password { get; private set; }
|
||||
public ImageItem CaptchaImage { get; private set; }
|
||||
public StringItem CaptchaText { get; private set; }
|
||||
public class BitMeTV : IndexerInterface
|
||||
{
|
||||
class BmtvConfig : ConfigurationData
|
||||
{
|
||||
public StringItem Username { get; private set; }
|
||||
|
||||
public BmtvConfig()
|
||||
{
|
||||
Username = new StringItem { Name = "Username" };
|
||||
Password = new StringItem { Name = "Password" };
|
||||
CaptchaImage = new ImageItem { Name = "Captcha Image" };
|
||||
CaptchaText = new StringItem { Name = "Captcha Text" };
|
||||
}
|
||||
public StringItem Password { get; private set; }
|
||||
|
||||
public override Item[] GetItems()
|
||||
{
|
||||
return new Item[] { Username, Password, CaptchaImage, CaptchaText };
|
||||
}
|
||||
}
|
||||
public ImageItem CaptchaImage { get; private set; }
|
||||
|
||||
static string BaseUrl = "http://www.bitmetv.org";
|
||||
static string LoginUrl = BaseUrl + "/login.php";
|
||||
static string LoginPost = BaseUrl + "/takelogin.php";
|
||||
static string CaptchaUrl = BaseUrl + "/visual.php";
|
||||
static string SearchUrl = BaseUrl + "/browse.php";
|
||||
public StringItem CaptchaText { get; private set; }
|
||||
|
||||
CookieContainer cookies;
|
||||
HttpClientHandler handler;
|
||||
HttpClient client;
|
||||
public BmtvConfig ()
|
||||
{
|
||||
Username = new StringItem { Name = "Username" };
|
||||
Password = new StringItem { Name = "Password" };
|
||||
CaptchaImage = new ImageItem { Name = "Captcha Image" };
|
||||
CaptchaText = new StringItem { Name = "Captcha Text" };
|
||||
}
|
||||
|
||||
public event Action<IndexerInterface, JToken> OnSaveConfigurationRequested;
|
||||
public override Item[] GetItems ()
|
||||
{
|
||||
return new Item[] { Username, Password, CaptchaImage, CaptchaText };
|
||||
}
|
||||
}
|
||||
|
||||
public BitMeTV()
|
||||
{
|
||||
IsConfigured = false;
|
||||
cookies = new CookieContainer();
|
||||
handler = new HttpClientHandler
|
||||
{
|
||||
CookieContainer = cookies,
|
||||
AllowAutoRedirect = true,
|
||||
UseCookies = true,
|
||||
};
|
||||
client = new HttpClient(handler);
|
||||
}
|
||||
static string BaseUrl = "http://www.bitmetv.org";
|
||||
static string LoginUrl = BaseUrl + "/login.php";
|
||||
static string LoginPost = BaseUrl + "/takelogin.php";
|
||||
static string CaptchaUrl = BaseUrl + "/visual.php";
|
||||
static string SearchUrl = BaseUrl + "/browse.php";
|
||||
|
||||
public string DisplayName { get { return "BitMeTV"; } }
|
||||
public string DisplayDescription { get { return "TV Episode specialty tracker"; } }
|
||||
public Uri SiteLink { get { return new Uri(BaseUrl); } }
|
||||
CookieContainer cookies;
|
||||
HttpClientHandler handler;
|
||||
HttpClient client;
|
||||
|
||||
public bool IsConfigured { get; private set; }
|
||||
public event Action<IndexerInterface, JToken> OnSaveConfigurationRequested;
|
||||
|
||||
public async Task<ConfigurationData> GetConfigurationForSetup()
|
||||
{
|
||||
var loginPage = await client.GetAsync(LoginUrl);
|
||||
var captchaImage = await client.GetByteArrayAsync(CaptchaUrl);
|
||||
var config = new BmtvConfig();
|
||||
config.CaptchaImage.Value = captchaImage;
|
||||
return (ConfigurationData)config;
|
||||
}
|
||||
public BitMeTV ()
|
||||
{
|
||||
IsConfigured = false;
|
||||
cookies = new CookieContainer ();
|
||||
handler = new HttpClientHandler {
|
||||
CookieContainer = cookies,
|
||||
AllowAutoRedirect = true,
|
||||
UseCookies = true,
|
||||
};
|
||||
client = new HttpClient (handler);
|
||||
}
|
||||
|
||||
public async Task ApplyConfiguration(JToken configJson)
|
||||
{
|
||||
var config = new BmtvConfig();
|
||||
config.LoadValuesFromJson(configJson);
|
||||
public string DisplayName { get { return "BitMeTV"; } }
|
||||
|
||||
var pairs = new Dictionary<string, string>
|
||||
{
|
||||
{ "username", config.Username.Value},
|
||||
{ "password", config.Password.Value},
|
||||
{ "secimage", config.CaptchaText.Value}
|
||||
};
|
||||
public string DisplayDescription { get { return "TV Episode specialty tracker"; } }
|
||||
|
||||
var content = new FormUrlEncodedContent(pairs);
|
||||
public Uri SiteLink { get { return new Uri (BaseUrl); } }
|
||||
|
||||
var response = await client.PostAsync(LoginPost, content);
|
||||
var responseContent = await response.Content.ReadAsStringAsync();
|
||||
public bool IsConfigured { get; private set; }
|
||||
|
||||
if (!responseContent.Contains("/logout.php"))
|
||||
{
|
||||
CQ dom = responseContent;
|
||||
var messageEl = dom["table tr > td.embedded > h2"].Last();
|
||||
var errorMessage = messageEl.Text();
|
||||
var captchaImage = await client.GetByteArrayAsync(CaptchaUrl);
|
||||
config.CaptchaImage.Value = captchaImage;
|
||||
config.CaptchaText.Value = "";
|
||||
throw new ExceptionWithConfigData(errorMessage, (ConfigurationData)config);
|
||||
}
|
||||
else
|
||||
{
|
||||
var configSaveData = new JObject();
|
||||
configSaveData["cookies"] = new JArray((
|
||||
from cookie in cookies.GetCookies(new Uri(BaseUrl)).Cast<Cookie>()
|
||||
select cookie.Name + ":" + cookie.Value
|
||||
).ToArray());
|
||||
public async Task<ConfigurationData> GetConfigurationForSetup ()
|
||||
{
|
||||
var loginPage = await client.GetAsync (LoginUrl);
|
||||
var captchaImage = await client.GetByteArrayAsync (CaptchaUrl);
|
||||
var config = new BmtvConfig ();
|
||||
config.CaptchaImage.Value = captchaImage;
|
||||
return (ConfigurationData)config;
|
||||
}
|
||||
|
||||
if (OnSaveConfigurationRequested != null)
|
||||
OnSaveConfigurationRequested(this, configSaveData);
|
||||
public async Task ApplyConfiguration (JToken configJson)
|
||||
{
|
||||
var config = new BmtvConfig ();
|
||||
config.LoadValuesFromJson (configJson);
|
||||
|
||||
IsConfigured = true;
|
||||
}
|
||||
}
|
||||
var pairs = new Dictionary<string, string> {
|
||||
{ "username", config.Username.Value },
|
||||
{ "password", config.Password.Value },
|
||||
{ "secimage", config.CaptchaText.Value }
|
||||
};
|
||||
|
||||
public void LoadFromSavedConfiguration(JToken jsonConfig)
|
||||
{
|
||||
cookies.FillFromJson(new Uri(BaseUrl), (JArray)jsonConfig["cookies"]);
|
||||
IsConfigured = true;
|
||||
}
|
||||
var content = new FormUrlEncodedContent (pairs);
|
||||
|
||||
public async Task<ReleaseInfo[]> PerformQuery(TorznabQuery query)
|
||||
{
|
||||
List<ReleaseInfo> releases = new List<ReleaseInfo>();
|
||||
var response = await client.PostAsync (LoginPost, content);
|
||||
var responseContent = await response.Content.ReadAsStringAsync ();
|
||||
|
||||
if (!responseContent.Contains ("/logout.php")) {
|
||||
CQ dom = responseContent;
|
||||
var messageEl = dom ["table tr > td.embedded > h2"].Last ();
|
||||
var errorMessage = messageEl.Text ();
|
||||
var captchaImage = await client.GetByteArrayAsync (CaptchaUrl);
|
||||
config.CaptchaImage.Value = captchaImage;
|
||||
config.CaptchaText.Value = "";
|
||||
throw new ExceptionWithConfigData (errorMessage, (ConfigurationData)config);
|
||||
} else {
|
||||
var configSaveData = new JObject ();
|
||||
configSaveData ["cookies"] = cookies.ToJson (SiteLink);
|
||||
|
||||
if (OnSaveConfigurationRequested != null)
|
||||
OnSaveConfigurationRequested (this, configSaveData);
|
||||
|
||||
IsConfigured = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadFromSavedConfiguration (JToken jsonConfig)
|
||||
{
|
||||
cookies.FillFromJson (new Uri (BaseUrl), (JArray)jsonConfig ["cookies"]);
|
||||
IsConfigured = true;
|
||||
}
|
||||
|
||||
public async Task<ReleaseInfo[]> PerformQuery (TorznabQuery query)
|
||||
{
|
||||
List<ReleaseInfo> releases = new List<ReleaseInfo> ();
|
||||
|
||||
|
||||
foreach (var title in query.ShowTitles ?? new string[] { string.Empty })
|
||||
{
|
||||
foreach (var title in query.ShowTitles ?? new string[] { string.Empty }) {
|
||||
|
||||
var searchString = title + " " + query.GetEpisodeSearchString();
|
||||
var episodeSearchUrl = string.Format("{0}?search={1}&cat=0", SearchUrl, HttpUtility.UrlEncode(searchString));
|
||||
var results = await client.GetStringAsync(episodeSearchUrl);
|
||||
CQ dom = results;
|
||||
var searchString = title + " " + query.GetEpisodeSearchString ();
|
||||
var episodeSearchUrl = string.Format ("{0}?search={1}&cat=0", SearchUrl, HttpUtility.UrlEncode (searchString));
|
||||
var results = await client.GetStringAsync (episodeSearchUrl);
|
||||
CQ dom = results;
|
||||
|
||||
var table = dom["tbody > tr > .latest"].Parent().Parent();
|
||||
var table = dom ["tbody > tr > .latest"].Parent ().Parent ();
|
||||
|
||||
foreach (var row in table.Children().Skip(1))
|
||||
{
|
||||
var release = new ReleaseInfo();
|
||||
foreach (var row in table.Children().Skip(1)) {
|
||||
var release = new ReleaseInfo ();
|
||||
|
||||
CQ qRow = row.Cq();
|
||||
CQ qDetailsCol = row.ChildElements.ElementAt(1).Cq();
|
||||
CQ qLink = qDetailsCol.Children("a").First();
|
||||
CQ qRow = row.Cq ();
|
||||
CQ qDetailsCol = row.ChildElements.ElementAt (1).Cq ();
|
||||
CQ qLink = qDetailsCol.Children ("a").First ();
|
||||
|
||||
release.MinimumRatio = 1;
|
||||
release.MinimumSeedTime = 172800;
|
||||
release.Comments = new Uri(BaseUrl + "/" + qLink.Attr("href"));
|
||||
release.Guid = release.Comments;
|
||||
release.Title = qLink.Attr("title");
|
||||
release.Description = release.Title;
|
||||
release.MinimumRatio = 1;
|
||||
release.MinimumSeedTime = 172800;
|
||||
release.Comments = new Uri (BaseUrl + "/" + qLink.Attr ("href"));
|
||||
release.Guid = release.Comments;
|
||||
release.Title = qLink.Attr ("title");
|
||||
release.Description = release.Title;
|
||||
|
||||
//"Tuesday, June 11th 2013 at 03:52:53 AM" to...
|
||||
//"Tuesday June 11 2013 03:52:53 AM"
|
||||
var timestamp = qDetailsCol.Children("font").Text().Trim() + " ";
|
||||
var timeParts = new List<string>(timestamp.Replace(" at", "").Replace(",", "").Split(' '));
|
||||
timeParts[2] = Regex.Replace(timeParts[2], "[^0-9.]", "");
|
||||
var formattedTimeString = string.Join(" ", timeParts.ToArray()).Trim();
|
||||
release.PublishDate = DateTime.ParseExact(formattedTimeString, "dddd MMMM d yyyy hh:mm:ss tt", CultureInfo.InvariantCulture);
|
||||
//"Tuesday, June 11th 2013 at 03:52:53 AM" to...
|
||||
//"Tuesday June 11 2013 03:52:53 AM"
|
||||
var timestamp = qDetailsCol.Children ("font").Text ().Trim () + " ";
|
||||
var timeParts = new List<string> (timestamp.Replace (" at", "").Replace (",", "").Split (' '));
|
||||
timeParts [2] = Regex.Replace (timeParts [2], "[^0-9.]", "");
|
||||
var formattedTimeString = string.Join (" ", timeParts.ToArray ()).Trim ();
|
||||
release.PublishDate = DateTime.ParseExact (formattedTimeString, "dddd MMMM d yyyy hh:mm:ss tt", CultureInfo.InvariantCulture);
|
||||
|
||||
release.Link = new Uri(BaseUrl + "/" + row.ChildElements.ElementAt(2).Cq().Children("a.index").Attr("href"));
|
||||
release.Link = new Uri (BaseUrl + "/" + row.ChildElements.ElementAt (2).Cq ().Children ("a.index").Attr ("href"));
|
||||
|
||||
var sizeCol = row.ChildElements.ElementAt(6);
|
||||
var sizeVal = float.Parse(sizeCol.ChildNodes[0].NodeValue);
|
||||
var sizeUnit = sizeCol.ChildNodes[2].NodeValue;
|
||||
release.Size = ReleaseInfo.GetBytes(sizeUnit, sizeVal);
|
||||
var sizeCol = row.ChildElements.ElementAt (6);
|
||||
var sizeVal = float.Parse (sizeCol.ChildNodes [0].NodeValue);
|
||||
var sizeUnit = sizeCol.ChildNodes [2].NodeValue;
|
||||
release.Size = ReleaseInfo.GetBytes (sizeUnit, sizeVal);
|
||||
|
||||
release.Seeders = int.Parse(row.ChildElements.ElementAt(8).Cq().Text());
|
||||
release.Peers = int.Parse(row.ChildElements.ElementAt(9).Cq().Text()) + release.Seeders;
|
||||
releases.Add(release);
|
||||
}
|
||||
}
|
||||
release.Seeders = int.Parse (row.ChildElements.ElementAt (8).Cq ().Text ());
|
||||
release.Peers = int.Parse (row.ChildElements.ElementAt (9).Cq ().Text ()) + release.Seeders;
|
||||
releases.Add (release);
|
||||
}
|
||||
}
|
||||
|
||||
return releases.ToArray();
|
||||
return releases.ToArray ();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public Task<byte[]> Download(Uri link)
|
||||
{
|
||||
return client.GetByteArrayAsync(link);
|
||||
}
|
||||
}
|
||||
public Task<byte[]> Download (Uri link)
|
||||
{
|
||||
return client.GetByteArrayAsync (link);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,179 +14,168 @@ using System.Web.UI.WebControls;
|
|||
|
||||
namespace Jackett
|
||||
{
|
||||
public class Freshon : IndexerInterface
|
||||
{
|
||||
public class Freshon : IndexerInterface
|
||||
{
|
||||
|
||||
static string BaseUrl = "https://freshon.tv";
|
||||
static string LoginUrl = BaseUrl + "/login.php";
|
||||
static string LoginPostUrl = BaseUrl + "/login.php?action=makelogin";
|
||||
static string SearchUrl = BaseUrl + "/browse.php";
|
||||
static string BaseUrl = "https://freshon.tv";
|
||||
static string LoginUrl = BaseUrl + "/login.php";
|
||||
static string LoginPostUrl = BaseUrl + "/login.php?action=makelogin";
|
||||
static string SearchUrl = BaseUrl + "/browse.php";
|
||||
|
||||
static string chromeUserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36";
|
||||
static string chromeUserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36";
|
||||
|
||||
CookieContainer cookies;
|
||||
HttpClientHandler handler;
|
||||
HttpClient client;
|
||||
CookieContainer cookies;
|
||||
HttpClientHandler handler;
|
||||
HttpClient client;
|
||||
|
||||
public bool IsConfigured { get; private set; }
|
||||
public bool IsConfigured { get; private set; }
|
||||
|
||||
public string DisplayName { get { return "FreshOnTV"; } }
|
||||
public string DisplayName { get { return "FreshOnTV"; } }
|
||||
|
||||
public string DisplayDescription { get { return "Our goal is to provide the latest stuff in the TV show domain"; } }
|
||||
public string DisplayDescription { get { return "Our goal is to provide the latest stuff in the TV show domain"; } }
|
||||
|
||||
public Uri SiteLink { get { return new Uri(BaseUrl); } }
|
||||
public Uri SiteLink { get { return new Uri (BaseUrl); } }
|
||||
|
||||
public event Action<IndexerInterface, JToken> OnSaveConfigurationRequested;
|
||||
public event Action<IndexerInterface, JToken> OnSaveConfigurationRequested;
|
||||
|
||||
public Freshon()
|
||||
{
|
||||
IsConfigured = false;
|
||||
cookies = new CookieContainer();
|
||||
handler = new HttpClientHandler
|
||||
{
|
||||
CookieContainer = cookies,
|
||||
AllowAutoRedirect = true,
|
||||
UseCookies = true,
|
||||
};
|
||||
client = new HttpClient(handler);
|
||||
}
|
||||
public Freshon ()
|
||||
{
|
||||
IsConfigured = false;
|
||||
cookies = new CookieContainer ();
|
||||
handler = new HttpClientHandler {
|
||||
CookieContainer = cookies,
|
||||
AllowAutoRedirect = true,
|
||||
UseCookies = true,
|
||||
};
|
||||
client = new HttpClient (handler);
|
||||
}
|
||||
|
||||
public async Task<ConfigurationData> GetConfigurationForSetup()
|
||||
{
|
||||
var request = CreateHttpRequest(new Uri(LoginUrl));
|
||||
var response = await client.SendAsync(request);
|
||||
await response.Content.ReadAsStreamAsync();
|
||||
var config = new ConfigurationDataBasicLogin();
|
||||
return config;
|
||||
}
|
||||
public async Task<ConfigurationData> GetConfigurationForSetup ()
|
||||
{
|
||||
var request = CreateHttpRequest (new Uri (LoginUrl));
|
||||
var response = await client.SendAsync (request);
|
||||
await response.Content.ReadAsStreamAsync ();
|
||||
var config = new ConfigurationDataBasicLogin ();
|
||||
return config;
|
||||
}
|
||||
|
||||
public async Task ApplyConfiguration(JToken configJson)
|
||||
{
|
||||
var config = new ConfigurationDataBasicLogin();
|
||||
config.LoadValuesFromJson(configJson);
|
||||
public async Task ApplyConfiguration (JToken configJson)
|
||||
{
|
||||
var config = new ConfigurationDataBasicLogin ();
|
||||
config.LoadValuesFromJson (configJson);
|
||||
|
||||
var pairs = new Dictionary<string, string>
|
||||
{
|
||||
{ "username", config.Username.Value},
|
||||
{ "password", config.Password.Value}
|
||||
};
|
||||
var pairs = new Dictionary<string, string> {
|
||||
{ "username", config.Username.Value },
|
||||
{ "password", config.Password.Value }
|
||||
};
|
||||
|
||||
var content = new FormUrlEncodedContent(pairs);
|
||||
var message = CreateHttpRequest(new Uri(LoginPostUrl));
|
||||
message.Method = HttpMethod.Post;
|
||||
message.Content = content;
|
||||
message.Headers.Referrer = new Uri(LoginUrl);
|
||||
var content = new FormUrlEncodedContent (pairs);
|
||||
var message = CreateHttpRequest (new Uri (LoginPostUrl));
|
||||
message.Method = HttpMethod.Post;
|
||||
message.Content = content;
|
||||
message.Headers.Referrer = new Uri (LoginUrl);
|
||||
|
||||
var response = await client.SendAsync(message);
|
||||
var responseContent = await response.Content.ReadAsStringAsync();
|
||||
var response = await client.SendAsync (message);
|
||||
var responseContent = await response.Content.ReadAsStringAsync ();
|
||||
|
||||
if (!responseContent.Contains("/logout.php"))
|
||||
{
|
||||
CQ dom = responseContent;
|
||||
var messageEl = dom[".error_text"];
|
||||
var errorMessage = messageEl.Text().Trim();
|
||||
throw new ExceptionWithConfigData(errorMessage, (ConfigurationData)config);
|
||||
}
|
||||
else
|
||||
{
|
||||
var configSaveData = new JObject();
|
||||
configSaveData["cookies"] = new JArray((
|
||||
from cookie in cookies.GetCookies(new Uri(BaseUrl)).Cast<Cookie>()
|
||||
select cookie.Name + ":" + cookie.Value
|
||||
).ToArray());
|
||||
if (!responseContent.Contains ("/logout.php")) {
|
||||
CQ dom = responseContent;
|
||||
var messageEl = dom [".error_text"];
|
||||
var errorMessage = messageEl.Text ().Trim ();
|
||||
throw new ExceptionWithConfigData (errorMessage, (ConfigurationData)config);
|
||||
} else {
|
||||
var configSaveData = new JObject ();
|
||||
configSaveData ["cookies"] = cookies.ToJson (SiteLink);
|
||||
|
||||
if (OnSaveConfigurationRequested != null)
|
||||
OnSaveConfigurationRequested(this, configSaveData);
|
||||
if (OnSaveConfigurationRequested != null)
|
||||
OnSaveConfigurationRequested (this, configSaveData);
|
||||
|
||||
IsConfigured = true;
|
||||
}
|
||||
}
|
||||
IsConfigured = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadFromSavedConfiguration(JToken jsonConfig)
|
||||
{
|
||||
cookies.FillFromJson(new Uri(BaseUrl), (JArray)jsonConfig["cookies"]);
|
||||
IsConfigured = true;
|
||||
}
|
||||
public void LoadFromSavedConfiguration (JToken jsonConfig)
|
||||
{
|
||||
cookies.FillFromJson (new Uri (BaseUrl), (JArray)jsonConfig ["cookies"]);
|
||||
IsConfigured = true;
|
||||
}
|
||||
|
||||
HttpRequestMessage CreateHttpRequest(Uri uri)
|
||||
{
|
||||
var message = new HttpRequestMessage();
|
||||
message.Method = HttpMethod.Get;
|
||||
message.RequestUri = uri;
|
||||
message.Headers.UserAgent.ParseAdd(chromeUserAgent);
|
||||
return message;
|
||||
}
|
||||
HttpRequestMessage CreateHttpRequest (Uri uri)
|
||||
{
|
||||
var message = new HttpRequestMessage ();
|
||||
message.Method = HttpMethod.Get;
|
||||
message.RequestUri = uri;
|
||||
message.Headers.UserAgent.ParseAdd (chromeUserAgent);
|
||||
return message;
|
||||
}
|
||||
|
||||
public async Task<ReleaseInfo[]> PerformQuery(TorznabQuery query)
|
||||
{
|
||||
List<ReleaseInfo> releases = new List<ReleaseInfo>();
|
||||
public async Task<ReleaseInfo[]> PerformQuery (TorznabQuery query)
|
||||
{
|
||||
List<ReleaseInfo> releases = new List<ReleaseInfo> ();
|
||||
|
||||
foreach (var title in query.ShowTitles ?? new string[] { string.Empty })
|
||||
{
|
||||
string episodeSearchUrl;
|
||||
foreach (var title in query.ShowTitles ?? new string[] { string.Empty }) {
|
||||
string episodeSearchUrl;
|
||||
|
||||
if (string.IsNullOrEmpty(title))
|
||||
episodeSearchUrl = SearchUrl;
|
||||
else
|
||||
{
|
||||
var searchString = title + " " + query.GetEpisodeSearchString();
|
||||
episodeSearchUrl = string.Format("{0}?search={1}&cat=0", SearchUrl, HttpUtility.UrlEncode(searchString));
|
||||
}
|
||||
if (string.IsNullOrEmpty (title))
|
||||
episodeSearchUrl = SearchUrl;
|
||||
else {
|
||||
var searchString = title + " " + query.GetEpisodeSearchString ();
|
||||
episodeSearchUrl = string.Format ("{0}?search={1}&cat=0", SearchUrl, HttpUtility.UrlEncode (searchString));
|
||||
}
|
||||
|
||||
var request = CreateHttpRequest(new Uri(episodeSearchUrl));
|
||||
var response = await client.SendAsync(request);
|
||||
var results = await response.Content.ReadAsStringAsync();
|
||||
var request = CreateHttpRequest (new Uri (episodeSearchUrl));
|
||||
var response = await client.SendAsync (request);
|
||||
var results = await response.Content.ReadAsStringAsync ();
|
||||
|
||||
CQ dom = results;
|
||||
CQ dom = results;
|
||||
|
||||
var rows = dom["#highlight > tbody > tr"];
|
||||
var rows = dom ["#highlight > tbody > tr"];
|
||||
|
||||
foreach (var row in rows.Skip(1))
|
||||
{
|
||||
var release = new ReleaseInfo();
|
||||
foreach (var row in rows.Skip(1)) {
|
||||
var release = new ReleaseInfo ();
|
||||
|
||||
var qRow = row.Cq();
|
||||
var qLink = qRow.Find("a.torrent_name_link").First();
|
||||
var qRow = row.Cq ();
|
||||
var qLink = qRow.Find ("a.torrent_name_link").First ();
|
||||
|
||||
release.MinimumRatio = 1;
|
||||
release.MinimumSeedTime = 172800;
|
||||
release.Title = qLink.Attr("title");
|
||||
release.Description = release.Title;
|
||||
release.Guid = new Uri(BaseUrl + qLink.Attr("href"));
|
||||
release.Comments = release.Guid;
|
||||
release.Link = new Uri(BaseUrl + qRow.Find("td.table_links > a").First().Attr("href"));
|
||||
release.MinimumRatio = 1;
|
||||
release.MinimumSeedTime = 172800;
|
||||
release.Title = qLink.Attr ("title");
|
||||
release.Description = release.Title;
|
||||
release.Guid = new Uri (BaseUrl + qLink.Attr ("href"));
|
||||
release.Comments = release.Guid;
|
||||
release.Link = new Uri (BaseUrl + qRow.Find ("td.table_links > a").First ().Attr ("href"));
|
||||
|
||||
DateTime pubDate;
|
||||
var dateString = qRow.Find("td.table_added").Text().Trim();
|
||||
if (dateString.StartsWith("Today "))
|
||||
pubDate = (DateTime.UtcNow + TimeSpan.Parse(dateString.Split(' ')[1])).ToLocalTime();
|
||||
else if (dateString.StartsWith("Yesterday "))
|
||||
pubDate = (DateTime.UtcNow + TimeSpan.Parse(dateString.Split(' ')[1]) - TimeSpan.FromDays(1)).ToLocalTime();
|
||||
else
|
||||
pubDate = DateTime.ParseExact(dateString, "d-MMM-yyyy HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal).ToLocalTime();
|
||||
release.PublishDate = pubDate;
|
||||
DateTime pubDate;
|
||||
var dateString = qRow.Find ("td.table_added").Text ().Trim ();
|
||||
if (dateString.StartsWith ("Today "))
|
||||
pubDate = (DateTime.UtcNow + TimeSpan.Parse (dateString.Split (' ') [1])).ToLocalTime ();
|
||||
else if (dateString.StartsWith ("Yesterday "))
|
||||
pubDate = (DateTime.UtcNow + TimeSpan.Parse (dateString.Split (' ') [1]) - TimeSpan.FromDays (1)).ToLocalTime ();
|
||||
else
|
||||
pubDate = DateTime.ParseExact (dateString, "d-MMM-yyyy HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal).ToLocalTime ();
|
||||
release.PublishDate = pubDate;
|
||||
|
||||
release.Seeders = int.Parse(qRow.Find("td.table_seeders").Text().Trim());
|
||||
release.Peers = int.Parse(qRow.Find("td.table_leechers").Text().Trim()) + release.Seeders;
|
||||
release.Seeders = int.Parse (qRow.Find ("td.table_seeders").Text ().Trim ());
|
||||
release.Peers = int.Parse (qRow.Find ("td.table_leechers").Text ().Trim ()) + release.Seeders;
|
||||
|
||||
var sizeCol = qRow.Find("td.table_size")[0];
|
||||
var sizeVal = float.Parse(sizeCol.ChildNodes[0].NodeValue.Trim());
|
||||
var sizeUnit = sizeCol.ChildNodes[2].NodeValue.Trim();
|
||||
release.Size = ReleaseInfo.GetBytes(sizeUnit, sizeVal);
|
||||
var sizeCol = qRow.Find ("td.table_size") [0];
|
||||
var sizeVal = float.Parse (sizeCol.ChildNodes [0].NodeValue.Trim ());
|
||||
var sizeUnit = sizeCol.ChildNodes [2].NodeValue.Trim ();
|
||||
release.Size = ReleaseInfo.GetBytes (sizeUnit, sizeVal);
|
||||
|
||||
releases.Add(release);
|
||||
}
|
||||
}
|
||||
releases.Add (release);
|
||||
}
|
||||
}
|
||||
|
||||
return releases.ToArray();
|
||||
}
|
||||
return releases.ToArray ();
|
||||
}
|
||||
|
||||
public async Task<byte[]> Download(Uri link)
|
||||
{
|
||||
var request = CreateHttpRequest(link);
|
||||
var response = await client.SendAsync(request);
|
||||
var bytes = await response.Content.ReadAsByteArrayAsync();
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
public async Task<byte[]> Download (Uri link)
|
||||
{
|
||||
var request = CreateHttpRequest (link);
|
||||
var response = await client.SendAsync (request);
|
||||
var bytes = await response.Content.ReadAsByteArrayAsync ();
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,191 +11,181 @@ using System.Web;
|
|||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class IPTorrents : IndexerInterface
|
||||
{
|
||||
public class IPTorrents : IndexerInterface
|
||||
{
|
||||
|
||||
public event Action<IndexerInterface, Newtonsoft.Json.Linq.JToken> OnSaveConfigurationRequested;
|
||||
public event Action<IndexerInterface, Newtonsoft.Json.Linq.JToken> OnSaveConfigurationRequested;
|
||||
|
||||
public string DisplayName { get { return "IPTorrents"; } }
|
||||
public string DisplayName { get { return "IPTorrents"; } }
|
||||
|
||||
public string DisplayDescription { get { return "Always a step ahead"; } }
|
||||
public string DisplayDescription { get { return "Always a step ahead"; } }
|
||||
|
||||
public Uri SiteLink { get { return new Uri(BaseUrl); } }
|
||||
public Uri SiteLink { get { return new Uri (BaseUrl); } }
|
||||
|
||||
public bool IsConfigured { get; private set; }
|
||||
public bool IsConfigured { get; private set; }
|
||||
|
||||
static string chromeUserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36";
|
||||
static string chromeUserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36";
|
||||
|
||||
|
||||
static string BaseUrl = "https://iptorrents.com";
|
||||
static string BaseUrl = "https://iptorrents.com";
|
||||
|
||||
string SearchUrl = BaseUrl + "/t?q=";
|
||||
string SearchUrl = BaseUrl + "/t?q=";
|
||||
|
||||
|
||||
CookieContainer cookies;
|
||||
HttpClientHandler handler;
|
||||
HttpClient client;
|
||||
CookieContainer cookies;
|
||||
HttpClientHandler handler;
|
||||
HttpClient client;
|
||||
|
||||
public IPTorrents()
|
||||
{
|
||||
IsConfigured = false;
|
||||
cookies = new CookieContainer();
|
||||
handler = new HttpClientHandler
|
||||
{
|
||||
CookieContainer = cookies,
|
||||
AllowAutoRedirect = true,
|
||||
UseCookies = true,
|
||||
};
|
||||
client = new HttpClient(handler);
|
||||
}
|
||||
public IPTorrents ()
|
||||
{
|
||||
IsConfigured = false;
|
||||
cookies = new CookieContainer ();
|
||||
handler = new HttpClientHandler {
|
||||
CookieContainer = cookies,
|
||||
AllowAutoRedirect = true,
|
||||
UseCookies = true,
|
||||
};
|
||||
client = new HttpClient (handler);
|
||||
}
|
||||
|
||||
public async Task<ConfigurationData> GetConfigurationForSetup()
|
||||
{
|
||||
await client.GetAsync(new Uri(BaseUrl));
|
||||
var config = new ConfigurationDataBasicLogin();
|
||||
return (ConfigurationData)config;
|
||||
}
|
||||
public async Task<ConfigurationData> GetConfigurationForSetup ()
|
||||
{
|
||||
await client.GetAsync (new Uri (BaseUrl));
|
||||
var config = new ConfigurationDataBasicLogin ();
|
||||
return (ConfigurationData)config;
|
||||
}
|
||||
|
||||
public async Task ApplyConfiguration(JToken configJson)
|
||||
{
|
||||
public async Task ApplyConfiguration (JToken configJson)
|
||||
{
|
||||
|
||||
var config = new ConfigurationDataBasicLogin();
|
||||
config.LoadValuesFromJson(configJson);
|
||||
var config = new ConfigurationDataBasicLogin ();
|
||||
config.LoadValuesFromJson (configJson);
|
||||
|
||||
var pairs = new Dictionary<string, string>
|
||||
{
|
||||
{ "username", config.Username.Value},
|
||||
{ "password", config.Password.Value}
|
||||
};
|
||||
var pairs = new Dictionary<string, string> {
|
||||
{ "username", config.Username.Value },
|
||||
{ "password", config.Password.Value }
|
||||
};
|
||||
|
||||
var content = new FormUrlEncodedContent(pairs);
|
||||
var message = new HttpRequestMessage();
|
||||
message.Method = HttpMethod.Post;
|
||||
message.Content = content;
|
||||
message.RequestUri = new Uri(BaseUrl);
|
||||
message.Headers.Referrer = new Uri(BaseUrl);
|
||||
message.Headers.UserAgent.ParseAdd(chromeUserAgent);
|
||||
var content = new FormUrlEncodedContent (pairs);
|
||||
var message = new HttpRequestMessage ();
|
||||
message.Method = HttpMethod.Post;
|
||||
message.Content = content;
|
||||
message.RequestUri = new Uri (BaseUrl);
|
||||
message.Headers.Referrer = new Uri (BaseUrl);
|
||||
message.Headers.UserAgent.ParseAdd (chromeUserAgent);
|
||||
|
||||
var response = await client.SendAsync(message);
|
||||
var responseContent = await response.Content.ReadAsStringAsync();
|
||||
var response = await client.SendAsync (message);
|
||||
var responseContent = await response.Content.ReadAsStringAsync ();
|
||||
|
||||
if (!responseContent.Contains("/my.php"))
|
||||
{
|
||||
CQ dom = responseContent;
|
||||
var messageEl = dom["body > div"].First();
|
||||
var errorMessage = messageEl.Text().Trim();
|
||||
throw new ExceptionWithConfigData(errorMessage, (ConfigurationData)config);
|
||||
}
|
||||
else
|
||||
{
|
||||
var configSaveData = new JObject();
|
||||
configSaveData["cookies"] = new JArray((
|
||||
from cookie in cookies.GetCookies(new Uri(BaseUrl)).Cast<Cookie>()
|
||||
select cookie.Name + ":" + cookie.Value
|
||||
).ToArray());
|
||||
if (!responseContent.Contains ("/my.php")) {
|
||||
CQ dom = responseContent;
|
||||
var messageEl = dom ["body > div"].First ();
|
||||
var errorMessage = messageEl.Text ().Trim ();
|
||||
throw new ExceptionWithConfigData (errorMessage, (ConfigurationData)config);
|
||||
} else {
|
||||
var configSaveData = new JObject ();
|
||||
configSaveData ["cookies"] = cookies.ToJson (SiteLink);
|
||||
|
||||
if (OnSaveConfigurationRequested != null)
|
||||
OnSaveConfigurationRequested(this, configSaveData);
|
||||
if (OnSaveConfigurationRequested != null)
|
||||
OnSaveConfigurationRequested (this, configSaveData);
|
||||
|
||||
IsConfigured = true;
|
||||
}
|
||||
IsConfigured = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
HttpRequestMessage CreateHttpRequest(Uri uri)
|
||||
{
|
||||
var message = new HttpRequestMessage();
|
||||
message.Method = HttpMethod.Get;
|
||||
message.RequestUri = uri;
|
||||
message.Headers.UserAgent.ParseAdd(chromeUserAgent);
|
||||
return message;
|
||||
}
|
||||
HttpRequestMessage CreateHttpRequest (Uri uri)
|
||||
{
|
||||
var message = new HttpRequestMessage ();
|
||||
message.Method = HttpMethod.Get;
|
||||
message.RequestUri = uri;
|
||||
message.Headers.UserAgent.ParseAdd (chromeUserAgent);
|
||||
return message;
|
||||
}
|
||||
|
||||
public void LoadFromSavedConfiguration(Newtonsoft.Json.Linq.JToken jsonConfig)
|
||||
{
|
||||
cookies.FillFromJson(new Uri(BaseUrl), (JArray)jsonConfig["cookies"]);
|
||||
IsConfigured = true;
|
||||
}
|
||||
public void LoadFromSavedConfiguration (Newtonsoft.Json.Linq.JToken jsonConfig)
|
||||
{
|
||||
cookies.FillFromJson (new Uri (BaseUrl), (JArray)jsonConfig ["cookies"]);
|
||||
IsConfigured = true;
|
||||
}
|
||||
|
||||
public async Task<ReleaseInfo[]> PerformQuery(TorznabQuery query)
|
||||
{
|
||||
public async Task<ReleaseInfo[]> PerformQuery (TorznabQuery query)
|
||||
{
|
||||
|
||||
List<ReleaseInfo> releases = new List<ReleaseInfo>();
|
||||
List<ReleaseInfo> releases = new List<ReleaseInfo> ();
|
||||
|
||||
|
||||
foreach (var title in query.ShowTitles ?? new string[] { string.Empty })
|
||||
{
|
||||
foreach (var title in query.ShowTitles ?? new string[] { string.Empty }) {
|
||||
|
||||
var searchString = title + " " + query.GetEpisodeSearchString();
|
||||
var episodeSearchUrl = SearchUrl + HttpUtility.UrlEncode(searchString);
|
||||
var searchString = title + " " + query.GetEpisodeSearchString ();
|
||||
var episodeSearchUrl = SearchUrl + HttpUtility.UrlEncode (searchString);
|
||||
|
||||
var request = CreateHttpRequest(new Uri(episodeSearchUrl));
|
||||
var response = await client.SendAsync(request);
|
||||
var results = await response.Content.ReadAsStringAsync();
|
||||
var request = CreateHttpRequest (new Uri (episodeSearchUrl));
|
||||
var response = await client.SendAsync (request);
|
||||
var results = await response.Content.ReadAsStringAsync ();
|
||||
|
||||
CQ dom = results;
|
||||
CQ dom = results;
|
||||
|
||||
var rows = dom["table.torrents > tbody > tr"];
|
||||
foreach (var row in rows.Skip(1))
|
||||
{
|
||||
var release = new ReleaseInfo();
|
||||
var rows = dom ["table.torrents > tbody > tr"];
|
||||
foreach (var row in rows.Skip(1)) {
|
||||
var release = new ReleaseInfo ();
|
||||
|
||||
var qRow = row.Cq();
|
||||
var qRow = row.Cq ();
|
||||
|
||||
var qTitleLink = qRow.Find("a.t_title").First();
|
||||
release.Title = qTitleLink.Text().Trim();
|
||||
release.Description = release.Title;
|
||||
release.Guid = new Uri(BaseUrl + qTitleLink.Attr("href"));
|
||||
release.Comments = release.Guid;
|
||||
var qTitleLink = qRow.Find ("a.t_title").First ();
|
||||
release.Title = qTitleLink.Text ().Trim ();
|
||||
release.Description = release.Title;
|
||||
release.Guid = new Uri (BaseUrl + qTitleLink.Attr ("href"));
|
||||
release.Comments = release.Guid;
|
||||
|
||||
DateTime pubDate;
|
||||
var descString = qRow.Find(".t_ctime").Text();
|
||||
var dateString = descString.Split('|').Last().Trim();
|
||||
dateString = dateString.Split(new string[] { " by " }, StringSplitOptions.None)[0];
|
||||
var dateValue = float.Parse(dateString.Split(' ')[0]);
|
||||
var dateUnit = dateString.Split(' ')[1];
|
||||
if (dateUnit.Contains("minute"))
|
||||
pubDate = DateTime.Now - TimeSpan.FromMinutes(dateValue);
|
||||
else if (dateUnit.Contains("hour"))
|
||||
pubDate = DateTime.Now - TimeSpan.FromHours(dateValue);
|
||||
else if (dateUnit.Contains("day"))
|
||||
pubDate = DateTime.Now - TimeSpan.FromDays(dateValue);
|
||||
else if (dateUnit.Contains("week"))
|
||||
pubDate = DateTime.Now - TimeSpan.FromDays(7 * dateValue);
|
||||
else if (dateUnit.Contains("month"))
|
||||
pubDate = DateTime.Now - TimeSpan.FromDays(30 * dateValue);
|
||||
else if (dateUnit.Contains("year"))
|
||||
pubDate = DateTime.Now - TimeSpan.FromDays(365 * dateValue);
|
||||
else
|
||||
pubDate = DateTime.MinValue;
|
||||
release.PublishDate = pubDate;
|
||||
DateTime pubDate;
|
||||
var descString = qRow.Find (".t_ctime").Text ();
|
||||
var dateString = descString.Split ('|').Last ().Trim ();
|
||||
dateString = dateString.Split (new string[] { " by " }, StringSplitOptions.None) [0];
|
||||
var dateValue = float.Parse (dateString.Split (' ') [0]);
|
||||
var dateUnit = dateString.Split (' ') [1];
|
||||
if (dateUnit.Contains ("minute"))
|
||||
pubDate = DateTime.Now - TimeSpan.FromMinutes (dateValue);
|
||||
else if (dateUnit.Contains ("hour"))
|
||||
pubDate = DateTime.Now - TimeSpan.FromHours (dateValue);
|
||||
else if (dateUnit.Contains ("day"))
|
||||
pubDate = DateTime.Now - TimeSpan.FromDays (dateValue);
|
||||
else if (dateUnit.Contains ("week"))
|
||||
pubDate = DateTime.Now - TimeSpan.FromDays (7 * dateValue);
|
||||
else if (dateUnit.Contains ("month"))
|
||||
pubDate = DateTime.Now - TimeSpan.FromDays (30 * dateValue);
|
||||
else if (dateUnit.Contains ("year"))
|
||||
pubDate = DateTime.Now - TimeSpan.FromDays (365 * dateValue);
|
||||
else
|
||||
pubDate = DateTime.MinValue;
|
||||
release.PublishDate = pubDate;
|
||||
|
||||
var qLink = row.ChildElements.ElementAt(3).Cq().Children("a");
|
||||
release.Link = new Uri(BaseUrl + qLink.Attr("href"));
|
||||
var qLink = row.ChildElements.ElementAt (3).Cq ().Children ("a");
|
||||
release.Link = new Uri (BaseUrl + qLink.Attr ("href"));
|
||||
|
||||
var sizeStr = row.ChildElements.ElementAt(5).Cq().Text().Trim();
|
||||
var sizeVal = float.Parse(sizeStr.Split(' ')[0]);
|
||||
var sizeUnit = sizeStr.Split(' ')[1];
|
||||
release.Size = ReleaseInfo.GetBytes(sizeUnit, sizeVal);
|
||||
var sizeStr = row.ChildElements.ElementAt (5).Cq ().Text ().Trim ();
|
||||
var sizeVal = float.Parse (sizeStr.Split (' ') [0]);
|
||||
var sizeUnit = sizeStr.Split (' ') [1];
|
||||
release.Size = ReleaseInfo.GetBytes (sizeUnit, sizeVal);
|
||||
|
||||
release.Seeders = int.Parse(qRow.Find(".t_seeders").Text().Trim());
|
||||
release.Peers = int.Parse(qRow.Find(".t_leechers").Text().Trim()) + release.Seeders;
|
||||
release.Seeders = int.Parse (qRow.Find (".t_seeders").Text ().Trim ());
|
||||
release.Peers = int.Parse (qRow.Find (".t_leechers").Text ().Trim ()) + release.Seeders;
|
||||
|
||||
releases.Add(release);
|
||||
}
|
||||
releases.Add (release);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return releases.ToArray();
|
||||
return releases.ToArray ();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<byte[]> Download(Uri link)
|
||||
{
|
||||
var request = CreateHttpRequest(link);
|
||||
var response = await client.SendAsync(request);
|
||||
var bytes = await response.Content.ReadAsByteArrayAsync();
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
public async Task<byte[]> Download (Uri link)
|
||||
{
|
||||
var request = CreateHttpRequest (link);
|
||||
var response = await client.SendAsync (request);
|
||||
var bytes = await response.Content.ReadAsByteArrayAsync ();
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,8 @@ namespace Jackett.Indexers
|
|||
HttpClientHandler handler;
|
||||
HttpClient client;
|
||||
|
||||
string cookieHeader;
|
||||
|
||||
public MoreThanTV()
|
||||
{
|
||||
IsConfigured = false;
|
||||
|
@ -68,22 +70,36 @@ namespace Jackett.Indexers
|
|||
|
||||
public async Task ApplyConfiguration(JToken configJson)
|
||||
{
|
||||
|
||||
var config = new ConfigurationDataBasicLogin();
|
||||
config.LoadValuesFromJson(configJson);
|
||||
|
||||
var pairs = new Dictionary<string, string>
|
||||
{
|
||||
{ "username", config.Username.Value},
|
||||
{ "password", config.Password.Value},
|
||||
{ "login", "Log in" },
|
||||
{ "keeplogged", "1" }
|
||||
};
|
||||
var pairs = new Dictionary<string, string> {
|
||||
{ "username", config.Username.Value },
|
||||
{ "password", config.Password.Value },
|
||||
{ "login", "Log in" },
|
||||
{ "keeplogged", "1" }
|
||||
};
|
||||
|
||||
var content = new FormUrlEncodedContent(pairs);
|
||||
|
||||
var response = await client.PostAsync(LoginUrl, content);
|
||||
var responseContent = await response.Content.ReadAsStringAsync();
|
||||
string responseContent;
|
||||
JArray cookieJArray;
|
||||
|
||||
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
|
||||
{
|
||||
// If Windows use .net http
|
||||
var response = await client.PostAsync(LoginUrl, content);
|
||||
responseContent = await response.Content.ReadAsStringAsync();
|
||||
cookieJArray = cookies.ToJson(SiteLink);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If UNIX system use curl
|
||||
var response = await CurlHelper.Shared.PostAsync(LoginUrl, pairs);
|
||||
responseContent = Encoding.UTF8.GetString(response.Content);
|
||||
cookieHeader = response.CookieHeader;
|
||||
cookieJArray = new JArray(response.CookiesFlat);
|
||||
}
|
||||
|
||||
if (!responseContent.Contains("logout.php?"))
|
||||
{
|
||||
|
@ -91,15 +107,13 @@ namespace Jackett.Indexers
|
|||
dom["#loginform > table"].Remove();
|
||||
var errorMessage = dom["#loginform"].Text().Trim().Replace("\n\t", " ");
|
||||
throw new ExceptionWithConfigData(errorMessage, (ConfigurationData)config);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
var configSaveData = new JObject();
|
||||
configSaveData["cookies"] = new JArray((
|
||||
from cookie in cookies.GetCookies(new Uri(BaseUrl)).Cast<Cookie>()
|
||||
select cookie.Name + ":" + cookie.Value
|
||||
).ToArray());
|
||||
|
||||
var configSaveData = new JObject();
|
||||
configSaveData["cookies"] = cookieJArray;
|
||||
if (OnSaveConfigurationRequested != null)
|
||||
OnSaveConfigurationRequested(this, configSaveData);
|
||||
|
||||
|
@ -107,9 +121,10 @@ namespace Jackett.Indexers
|
|||
}
|
||||
}
|
||||
|
||||
public void LoadFromSavedConfiguration(Newtonsoft.Json.Linq.JToken jsonConfig)
|
||||
public void LoadFromSavedConfiguration(JToken jsonConfig)
|
||||
{
|
||||
cookies.FillFromJson(new Uri(BaseUrl), (JArray)jsonConfig["cookies"]);
|
||||
cookies.FillFromJson(SiteLink, (JArray)jsonConfig["cookies"]);
|
||||
cookieHeader = cookies.GetCookieHeader(SiteLink);
|
||||
IsConfigured = true;
|
||||
}
|
||||
|
||||
|
@ -133,7 +148,18 @@ namespace Jackett.Indexers
|
|||
|
||||
var searchString = title + " " + query.GetEpisodeSearchString();
|
||||
var episodeSearchUrl = SearchUrl + HttpUtility.UrlEncode(searchString);
|
||||
var results = await client.GetStringAsync(episodeSearchUrl);
|
||||
|
||||
string results;
|
||||
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
|
||||
{
|
||||
results = await client.GetStringAsync(episodeSearchUrl);
|
||||
}
|
||||
else
|
||||
{
|
||||
var response = await CurlHelper.Shared.GetAsync(episodeSearchUrl, cookieHeader);
|
||||
results = Encoding.UTF8.GetString(response.Content);
|
||||
}
|
||||
|
||||
var json = JObject.Parse(results);
|
||||
foreach (JObject r in json["response"]["results"])
|
||||
{
|
||||
|
@ -176,9 +202,18 @@ namespace Jackett.Indexers
|
|||
return new DateTime(unixStart.Ticks + unixTimeStampInTicks);
|
||||
}
|
||||
|
||||
public Task<byte[]> Download(Uri link)
|
||||
public async Task<byte[]> Download(Uri link)
|
||||
{
|
||||
return client.GetByteArrayAsync(link);
|
||||
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
|
||||
{
|
||||
return await client.GetByteArrayAsync(link);
|
||||
}
|
||||
else
|
||||
{
|
||||
var response = await CurlHelper.Shared.GetAsync(link.ToString(), cookieHeader);
|
||||
return response.Content;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
|
@ -60,10 +60,6 @@
|
|||
<Reference Include="ModernHttpClient">
|
||||
<HintPath>..\packages\modernhttpclient.2.3.0\lib\Portable-Net45+WinRT45+WP8+WPA81\ModernHttpClient.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Newtonsoft.Json.6.0.8\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NLog">
|
||||
<HintPath>..\packages\NLog.3.2.0.0\lib\net45\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
|
@ -79,6 +75,9 @@
|
|||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Newtonsoft.Json">
|
||||
<HintPath>..\packages\Newtonsoft.Json.6.0.8\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ApiKey.cs" />
|
||||
|
@ -116,6 +115,7 @@
|
|||
<Compile Include="TorznabQuery.cs" />
|
||||
<Compile Include="TVRage.cs" />
|
||||
<Compile Include="WebApi.cs" />
|
||||
<Compile Include="CurlHelper.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
|
@ -203,7 +203,12 @@
|
|||
</Content>
|
||||
<Content Include="Resources\validator_reply.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\CurlSharp\CurlSharp.csproj">
|
||||
<Project>{74420A79-CC16-442C-8B1E-7C1B913844F0}</Project>
|
||||
<Name>CurlSharp</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include=".NETFramework,Version=v4.5.1">
|
||||
<Visible>False</Visible>
|
||||
|
|
|
@ -14,93 +14,84 @@ using System.Windows.Forms;
|
|||
|
||||
namespace Jackett
|
||||
{
|
||||
class Program
|
||||
{
|
||||
public static string AppConfigDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Jackett");
|
||||
class Program
|
||||
{
|
||||
public static string AppConfigDirectory = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.CommonApplicationData), "Jackett");
|
||||
|
||||
public static Server ServerInstance { get; private set; }
|
||||
public static Server ServerInstance { get; private set; }
|
||||
|
||||
public static bool IsFirstRun { get; private set; }
|
||||
public static bool IsFirstRun { get; private set; }
|
||||
|
||||
public static Logger LoggerInstance { get; private set; }
|
||||
public static Logger LoggerInstance { get; private set; }
|
||||
|
||||
public static ManualResetEvent ExitEvent { get; private set; }
|
||||
public static ManualResetEvent ExitEvent { get; private set; }
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
ExitEvent = new ManualResetEvent(false);
|
||||
static void Main (string[] args)
|
||||
{
|
||||
ExitEvent = new ManualResetEvent (false);
|
||||
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(AppConfigDirectory))
|
||||
{
|
||||
IsFirstRun = true;
|
||||
Directory.CreateDirectory(AppConfigDirectory);
|
||||
}
|
||||
Console.WriteLine("App config/log directory: " + AppConfigDirectory);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show("Could not create settings directory.");
|
||||
Application.Exit();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (!Directory.Exists (AppConfigDirectory)) {
|
||||
IsFirstRun = true;
|
||||
Directory.CreateDirectory (AppConfigDirectory);
|
||||
}
|
||||
Console.WriteLine ("App config/log directory: " + AppConfigDirectory);
|
||||
} catch (Exception ex) {
|
||||
MessageBox.Show ("Could not create settings directory.");
|
||||
Application.Exit ();
|
||||
return;
|
||||
}
|
||||
|
||||
var logConfig = new LoggingConfiguration();
|
||||
var logConfig = new LoggingConfiguration ();
|
||||
|
||||
var logFile = new FileTarget();
|
||||
logConfig.AddTarget("file", logFile);
|
||||
logFile.FileName = Path.Combine(AppConfigDirectory, "log.txt");
|
||||
logFile.Layout = "${longdate} ${level} ${message} \n ${exception:format=ToString}\n";
|
||||
var logFileRule = new LoggingRule("*", LogLevel.Debug, logFile);
|
||||
logConfig.LoggingRules.Add(logFileRule);
|
||||
var logFile = new FileTarget ();
|
||||
logConfig.AddTarget ("file", logFile);
|
||||
logFile.FileName = Path.Combine (AppConfigDirectory, "log.txt");
|
||||
logFile.Layout = "${longdate} ${level} ${message} \n ${exception:format=ToString}\n";
|
||||
var logFileRule = new LoggingRule ("*", LogLevel.Debug, logFile);
|
||||
logConfig.LoggingRules.Add (logFileRule);
|
||||
|
||||
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
|
||||
{
|
||||
var logAlert = new MessageBoxTarget();
|
||||
logConfig.AddTarget("alert", logAlert);
|
||||
logAlert.Layout = "${message}";
|
||||
logAlert.Caption = "Alert";
|
||||
var logAlertRule = new LoggingRule("*", LogLevel.Fatal, logAlert);
|
||||
logConfig.LoggingRules.Add(logAlertRule);
|
||||
}
|
||||
if (Environment.OSVersion.Platform == PlatformID.Win32NT) {
|
||||
var logAlert = new MessageBoxTarget ();
|
||||
logConfig.AddTarget ("alert", logAlert);
|
||||
logAlert.Layout = "${message}";
|
||||
logAlert.Caption = "Alert";
|
||||
var logAlertRule = new LoggingRule ("*", LogLevel.Fatal, logAlert);
|
||||
logConfig.LoggingRules.Add (logAlertRule);
|
||||
}
|
||||
|
||||
var logConsole = new ConsoleTarget();
|
||||
logConfig.AddTarget("console", logConsole);
|
||||
logConsole.Layout = "${longdate} ${level} ${message} ${exception:format=ToString}";
|
||||
var logConsoleRule = new LoggingRule("*", LogLevel.Debug, logConsole);
|
||||
logConfig.LoggingRules.Add(logConsoleRule);
|
||||
var logConsole = new ConsoleTarget ();
|
||||
logConfig.AddTarget ("console", logConsole);
|
||||
logConsole.Layout = "${longdate} ${level} ${message} ${exception:format=ToString}";
|
||||
var logConsoleRule = new LoggingRule ("*", LogLevel.Debug, logConsole);
|
||||
logConfig.LoggingRules.Add (logConsoleRule);
|
||||
|
||||
LogManager.Configuration = logConfig;
|
||||
LoggerInstance = LogManager.GetCurrentClassLogger();
|
||||
LogManager.Configuration = logConfig;
|
||||
LoggerInstance = LogManager.GetCurrentClassLogger ();
|
||||
|
||||
var serverTask = Task.Run(async () =>
|
||||
{
|
||||
ServerInstance = new Server();
|
||||
await ServerInstance.Start();
|
||||
});
|
||||
var serverTask = Task.Run (async () => {
|
||||
ServerInstance = new Server ();
|
||||
await ServerInstance.Start ();
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
|
||||
Application.Run(new Main());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
try {
|
||||
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
|
||||
Application.Run (new Main ());
|
||||
} catch (Exception ex) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine("Running in headless mode.");
|
||||
Console.WriteLine ("Running in headless mode.");
|
||||
|
||||
Task.WaitAll(serverTask);
|
||||
Console.WriteLine("Server thread exit");
|
||||
}
|
||||
Task.WaitAll (serverTask);
|
||||
Console.WriteLine ("Server thread exit");
|
||||
}
|
||||
|
||||
static public void RestartAsAdmin()
|
||||
{
|
||||
var startInfo = new ProcessStartInfo(Application.ExecutablePath.ToString()) { Verb = "runas" };
|
||||
Process.Start(startInfo);
|
||||
Environment.Exit(0);
|
||||
}
|
||||
}
|
||||
static public void RestartAsAdmin ()
|
||||
{
|
||||
var startInfo = new ProcessStartInfo (Application.ExecutablePath.ToString ()) { Verb = "runas" };
|
||||
Process.Start (startInfo);
|
||||
Environment.Exit (0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,26 +60,26 @@ namespace Jackett
|
|||
}
|
||||
catch (HttpListenerException ex)
|
||||
{
|
||||
var errorStr = "App must be ran as Admin for permission to use port "
|
||||
+ Port + Environment.NewLine
|
||||
+ "Restart app with admin privileges?";
|
||||
|
||||
Program.LoggerInstance.FatalException("Failed to start HTTP server", ex);
|
||||
|
||||
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
|
||||
if (ex.ErrorCode == 5)
|
||||
{
|
||||
var dialogResult = MessageBox.Show(errorStr, "Error", MessageBoxButtons.YesNo);
|
||||
if (dialogResult == DialogResult.No)
|
||||
var errorStr = "App must be ran as admin for permission to use port "
|
||||
+ Port + Environment.NewLine + "Restart app with admin privileges?";
|
||||
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
|
||||
{
|
||||
Program.LoggerInstance.FatalException("App must be ran as Admin for permission to use port " + Port, ex);
|
||||
Application.Exit();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
Program.RestartAsAdmin();
|
||||
var dialogResult = MessageBox.Show(errorStr, "Error", MessageBoxButtons.YesNo);
|
||||
if (dialogResult == DialogResult.No)
|
||||
{
|
||||
Application.Exit();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
Program.RestartAsAdmin();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
Program.LoggerInstance.FatalException("Failed to start HTTP server. " + ex.Message, ex);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -95,7 +95,9 @@ namespace Jackett
|
|||
Process.Start("http://127.0.0.1:" + Port);
|
||||
#endif
|
||||
}
|
||||
catch (Exception) { }
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
|
@ -152,14 +154,18 @@ namespace Jackett
|
|||
var errorBytes = Encoding.UTF8.GetBytes(exception.Message);
|
||||
await context.Response.OutputStream.WriteAsync(errorBytes, 0, errorBytes.Length);
|
||||
}
|
||||
catch (Exception) { }
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
context.Response.Close();
|
||||
}
|
||||
catch (Exception) { }
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue