<commit_before>﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.Xml;
using System.Collections.Specialized;
using Dropio.Core.Types;
using System.Security.Cryptography;
using System.Web;

namespace Dropio.Core
{
    public abstract class ServiceAdapter
    {
        public const string DROPS = "drops/";
        public const string ASSETS = "/assets/";
        public const string COMMENTS = "/comments/";
        public const string SEND_TO = "/send_to/";
        public const string FROM_API = "/from_api";
        public const string VERSION = "1.0";

        public abstract string BaseUrl { get; }
        public abstract string ApiBaseUrl { get; }
        public abstract string UploadUrl { get; }
        public string ApiKey { get; set; }

        delegate void GetResponse(HttpWebResponse response);
        delegate void ReadDocument(XmlDocument doc);

        /// <summary>
        /// Delegate
        /// </summary>
        public delegate void UploadProgressHandler(object sender, UploadProgressEventArgs e);

        /// <summary>
        /// UploadProgressHandler is fired during a synchronous upload process to signify that 
        /// a segment of uploading has been completed. This is approximately 50 bytes. The total
        /// uploaded is recorded in the <see cref="UploadProgressEventArgs"/> class.
        /// </summary>
        public event UploadProgressHandler OnUploadProgress;

        #region Implementation

        /// <summary>
        /// Completes the request.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <param name="respond">The respond action.</param>
        private void CompleteRequest(HttpWebRequest request, GetResponse respond)
        {
            HttpWebResponse response = null;

            try
            {
                response = request.GetResponse() as HttpWebResponse;

                if (response.StatusCode == HttpStatusCode.OK)
                {
                    if (respond != null)
                    {
                        respond(response);
                    }
                }
                else
                {
                    throw new ServiceException(ServiceError.BadRequest, "There was a problem with your request.");
                }
            }
            catch (WebException exc)
            {
                this.HandleException(exc);
            }
            finally
            {
                if (response != null)
                {
                    response.Close();
                }

                response = null;
            }
        }

        /// <summary>
        /// Reads the response.
        /// </summary>
        /// <param name="response">The response.</param>
        private void ReadResponse(HttpWebResponse response, ReadDocument read)
        {
            using (StreamReader reader = new StreamReader(response.GetResponseStream()))
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(reader);
                if (read != null)
                {
                    read(doc);
                }
            }
        }

        /// <summary>
        /// Generates the authenticated drop URL.
        /// </summary>
        /// <param name="drop">The drop.</param>
        /// <returns></returns>
        public string GenerateAuthenticatedDropUrl(Drop drop)
        {
            string unixTime = GenerateUnixTimestamp().ToString();
            string signature = GenerateSignature(drop, unixTime);
            StringBuilder sb = new StringBuilder();
            sb.Append(this.BaseUrl);
            sb.Append(drop.Name);
            sb.Append(FROM_API);
            sb.Append("?&signature=");
            sb.Append(signature);
            sb.Append("&expires=");
            sb.Append(unixTime);
            return sb.ToString(); 
        }

        /// <summary>
        /// Generates the authenticated asset URL.
        /// </summary>
        /// <param name="asset">The asset.</param>
        /// <returns></returns>
        public string GenerateAuthenticatedAssetUrl(Asset asset)
        {
            string unixTime = GenerateUnixTimestamp().ToString();
            string signature = GenerateSignature(asset.Drop, unixTime);
            StringBuilder sb = new StringBuilder();
            sb.Append(this.BaseUrl);
            sb.Append(asset.Drop.Name);
            sb.Append("/asset/");
            sb.Append(asset.Name);
            sb.Append(FROM_API);
            sb.Append("?&signature=");
            sb.Append(signature);
            sb.Append("&expires=");
            sb.Append(unixTime);
            return sb.ToString();
        }

        /// <summary>
        /// Generates the signature.
        /// </summary>
        /// <param name="drop">The drop.</param>
        /// <param name="expires">The expires.</param>
        /// <returns></returns>
        protected string GenerateSignature(Drop drop, string expires)
        {
            string token = string.IsNullOrEmpty(drop.AdminToken) ? drop.GuestToken : drop.AdminToken;
            string before = expires + "+" + token + "+" + drop.Name;
            
            SHA1 sha1 = new SHA1CryptoServiceProvider();
            byte[] input = Encoding.UTF8.GetBytes(before);
            byte[] result = sha1.ComputeHash(input);
            string hex = BitConverter.ToString(result);
            hex = hex.Replace("-", "");

            return hex;
        }

        /// <summary>
        /// Generates the unix timestamp.
        /// </summary>
        /// <returns></returns>
        protected long GenerateUnixTimestamp()
        {
            TimeSpan ts = (DateTime.UtcNow.AddMinutes(10) - new DateTime(1970, 1, 1, 0, 0, 0));
            return (long) ts.TotalSeconds;
        }

        /// <summary>
        /// Creates a Drop.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="guestsCanAdd">if set to <c>true</c> [guests can add].</param>
        /// <param name="guestsCanComment">if set to <c>true</c> [guests can comment].</param>
        /// <param name="guestsCanDelete">if set to <c>true</c> [guests can delete].</param>
        /// <param name="expirationLength">Length of the expiration.</param>
        /// <param name="password">The password.</param>
        /// <param name="adminPassword">The admin password.</param>
        /// <param name="premiumCode">The premium code.</param>
        /// <returns></returns>
        public Drop CreateDrop(string name, bool guestsCanAdd, bool guestsCanComment, bool guestsCanDelete, ExpirationLength expirationLength, string password, string adminPassword, string premiumCode)
        {
            Drop d = null;

            NameValueCollection parameters = new NameValueCollection();

            parameters.Add("name", name);
            parameters.Add("guests_can_add", guestsCanAdd.ToString());
            parameters.Add("guests_can_comment", guestsCanComment.ToString());
            parameters.Add("guests_can_delete", guestsCanDelete.ToString());
            parameters.Add("expiration_length", this.MapExpirationLength(expirationLength));
            parameters.Add("password", password);
            parameters.Add("admin_password", <PASSWORD>Password);
            parameters.Add("premium_code", premiumCode);

            HttpWebRequest request = this.CreatePostRequest(this.CreateDropUrl(string.Empty), parameters);
            CompleteRequest(request, delegate(HttpWebResponse response)
            {
                ReadResponse(response, (XmlDocument doc) => d = this.CreateAndMapDrop(doc));
            });

            return d;
        }

        /// <summary>
        /// Finds a drop by name.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="token">The token.</param>
        /// <returns></returns>
        public Drop FindDrop(string name, string token)
        {
            if (string.IsNullOrEmpty(name))<commit_msg>Fixed an issue where guest permissions were failing<commit_after>﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.Xml;
using System.Collections.Specialized;
using Dropio.Core.Types;
using System.Security.Cryptography;
using System.Web;

namespace Dropio.Core
{
    public abstract class ServiceAdapter
    {
        public const string DROPS = "drops/";
        public const string ASSETS = "/assets/";
        public const string COMMENTS = "/comments/";
        public const string SEND_TO = "/send_to/";
        public const string FROM_API = "/from_api";
        public const string VERSION = "1.0";

        public abstract string BaseUrl { get; }
        public abstract string ApiBaseUrl { get; }
        public abstract string UploadUrl { get; }
        public string ApiKey { get; set; }

        delegate void GetResponse(HttpWebResponse response);
        delegate void ReadDocument(XmlDocument doc);

        /// <summary>
        /// Delegate
        /// </summary>
        public delegate void UploadProgressHandler(object sender, UploadProgressEventArgs e);

        /// <summary>
        /// UploadProgressHandler is fired during a synchronous upload process to signify that 
        /// a segment of uploading has been completed. This is approximately 50 bytes. The total
        /// uploaded is recorded in the <see cref="UploadProgressEventArgs"/> class.
        /// </summary>
        public event UploadProgressHandler OnUploadProgress;

        #region Implementation

        /// <summary>
        /// Completes the request.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <param name="respond">The respond action.</param>
        private void CompleteRequest(HttpWebRequest request, GetResponse respond)
        {
            HttpWebResponse response = null;

            try
            {
                response = request.GetResponse() as HttpWebResponse;

                if (response.StatusCode == HttpStatusCode.OK)
                {
                    if (respond != null)
                    {
                        respond(response);
                    }
                }
                else
                {
                    throw new ServiceException(ServiceError.BadRequest, "There was a problem with your request.");
                }
            }
            catch (WebException exc)
            {
                this.HandleException(exc);
            }
            finally
            {
                if (response != null)
                {
                    response.Close();
                }

                response = null;
            }
        }

        /// <summary>
        /// Reads the response.
        /// </summary>
        /// <param name="response">The response.</param>
        private void ReadResponse(HttpWebResponse response, ReadDocument read)
        {
            using (StreamReader reader = new StreamReader(response.GetResponseStream()))
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(reader);
                if (read != null)
                {
                    read(doc);
                }
            }
        }

        /// <summary>
        /// Generates the authenticated drop URL.
        /// </summary>
        /// <param name="drop">The drop.</param>
        /// <returns></returns>
        public string GenerateAuthenticatedDropUrl(Drop drop)
        {
            string unixTime = GenerateUnixTimestamp().ToString();
            string signature = GenerateSignature(drop, unixTime);
            StringBuilder sb = new StringBuilder();
            sb.Append(this.BaseUrl);
            sb.Append(drop.Name);
            sb.Append(FROM_API);
            sb.Append("?&signature=");
            sb.Append(signature);
            sb.Append("&expires=");
            sb.Append(unixTime);
            return sb.ToString(); 
        }

        /// <summary>
        /// Generates the authenticated asset URL.
        /// </summary>
        /// <param name="asset">The asset.</param>
        /// <returns></returns>
        public string GenerateAuthenticatedAssetUrl(Asset asset)
        {
            string unixTime = GenerateUnixTimestamp().ToString();
            string signature = GenerateSignature(asset.Drop, unixTime);
            StringBuilder sb = new StringBuilder();
            sb.Append(this.BaseUrl);
            sb.Append(asset.Drop.Name);
            sb.Append("/asset/");
            sb.Append(asset.Name);
            sb.Append(FROM_API);
            sb.Append("?&signature=");
            sb.Append(signature);
            sb.Append("&expires=");
            sb.Append(unixTime);
            return sb.ToString();
        }

        /// <summary>
        /// Generates the signature.
        /// </summary>
        /// <param name="drop">The drop.</param>
        /// <param name="expires">The expires.</param>
        /// <returns></returns>
        protected string GenerateSignature(Drop drop, string expires)
        {
            string token = string.IsNullOrEmpty(drop.AdminToken) ? drop.GuestToken : drop.AdminToken;
            string before = expires + "+" + token + "+" + drop.Name;
            
            SHA1 sha1 = new SHA1CryptoServiceProvider();
            byte[] input = Encoding.UTF8.GetBytes(before);
            byte[] result = sha1.ComputeHash(input);
            string hex = BitConverter.ToString(result);
            hex = hex.Replace("-", "");

            return hex;
        }

        /// <summary>
        /// Generates the unix timestamp.
        /// </summary>
        /// <returns></returns>
        protected long GenerateUnixTimestamp()
        {
            TimeSpan ts = (DateTime.UtcNow.AddMinutes(10) - new DateTime(1970, 1, 1, 0, 0, 0));
            return (long) ts.TotalSeconds;
        }

        /// <summary>
        /// Creates a Drop.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="guestsCanAdd">if set to <c>true</c> [guests can add].</param>
        /// <param name="guestsCanComment">if set to <c>true</c> [guests can comment].</param>
        /// <param name="guestsCanDelete">if set to <c>true</c> [guests can delete].</param>
        /// <param name="expirationLength">Length of the expiration.</param>
        /// <param name="password"><PASSWORD>.</param>
        /// <param name="adminPassword">The admin password.</param>
        /// <param name="premiumCode">The premium code.</param>
        /// <returns></returns>
        public Drop CreateDrop(string name, bool guestsCanAdd, bool guestsCanComment, bool guestsCanDelete, ExpirationLength expirationLength, string password, string adminPassword, string premiumCode)
        {
            Drop d = null;

            NameValueCollection parameters = new NameValueCollection();

            parameters.Add("name", name);
            parameters.Add("guests_can_add", guestsCanAdd.ToString().ToLower());
            parameters.Add("guests_can_comment", guestsCanComment.ToString().ToLower());
            parameters.Add("guests_can_delete", guestsCanDelete.ToString().ToLower());
            parameters.Add("expiration_length", this.MapExpirationLength(expirationLength));
            parameters.Add("password", password);
            parameters.Add("admin_password", <PASSWORD>);
            parameters.Add("premium_code", premiumCode);

            HttpWebRequest request = this.CreatePostRequest(this.CreateDropUrl(string.Empty), parameters);
            CompleteRequest(request, delegate(HttpWebResponse response)
            {
                ReadResponse(response, (XmlDocument doc) => d = this.CreateAndMapDrop(doc));
            });

            return d;
        }

        /// <summary>
        /// Finds a drop by name.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="token">The token.</param>
        /// <returns></returns>
        public Drop FindDrop(string name, string token)
        {
            if (string.IsNullOrEmpty(name))
{'fraction_non_alphanumeric': 0.12118403164009393, 'fraction_numerical': 0.002471882338400692, 'mean_word_length': 1.7597203274215552, 'pattern_counts': {'":': 0, '<': 152, '<?xml version=': 0, '>': 154, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6586079', 'n_tokens_mistral': 4057, 'n_tokens_neox': 3922, 'n_words': 973}