예제 #1
0
        /// <summary>
        ///     Returns the specified theme file as a stream.
        /// </summary>
        /// <param name="themeFileName"></param>
        /// <param name="billingRef"></param>
        /// <returns></returns>
        public Stream GetThemeFile(string themeFileName, string billingRef)
        {
            var timestamp = DateTime.UtcNow;

            var hmac = HMAC.CalculateHMAC(
                SigningKey,
                timestamp,
                SubscriberId,
                themeFileName,
                billingRef);

            var urlBuilder = new StringBuilder(string.Format(
                                                   "{0}/themefile/{1}/{2}", EndpointAddress, SubscriberId, themeFileName));

            if (!string.IsNullOrEmpty(billingRef))
            {
                urlBuilder.AppendFormat("?billingref={0}", billingRef);
            }

            var request = (HttpWebRequest)WebRequest.Create(urlBuilder.ToString());

            request.Method = "GET";
            request.Headers["x-hd-date"] = timestamp.ToString("r");
            request.Headers[HttpRequestHeader.Authorization] = hmac;

            if (!string.IsNullOrEmpty(ProxyServerAddress))
            {
                request.Proxy = new WebProxy(ProxyServerAddress);
            }

            var response = (HttpWebResponse)request.GetResponse();

            return(response.GetResponseStream());
        }
예제 #2
0
        /// <summary>
        /// Deletes a theme file.
        /// </summary>
        /// <param name="themeName"></param>
        /// <param name="billingRef"></param>
        public void DeleteTheme(string themeName, string billingRef)
        {
            var timestamp = DateTime.UtcNow;

            string hmac = HMAC.CalculateHMAC(
                SigningKey,
                timestamp,
                SubscriberId,
                themeName,
                billingRef);

            StringBuilder urlBuilder = new StringBuilder(string.Format(
                                                             "{0}/theme/{1}/{2}", EndpointAddress, SubscriberId, themeName));

            if (!string.IsNullOrEmpty(billingRef))
            {
                urlBuilder.AppendFormat("?billingref={0}", billingRef);
            }

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(urlBuilder.ToString());

            request.Method = "DELETE";
            request.Headers["x-hd-date"] = timestamp.ToString("r");
            request.Headers[HttpRequestHeader.Authorization] = hmac;

            if (!string.IsNullOrEmpty(ProxyServerAddress))
            {
                request.Proxy = new WebProxy(ProxyServerAddress);
            }

            using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
            {
                // Throw away the response, which will be empty.
            }
        }
예제 #3
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="template">The template for which component information is being requested.</param>
        /// <param name="includeDialogs">Indicates whether or not information about dialogs should be included.</param>
        /// <param name="billingRef">This parameter lets you specify information that will be included in usage logs for this call. For example, you can use a string to uniquely identify the end user that initiated the request and/or the context in which the call was made. When you review usage logs, you can then see which end users initiated each request. That information could then be used to pass costs on to those end users if desired.</param>
        /// <param name="uploadPackage">Indicates if the package should be uploaded (forcefully) or not. This should only be true if the package does not already exist in the Cloud Services cache.</param>
        /// <returns></returns>
        protected internal override ComponentInfo GetComponentInfoImpl(
            Template template,
            bool includeDialogs,
            string billingRef,
            bool uploadPackage)
        {
            var timestamp = DateTime.UtcNow;

            if (!(template.Location is PackageTemplateLocation))
            {
                throw new Exception("HotDocs Cloud Services requires the use of template packages. Please use a PackageTemplateLocation derivative.");
            }
            PackageTemplateLocation packageTemplateLocation = (PackageTemplateLocation)template.Location;

            string hmac = HMAC.CalculateHMAC(
                SigningKey,
                timestamp,
                SubscriberId,
                packageTemplateLocation.PackageID,
                template.FileName,
                uploadPackage,
                billingRef,
                includeDialogs);

            return(_proxy.GetComponentInfo(
                       SubscriberId,
                       packageTemplateLocation.PackageID,
                       template.FileName,
                       includeDialogs,
                       billingRef,
                       timestamp,
                       GetPackageIfNeeded(packageTemplateLocation, uploadPackage),
                       hmac));
        }
        private string ResumeSessionImpl(string state, Func <string, PackageTemplateLocation> locationGetter,
                                         bool uploadPackage)
        {
            if (string.IsNullOrEmpty(state))
            {
                throw new Exception("A session state string must be provided in order to resume a session.");
            }

            if (uploadPackage)
            {
                var    base64     = state.Split('#')[0];
                var    json       = Encoding.UTF8.GetString(Convert.FromBase64String(base64));
                var    jss        = new JavaScriptSerializer();
                var    stateDict  = jss.Deserialize <dynamic>(json);
                string packageID  = stateDict["PackageID"];
                string billingRef = stateDict["BillingRef"];

                UploadPackage(packageID, billingRef, locationGetter(packageID).GetPackageStream());
            }

            var timestamp = DateTime.UtcNow;

            var hmac = HMAC.CalculateHMAC(
                SigningKey,
                timestamp,
                SubscriberId,
                state);

            var url = string.Format("{0}/resumesession/{1}", EmbeddedEndpointAddress, SubscriberId);

            var request = (HttpWebRequest)WebRequest.Create(url);

            request.Method               = "POST";
            request.ContentType          = "text/xml; charset=utf-8";
            request.Headers["x-hd-date"] = timestamp.ToString("r");
            request.Headers[HttpRequestHeader.Authorization] = hmac;

            var data = Encoding.UTF8.GetBytes(state);

            request.ContentLength = data.Length;

            if (!string.IsNullOrEmpty(ProxyServerAddress))
            {
                request.Proxy = new WebProxy(ProxyServerAddress);
            }
            else
            {
                request.Proxy = null;
            }

            var stream = request.GetRequestStream();

            stream.Write(data, 0, data.Length);

            var response = (HttpWebResponse)request.GetResponse();
            var reader   = new StreamReader(response.GetResponseStream());

            return(reader.ReadLine());
        }
