418 lines
15 KiB
C#
418 lines
15 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Drawing;
|
|
using System.IO;
|
|
using System.IO.Compression;
|
|
using System.Linq;
|
|
using System.Net;
|
|
using System.Net.Cache;
|
|
using System.Net.Security;
|
|
using System.Runtime.InteropServices;
|
|
using System.Security.Cryptography.X509Certificates;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading;
|
|
|
|
namespace StoreHub.KJDWebService.Commons
|
|
{
|
|
public class HtmlUtils
|
|
{
|
|
static public string UrlDecodeUtf8(string value)
|
|
{
|
|
if (value == null)
|
|
{
|
|
return null;
|
|
}
|
|
Encoding encoding = Encoding.UTF8;//你的编码 也可能是GBK
|
|
int length = value.Length;
|
|
UrlDecoder decoder = new UrlDecoder(length, encoding);
|
|
for (int i = 0; i < length; i++)
|
|
{
|
|
char ch = value[i];
|
|
if (ch == '+')
|
|
{
|
|
ch = ' ';
|
|
}
|
|
else if ((ch == '%') && (i < (length - 2)))
|
|
{
|
|
if ((value[i + 1] == 'u') && (i < (length - 5)))
|
|
{
|
|
int num3 = HexToInt(value[i + 2]);
|
|
int num4 = HexToInt(value[i + 3]);
|
|
int num5 = HexToInt(value[i + 4]);
|
|
int num6 = HexToInt(value[i + 5]);
|
|
if (((num3 < 0) || (num4 < 0)) || ((num5 < 0) || (num6 < 0)))
|
|
{
|
|
goto Label_010B;
|
|
}
|
|
ch = (char)((((num3 << 12) | (num4 << 8)) | (num5 << 4)) | num6);
|
|
i += 5;
|
|
decoder.AddChar(ch);
|
|
continue;
|
|
}
|
|
int num7 = HexToInt(value[i + 1]);
|
|
int num8 = HexToInt(value[i + 2]);
|
|
if ((num7 >= 0) && (num8 >= 0))
|
|
{
|
|
byte b = (byte)((num7 << 4) | num8);
|
|
i += 2;
|
|
decoder.AddByte(b);
|
|
continue;
|
|
}
|
|
}
|
|
Label_010B:
|
|
if ((ch & 0xff80) == 0)
|
|
{
|
|
decoder.AddByte((byte)ch);
|
|
}
|
|
else
|
|
{
|
|
decoder.AddChar(ch);
|
|
}
|
|
}
|
|
return decoder.GetString();
|
|
}
|
|
|
|
/// <summary>
|
|
/// URL UTF-8转码
|
|
/// </summary>
|
|
/// <param name="IndexKey"></param>
|
|
/// <returns></returns>
|
|
public static string UrlEncodeUtf8(string IndexKey)
|
|
{
|
|
if (String.IsNullOrEmpty(IndexKey))
|
|
return "";
|
|
return WebUtility.UrlEncode(IndexKey);
|
|
}
|
|
|
|
/// <summary>
|
|
/// post 数据
|
|
/// </summary>
|
|
/// <param name="url"></param>
|
|
/// <param name="postData"></param>
|
|
/// <returns></returns>
|
|
public static string PostUtf8(string url, StringBuilder postData)
|
|
{
|
|
try
|
|
{
|
|
WebClientx wc = new WebClientx();
|
|
byte[] sendData = Encoding.GetEncoding("utf-8").GetBytes(postData.ToString());
|
|
wc.Headers.Add("ContentLength", sendData.Length.ToString());
|
|
wc.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
|
|
wc.Proxy = null;
|
|
return Encoding.UTF8.GetString(wc.UploadData(url, "POST", sendData));
|
|
}
|
|
catch
|
|
{
|
|
return "";
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 浏览器标识
|
|
/// </summary>
|
|
public static string UserAgent = @"Mozilla/5.0+(Windows+NT+10.0;+WOW64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/57.0.2987.133+Safari/537.36
|
|
Mozilla/5.0+(Windows+NT+6.1)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/57.0.2987.133+Safari/537.36
|
|
Mozilla/5.0+(Windows+NT+10.0;+WOW64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/54.0.2840.99+Safari/537.36
|
|
Mozilla/5.0+(Windows+NT+5.1)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/31.0.1650.63+Safari/537.36
|
|
Mozilla/5.0+(compatible;+MSIE+9.0;+Windows+NT+6.1;+Win64;+x64;+Trident/5.0)
|
|
Mozilla/5.0+(Windows+NT+5.1)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/45.0.2454.101+Safari/537.36
|
|
Mozilla/5.0+(Windows+NT+6.1;+WOW64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/45.0.2454.101+Safari/537.36
|
|
Mozilla/5.0+(Windows+NT+6.3;+WOW64;+Trident/7.0;+rv:11.0)+like+Gecko
|
|
Mozilla/5.0+(Windows+NT+10.0;+WOW64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/57.0.2987.133+Safari/537.36
|
|
Mozilla/5.0+(compatible;+MSIE+9.0;+Windows+NT+6.1;+WOW64;+Trident/5.0)
|
|
Mozilla/5.0+(Windows+NT+6.3;+Win64;+x64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/57.0.2987.133+Safari/537.36
|
|
Mozilla/5.0+(Windows+NT+6.1;+WOW64)+AppleWebKit/537.1+(KHTML,+like+Gecko)+Chrome/21.0.1180.89+Safari/537.1
|
|
Mozilla/5.0+(Windows+NT+6.1;+WOW64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/45.0.2454.101+Safari/537.36
|
|
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.104 Safari/537.36 Core/1.53.2372.400 QQBrowser/9.5.10548.400";
|
|
|
|
/// <summary>
|
|
/// post 数据
|
|
/// </summary>
|
|
/// <param name="url"></param>
|
|
/// <param name="postData"></param>
|
|
/// <returns></returns>
|
|
public static string PostUtf8(string url, string postData, string contentType = "")
|
|
{
|
|
//return PostUtf8(url, Encoding.UTF8.GetBytes(postData));
|
|
|
|
bool isError = false;
|
|
string[] l = UserAgent.Split('\n');
|
|
reTry:
|
|
try
|
|
{
|
|
string codeType = "utf-8";
|
|
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
|
|
request.UserAgent = l[new Random(Guid.NewGuid().GetHashCode()).Next(l.Length)].Trim();
|
|
byte[] byteData = Encoding.GetEncoding(codeType).GetBytes(postData);
|
|
request.Method = "POST";
|
|
request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
|
|
request.Timeout = 30 * 1000;
|
|
request.ReadWriteTimeout = 30 * 1000;
|
|
request.Proxy = null;
|
|
request.ContentType = "application/x-www-form-urlencoded; charset=" + codeType;
|
|
//if (BaseClass.SaLevel > 0)
|
|
{
|
|
//260306 采用GZip/deflate压缩
|
|
//request.Headers.Set(HttpRequestHeader.AcceptEncoding, "gzip, deflate, br, zstd");
|
|
//request.Headers.Set(HttpRequestHeader.AcceptEncoding, "gzip, deflate");
|
|
}
|
|
if (url.StartsWith("https://openapi.jinritemai.com/"))
|
|
{
|
|
request.Headers.Add("X-USE-BOE", "1");
|
|
request.Headers.Add("Origin-From", "djt_prod");
|
|
request.Headers.Add("djt_prod", "boe_time_sku");
|
|
}
|
|
if (!string.IsNullOrEmpty(contentType))
|
|
{
|
|
request.ContentType = contentType;
|
|
}
|
|
request.ContentLength = byteData.Length;
|
|
request.Referer = url;
|
|
request.CookieContainer = new CookieContainer();
|
|
request.AllowAutoRedirect = false;
|
|
using (Stream requestStream = request.GetRequestStream())
|
|
{
|
|
requestStream.Write(byteData, 0, byteData.Length);
|
|
}
|
|
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
|
|
|
|
Stream receiveStream = response.GetResponseStream();
|
|
StreamReader readStream = new StreamReader(receiveStream, Encoding.GetEncoding(codeType));
|
|
|
|
return readStream.ReadToEnd().Trim();
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
//{
|
|
// isError = true;
|
|
// goto reTry;
|
|
//}
|
|
Thread.Sleep(50);
|
|
return "";
|
|
}
|
|
|
|
}
|
|
|
|
|
|
public static int HexToInt(char h)
|
|
{
|
|
if ((h >= '0') && (h <= '9'))
|
|
{
|
|
return (h - '0');
|
|
}
|
|
if ((h >= 'a') && (h <= 'f'))
|
|
{
|
|
return ((h - 'a') + 10);
|
|
}
|
|
if ((h >= 'A') && (h <= 'F'))
|
|
{
|
|
return ((h - 'A') + 10);
|
|
}
|
|
return -1;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// class UrlDecoder
|
|
/// </summary>
|
|
class UrlDecoder
|
|
{
|
|
// Fields
|
|
private int _bufferSize;
|
|
private byte[] _byteBuffer;
|
|
private char[] _charBuffer;
|
|
private Encoding _encoding;
|
|
private int _numBytes;
|
|
private int _numChars;
|
|
|
|
// Methods
|
|
internal UrlDecoder(int bufferSize, Encoding encoding)
|
|
{
|
|
this._bufferSize = bufferSize;
|
|
this._encoding = encoding;
|
|
this._charBuffer = new char[bufferSize];
|
|
}
|
|
|
|
internal void AddByte(byte b)
|
|
{
|
|
if (this._byteBuffer == null)
|
|
{
|
|
this._byteBuffer = new byte[this._bufferSize];
|
|
}
|
|
this._byteBuffer[this._numBytes++] = b;
|
|
}
|
|
|
|
internal void AddChar(char ch)
|
|
{
|
|
if (this._numBytes > 0)
|
|
{
|
|
this.FlushBytes();
|
|
}
|
|
this._charBuffer[this._numChars++] = ch;
|
|
}
|
|
|
|
private void FlushBytes()
|
|
{
|
|
if (this._numBytes > 0)
|
|
{
|
|
this._numChars += this._encoding.GetChars(this._byteBuffer, 0, this._numBytes, this._charBuffer, this._numChars);
|
|
this._numBytes = 0;
|
|
}
|
|
}
|
|
|
|
internal string GetString()
|
|
{
|
|
if (this._numBytes > 0)
|
|
{
|
|
this.FlushBytes();
|
|
}
|
|
if (this._numChars > 0)
|
|
{
|
|
return new string(this._charBuffer, 0, this._numChars);
|
|
}
|
|
return string.Empty;
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 下载器
|
|
/// </summary>
|
|
public class WebClientx : WebClient
|
|
{
|
|
/// <summary>
|
|
/// 默认超时多少秒
|
|
/// </summary>
|
|
public int Timeout = 100;
|
|
/// <summary>
|
|
/// 允许自动重定向
|
|
/// </summary>
|
|
public bool AllowAutoRedirect = true;
|
|
public bool IsDelete = false;
|
|
|
|
private string OutIP = "";
|
|
/// <summary>
|
|
/// 证书列表
|
|
/// </summary>
|
|
public static List<Certificate> X509List = new List<Certificate>();
|
|
/// <summary>
|
|
/// 绑定IP
|
|
/// </summary>
|
|
/// <param name="outIp"></param>
|
|
public WebClientx(string outIp)
|
|
{
|
|
OutIP = outIp;
|
|
CachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore);
|
|
}
|
|
|
|
public WebClientx()
|
|
{
|
|
}
|
|
/// <summary>
|
|
/// 重写
|
|
/// </summary>
|
|
/// <param name="address"></param>
|
|
/// <returns></returns>
|
|
protected override WebRequest GetWebRequest(Uri address)
|
|
{
|
|
string s = address.ToString();
|
|
if (string.IsNullOrEmpty(s) || s.Length < 7 || !(s.Substring(0, 7).ToLower() == "http://" || s.Substring(0, 8).ToLower() == "https://"))
|
|
return null;
|
|
var request = (HttpWebRequest)base.GetWebRequest(address);
|
|
request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
|
|
request.Timeout = 1000 * Timeout;
|
|
request.ReadWriteTimeout = 500 * Timeout;
|
|
request.AllowAutoRedirect = AllowAutoRedirect;
|
|
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(ValidateServerCertificate);
|
|
if (IsDelete)
|
|
request.Method = "DELETE";
|
|
if (!string.IsNullOrEmpty(OutIP))
|
|
{
|
|
request.ServicePoint.BindIPEndPointDelegate = (servicePoint, remoteEndPoint, retryCount) =>
|
|
{
|
|
servicePoint.MaxIdleTime = 20;
|
|
return new IPEndPoint(IPAddress.Parse(OutIP), 0);
|
|
};
|
|
}
|
|
if (request.RequestUri.Scheme == "https") //挂接验证服务端证书的回调
|
|
{
|
|
X509Certificate2 x509c = null;
|
|
for (int i = 0; i < X509List.Count; i++)
|
|
{
|
|
if (X509List[i].Domain.ToLower() == address.Host.ToLower())
|
|
{
|
|
x509c = X509List[i].X509;
|
|
break;
|
|
}
|
|
}
|
|
if (x509c == null)
|
|
{
|
|
ServicePointManager.ServerCertificateValidationCallback =
|
|
new RemoteCertificateValidationCallback(RemoteCertificateValidationCallback);
|
|
try
|
|
{
|
|
X509Store _store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
|
|
_store.Open(OpenFlags.ReadWrite);
|
|
string findValue = Dns.GetHostName(); //获取本地主机名称作为证书查找的参数
|
|
X509Certificate2Collection _certsCollection =
|
|
_store.Certificates.Find(X509FindType.FindByIssuerName, findValue, false);
|
|
if (_certsCollection.Count > 0)
|
|
{
|
|
x509c = _certsCollection[0];
|
|
request.ClientCertificates.Add(x509c);
|
|
}
|
|
}
|
|
catch { }
|
|
|
|
}
|
|
}
|
|
return request;
|
|
}
|
|
/// <summary>
|
|
/// 获取证书
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="certificate"></param>
|
|
/// <param name="chain"></param>
|
|
/// <param name="sslPolicyErrors"></param>
|
|
/// <returns></returns>
|
|
public bool RemoteCertificateValidationCallback(Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
|
|
{
|
|
return true;
|
|
}
|
|
public static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
|
|
{
|
|
//if (sslPolicyErrors == SslPolicyErrors.None) {
|
|
// return true;
|
|
//}
|
|
|
|
//Console.WriteLine("Certificate error: {0}", sslPolicyErrors);
|
|
|
|
//// Do not allow this client to communicate with unauthenticated servers.
|
|
//return false;
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 网站证书
|
|
/// </summary>
|
|
public class Certificate
|
|
{
|
|
/// <summary>
|
|
/// 域名
|
|
/// </summary>
|
|
public string Domain { get; set; }
|
|
/// <summary>
|
|
/// 证书
|
|
/// </summary>
|
|
public X509Certificate2 X509 { get; set; }
|
|
}
|
|
}
|
|
|
|
|
|
|