This commit is contained in:
2020-07-09 08:50:24 +08:00
parent 13d25f4707
commit c523462b82
1818 changed files with 174940 additions and 582 deletions

View File

@@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BestHTTP.Forms
{
/// <summary>
/// This class represents a HTTP Form's field.
/// </summary>
public class HTTPFieldData
{
/// <summary>
/// The form's field.
/// </summary>
public string Name { get; set; }
/// <summary>
/// Filename of the field. Optional.
/// </summary>
public string FileName { get; set; }
/// <summary>
/// Mime-type of the field. Optional
/// </summary>
public string MimeType { get; set; }
/// <summary>
/// Encoding of the data. Optional
/// </summary>
public Encoding Encoding { get; set; }
/// <summary>
/// The field's textual data.
/// </summary>
public string Text { get; set; }
/// <summary>
/// The field's binary data.
/// </summary>
public byte[] Binary { get; set; }
/// <summary>
/// Will return with the binary data, or if it's not present the textual data will be decoded to binary.
/// </summary>
public byte[] Payload
{
get
{
if (Binary != null)
return Binary;
if (Encoding == null)
Encoding = Encoding.UTF8;
return Binary = Encoding.GetBytes(Text);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7ccf16c6a45074f289839d19bf770289
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,141 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BestHTTP.Forms
{
/// <summary>
/// Base class of a concrete implementation. Don't use it to create a form, use instead one of the already wrote implementation(HTTPMultiPartForm, HTTPUrlEncodedForm), or create a new one by inheriting from this base class.
/// </summary>
public class HTTPFormBase
{
const int LongLength = 256;
#region Properties
/// <summary>
/// A list that holds the form's fields.
/// </summary>
public List<HTTPFieldData> Fields { get; set; }
/// <summary>
/// Returns true if the Fields has no element.
/// </summary>
public bool IsEmpty { get { return Fields == null || Fields.Count == 0; } }
/// <summary>
/// True if new fields has been added to our list.
/// </summary>
public bool IsChanged { get; protected set; }
/// <summary>
/// True if there are at least one form-field with binary data.
/// </summary>
public bool HasBinary { get; protected set; }
/// <summary>
/// True if there are at least one form-field with a long textual data.
/// </summary>
public bool HasLongValue { get; protected set; }
#endregion
#region Field Management
public void AddBinaryData(string fieldName, byte[] content)
{
AddBinaryData(fieldName, content, null, null);
}
public void AddBinaryData(string fieldName, byte[] content, string fileName)
{
AddBinaryData(fieldName, content, fileName, null);
}
public void AddBinaryData(string fieldName, byte[] content, string fileName, string mimeType)
{
if (Fields == null)
Fields = new List<HTTPFieldData>();
HTTPFieldData field = new HTTPFieldData();
field.Name = fieldName;
if (fileName == null)
field.FileName = fieldName + ".dat";
else
field.FileName = fileName;
if (mimeType == null)
field.MimeType = "application/octet-stream";
else
field.MimeType = mimeType;
field.Binary = content;
Fields.Add(field);
HasBinary = IsChanged = true;
}
public void AddField(string fieldName, string value)
{
AddField(fieldName, value, System.Text.Encoding.UTF8);
}
public void AddField(string fieldName, string value, System.Text.Encoding e)
{
if (Fields == null)
Fields = new List<HTTPFieldData>();
HTTPFieldData field = new HTTPFieldData();
field.Name = fieldName;
field.FileName = null;
if (e != null)
field.MimeType = "text/plain; charset=\"" + e.WebName + "\"";
field.Text = value;
field.Encoding = e;
Fields.Add(field);
IsChanged = true;
HasLongValue |= value.Length > LongLength;
}
#endregion
#region Virtual Functions
/// <summary>
/// It should 'clone' all the data from the given HTTPFormBase object.
/// Called after the form-implementation created.
/// </summary>
public virtual void CopyFrom(HTTPFormBase fields)
{
this.Fields = new List<HTTPFieldData>(fields.Fields);
this.IsChanged = true;
this.HasBinary = fields.HasBinary;
this.HasLongValue = fields.HasLongValue;
}
/// <summary>
/// Prepares the request to sending a form. It should set only the headers.
/// </summary>
public virtual void PrepareRequest(HTTPRequest request)
{
throw new NotImplementedException();
}
/// <summary>
/// Prepares and returns with the form's raw data.
/// </summary>
public virtual byte[] GetData()
{
throw new NotImplementedException();
}
#endregion
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e53224c827a7d456fb88488b1981a8d9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BestHTTP.Forms
{
public enum HTTPFormUsage
{
/// <summary>
/// The plugin will try to choose the best form sending method.
/// </summary>
Automatic,
/// <summary>
/// The plugin will use the Url-Encoded form sending.
/// </summary>
UrlEncoded,
/// <summary>
/// The plugin will use the Multipart form sending.
/// </summary>
Multipart,
#if !BESTHTTP_DISABLE_UNITY_FORM
/// <summary>
/// The legacy, Unity-based form sending.
/// </summary>
Unity
#endif
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d4dbcc2441f514917998d3c7674f4d4c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 938113fbaaf4d4702a76b03aadd511c3
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,79 @@
using BestHTTP.Extensions;
namespace BestHTTP.Forms
{
/// <summary>
/// A HTTP Form implementation to send textual and binary values.
/// </summary>
public sealed class HTTPMultiPartForm : HTTPFormBase
{
#region Private Fields
/// <summary>
/// A random boundary generated in the constructor.
/// </summary>
private string Boundary;
/// <summary>
///
/// </summary>
private byte[] CachedData;
#endregion
public HTTPMultiPartForm()
{
this.Boundary = this.GetHashCode().ToString("X");
}
#region IHTTPForm Implementation
public override void PrepareRequest(HTTPRequest request)
{
// Set up Content-Type header for the request
request.SetHeader("Content-Type", "multipart/form-data; boundary=\"" + Boundary + "\"");
}
public override byte[] GetData()
{
if (CachedData != null)
return CachedData;
using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
{
for (int i = 0; i < Fields.Count; ++i)
{
HTTPFieldData field = Fields[i];
// Set the boundary
ms.WriteLine("--" + Boundary);
// Set up Content-Disposition header to our form with the name
ms.WriteLine("Content-Disposition: form-data; name=\"" + field.Name + "\"" + (!string.IsNullOrEmpty(field.FileName) ? "; filename=\"" + field.FileName + "\"" : string.Empty));
// Set up Content-Type head for the form.
if (!string.IsNullOrEmpty(field.MimeType))
ms.WriteLine("Content-Type: " + field.MimeType);
ms.WriteLine("Content-Length: " + field.Payload.Length.ToString());
ms.WriteLine();
// Write the actual data to the MemoryStream
ms.Write(field.Payload, 0, field.Payload.Length);
ms.Write(HTTPRequest.EOL, 0, HTTPRequest.EOL.Length);
}
// Write out the trailing boundary
ms.WriteLine("--" + Boundary + "--");
IsChanged = false;
// Set the RawData of our request
return CachedData = ms.ToArray();
}
}
#endregion
};
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b3a289c2138544bb4b2da0718726118e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,69 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BestHTTP.Forms
{
/// <summary>
/// A HTTP Form implementation to send textual values.
/// </summary>
public sealed class HTTPUrlEncodedForm : HTTPFormBase
{
private const int EscapeTreshold = 256;
private byte[] CachedData;
public override void PrepareRequest(HTTPRequest request)
{
request.SetHeader("Content-Type", "application/x-www-form-urlencoded");
}
public override byte[] GetData()
{
if (CachedData != null && !IsChanged)
return CachedData;
StringBuilder sb = new StringBuilder();
// Create a "field1=value1&field2=value2" formatted string
for (int i = 0; i < Fields.Count; ++i)
{
var field = Fields[i];
if (i > 0)
sb.Append("&");
sb.Append(EscapeString(field.Name));
sb.Append("=");
if (!string.IsNullOrEmpty(field.Text) || field.Binary == null)
sb.Append(EscapeString(field.Text));
else
// If forced to this form type with binary data, we will create a string from the binary data first and encode this string.
sb.Append(EscapeString(Encoding.UTF8.GetString(field.Binary, 0, field.Binary.Length)));
}
IsChanged = false;
return CachedData = Encoding.UTF8.GetBytes(sb.ToString());
}
public static string EscapeString(string originalString)
{
if (originalString.Length < EscapeTreshold)
return Uri.EscapeDataString(originalString);
else
{
int loops = originalString.Length / EscapeTreshold;
StringBuilder sb = new StringBuilder(loops);
for (int i = 0; i <= loops; i++)
sb.Append(i < loops ?
Uri.EscapeDataString(originalString.Substring(EscapeTreshold * i, EscapeTreshold)) :
Uri.EscapeDataString(originalString.Substring(EscapeTreshold * i)));
return sb.ToString();
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 59a3665fc7cb0458e9af5eaa133b0dbe
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,58 @@
#if !BESTHTTP_DISABLE_UNITY_FORM
using UnityEngine;
namespace BestHTTP.Forms
{
/// <summary>
/// For backward compatibility.
/// </summary>
public sealed class UnityForm : HTTPFormBase
{
public WWWForm Form { get; set; }
public UnityForm()
{
}
public UnityForm(WWWForm form)
{
Form = form;
}
public override void CopyFrom(HTTPFormBase fields)
{
this.Fields = fields.Fields;
this.IsChanged = true;
if (Form == null)
{
Form = new WWWForm();
if (Fields != null)
for (int i = 0; i < Fields.Count; ++i)
{
var field = Fields[i];
if (string.IsNullOrEmpty(field.Text) && field.Binary != null)
Form.AddBinaryData(field.Name, field.Binary, field.FileName, field.MimeType);
else
Form.AddField(field.Name, field.Text, field.Encoding);
}
}
}
public override void PrepareRequest(HTTPRequest request)
{
if (Form.headers.ContainsKey("Content-Type"))
request.SetHeader("Content-Type", Form.headers["Content-Type"] as string);
else
request.SetHeader("Content-Type", "application/x-www-form-urlencoded");
}
public override byte[] GetData()
{
return Form.data;
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4453cf1b8d47f43799986c7c32b426a0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: