using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;
using FastReport.Cloud.OAuth;
using FastReport.Cloud.StorageClient.SkyDrive;
using FastReport.Utils;
namespace FastReport.Cloud.StorageClient.Box
{
///
/// Box cloud storage client.
///
public class BoxStorageClient : CloudStorageClient
{
#region Fields
private ClientInfo clientInfo;
private string authCode;
private string accessToken;
#endregion // Fields
#region Properties
///
/// Gets or sets the client info.
///
public ClientInfo ClientInfo
{
get { return clientInfo; }
set { clientInfo = value; }
}
///
/// Gets or sets the authorization code.
///
public string AuthCode
{
get { return authCode; }
set { authCode = value; }
}
///
/// Gets or sets the access token.
///
public string AccessToken
{
get { return accessToken; }
set { accessToken = value; }
}
#endregion // Properties
#region Constructors
///
/// Initializes a new instance of the class.
///
public BoxStorageClient() : base()
{
this.clientInfo = new ClientInfo("", "", "");
authCode = "";
accessToken = "";
}
///
/// Initializes a new instance of the class.
///
/// The storage client info.
public BoxStorageClient(ClientInfo clientInfo) : base()
{
this.clientInfo = clientInfo;
authCode = "";
accessToken = "";
}
///
/// Initializes a new instance of the class.
///
/// Client ID.
/// Client Secret.
public BoxStorageClient(string clientId, string clientSecret) : base()
{
this.clientInfo = new ClientInfo("", clientId, clientSecret);
authCode = "";
accessToken = "";
}
#endregion // Constructors
#region Private Methods
private byte[] BuildGetAccessTokenRequestContent()
{
Dictionary data = new Dictionary();
data.Add("client_id", clientInfo.Id);
data.Add("client_secret", clientInfo.Secret);
data.Add("code", authCode);
//data.Add("redirect_uri", @"urn:ietf:wg:oauth:2.0:oob");
data.Add("grant_type", "authorization_code");
return Encoding.UTF8.GetBytes(HttpUtils.UrlDataEncode(data));
}
private string GetUploadUri(string fileid = "")
{
if (String.IsNullOrEmpty(fileid))
return @"https://upload.box.com/api/2.0/files/content";
else
return String.Format(@"https://upload.box.com/api/2.0/files/{0}/content", fileid);
}
private void UploadNewFile(MemoryStream ms, string fileid = "")
{
System.Net.ServicePointManager.SecurityProtocol = (SecurityProtocolType)(0xc0 | 0x300 | 0xc00);
string uri = GetUploadUri(fileid);
WebRequest request = WebRequest.Create(uri);
request.Method = HttpMethod.Post;
RequestUtils.SetProxySettings(request, ProxySettings);
request.Headers.Add("Authorization", String.Format("Bearer {0}", accessToken));
request.ContentType = "multipart/form-data; boundary=\"foo_bar_baz\"";
List content = new List();
StringBuilder sb = new StringBuilder("--foo_bar_baz\r\n");
sb.Append(String.Format("Content-Disposition: form-data; filename=\"{0}\"; name=\"filename\"\r\n", Filename));
sb.Append("Content-Type: application/octet-stream\r\n");
sb.Append("\r\n");
content.AddRange(Encoding.UTF8.GetBytes(sb.ToString()));
int msLength = Convert.ToInt32(ms.Length);
byte[] msBuffer = new byte[msLength];
ms.Read(msBuffer, 0, msLength);
content.AddRange(msBuffer);
sb = new StringBuilder("\r\n--foo_bar_baz\r\n");
sb.Append("Content-Disposition: form-data; name=\"folder_id\"");
sb.Append("\r\n\r\n0\r\n");
sb.Append("--foo_bar_baz--");
content.AddRange(Encoding.UTF8.GetBytes(sb.ToString()));
int length = content.Count;
byte[] buffer = new byte[length];
buffer = content.ToArray();
request.ContentLength = buffer.Length;
using (Stream rs = request.GetRequestStream())
{
rs.Write(buffer, 0, buffer.Length);
}
WebResponse response = request.GetResponse();
Stream stream = response.GetResponseStream();
}
private void UploadExistFile(MemoryStream ms)
{
UploadNewFile(ms, GetFileID());
}
private string GetFileID()
{
WebRequest request = WebRequest.Create(@"https://api.box.com/2.0/folders/0/items/");
request.ContentType = "application/json";
request.Headers.Add("Authorization", String.Format("Bearer {0}", accessToken));
WebResponse response = request.GetResponse();
string JSONString = String.Empty;
using (Stream responseStream = response.GetResponseStream())
{
StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);
JSONString += reader.ReadToEnd();
}
int indexFilename = JSONString.IndexOf(Filename);
int firstBracketIndex = 0;
int i = 1;
bool file_version_bracketWas = false;
while (true)
{
if (JSONString[indexFilename - i].ToString() == "{")
{
if (file_version_bracketWas)
{
firstBracketIndex = indexFilename - i;
break;
}
else
{
file_version_bracketWas = true;
}
}
i++;
}
string fileJson = JSONString.Substring(firstBracketIndex, indexFilename - firstBracketIndex);
int idIndex = fileJson.IndexOf("id");
string idString = fileJson.Substring(idIndex + 4, fileJson.IndexOf(",", idIndex) - idIndex - 4);
//string str = fileJson.Substring(idIndex, fileJson.Length - fileJson)
return idString.Replace("\"", "");
}
#endregion // Private Methods
#region Protected Methods
///
protected override void SaveMemoryStream(MemoryStream ms)
{
bool isExist = false;
try
{
UploadNewFile(ms);
}
catch (Exception ex)
{
if (ex.Message.Contains("409"))
isExist = true;
else
throw new CloudStorageException(ex.Message, ex);
}
try
{
if (isExist)
UploadExistFile(ms);
}
catch (Exception ex)
{
throw new CloudStorageException(ex.Message, ex);
}
}
#endregion // Protected Methods
#region Public Methods
///
/// Gets the authorization URL.
///
/// The authorization URL stirng.
public string GetAuthorizationUrl()
{
return String.Format($@"https://account.box.com/api/oauth2/authorize?client_id={clientInfo.Id}&response_type=code");
}
///
/// Gets the access token.
///
/// The access token string.
public string GetAccessToken()
{
System.Net.ServicePointManager.SecurityProtocol = (SecurityProtocolType)(0xc0 | 0x300 | 0xc00);
WebRequest request = WebRequest.Create(@"https://api.box.com/oauth2/token");
request.Method = HttpMethod.Post;
RequestUtils.SetProxySettings(request, ProxySettings);
request.ContentType = "application/x-www-form-urlencoded";
byte[] content = BuildGetAccessTokenRequestContent();
request.ContentLength = content.Length;
using (Stream rs = request.GetRequestStream())
{
rs.Write(content, 0, content.Length);
}
using (WebResponse response = request.GetResponse())
{
accessToken = Parser.ParseGoogleDriveToken(response.GetResponseStream());
}
//WebResponse response = request.GetResponse();
//accessToken = Parser.ParseGoogleDriveToken(response.GetResponseStream());
return accessToken;
}
#endregion // Public Methods
}
}