diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/BasicHtmlWebResponseObject.Common.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/BasicHtmlWebResponseObject.Common.cs index 22709a2bc..c2899459a 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/BasicHtmlWebResponseObject.Common.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/BasicHtmlWebResponseObject.Common.cs @@ -3,22 +3,58 @@ Copyright (c) Microsoft Corporation. All rights reserved. --********************************************************************/ using System; -using System.Management.Automation; -using System.Net; -using System.IO; -using System.Text; -using System.Text.RegularExpressions; using System.Collections.Generic; using System.Diagnostics; +using System.IO; +using System.Management.Automation; +using System.Net; using System.Net.Http; +using System.Text; +using System.Text.RegularExpressions; namespace Microsoft.PowerShell.Commands { /// /// Response object for html content without DOM parsing /// - public partial class BasicHtmlWebResponseObject : WebResponseObject + public class BasicHtmlWebResponseObject : WebResponseObject { + #region Private Fields + + private static Regex s_attribNameValueRegex; + private static Regex s_attribsRegex; + private static Regex s_imageRegex; + private static Regex s_inputFieldRegex; + private static Regex s_linkRegex; + private static Regex s_tagRegex; + + #endregion Private Fields + + #region Constructors + + /// + /// Constructor for BasicHtmlWebResponseObject + /// + /// + public BasicHtmlWebResponseObject(HttpResponseMessage response) + : this(response, null) + { } + + /// + /// Constructor for HtmlWebResponseObject with memory stream + /// + /// + /// + public BasicHtmlWebResponseObject(HttpResponseMessage response, Stream contentStream) + : base(response, contentStream) + { + EnsureHtmlParser(); + InitializeContent(); + InitializeRawContent(response); + } + + #endregion Constructors + #region Properties /// @@ -117,19 +153,40 @@ namespace Microsoft.PowerShell.Commands #endregion Properties - #region Private Fields - - private static Regex s_tagRegex; - private static Regex s_attribsRegex; - private static Regex s_attribNameValueRegex; - private static Regex s_inputFieldRegex; - private static Regex s_linkRegex; - private static Regex s_imageRegex; - - #endregion Private Fields - #region Methods + /// + /// Reads the response content from the web response. + /// + protected void InitializeContent() + { + string contentType = ContentHelper.GetContentType(BaseResponse); + if (ContentHelper.IsText(contentType)) + { + Encoding encoding = null; + // fill the Content buffer + string characterSet = WebResponseHelper.GetCharacterSet(BaseResponse); + this.Content = StreamHelper.DecodeStream(RawContentStream, characterSet, out encoding); + this.Encoding = encoding; + } + else + { + this.Content = string.Empty; + } + } + + private PSObject CreateHtmlObject(string html, string tagName) + { + PSObject elementObject = new PSObject(); + + elementObject.Properties.Add(new PSNoteProperty("outerHTML", html)); + elementObject.Properties.Add(new PSNoteProperty("tagName", tagName)); + + ParseAttributes(html, elementObject); + + return elementObject; + } + private void EnsureHtmlParser() { if (s_tagRegex == null) @@ -169,16 +226,11 @@ namespace Microsoft.PowerShell.Commands } } - private PSObject CreateHtmlObject(string html, string tagName) + private void InitializeRawContent(HttpResponseMessage baseResponse) { - PSObject elementObject = new PSObject(); - - elementObject.Properties.Add(new PSNoteProperty("outerHTML", html)); - elementObject.Properties.Add(new PSNoteProperty("tagName", tagName)); - - ParseAttributes(html, elementObject); - - return elementObject; + StringBuilder raw = ContentHelper.GetRawContentHeader(baseResponse); + raw.Append(Content); + this.RawContent = raw.ToString(); } private void ParseAttributes(string outerHtml, PSObject elementObject) @@ -223,70 +275,6 @@ namespace Microsoft.PowerShell.Commands } } - /// - /// Reads the response content from the web response. - /// - protected void InitializeContent() - { - string contentType = ContentHelper.GetContentType(BaseResponse); - if (ContentHelper.IsText(contentType)) - { - Encoding encoding = null; - // fill the Content buffer - string characterSet = WebResponseHelper.GetCharacterSet(BaseResponse); - this.Content = StreamHelper.DecodeStream(RawContentStream, characterSet, out encoding); - this.Encoding = encoding; - } - else - { - this.Content = string.Empty; - } - } - - #endregion Methods - } - - // TODO: Merge Partials - - // - /// Response object for html content without DOM parsing - /// - public partial class BasicHtmlWebResponseObject : WebResponseObject - { - #region Constructors - - /// - /// Constructor for BasicHtmlWebResponseObject - /// - /// - public BasicHtmlWebResponseObject(HttpResponseMessage response) - : this(response, null) - { } - - /// - /// Constructor for HtmlWebResponseObject with memory stream - /// - /// - /// - public BasicHtmlWebResponseObject(HttpResponseMessage response, Stream contentStream) - : base(response, contentStream) - { - EnsureHtmlParser(); - InitializeContent(); - InitializeRawContent(response); - } - - #endregion Constructors - - #region Methods - - private void InitializeRawContent(HttpResponseMessage baseResponse) - { - StringBuilder raw = ContentHelper.GetRawContentHeader(baseResponse); - raw.Append(Content); - this.RawContent = raw.ToString(); - } - #endregion Methods } } diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/ContentHelper.Common.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/ContentHelper.Common.cs index 8bc5546b1..82f3033b7 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/ContentHelper.Common.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/ContentHelper.Common.cs @@ -3,45 +3,49 @@ Copyright (c) Microsoft Corporation. All rights reserved. --********************************************************************/ using System; -using System.Management.Automation; -using System.Text; -using Microsoft.Win32; using System.Linq; +using System.Management.Automation; using System.Net.Http; using System.Net.Http.Headers; +using System.Text; +using Microsoft.Win32; namespace Microsoft.PowerShell.Commands { - internal static partial class ContentHelper + internal static class ContentHelper { #region Constants - // used to split contentType arguments - private static readonly char[] s_contentTypeParamSeparator = { ';' }; - // default codepage encoding for web content. See RFC 2616. private const string _defaultCodePage = "ISO-8859-1"; #endregion Constants + #region Fields + + // used to split contentType arguments + private static readonly char[] s_contentTypeParamSeparator = { ';' }; + + #endregion Fields + #region Internal Methods - internal static bool IsText(string contentType) + internal static string GetContentType(HttpResponseMessage response) { - contentType = GetContentTypeSignature(contentType); - return CheckIsText(contentType); + // ContentType may not exist in response header. Return null if not. + return response.Content.Headers.ContentType?.MediaType; } - internal static bool IsXml(string contentType) + internal static Encoding GetDefaultEncoding() { - contentType = GetContentTypeSignature(contentType); - return CheckIsXml(contentType); + return GetEncodingOrDefault((string)null); } - internal static bool IsJson(string contentType) + internal static Encoding GetEncoding(HttpResponseMessage response) { - contentType = GetContentTypeSignature(contentType); - return CheckIsJson(contentType); + // ContentType may not exist in response header. + string charSet = response.Content.Headers.ContentType?.CharSet; + return GetEncodingOrDefault(charSet); } internal static Encoding GetEncodingOrDefault(string characterSet) @@ -63,22 +67,87 @@ namespace Microsoft.PowerShell.Commands return encoding; } - internal static Encoding GetDefaultEncoding() + internal static StringBuilder GetRawContentHeader(HttpResponseMessage response) { - return GetEncodingOrDefault((string)null); + StringBuilder raw = new StringBuilder(); + + string protocol = WebResponseHelper.GetProtocol(response); + if (!string.IsNullOrEmpty(protocol)) + { + int statusCode = WebResponseHelper.GetStatusCode(response); + string statusDescription = WebResponseHelper.GetStatusDescription(response); + raw.AppendFormat("{0} {1} {2}", protocol, statusCode, statusDescription); + raw.AppendLine(); + } + + HttpHeaders[] headerCollections = + { + response.Headers, + response.Content == null ? null : response.Content.Headers + }; + + foreach (var headerCollection in headerCollections) + { + if (headerCollection == null) + { + continue; + } + foreach (var header in headerCollection) + { + // Headers may have multiple entries with different values + foreach (var headerValue in header.Value) + { + raw.Append(header.Key); + raw.Append(": "); + raw.Append(headerValue); + raw.AppendLine(); + } + } + } + + raw.AppendLine(); + return raw; + } + + internal static bool IsJson(string contentType) + { + contentType = GetContentTypeSignature(contentType); + return CheckIsJson(contentType); + } + + internal static bool IsText(string contentType) + { + contentType = GetContentTypeSignature(contentType); + return CheckIsText(contentType); + } + + internal static bool IsXml(string contentType) + { + contentType = GetContentTypeSignature(contentType); + return CheckIsXml(contentType); } #endregion Internal Methods #region Private Helper Methods - private static string GetContentTypeSignature(string contentType) + private static bool CheckIsJson(string contentType) { if (String.IsNullOrEmpty(contentType)) - return null; + return false; - string sig = contentType.Split(s_contentTypeParamSeparator, 2)[0].ToUpperInvariant(); - return (sig); + // the correct type for JSON content, as specified in RFC 4627 + bool isJson = contentType.Equals("application/json", StringComparison.OrdinalIgnoreCase); + + // add in these other "javascript" related types that + // sometimes get sent down as the mime type for JSON content + isJson |= contentType.Equals("text/json", StringComparison.OrdinalIgnoreCase) + || contentType.Equals("application/x-javascript", StringComparison.OrdinalIgnoreCase) + || contentType.Equals("text/x-javascript", StringComparison.OrdinalIgnoreCase) + || contentType.Equals("application/javascript", StringComparison.OrdinalIgnoreCase) + || contentType.Equals("text/javascript", StringComparison.OrdinalIgnoreCase); + + return (isJson); } private static bool CheckIsText(string contentType) @@ -132,85 +201,15 @@ namespace Microsoft.PowerShell.Commands return (isXml); } - private static bool CheckIsJson(string contentType) + private static string GetContentTypeSignature(string contentType) { if (String.IsNullOrEmpty(contentType)) - return false; + return null; - // the correct type for JSON content, as specified in RFC 4627 - bool isJson = contentType.Equals("application/json", StringComparison.OrdinalIgnoreCase); - - // add in these other "javascript" related types that - // sometimes get sent down as the mime type for JSON content - isJson |= contentType.Equals("text/json", StringComparison.OrdinalIgnoreCase) - || contentType.Equals("application/x-javascript", StringComparison.OrdinalIgnoreCase) - || contentType.Equals("text/x-javascript", StringComparison.OrdinalIgnoreCase) - || contentType.Equals("application/javascript", StringComparison.OrdinalIgnoreCase) - || contentType.Equals("text/javascript", StringComparison.OrdinalIgnoreCase); - - return (isJson); + string sig = contentType.Split(s_contentTypeParamSeparator, 2)[0].ToUpperInvariant(); + return (sig); } - #endregion Internal Helper Methods - } - - // TODO: merge Partials - - internal static partial class ContentHelper - { - internal static Encoding GetEncoding(HttpResponseMessage response) - { - // ContentType may not exist in response header. - string charSet = response.Content.Headers.ContentType?.CharSet; - return GetEncodingOrDefault(charSet); - } - - internal static string GetContentType(HttpResponseMessage response) - { - // ContentType may not exist in response header. Return null if not. - return response.Content.Headers.ContentType?.MediaType; - } - - internal static StringBuilder GetRawContentHeader(HttpResponseMessage response) - { - StringBuilder raw = new StringBuilder(); - - string protocol = WebResponseHelper.GetProtocol(response); - if (!string.IsNullOrEmpty(protocol)) - { - int statusCode = WebResponseHelper.GetStatusCode(response); - string statusDescription = WebResponseHelper.GetStatusDescription(response); - raw.AppendFormat("{0} {1} {2}", protocol, statusCode, statusDescription); - raw.AppendLine(); - } - - HttpHeaders[] headerCollections = - { - response.Headers, - response.Content == null ? null : response.Content.Headers - }; - - foreach (var headerCollection in headerCollections) - { - if (headerCollection == null) - { - continue; - } - foreach (var header in headerCollection) - { - // Headers may have multiple entries with different values - foreach (var headerValue in header.Value) - { - raw.Append(header.Key); - raw.Append(": "); - raw.Append(headerValue); - raw.AppendLine(); - } - } - } - - raw.AppendLine(); - return raw; - } + #endregion Private Helper Methods } }