예제 #5
0
        /// <summary>
        /// Uploads a package to HotDocs Cloud Services from a stream.
        /// </summary>
        /// <include file="../../Shared/Help.xml" path="Help/string/param[@name='packageID']"/>
        /// <include file="../../Shared/Help.xml" path="Help/string/param[@name='billingRef']"/>
        /// <param name="packageStream">A stream containing the package to be uploaded.</param>
        /// <remarks>
        /// This call throws an exception if the package is already cached in Cloud Services.
        /// The point of the exception is to discourage consumers from constantly re-uploading the
        /// same package.  Consumers should upload a package only if:
        /// 1) They have already attempted their request and received a "package not found" error.
        /// or
        /// 2) They happen to know that the package is not already cached, e.g. the package is new.
        /// </remarks>
        public void UploadPackage(
            string packageID,
            string billingRef,
            Stream packageStream)
        {
            try
            {
                var timestamp = DateTime.UtcNow;

                string hmac = HMAC.CalculateHMAC(
                    SigningKey,
                    timestamp,
                    SubscriberId,
                    packageID,
                    null,
                    true,
                    billingRef);

                StringBuilder urlBuilder = new StringBuilder(string.Format(
                                                                 "{0}/{1}/{2}", EndpointAddress, SubscriberId, packageID));

                if (!string.IsNullOrEmpty(billingRef))
                {
                    urlBuilder.AppendFormat("?billingRef={0}", billingRef);
                }

                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(urlBuilder.ToString());
                request.Method               = "PUT";
                request.ContentType          = "application/binary";
                request.Headers["x-hd-date"] = timestamp.ToString("r");
                request.Headers[HttpRequestHeader.Authorization] = hmac;

                if (packageStream.CanSeek)
                {
                    request.ContentLength             = packageStream.Length;
                    request.AllowWriteStreamBuffering = false;
                }

                if (!string.IsNullOrEmpty(ProxyServerAddress))
                {
                    request.Proxy = new WebProxy(ProxyServerAddress);
                }

                packageStream.CopyTo(request.GetRequestStream());

                using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                {
                    // Throw away the response, which will be empty.
                }
            }
            finally
            {
                packageStream.Close();
            }
        }
        /// <summary>
        ///     GetComponentInfo returns metadata about the variables/types (and optionally dialogs and mapping info)
        ///     for the indicated template's interview.
        /// </summary>
        /// <param name="template">An instance of the Template class, for which you are requesting component information.</param>
        /// <param name="includeDialogs">Whether to include dialog &amp; mapping information in the returned results.</param>
        /// <include file="../Shared/Help.xml" path="Help/string/param[@name='logRef']" />
        /// <returns>The requested component information.</returns>
        public ComponentInfo GetComponentInfo(Template template, bool includeDialogs, string logRef = "")
        {
            if (template == null)
            {
                throw new ArgumentNullException("template");
            }

            using (var client = new HttpClient())
            {
                var packageTemplateLocation = (PackageTemplateLocation)template.Location;
                var packageId = packageTemplateLocation.PackageID;
                var timestamp = DateTime.UtcNow;

                var hmac = HMAC.CalculateHMAC(
                    SigningKey,
                    timestamp,
                    SubscriberId,
                    packageId,
                    template.FileName,
                    false,
                    logRef,
                    includeDialogs);


                var request = new HttpRequestMessage
                {
                    RequestUri =
                        new Uri(
                            string.Format(
                                "{0}/componentinfo/{1}/{2}/{3}?includedialogs={4}&billingref={5}{6}",
                                HostAddress,
                                SubscriberId, packageId, Uri.EscapeDataString(template.FileName), includeDialogs,
                                Uri.EscapeDataString(logRef), GetRetrieveFromHubParam())),
                    Method = HttpMethod.Get
                };

                request.Headers.Add("x-hd-date", timestamp.ToString("yyyy-MM-ddTHH:mm:ssZ"));
                request.Headers.Authorization = new AuthenticationHeaderValue("basic", hmac);


                var result =
                    client.SendAsync(request).Result;

                HandleStatusCode(result);
                var streamResult = result.Content.ReadAsStreamAsync().Result;

                using (var stream = (MemoryStream)streamResult)
                {
                    stream.Position = 0;
                    var serializer = new XmlSerializer(typeof(ComponentInfo));
                    return((ComponentInfo)serializer.Deserialize(stream));
                }
            }
        }
