1 /* 2 PowerShell 6.0 3  4 Copyright (c) Microsoft Corporation. All rights reserved. 5  6 All rights reserved. 7  8 MIT License 9  10 Permission is hereby granted, free of charge, to any person obtaining a copy 11 of this software and associated documentation files (the ""Software""), to deal 12 in the Software without restriction, including without limitation the rights 13 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 copies of the Software, and to permit persons to whom the Software is 15 furnished to do so, subject to the following conditions: 16  17 The above copyright notice and this permission notice shall be included in all 18 copies or substantial portions of the Software. 19  20 THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 SOFTWARE. 27 */ 28  29 /********************************************************************++ 30 Copyright (c) Microsoft Corporation. All rights reserved. 31 --********************************************************************/ 32  33 using System; 34 using System.IO; 35 using System.Management.Automation; 36 using System.Xml; 37  38  39 using Dbg = System.Management.Automation.Diagnostics; 40  41  42  43 namespace Microsoft.PowerShell 44 { 45  /// <summary> 46  /// 47  /// Wraps Hitesh's xml serializer in such a way that it will select the proper serializer based on the data 48  /// format. 49  /// 50  /// </summary> 51  52  internal class Serialization 53  { 54  /// <summary> 55  /// 56  /// Describes the format of the data streamed between minishells, e.g. the allowed arguments to the minishell 57  /// -outputformat and -inputformat command line parameters. 58  /// 59  /// </summary> 60  61  internal enum DataFormat 62  { 63  /// <summary> 64  /// 65  /// text format -- i.e. stream text just as out-default would display it. 66  /// 67  /// </summary> 68  69  Text = 0, 70  71  /// <summary> 72  /// 73  /// XML-serialized format 74  /// 75  /// </summary> 76  77  XML = 0xFF, 78  79  /// <summary> 80  /// 81  /// Indicates that the data should be discarded instead of processed. 82  /// 83  /// </summary> 84  None = 2 85  } 86  87  88  89  protected Serialization(DataFormat dataFormat, string streamName)90  Serialization(DataFormat dataFormat, string streamName) 91  { 92  Dbg.Assert(!string.IsNullOrEmpty(streamName), "stream needs a name"); 93  94  format = dataFormat; 95  this.streamName = streamName; 96  } 97  98  99  100  protected static string XmlCliTag = "#< CLIXML"; 101  102  protected string streamName; 103  protected DataFormat format; 104  } 105  106  107  108  internal 109  class WrappedSerializer : Serialization 110  { 111  internal WrappedSerializer(DataFormat dataFormat, string streamName, TextWriter output)112  WrappedSerializer(DataFormat dataFormat, string streamName, TextWriter output) 113  : 114  base(dataFormat, streamName) 115  { 116  Dbg.Assert(output != null, "output should have a value"); 117  118  textWriter = output; 119  switch (format) 120  { 121  case DataFormat.XML: 122  XmlWriterSettings settings = new XmlWriterSettings(); 123  settings.CheckCharacters = false; 124  settings.OmitXmlDeclaration = true; 125  _xmlWriter = XmlWriter.Create(textWriter, settings); 126  _xmlSerializer = new Serializer(_xmlWriter); 127  break; 128  case DataFormat.Text: 129  default: 130  // do nothing; we'll just write to the TextWriter 131  // or discard it. 132  133  break; 134  } 135  } 136  137  138  139  internal 140  void Serialize(object o)141  Serialize(object o) 142  { 143  Serialize(o, this.streamName); 144  } 145  146  internal 147  void Serialize(object o, string streamName)148  Serialize(object o, string streamName) 149  { 150  switch (format) 151  { 152  case DataFormat.None: 153  break; 154  case DataFormat.XML: 155  if (_firstCall) 156  { 157  _firstCall = false; 158  textWriter.WriteLine(Serialization.XmlCliTag); 159  } 160  _xmlSerializer.Serialize(o, streamName); 161  break; 162  case DataFormat.Text: 163  default: 164  textWriter.Write(o.ToString()); 165  break; 166  } 167  } 168  169  170  internal 171  void End()172  End() 173  { 174  switch (format) 175  { 176  case DataFormat.None: 177  // do nothing 178  break; 179  180  case DataFormat.XML: 181  _xmlSerializer.Done(); 182  _xmlSerializer = null; 183  break; 184  185  case DataFormat.Text: 186  default: 187  // do nothing 188  189  break; 190  } 191  } 192  193  194  internal TextWriter textWriter; 195  private XmlWriter _xmlWriter; 196  private Serializer _xmlSerializer; 197  private bool _firstCall = true; 198  } 199  200  201  202  internal 203  class WrappedDeserializer : Serialization 204  { 205  internal WrappedDeserializer(DataFormat dataFormat, string streamName, TextReader input)206  WrappedDeserializer(DataFormat dataFormat, string streamName, TextReader input) 207  : 208  base(dataFormat, streamName) 209  { 210  Dbg.Assert(input != null, "input should have a value"); 211  212  // If the data format is none - do nothing... 213  if (dataFormat == DataFormat.None) 214  return; 215  216  textReader = input; 217  _firstLine = textReader.ReadLine(); 218  if (String.Compare(_firstLine, Serialization.XmlCliTag, StringComparison.OrdinalIgnoreCase) == 0) 219  { 220  // format should be XML 221  222  dataFormat = DataFormat.XML; 223  } 224  225  switch (format) 226  { 227  case DataFormat.XML: 228  _xmlReader = XmlReader.Create(textReader, new XmlReaderSettings { XmlResolver = null }); 229  _xmlDeserializer = new Deserializer(_xmlReader); 230  break; 231  case DataFormat.Text: 232  default: 233  // do nothing; we'll just read from the TextReader 234  235  break; 236  } 237  } 238  239  240  241  internal 242  object Deserialize()243  Deserialize() 244  { 245  object o; 246  switch (format) 247  { 248  case DataFormat.None: 249  _atEnd = true; 250  return null; 251  252  case DataFormat.XML: 253  string unused; 254  o = _xmlDeserializer.Deserialize(out unused); 255  break; 256  257  case DataFormat.Text: 258  default: 259  if (_atEnd) 260  { 261  return null; 262  } 263  if (_firstLine != null) 264  { 265  o = _firstLine; 266  _firstLine = null; 267  } 268  else 269  { 270  o = textReader.ReadLine(); 271  if (o == null) 272  { 273  _atEnd = true; 274  } 275  } 276  break; 277  } 278  return o; 279  } 280  281  282  283  internal 284  bool 285  AtEnd 286  { 287  get 288  { 289  bool result = false; 290  switch (format) 291  { 292  case DataFormat.None: 293  _atEnd = true; 294  result = true; 295  break; 296  297  case DataFormat.XML: 298  result = _xmlDeserializer.Done(); 299  break; 300  301  case DataFormat.Text: 302  default: 303  result = _atEnd; 304  break; 305  } 306  return result; 307  } 308  } 309  310  311  312  internal 313  void End()314  End() 315  { 316  switch (format) 317  { 318  case DataFormat.None: 319  case DataFormat.XML: 320  case DataFormat.Text: 321  default: 322  // do nothing 323  324  break; 325  } 326  } 327  328  329  internal TextReader textReader; 330  private XmlReader _xmlReader; 331  private Deserializer _xmlDeserializer; 332  private string _firstLine; 333  private bool _atEnd; 334  } 335 } // namespace 336 /*http://example.com*/ 337