예제 #7
0
        /// <summary>
        /// </summary>
        /// <param name="template"></param>
        /// <param name="includeDialogs">Indicates whether or not information about dialogs should be included.</param>
        /// <param name="billingRef">
        ///     This parameter lets you specify information that will be included in usage logs for this call.
        ///     For example, you can use a string to uniquely identify the end user that initiated the request and/or the context
        ///     in which the call was made. When you review usage logs, you can then see which end users initiated each request.
        ///     That information could then be used to pass costs on to those end users if desired.
        /// </param>
        /// <param name="uploadPackage">
        ///     Indicates if the package should be uploaded (forcefully) or not. This should only be true
        ///     if the package does not already exist in the Cloud Services cache.
        /// </param>
        /// <returns></returns>
        protected internal override ComponentInfo GetComponentInfoImpl(
            Template template,
            bool includeDialogs,
            string billingRef,
            bool uploadPackage)
        {
            if (!(template.Location is PackageTemplateLocation))
            {
                throw new Exception(
                          "HotDocs Cloud Services requires the use of template packages. Please use a PackageTemplateLocation derivative.");
            }
            var packageTemplateLocation = (PackageTemplateLocation)template.Location;

            if (uploadPackage)
            {
                UploadPackage(packageTemplateLocation.PackageID, billingRef, packageTemplateLocation.GetPackageStream());
            }

            var timestamp = DateTime.UtcNow;
            var hmac      = HMAC.CalculateHMAC(
                SigningKey,
                timestamp,
                SubscriberId,
                packageTemplateLocation.PackageID,
                template.FileName,
                false,
                billingRef,
                includeDialogs);

            var urlBuilder = new StringBuilder(string.Format(
                                                   "{0}/componentinfo/{1}/{2}/{3}?includedialogs={4}&billingref={5}&retrievefromhub={6}",
                                                   EndpointAddress, SubscriberId, packageTemplateLocation.PackageID, template.FileName, includeDialogs,
                                                   billingRef, _retrieveFromHub));

            var request = (HttpWebRequest)WebRequest.Create(urlBuilder.ToString());

            request.Method = "GET";
            request.Headers["x-hd-date"] = timestamp.ToString("r");
            request.Headers[HttpRequestHeader.Authorization] = hmac;

            if (!string.IsNullOrEmpty(ProxyServerAddress))
            {
                request.Proxy = new WebProxy(ProxyServerAddress);
            }

            var response = (HttpWebResponse)request.GetResponse();

            var serializer = new XmlSerializer(typeof(ComponentInfo));
            var stream     = new MemoryStream();

            return((ComponentInfo)serializer.Deserialize(response.GetResponseStream()));
        }
예제 #8
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="answers">An array of answers as binary objects, which will be overlayed successively to produce a single <c>BinaryObject</c>.</param>
        /// <param name="billingRef">This parameter lets you specify information that will be included in usage logs for this call. For example, you can use a string to uniquely identify the end user that initiated the request and/or the context in which the call was made. When you review usage logs, you can then see which end users initiated each request. That information could then be used to pass costs on to those end users if desired.</param>
        /// <returns></returns>
        protected internal override BinaryObject GetAnswersImpl(BinaryObject[] answers, string billingRef)
        {
            DateTime timestamp = DateTime.UtcNow;

            string hmac = HMAC.CalculateHMAC(
                SigningKey,
                timestamp,
                SubscriberId,
                billingRef);

            return(_proxy.GetAnswers(
                       SubscriberId,
                       answers.ToArray(),
                       billingRef,
                       timestamp,
                       hmac));
        }
예제 #9
0
        /// <summary>
        /// Returns a list of themes that belong to the current subscriber
        /// and have the specified prefix.
        /// </summary>
        /// <param name="prefix"></param>
        /// <param name="billingRef"></param>
        /// <returns></returns>
        public IEnumerable <string> GetThemeList(string prefix, string billingRef)
        {
            var timestamp = DateTime.UtcNow;

            string hmac = HMAC.CalculateHMAC(
                SigningKey,
                timestamp,
                SubscriberId,
                prefix,
                billingRef);

            StringBuilder urlBuilder = new StringBuilder(string.Format(
                                                             "{0}/theme/{1}", EndpointAddress, SubscriberId));

            if (!string.IsNullOrEmpty(prefix))
            {
                urlBuilder.AppendFormat("/" + prefix);
            }

            if (!string.IsNullOrEmpty(billingRef))
            {
                urlBuilder.AppendFormat("?billingref={0}", billingRef);
            }

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(urlBuilder.ToString());

            request.Method = "GET";
            request.Headers["x-hd-date"] = timestamp.ToString("r");
            request.Headers[HttpRequestHeader.Authorization] = hmac;

            if (!string.IsNullOrEmpty(ProxyServerAddress))
            {
                request.Proxy = new WebProxy(ProxyServerAddress);
            }

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();

            using (StreamReader reader = new StreamReader(response.GetResponseStream()))
            {
                while (!reader.EndOfStream)
                {
                    yield return(reader.ReadLine());
                }
            }
        }
        public Stream GetFile(string fileName, string logRef)
        {
            using (var client = new HttpClient())
            {
                var request = new HttpRequestMessage
                {
                    Method     = HttpMethod.Get,
                    RequestUri =
                        new Uri(
                            string.Format("{0}/interviewfile/{1}/{2}?filename={3}&billingRef={4}&retrievefromhub={5}",
                                          HostAddress, SubscriberId, PackageID, fileName, logRef, RetrieveFromHub))
                };

                var timestamp = DateTime.UtcNow;

                var hmac = HMAC.CalculateHMAC(
                    SigningKey,
                    timestamp,
                    SubscriberId,
                    PackageID,
                    fileName,
                    logRef);

                request.Headers.TryAddWithoutValidation("Authorization", hmac);
                request.Headers.Add("x-hd-date", timestamp.ToString("yyyy-MM-ddTHH:mm:ssZ"));

                var result = client.SendAsync(request).Result;

                if (result.IsSuccessStatusCode)
                {
                    return(result.Content.ReadAsStreamAsync().Result);
                }

                if (result.StatusCode == HttpStatusCode.NotFound)
                {
                    throw new Exception(result.ReasonPhrase);
                }

                throw new Exception(string.Format(
                                        "The server returned a '{0}' when searching for the file '{1}'", result.ReasonPhrase, fileName));
            }
        }
예제 #11
0
        /// <summary>
        /// Uploads a theme file from a stream.
        /// </summary>
        /// <param name="themeFileName"></param>
        /// <param name="stream"></param>
        /// <param name="billingRef"></param>
        public void PutThemeFile(string themeFileName, Stream stream, string billingRef)
        {
            var timestamp = DateTime.UtcNow;

            string hmac = HMAC.CalculateHMAC(
                SigningKey,
                timestamp,
                SubscriberId,
                themeFileName,
                billingRef);

            StringBuilder urlBuilder = new StringBuilder(string.Format(
                                                             "{0}/themefile/{1}/{2}", EndpointAddress, SubscriberId, themeFileName));

            if (!string.IsNullOrEmpty(billingRef))
            {
                urlBuilder.AppendFormat("?billingref={0}", billingRef);
            }

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(urlBuilder.ToString());

            request.Method = "PUT";
            request.Headers["x-hd-date"] = timestamp.ToString("r");
            request.Headers[HttpRequestHeader.Authorization] = hmac;
            request.ContentLength = stream.Length;             // Stream must support this.

            if (!string.IsNullOrEmpty(ProxyServerAddress))
            {
                request.Proxy = new WebProxy(ProxyServerAddress);
            }

            stream.CopyTo(request.GetRequestStream());

            using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
            {
                // Throw away the response, which will be empty.
            }
        }
예제 #12
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="template"></param>
        /// <param name="answers"></param>
        /// <param name="settings"></param>
        /// <param name="billingRef">This parameter lets you specify information that will be included in usage logs for this call. For example, you can use a string to uniquely identify the end user that initiated the request and/or the context in which the call was made. When you review usage logs, you can then see which end users initiated each request. That information could then be used to pass costs on to those end users if desired.</param>
        /// <param name="uploadPackage">Indicates if the package should be uploaded (forcefully) or not. This should only be true if the package does not already exist in the Cloud Services cache.</param>
        /// <returns></returns>
        protected internal override AssemblyResult AssembleDocumentImpl(
            Template template,
            string answers,
            AssembleDocumentSettings settings,
            string billingRef,
            bool uploadPackage)
        {
            if (!(template.Location is PackageTemplateLocation))
            {
                throw new Exception("HotDocs Cloud Services requires the use of template packages. Please use a PackageTemplateLocation derivative.");
            }
            PackageTemplateLocation packageTemplateLocation = (PackageTemplateLocation)template.Location;

            if (uploadPackage)
            {
                UploadPackage(packageTemplateLocation.PackageID, billingRef, packageTemplateLocation.GetPackageStream());
            }

            var timestamp = DateTime.UtcNow;

            string hmac = HMAC.CalculateHMAC(
                SigningKey,
                timestamp,
                SubscriberId,
                packageTemplateLocation.PackageID,
                template.FileName,
                false,
                billingRef,
                settings.Format,
                settings.Settings);

            StringBuilder urlBuilder = new StringBuilder(string.Format(
                                                             "{0}/assemble/{1}/{2}/{3}?format={4}&billingref={5}",
                                                             EndpointAddress, SubscriberId, packageTemplateLocation.PackageID, template.FileName ?? "",
                                                             settings.Format.ToString(), billingRef));

            if (settings.Settings != null)
            {
                foreach (KeyValuePair <string, string> kv in settings.Settings)
                {
                    urlBuilder.AppendFormat("&{0}={1}", kv.Key, kv.Value ?? "");
                }
            }

            // Note that the Comments and/or Keywords values, and therefore the resulting URL, could
            // be extremely long.  Consumers should be aware that overly-long URLs could be rejected
            // by Cloud Services.  If the Comments and/or Keywords values cannot be truncated, the
            // consumer should use the SOAP version of the client.
            var outputOptionsPairs = GetOutputOptionsPairs(settings.OutputOptions);

            foreach (KeyValuePair <string, string> kv in outputOptionsPairs)
            {
                urlBuilder.AppendFormat("&{0}={1}", kv.Key, kv.Value ?? "");
            }

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(urlBuilder.ToString());

            request.Method               = "POST";
            request.ContentType          = "text/xml";
            request.Headers["x-hd-date"] = timestamp.ToString("r");
            request.Headers[HttpRequestHeader.Authorization] = hmac;
            request.Timeout       = 10 * 60 * 1000;       // Ten minute timeout
            request.ContentLength = answers != null ? answers.Length : 0L;

            if (!string.IsNullOrEmpty(ProxyServerAddress))
            {
                request.Proxy = new WebProxy(ProxyServerAddress);
            }

            if (answers != null)
            {
                byte[] data = Encoding.UTF8.GetBytes(answers);
                request.GetRequestStream().Write(data, 0, data.Length);
            }
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();

            Directory.CreateDirectory(OutputDir);
            using (var resultsStream = new MemoryStream())
            {
                // Each part is written to a file whose name is specified in the content-disposition
                // header, except for the AssemblyResult part, which has a file name of "meta0.xml",
                // and is parsed into an AssemblyResult object.
                _parser.WritePartsToStreams(
                    response.GetResponseStream(),
                    h =>
                {
                    string fileName = GetFileNameFromHeaders(h);
                    if (fileName != null)
                    {
                        if (fileName.Equals("meta0.xml", StringComparison.OrdinalIgnoreCase))
                        {
                            return(resultsStream);
                        }

                        return(new FileStream(Path.Combine(OutputDir, fileName), FileMode.Create));
                    }
                    return(Stream.Null);
                },
                    (new ContentType(response.ContentType)).Boundary);

                if (resultsStream.Position > 0)
                {
                    resultsStream.Position = 0;
                    var serializer = new XmlSerializer(typeof(AssemblyResult));
                    return((AssemblyResult)serializer.Deserialize(resultsStream));
                }
                return(null);
            }
        }
        /// <summary>
        ///     Assemble a document from the given template, answers and settings.
        /// </summary>
        /// <param name="template">An instance of the Template class.</param>
        /// <param name="answers">
        ///     Either an XML answer string, or a string containing encoded
        ///     interview answers as posted from a HotDocs browser interview.
        /// </param>
        /// <param name="settings">An instance of the AssembleDocumentResult class.</param>
        /// <include file="../Shared/Help.xml" path="Help/string/param[@name='logRef']" />
        /// <returns>An AssemblyResult object containing all the files and data resulting from the request.</returns>
        public AssembleDocumentResult AssembleDocument(Template template, TextReader answers,
                                                       AssembleDocumentSettings settings, string logRef = "")
        {
            if (template == null)
            {
                throw new ArgumentNullException("template");
            }

            using (var client = new HttpClient())
            {
                AssembleDocumentResult adr  = null;
                var packageTemplateLocation = (PackageTemplateLocation)template.Location;
                var packageId = packageTemplateLocation.PackageID;
                var of        = ConvertFormat(settings.Format);
                var timestamp = DateTime.UtcNow;

                var hmac = HMAC.CalculateHMAC(
                    SigningKey,
                    timestamp,
                    SubscriberId,
                    packageId,
                    template.FileName,
                    false,
                    logRef,
                    of,
                    settings.Settings);

                var urlBuilder =
                    new StringBuilder().AppendFormat("{0}/assemble/{1}/{2}/{3}?" +
                                                     "format={4}&" +
                                                     "encodefilenames={5}&" +
                                                     "billingref={6}{7}",
                                                     HostAddress, SubscriberId, packageId, Uri.EscapeDataString(template.FileName),
                                                     of,
                                                     true,
                                                     Uri.EscapeDataString(logRef),
                                                     GetRetrieveFromHubParam());

                if (settings.Settings != null)
                {
                    foreach (var kv in settings.Settings)
                    {
                        urlBuilder.AppendFormat("&{0}={1}", kv.Key, kv.Value ?? "");
                    }
                }

                var request = new HttpRequestMessage
                {
                    RequestUri = new Uri(urlBuilder.ToString()),
                    Method     = HttpMethod.Post
                };

                request.Headers.Add("x-hd-date", timestamp.ToString("yyyy-MM-ddTHH:mm:ssZ"));
                request.Headers.Authorization = new AuthenticationHeaderValue("basic", hmac);

                var stringContent = answers == null
                    ? new StringContent(string.Empty)
                    : new StringContent(answers.ReadToEnd());

                request.Content = stringContent;

                request.Content.Headers.TryAddWithoutValidation("Content-Type", "text/xml");

                var result = client.SendAsync(request).Result;

                var parser = new MultipartMimeParser();

                HandleStatusCode(result);

                var streamResult = result.Content.ReadAsStreamAsync().Result;

                var streams = new List <MemoryStream>();

                using (var resultsStream = new MemoryStream())
                {
                    // Each part is written to a file whose name is specified in the content-disposition
                    // header, except for the AssemblyResult part, which has a file name of "meta0.xml",
                    // and is parsed into an AssemblyResult object.
                    parser.WritePartsToStreams(
                        streamResult,
                        h =>
                    {
                        var fileName = GetFileNameFromHeaders(h);
                        if (fileName == null)
                        {
                            return(Stream.Null);
                        }

                        if (fileName.Equals("meta0.xml", StringComparison.OrdinalIgnoreCase))
                        {
                            return(resultsStream);
                        }

                        var stream = new MemoryStream();
                        streams.Add(stream);
                        return(stream);
                    },
                        (new ContentType(result.Content.Headers.ContentType.ToString())).Boundary);

                    if (resultsStream.Position <= 0)
                    {
                        return(null);
                    }

                    resultsStream.Position = 0;
                    var serializer = new XmlSerializer(typeof(AssemblyResult));
                    var asmResult  = (AssemblyResult)serializer.Deserialize(resultsStream);

                    if (asmResult == null)
                    {
                        return(adr);
                    }

                    for (var i = 0; i < asmResult.Documents.Length; i++)
                    {
                        asmResult.Documents[i].Data = streams[i].ToArray();
                        streams[i].Dispose();
                    }

                    adr = Util.ConvertAssemblyResult(template, asmResult, settings.Format);
                }

                return(adr);
            }
        }
예제 #14
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="template">The template for which the interview is being requested.</param>
        /// <param name="answers">The answers to use with the interview.</param>
        /// <param name="settings">The settings to use when requesting the interview.</param>
        /// <param name="billingRef">This parameter lets you specify information that will be included in usage logs for this call. For example, you can use a string to uniquely identify the end user that initiated the request and/or the context in which the call was made. When you review usage logs, you can then see which end users initiated each request. That information could then be used to pass costs on to those end users if desired.</param>
        /// <param name="uploadPackage">Indicates if the package should be uploaded (forcefully) or not. This should only be true if the package does not already exist in the Cloud Services cache.</param>
        /// <returns></returns>
        protected internal override BinaryObject[] GetInterviewImpl(
            Template template,
            string answers,
            InterviewSettings settings,
            string billingRef,
            bool uploadPackage)
        {
            var timestamp = DateTime.UtcNow;

            if (!(template.Location is PackageTemplateLocation))
            {
                throw new Exception("HotDocs Cloud Services requires the use of template packages. Please use a PackageTemplateLocation derivative.");
            }
            PackageTemplateLocation packageTemplateLocation = (PackageTemplateLocation)template.Location;

            string interviewImageUrl = string.Empty;

            if (settings != null)
            {
                settings.Settings.TryGetValue("TempInterviewUrl", out interviewImageUrl);
            }
            else
            {
                settings = new InterviewSettings();
            }

            Dictionary <string, string> settingsDict = new Dictionary <string, string>(settings.Settings);

            // Workaround for bug in server that does not honor the Disable settings, so we have to just clear the url instead.
            // To do this, we make a copy of the settings that were given to us, modify them, and then use the modified version
            // in the call to Cloud Services.
            // TODO: After TFS #5598 is fixed, we can remove this workaround.
            // Note: TFS #5598 has been fixed, but the cloud implememntation does not pass those values through
            // to the cloud implmementation of HotDocs Server, so for now we leave these next 4 lines here that provide
            // equivalent functionality:
            if (settings.DisableDocumentPreview)
            {
                settingsDict.Remove("DocPreviewUrl");
            }
            if (settings.DisableSaveAnswers)
            {
                settingsDict.Remove("SaveAnswersPageUrl");
            }

            string hmac = HMAC.CalculateHMAC(
                SigningKey,
                timestamp,
                SubscriberId,
                packageTemplateLocation.PackageID,
                template.FileName,
                uploadPackage,
                billingRef,
                settings.Format,
                interviewImageUrl,
                settingsDict);

            return(_proxy.GetInterview(
                       SubscriberId,
                       packageTemplateLocation.PackageID,
                       template.FileName,
                       GetBinaryObjectArrayFromString(answers),
                       settings.Format,
                       settings.MarkedVariables.ToArray <string>(),
                       interviewImageUrl,
                       settingsDict,
                       billingRef,
                       timestamp,
                       GetPackageIfNeeded(packageTemplateLocation, uploadPackage),
                       hmac));
        }
예제 #15
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="template">The template to assemble.</param>
        /// <param name="answers">The answers to use when assembling the document.</param>
        /// <param name="settings">The settings to use when assembling the document.</param>
        /// <param name="billingRef">This parameter lets you specify information that will be included in usage logs for this call. For example, you can use a string to uniquely identify the end user that initiated the request and/or the context in which the call was made. When you review usage logs, you can then see which end users initiated each request. That information could then be used to pass costs on to those end users if desired.</param>
        /// <param name="uploadPackage">Indicates if the package should be uploaded (forcefully) or not. This should only be true if the package does not already exist in the Cloud Services cache.</param>
        /// <returns></returns>
        protected internal override AssemblyResult AssembleDocumentImpl(
            Template template,
            string answers,
            AssembleDocumentSettings settings,
            string billingRef,
            bool uploadPackage)
        {
            var timestamp = DateTime.UtcNow;

            if (!(template.Location is PackageTemplateLocation))
            {
                throw new Exception("HotDocs Cloud Services requires the use of template packages. Please use a PackageTemplateLocation derivative.");
            }
            PackageTemplateLocation packageTemplateLocation = (PackageTemplateLocation)template.Location;

            // Determine the output format to use (e.g., translate settings.Type to Contracts.InterviewFormat)
            OutputFormat outputFormat;

            switch (settings.Format)
            {
            case DocumentType.HFD:
                outputFormat = OutputFormat.HFD;
                break;

            case DocumentType.HPD:
                outputFormat = OutputFormat.HPD;
                break;

            case DocumentType.HTML:
                outputFormat = OutputFormat.HTML;
                break;

            case DocumentType.HTMLwDataURIs:
                outputFormat = OutputFormat.HTMLwDataURIs;
                break;

            case DocumentType.MHTML:
                outputFormat = OutputFormat.MHTML;
                break;

            case DocumentType.Native:
                outputFormat = OutputFormat.Native;
                break;

            case DocumentType.PDF:
                outputFormat = OutputFormat.PDF;
                break;

            case DocumentType.PlainText:
                outputFormat = OutputFormat.PlainText;
                break;

            case DocumentType.WordDOC:
                outputFormat = OutputFormat.DOCX;
                break;

            case DocumentType.WordDOCX:
                outputFormat = OutputFormat.DOCX;
                break;

            case DocumentType.WordPerfect:
                outputFormat = OutputFormat.WPD;
                break;

            case DocumentType.WordRTF:
                outputFormat = OutputFormat.RTF;
                break;

            default:
                outputFormat = OutputFormat.None;
                break;
            }

            // Always include the Answers output
            outputFormat |= OutputFormat.Answers;

            string hmac = HMAC.CalculateHMAC(
                SigningKey,
                timestamp,
                SubscriberId,
                packageTemplateLocation.PackageID,
                template.FileName,
                uploadPackage,
                billingRef,
                outputFormat,
                settings.Settings);

            return(_proxy.AssembleDocument(
                       SubscriberId,
                       packageTemplateLocation.PackageID,
                       template.FileName,
                       GetBinaryObjectArrayFromString(answers),
                       outputFormat,
                       settings.OutputOptions,
                       settings.Settings,
                       billingRef,
                       timestamp,
                       GetPackageIfNeeded(packageTemplateLocation, uploadPackage),
                       hmac));
        }
예제 #16
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="template"></param>
        /// <param name="answers"></param>
        /// <param name="settings"></param>
        /// <param name="billingRef">This parameter lets you specify information that will be included in usage logs for this call. For example, you can use a string to uniquely identify the end user that initiated the request and/or the context in which the call was made. When you review usage logs, you can then see which end users initiated each request. That information could then be used to pass costs on to those end users if desired.</param>
        /// <param name="uploadPackage">Indicates if the package should be uploaded (forcefully) or not. This should only be true if the package does not already exist in the Cloud Services cache.</param>
        /// <returns></returns>
        protected internal override BinaryObject[] GetInterviewImpl(
            Template template,
            string answers,
            InterviewSettings settings,
            string billingRef,
            bool uploadPackage)
        {
            if (!(template.Location is PackageTemplateLocation))
            {
                throw new Exception("HotDocs Cloud Services requires the use of template packages. Please use a PackageTemplateLocation derivative.");
            }
            PackageTemplateLocation packageTemplateLocation = (PackageTemplateLocation)template.Location;

            if (uploadPackage)
            {
                UploadPackage(packageTemplateLocation.PackageID, billingRef, packageTemplateLocation.GetPackageStream());
            }

            var timestamp = DateTime.UtcNow;

            string interviewImageUrl = string.Empty;

            if (settings != null)
            {
                settings.Settings.TryGetValue("TempInterviewUrl", out interviewImageUrl);
            }
            else
            {
                settings = new InterviewSettings();
            }

            string hmac = HMAC.CalculateHMAC(
                SigningKey,
                timestamp,
                SubscriberId,
                packageTemplateLocation.PackageID,
                template.FileName,
                false,
                billingRef,
                settings.Format,
                interviewImageUrl,
                settings.Settings);

            StringBuilder urlBuilder = new StringBuilder(string.Format(
                                                             "{0}/interview/{1}/{2}/{3}?format={4}&markedvariables={5}&tempimageurl={6}&billingref={7}",
                                                             EndpointAddress, SubscriberId, packageTemplateLocation.PackageID, template.FileName, settings.Format.ToString(),
                                                             settings.MarkedVariables != null ? string.Join(",", settings.MarkedVariables) : null, interviewImageUrl, billingRef));

            if (settings.Settings != null)
            {
                foreach (KeyValuePair <string, string> kv in settings.Settings)
                {
                    urlBuilder.AppendFormat("&{0}={1}", kv.Key, kv.Value ?? "");
                }
            }

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(urlBuilder.ToString());

            request.Method               = "POST";
            request.ContentType          = "text/xml";
            request.Headers["x-hd-date"] = timestamp.ToString("r");
            request.Headers[HttpRequestHeader.Authorization] = hmac;
            request.ContentLength = answers != null ? answers.Length : 0L;

            if (!string.IsNullOrEmpty(ProxyServerAddress))
            {
                request.Proxy = new WebProxy(ProxyServerAddress);
            }

            using (Stream stream = request.GetRequestStream())
            {
                if (answers != null)
                {
                    byte[] data = Encoding.UTF8.GetBytes(answers);
                    stream.Write(data, 0, data.Length);
                }
            }

            using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
            {
                Directory.CreateDirectory(OutputDir);
                using (var resultsStream = new MemoryStream())
                {
                    // Each part is written to a file whose name is specified in the content-disposition
                    // header, except for the BinaryObject[] part, which has a file name of "meta0.xml",
                    // and is parsed into an BinaryObject[] object.
                    _parser.WritePartsToStreams(
                        response.GetResponseStream(),
                        h =>
                    {
                        string id = GetFileNameFromHeaders(h);
                        if (id != null)
                        {
                            if (id.Equals("meta0.xml", StringComparison.OrdinalIgnoreCase))
                            {
                                return(resultsStream);
                            }

                            // The following stream will be closed by the parser
                            return(new FileStream(Path.Combine(OutputDir, id), FileMode.Create));
                        }
                        return(Stream.Null);
                    },
                        (new ContentType(response.ContentType)).Boundary);

                    if (resultsStream.Position > 0)
                    {
                        resultsStream.Position = 0;
                        var serializer = new XmlSerializer(typeof(BinaryObject[]));
                        return((BinaryObject[])serializer.Deserialize(resultsStream));
                    }
                    return(null);
                }
            }
        }
        private string CreateSessionImpl(
            Template template,
            string billingRef,
            string answers,
            string[] markedVariables,
            InterviewFormat interviewFormat,
            OutputFormat outputFormat,
            Dictionary <string, string> settings,
            string theme,
            bool showDownloadLinks,
            bool uploadPackage)
        {
            if (!(template.Location is PackageTemplateLocation))
            {
                throw new Exception("HotDocs Cloud Services requires the use of template packages. Please use a PackageTemplateLocation derivative.");
            }
            PackageTemplateLocation packageTemplateLocation = (PackageTemplateLocation)template.Location;

            if (uploadPackage)
            {
                UploadPackage(packageTemplateLocation.PackageID, billingRef, packageTemplateLocation.GetPackageStream());
            }

            var timestamp = DateTime.UtcNow;

            string hmac = HMAC.CalculateHMAC(
                SigningKey,
                timestamp,
                SubscriberId,
                packageTemplateLocation.PackageID,
                billingRef,
                interviewFormat,
                outputFormat,
                settings);                 // Additional settings = null for this app

            StringBuilder urlBuilder = new StringBuilder(string.Format(
                                                             "{0}/embed/newsession/{1}/{2}?interviewformat={3}&outputformat={4}",
                                                             EndpointAddress, SubscriberId, packageTemplateLocation.PackageID,
                                                             interviewFormat.ToString(), outputFormat.ToString()));

            if (markedVariables != null && markedVariables.Length > 0)
            {
                urlBuilder.AppendFormat("&markedvariables={0}", string.Join(",", markedVariables));
            }

            if (!string.IsNullOrEmpty(theme))
            {
                urlBuilder.AppendFormat("&theme={0}", theme);
            }

            if (!string.IsNullOrEmpty(billingRef))
            {
                urlBuilder.AppendFormat("&billingref={0}", billingRef);
            }

            if (showDownloadLinks)
            {
                urlBuilder.Append("&showdownloadlinks=true");
            }

            if (settings != null)
            {
                foreach (KeyValuePair <string, string> kv in settings)
                {
                    urlBuilder.AppendFormat("&{0}={1}", kv.Key, kv.Value ?? "");
                }
            }

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(urlBuilder.ToString());

            request.Method               = "POST";
            request.ContentType          = "text/xml";
            request.Headers["x-hd-date"] = timestamp.ToString("r");
            request.Headers[HttpRequestHeader.Authorization] = hmac;
            request.ContentLength = answers != null ? answers.Length : 0;

            if (!string.IsNullOrEmpty(ProxyServerAddress))
            {
                request.Proxy = new WebProxy(ProxyServerAddress);
            }
            else
            {
                request.Proxy = null;
            }

            Stream stream = request.GetRequestStream();

            if (answers != null)
            {
                byte[] data = Encoding.UTF8.GetBytes(answers);
                stream.Write(data, 0, data.Length);
            }
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            StreamReader    reader   = new StreamReader(response.GetResponseStream());

            return(reader.ReadLine());
        }
        /// <summary>
        ///     GetInterview returns an HTML fragment suitable for inclusion in any standards-mode web page, which embeds a HotDocs
        ///     interview
        ///     directly in that web page.
        /// </summary>
        /// <param name="template">The template for which to return an interview.</param>
        /// <param name="answers">The answers to use when building an interview.</param>
        /// <param name="settings">The <see cref="InterviewSettings" /> to use when building an interview.</param>
        /// <param name="markedVariables">
        ///     The variables to highlight to the user as needing special attention.
        ///     This is usually populated with <see cref="AssembleDocumentResult.UnansweredVariables" />
        ///     from <see cref="AssembleDocument" />.
        /// </param>
        /// <include file="../Shared/Help.xml" path="Help/string/param[@name='logRef']" />
        /// <returns>Returns the results of building the interview as an <see cref="InterviewResult" /> object.</returns>
        public InterviewResult GetInterview(Template template, TextReader answers, InterviewSettings settings,
                                            IEnumerable <string> markedVariables, string logRef = "")
        {
            if (template == null)
            {
                throw new ArgumentNullException("template");
            }

            if (settings == null)
            {
                throw new ArgumentNullException("settings");
            }

            using (var client = new HttpClient())
            {
                var packageTemplateLocation = (PackageTemplateLocation)template.Location;
                var packageId = packageTemplateLocation.PackageID;
                var timestamp = DateTime.UtcNow;

                var hmac = HMAC.CalculateHMAC(
                    SigningKey,
                    timestamp,
                    SubscriberId,
                    packageId,
                    template.FileName,
                    false,
                    logRef,
                    settings.Format,
                    settings.InterviewFilesUrl,
                    settings.Settings);

                var urlBuilder = new StringBuilder().AppendFormat("{0}/interview/{1}/{2}/{3}?" +
                                                                  "format={4}&" +
                                                                  "markedvariables{5}&" +
                                                                  "tempimageurl={6}&" +
                                                                  "encodeFileNames={7}&" +
                                                                  "billingref={8}" +
                                                                  "{9}",
                                                                  HostAddress, SubscriberId, packageId, Uri.EscapeDataString(template.FileName),
                                                                  settings.Format,
                                                                  markedVariables != null && markedVariables.Any()
                        ? "=" + Uri.EscapeDataString(string.Join(",", settings.MarkedVariables))
                        : null,
                                                                  Uri.EscapeDataString(settings.InterviewFilesUrl),
                                                                  true,
                                                                  Uri.EscapeDataString(logRef),
                                                                  GetRetrieveFromHubParam());

                foreach (var kv in settings.Settings)
                {
                    urlBuilder.AppendFormat("&{0}={1}", kv.Key, kv.Value ?? "");
                }

                var request = new HttpRequestMessage
                {
                    RequestUri = new Uri(urlBuilder.ToString()),
                    Method     = HttpMethod.Post
                };

                request.Headers.Add("x-hd-date", timestamp.ToString("yyyy-MM-ddTHH:mm:ssZ"));
                request.Headers.Authorization = new AuthenticationHeaderValue("basic", hmac);

                var stringContent = answers == null
                    ? new StringContent(string.Empty)
                    : new StringContent(answers.ReadToEnd());

                request.Content = stringContent;

                var result = client.SendAsync(request).Result;

                HandleStatusCode(result);

                var streamResult = result.Content.ReadAsStreamAsync().Result;

                var parser    = new MultipartMimeParser();
                var outputDir = Path.GetTempPath();
                Directory.CreateDirectory(outputDir);
                var streams = new List <MemoryStream>();

                using (var resultsStream = new MemoryStream())
                {
                    // Each part is written to a file whose name is specified in the content-disposition
                    // header, except for the BinaryObject[] part, which has a file name of "meta0.xml",
                    // and is parsed into an BinaryObject[] object.
                    parser.WritePartsToStreams(
                        streamResult,
                        h =>
                    {
                        var fileName = GetFileNameFromHeaders(h);

                        if (string.IsNullOrEmpty(fileName))
                        {
                            return(Stream.Null);
                        }

                        if (fileName.Equals("meta0.xml", StringComparison.OrdinalIgnoreCase))
                        {
                            return(resultsStream);
                        }

                        // The following stream will be closed by the parser
                        var stream = new MemoryStream();
                        streams.Add(stream);
                        return(stream);
                    },
                        (new ContentType(result.Content.Headers.ContentType.ToString())).Boundary);

                    if (resultsStream.Position <= 0)
                    {
                        return(null);
                    }

                    resultsStream.Position = 0;
                    var serializer = new XmlSerializer(typeof(BinaryObject[]));
                    var binObjects = (BinaryObject[])serializer.Deserialize(resultsStream);

                    for (var i = 0; i < binObjects.Length; i++)
                    {
                        binObjects[i].Data = streams[i].ToArray();
                        streams[i].Dispose();
                    }

                    var interviewContent = Util.ExtractString(binObjects[0]);
                    return(new InterviewResult {
                        HtmlFragment = interviewContent
                    });
                }
            }
        }