ObjectStateFormatter.cs 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096
  1. //
  2. // System.Web.UI.ObjectStateFormatter
  3. //
  4. // Authors:
  5. // Ben Maurer ([email protected])
  6. // Gonzalo Paniagua ([email protected])
  7. //
  8. // (C) 2003 Ben Maurer
  9. // (c) Copyright 2004-2010 Novell, Inc. (http://www.novell.com)
  10. //
  11. //
  12. // Permission is hereby granted, free of charge, to any person obtaining
  13. // a copy of this software and associated documentation files (the
  14. // "Software"), to deal in the Software without restriction, including
  15. // without limitation the rights to use, copy, modify, merge, publish,
  16. // distribute, sublicense, and/or sell copies of the Software, and to
  17. // permit persons to whom the Software is furnished to do so, subject to
  18. // the following conditions:
  19. //
  20. // The above copyright notice and this permission notice shall be
  21. // included in all copies or substantial portions of the Software.
  22. //
  23. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  24. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  26. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  27. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  28. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  29. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  30. //
  31. //#define TRACE
  32. using System.Collections;
  33. using System.ComponentModel;
  34. using System.Globalization;
  35. using System.Drawing;
  36. using System.IO;
  37. using System.Reflection;
  38. using System.Runtime.Serialization.Formatters.Binary;
  39. using System.Runtime.Serialization;
  40. using System.Text;
  41. using System.Web.UI.WebControls;
  42. using System.Web.Util;
  43. using System.Diagnostics;
  44. using System.Security.Cryptography;
  45. using System.Web.Configuration;
  46. namespace System.Web.UI {
  47. #if NET_2_0
  48. public
  49. #else
  50. internal
  51. #endif
  52. sealed class ObjectStateFormatter : IFormatter, IStateFormatter
  53. {
  54. Page page;
  55. HashAlgorithm algo;
  56. byte [] vkey;
  57. public ObjectStateFormatter ()
  58. {
  59. }
  60. internal ObjectStateFormatter (Page page)
  61. {
  62. this.page = page;
  63. }
  64. internal ObjectStateFormatter (byte [] vkey)
  65. {
  66. this.vkey = vkey;
  67. }
  68. internal bool EnableMac {
  69. get {
  70. if (page == null) {
  71. if (vkey == null)
  72. return false;
  73. return true;
  74. } else {
  75. #if NET_2_0
  76. return page.EnableViewStateMac;
  77. #elif NET_1_1
  78. return page.EnableViewStateMacInternal;
  79. #else
  80. return false;
  81. #endif
  82. }
  83. }
  84. }
  85. internal HashAlgorithm GetAlgo ()
  86. {
  87. if (algo != null)
  88. return algo;
  89. if (!EnableMac)
  90. return null;
  91. byte [] algoKey;
  92. if (page != null) {
  93. #if NET_2_0
  94. MachineKeySection mconfig = (MachineKeySection) WebConfigurationManager.GetWebApplicationSection ("system.web/machineKey");
  95. algoKey = MachineKeySectionUtils.ValidationKeyBytes (mconfig);
  96. #else
  97. MachineKeyConfig mconfig = HttpContext.GetAppConfig ("system.web/machineKey") as MachineKeyConfig;
  98. algoKey = mconfig.ValidationKey;
  99. #endif
  100. } else
  101. algoKey = vkey;
  102. algo = new HMACSHA1 (algoKey);
  103. return algo;
  104. }
  105. static int ValidateInput (HashAlgorithm algo, byte [] data, int offset, int size)
  106. {
  107. if (algo == null)
  108. throw new HttpException ("Unable to validate data.");
  109. int hash_size = algo.HashSize / 8;
  110. if (size != 0 && size < hash_size)
  111. throw new HttpException ("Unable to validate data.");
  112. int data_length = size - hash_size;
  113. MemoryStream data_stream = new MemoryStream (data, offset, data_length, false, false);
  114. byte [] hash = algo.ComputeHash (data_stream);
  115. for (int i = 0; i < hash_size; i++) {
  116. if (hash [i] != data [data_length + i])
  117. throw new HttpException ("Unable to validate data.");
  118. }
  119. return data_length;
  120. }
  121. public object Deserialize (Stream inputStream)
  122. {
  123. if (inputStream == null)
  124. throw new ArgumentNullException ("inputStream");
  125. return DeserializeObject (new BinaryReader (inputStream));
  126. }
  127. public object Deserialize (string inputString)
  128. {
  129. if (inputString == null)
  130. throw new ArgumentNullException ("inputString");
  131. #if NET_2_0
  132. if (inputString.Length == 0)
  133. throw new ArgumentNullException ("inputString");
  134. #else
  135. if (inputString == "")
  136. return "";
  137. #endif
  138. byte [] buffer = Convert.FromBase64String (inputString);
  139. int length;
  140. if (buffer == null || (length = buffer.Length) == 0)
  141. throw new ArgumentNullException ("inputString");
  142. if (page != null && EnableMac)
  143. length = ValidateInput (GetAlgo (), buffer, 0, length);
  144. #if NET_2_0
  145. bool isEncrypted = ((int)buffer [--length] == 1)? true : false;
  146. #endif
  147. Stream ms = new MemoryStream (buffer, 0, length, false, false);
  148. #if NET_2_0
  149. if (isEncrypted)
  150. ms = new CryptoStream (ms, page.GetCryptoTransform (CryptoStreamMode.Read), CryptoStreamMode.Read);
  151. #endif
  152. return Deserialize (ms);
  153. }
  154. public string Serialize (object stateGraph)
  155. {
  156. if (stateGraph == null)
  157. return "";
  158. MemoryStream ms = new MemoryStream ();
  159. Stream output = ms;
  160. #if NET_2_0
  161. bool needEncryption = page == null ? false : page.NeedViewStateEncryption;
  162. if (needEncryption){
  163. output = new CryptoStream (output, page.GetCryptoTransform (CryptoStreamMode.Write), CryptoStreamMode.Write);
  164. }
  165. #endif
  166. Serialize (output, stateGraph);
  167. #if NET_2_0
  168. ms.WriteByte((byte)(needEncryption? 1 : 0));
  169. #endif
  170. #if TRACE
  171. ms.WriteTo (File.OpenWrite (Path.GetTempFileName ()));
  172. #endif
  173. if (EnableMac && ms.Length > 0) {
  174. HashAlgorithm algo = GetAlgo ();
  175. if (algo != null) {
  176. byte [] hash = algo.ComputeHash (ms.GetBuffer (), 0, (int) ms.Length);
  177. ms.Write (hash, 0, hash.Length);
  178. }
  179. }
  180. return Convert.ToBase64String (ms.GetBuffer (), 0, (int) ms.Length);
  181. }
  182. public void Serialize (Stream outputStream, object stateGraph)
  183. {
  184. if (outputStream == null)
  185. throw new ArgumentNullException ("outputStream");
  186. if (stateGraph == null)
  187. throw new ArgumentNullException ("stateGraph");
  188. SerializeValue (new BinaryWriter (outputStream), stateGraph);
  189. }
  190. void SerializeValue (BinaryWriter w, object o)
  191. {
  192. ObjectFormatter.WriteObject (w, o, new WriterContext ());
  193. }
  194. object DeserializeObject (BinaryReader r)
  195. {
  196. return ObjectFormatter.ReadObject (r, new ReaderContext ());
  197. }
  198. #region IFormatter
  199. object IFormatter.Deserialize (Stream serializationStream)
  200. {
  201. return Deserialize (serializationStream);
  202. }
  203. void IFormatter.Serialize (Stream serializationStream, object stateGraph)
  204. {
  205. Serialize (serializationStream, stateGraph);
  206. }
  207. SerializationBinder IFormatter.Binder {
  208. get { return null; }
  209. set { }
  210. }
  211. StreamingContext IFormatter.Context {
  212. get { return new StreamingContext (StreamingContextStates.All); }
  213. set { }
  214. }
  215. ISurrogateSelector IFormatter.SurrogateSelector {
  216. get { return null; }
  217. set { }
  218. }
  219. #endregion
  220. #region Object Readers/Writers
  221. sealed class WriterContext
  222. {
  223. Hashtable cache;
  224. short nextKey = 0;
  225. short key = 0;
  226. public short Key {
  227. get { return key; }
  228. }
  229. public bool RegisterCache (object o)
  230. {
  231. if (nextKey == short.MaxValue)
  232. return false;
  233. if (cache == null) {
  234. cache = new Hashtable ();
  235. cache.Add (o, key = nextKey++);
  236. return false;
  237. }
  238. object posKey = cache [o];
  239. if (posKey == null) {
  240. cache.Add (o, key = nextKey++);
  241. return false;
  242. }
  243. key = (short) posKey;
  244. return true;
  245. }
  246. }
  247. sealed class ReaderContext
  248. {
  249. ArrayList cache;
  250. public void CacheItem (object o)
  251. {
  252. if (cache == null)
  253. cache = new ArrayList ();
  254. cache.Add (o);
  255. }
  256. public object GetCache (short key)
  257. {
  258. return cache [key];
  259. }
  260. }
  261. abstract class ObjectFormatter
  262. {
  263. static readonly Hashtable writeMap = new Hashtable ();
  264. static ObjectFormatter [] readMap = new ObjectFormatter [256];
  265. static BinaryObjectFormatter binaryObjectFormatter;
  266. static TypeFormatter typeFormatter;
  267. static EnumFormatter enumFormatter;
  268. static SingleRankArrayFormatter singleRankArrayFormatter;
  269. static TypeConverterFormatter typeConverterFormatter;
  270. static ObjectFormatter ()
  271. {
  272. new StringFormatter ().Register ();
  273. new Int64Formatter ().Register ();
  274. new Int32Formatter ().Register ();
  275. new Int16Formatter ().Register ();
  276. new ByteFormatter ().Register ();
  277. new BooleanFormatter ().Register ();
  278. new CharFormatter ().Register ();
  279. new DateTimeFormatter ().Register ();
  280. new PairFormatter ().Register ();
  281. new TripletFormatter ().Register ();
  282. new ArrayListFormatter ().Register ();
  283. new HashtableFormatter ().Register ();
  284. new ObjectArrayFormatter ().Register ();
  285. new UnitFormatter ().Register ();
  286. new FontUnitFormatter ().Register ();
  287. new IndexedStringFormatter ().Register ();
  288. new ColorFormatter ().Register ();
  289. enumFormatter = new EnumFormatter ();
  290. enumFormatter.Register ();
  291. typeFormatter = new TypeFormatter ();
  292. typeFormatter.Register ();
  293. singleRankArrayFormatter = new SingleRankArrayFormatter ();
  294. singleRankArrayFormatter.Register ();
  295. typeConverterFormatter = new TypeConverterFormatter ();
  296. typeConverterFormatter.Register ();
  297. binaryObjectFormatter = new BinaryObjectFormatter ();
  298. binaryObjectFormatter.Register ();
  299. }
  300. // 0 == null
  301. static byte nextId = 1;
  302. public ObjectFormatter ()
  303. {
  304. PrimaryId = nextId ++;
  305. if (NumberOfIds == 1)
  306. return;
  307. SecondaryId = nextId ++;
  308. if (NumberOfIds == 2)
  309. return;
  310. TertiaryId = nextId ++;
  311. if (NumberOfIds == 3)
  312. return;
  313. throw new Exception ();
  314. }
  315. protected readonly byte PrimaryId, SecondaryId = 255, TertiaryId = 255;
  316. protected abstract void Write (BinaryWriter w, object o, WriterContext ctx);
  317. protected abstract object Read (byte token, BinaryReader r, ReaderContext ctx);
  318. protected abstract Type Type { get; }
  319. protected virtual int NumberOfIds { get { return 1; } }
  320. public virtual void Register ()
  321. {
  322. writeMap [Type] = this;
  323. readMap [PrimaryId] = this;
  324. if (SecondaryId != 255) {
  325. readMap [SecondaryId] = this;
  326. if (TertiaryId != 255)
  327. readMap [TertiaryId] = this;
  328. }
  329. }
  330. public static void WriteObject (BinaryWriter w, object o, WriterContext ctx)
  331. {
  332. #if TRACE && !TARGET_J2EE
  333. if (o != null) {
  334. Trace.WriteLine (String.Format ("Writing {0} (type: {1})", o, o.GetType ()));
  335. Trace.Indent ();
  336. } else {
  337. Trace.WriteLine ("Writing null");
  338. }
  339. long pos = w.BaseStream.Position;
  340. #endif
  341. if (o == null) {
  342. w.Write ((byte) 0);
  343. return;
  344. }
  345. Type t = o.GetType ();
  346. #if TRACE
  347. Trace.WriteLine (String.Format ("Looking up formatter for type {0}", t));
  348. #endif
  349. ObjectFormatter fmt = writeMap [t] as ObjectFormatter;
  350. #if TRACE
  351. Trace.WriteLine (String.Format ("Formatter from writeMap: '{0}'", fmt));
  352. #endif
  353. if (fmt == null) {
  354. // Handle abstract types here
  355. if (o is Type)
  356. fmt = typeFormatter;
  357. else if (t.IsEnum)
  358. fmt = enumFormatter;
  359. else if (t.IsArray && ((Array) o).Rank == 1)
  360. fmt = singleRankArrayFormatter;
  361. else {
  362. TypeConverter converter;
  363. converter = TypeDescriptor.GetConverter (o);
  364. #if TRACE
  365. Trace.WriteLine (String.Format ("Type converter: '{0}' (to string: {1}; from {2}: {3})",
  366. converter,
  367. converter != null ? converter.CanConvertTo (typeof (string)) : false,
  368. t,
  369. converter != null ? converter.CanConvertFrom (t) : false));
  370. #endif
  371. // Do not use the converter if it's an instance of
  372. // TypeConverter itself - it reports it is able to
  373. // convert to string, but it's only a conversion
  374. // consisting of a call to ToString() with no
  375. // reverse conversion supported. This leads to
  376. // problems when deserializing the object.
  377. if (converter == null || converter.GetType () == typeof (TypeConverter) ||
  378. !converter.CanConvertTo (typeof (string)) || !converter.CanConvertFrom (typeof (string)))
  379. fmt = binaryObjectFormatter;
  380. else {
  381. typeConverterFormatter.Converter = converter;
  382. fmt = typeConverterFormatter;
  383. }
  384. }
  385. }
  386. #if TRACE
  387. Trace.WriteLine (String.Format ("Writing with formatter '{0}'", fmt.GetType ()));
  388. #endif
  389. fmt.Write (w, o, ctx);
  390. #if TRACE && !TARGET_J2EE
  391. Trace.Unindent ();
  392. Trace.WriteLine (String.Format ("Wrote {0} (type: {1}) {2} bytes", o, o.GetType (), w.BaseStream.Position - pos));
  393. #endif
  394. }
  395. public static object ReadObject (BinaryReader r, ReaderContext ctx)
  396. {
  397. byte sig = r.ReadByte ();
  398. if (sig == 0)
  399. return null;
  400. return readMap [sig].Read (sig, r, ctx);
  401. }
  402. protected void Write7BitEncodedInt (BinaryWriter w, int value)
  403. {
  404. do {
  405. int high = (value >> 7) & 0x01ffffff;
  406. byte b = (byte)(value & 0x7f);
  407. if (high != 0)
  408. b = (byte)(b | 0x80);
  409. w.Write(b);
  410. value = high;
  411. } while(value != 0);
  412. }
  413. protected int Read7BitEncodedInt (BinaryReader r)
  414. {
  415. int ret = 0;
  416. int shift = 0;
  417. byte b;
  418. do {
  419. b = r.ReadByte();
  420. ret = ret | ((b & 0x7f) << shift);
  421. shift += 7;
  422. } while ((b & 0x80) == 0x80);
  423. return ret;
  424. }
  425. }
  426. #region Primitive Formatters
  427. class StringFormatter : ObjectFormatter
  428. {
  429. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  430. {
  431. if (ctx.RegisterCache (o)) {
  432. w.Write (SecondaryId);
  433. w.Write (ctx.Key);
  434. } else {
  435. w.Write (PrimaryId);
  436. w.Write ((string)o);
  437. }
  438. }
  439. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  440. {
  441. if (token == PrimaryId) {
  442. string s = r.ReadString ();
  443. ctx.CacheItem (s);
  444. return s;
  445. } else {
  446. return ctx.GetCache (r.ReadInt16 ());
  447. }
  448. }
  449. protected override Type Type {
  450. get { return typeof (string); }
  451. }
  452. protected override int NumberOfIds {
  453. get { return 2; }
  454. }
  455. }
  456. class IndexedStringFormatter : StringFormatter
  457. {
  458. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  459. {
  460. IndexedString s = o as IndexedString;
  461. if (s == null)
  462. throw new InvalidOperationException ("object is not of the IndexedString type");
  463. base.Write (w, s.Value, ctx);
  464. }
  465. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  466. {
  467. string s = base.Read (token, r, ctx) as string;
  468. if (String.IsNullOrEmpty (s))
  469. throw new InvalidOperationException ("string must not be null or empty.");
  470. return new IndexedString (s);
  471. }
  472. protected override Type Type {
  473. get { return typeof (IndexedString); }
  474. }
  475. protected override int NumberOfIds {
  476. get { return 2; }
  477. }
  478. }
  479. class Int64Formatter : ObjectFormatter
  480. {
  481. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  482. {
  483. w.Write (PrimaryId);
  484. w.Write ((long)o);
  485. }
  486. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  487. {
  488. return r.ReadInt64 ();
  489. }
  490. protected override Type Type {
  491. get { return typeof (long); }
  492. }
  493. }
  494. class Int32Formatter : ObjectFormatter
  495. {
  496. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  497. {
  498. int i = (int) o;
  499. if ((int)(byte) i == i) {
  500. w.Write (SecondaryId);
  501. w.Write ((byte) i);
  502. } else {
  503. w.Write (PrimaryId);
  504. w.Write (i);
  505. }
  506. }
  507. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  508. {
  509. if (token == PrimaryId)
  510. return r.ReadInt32 ();
  511. else
  512. return (int) r.ReadByte ();
  513. }
  514. protected override Type Type {
  515. get { return typeof (int); }
  516. }
  517. protected override int NumberOfIds {
  518. get { return 2; }
  519. }
  520. }
  521. class Int16Formatter : ObjectFormatter
  522. {
  523. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  524. {
  525. w.Write (PrimaryId);
  526. w.Write ((short)o);
  527. }
  528. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  529. {
  530. return r.ReadInt16 ();
  531. }
  532. protected override Type Type {
  533. get { return typeof (short); }
  534. }
  535. }
  536. class ByteFormatter : ObjectFormatter
  537. {
  538. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  539. {
  540. w.Write (PrimaryId);
  541. w.Write ((byte)o);
  542. }
  543. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  544. {
  545. return r.ReadByte ();
  546. }
  547. protected override Type Type {
  548. get { return typeof (byte); }
  549. }
  550. }
  551. class BooleanFormatter : ObjectFormatter
  552. {
  553. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  554. {
  555. if ((bool)o == true)
  556. w.Write (PrimaryId);
  557. else
  558. w.Write (SecondaryId);
  559. }
  560. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  561. {
  562. return token == PrimaryId;
  563. }
  564. protected override Type Type {
  565. get { return typeof (bool); }
  566. }
  567. protected override int NumberOfIds {
  568. get { return 2; }
  569. }
  570. }
  571. class CharFormatter : ObjectFormatter
  572. {
  573. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  574. {
  575. w.Write (PrimaryId);
  576. w.Write ((char) o);
  577. }
  578. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  579. {
  580. return r.ReadChar ();
  581. }
  582. protected override Type Type {
  583. get { return typeof (char); }
  584. }
  585. }
  586. class DateTimeFormatter : ObjectFormatter
  587. {
  588. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  589. {
  590. w.Write (PrimaryId);
  591. w.Write (((DateTime) o).Ticks);
  592. }
  593. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  594. {
  595. return new DateTime (r.ReadInt64 ());
  596. }
  597. protected override Type Type {
  598. get { return typeof (DateTime); }
  599. }
  600. }
  601. class PairFormatter : ObjectFormatter
  602. {
  603. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  604. {
  605. Pair p = (Pair) o;
  606. w.Write (PrimaryId);
  607. WriteObject (w, p.First, ctx);
  608. WriteObject (w, p.Second, ctx);
  609. }
  610. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  611. {
  612. Pair p = new Pair ();
  613. p.First = ReadObject (r, ctx);
  614. p.Second = ReadObject (r, ctx);
  615. return p;
  616. }
  617. protected override Type Type {
  618. get { return typeof (Pair); }
  619. }
  620. }
  621. class TripletFormatter : ObjectFormatter
  622. {
  623. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  624. {
  625. Triplet t = (Triplet) o;
  626. w.Write (PrimaryId);
  627. WriteObject (w, t.First, ctx);
  628. WriteObject (w, t.Second, ctx);
  629. WriteObject (w, t.Third, ctx);
  630. }
  631. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  632. {
  633. Triplet t = new Triplet ();
  634. t.First = ReadObject (r, ctx);
  635. t.Second = ReadObject (r, ctx);
  636. t.Third = ReadObject (r, ctx);
  637. return t;
  638. }
  639. protected override Type Type {
  640. get { return typeof (Triplet); }
  641. }
  642. }
  643. class ArrayListFormatter : ObjectFormatter
  644. {
  645. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  646. {
  647. ArrayList l = (ArrayList) o;
  648. w.Write (PrimaryId);
  649. Write7BitEncodedInt (w, l.Count);
  650. for (int i = 0; i < l.Count; i++)
  651. WriteObject (w, l [i], ctx);
  652. }
  653. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  654. {
  655. int len = Read7BitEncodedInt (r);
  656. ArrayList l = new ArrayList (len);
  657. for (int i = 0; i < len; i++)
  658. l.Add (ReadObject (r, ctx));
  659. return l;
  660. }
  661. protected override Type Type {
  662. get { return typeof (ArrayList); }
  663. }
  664. }
  665. class HashtableFormatter : ObjectFormatter
  666. {
  667. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  668. {
  669. Hashtable ht = (Hashtable) o;
  670. w.Write (PrimaryId);
  671. Write7BitEncodedInt (w, ht.Count);
  672. foreach (DictionaryEntry de in ht) {
  673. WriteObject (w, de.Key, ctx);
  674. WriteObject (w, de.Value, ctx);
  675. }
  676. }
  677. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  678. {
  679. int len = Read7BitEncodedInt (r);
  680. Hashtable ht = new Hashtable (len);
  681. for (int i = 0; i < len; i++) {
  682. object key = ReadObject (r, ctx);
  683. object val = ReadObject (r, ctx);
  684. ht.Add (key, val);
  685. }
  686. return ht;
  687. }
  688. protected override Type Type {
  689. get { return typeof (Hashtable); }
  690. }
  691. }
  692. class ObjectArrayFormatter : ObjectFormatter
  693. {
  694. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  695. {
  696. object [] val = (object []) o;
  697. w.Write (PrimaryId);
  698. Write7BitEncodedInt (w, val.Length);
  699. for (int i = 0; i < val.Length; i++)
  700. WriteObject (w, val [i], ctx);
  701. }
  702. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  703. {
  704. int len = Read7BitEncodedInt (r);
  705. object [] ret = new object [len];
  706. for (int i = 0; i < len; i++)
  707. ret [i] = ReadObject (r, ctx);
  708. return ret;
  709. }
  710. protected override Type Type {
  711. get { return typeof (object []); }
  712. }
  713. }
  714. #endregion
  715. #region System.Web Optimizations
  716. class ColorFormatter : ObjectFormatter
  717. {
  718. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  719. {
  720. Color c = (Color) o;
  721. if (c.IsEmpty || c.IsKnownColor) {
  722. w.Write (SecondaryId);
  723. if (c.IsEmpty)
  724. w.Write (-1); //isempty marker
  725. else
  726. w.Write ((int) c.ToKnownColor ());
  727. } else {
  728. w.Write (PrimaryId);
  729. w.Write (c.ToArgb ());
  730. }
  731. }
  732. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  733. {
  734. int value = r.ReadInt32 ();
  735. if (token == PrimaryId)
  736. return Color.FromArgb (value);
  737. else {
  738. if (value == -1) //isempty marker
  739. return Color.Empty;
  740. return Color.FromKnownColor ((KnownColor)value);
  741. }
  742. }
  743. protected override Type Type {
  744. get { return typeof (Color); }
  745. }
  746. protected override int NumberOfIds {
  747. get { return 2; }
  748. }
  749. }
  750. #endregion
  751. #region Special Formatters
  752. class EnumFormatter : ObjectFormatter
  753. {
  754. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  755. {
  756. object value = Convert.ChangeType (o, ((Enum) o).GetTypeCode ());
  757. w.Write (PrimaryId);
  758. WriteObject (w, o.GetType (), ctx);
  759. WriteObject (w, value, ctx);
  760. }
  761. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  762. {
  763. Type t = (Type) ReadObject (r, ctx);
  764. object value = ReadObject (r, ctx);
  765. return Enum.ToObject (t, value);
  766. }
  767. protected override Type Type {
  768. get { return typeof (Enum); }
  769. }
  770. }
  771. class TypeFormatter : ObjectFormatter
  772. {
  773. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  774. {
  775. if (ctx.RegisterCache (o)) {
  776. w.Write (SecondaryId);
  777. w.Write (ctx.Key);
  778. } else {
  779. w.Write (PrimaryId);
  780. w.Write (((Type) o).FullName);
  781. // We should cache the name of the assembly
  782. w.Write (((Type) o).Assembly.FullName);
  783. }
  784. }
  785. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  786. {
  787. if (token == PrimaryId) {
  788. string type = r.ReadString ();
  789. string assembly = r.ReadString ();
  790. Type t = Assembly.Load (assembly).GetType (type);
  791. ctx.CacheItem (t);
  792. return t;
  793. } else {
  794. return ctx.GetCache (r.ReadInt16 ());
  795. }
  796. }
  797. protected override Type Type {
  798. get { return typeof (Type); }
  799. }
  800. protected override int NumberOfIds {
  801. get { return 2; }
  802. }
  803. }
  804. class SingleRankArrayFormatter : ObjectFormatter
  805. {
  806. readonly BinaryFormatter _binaryFormatter = new BinaryFormatter ();
  807. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  808. {
  809. Array val = (Array) o;
  810. if (val.GetType ().GetElementType ().IsPrimitive) {
  811. w.Write (SecondaryId);
  812. _binaryFormatter.Serialize (w.BaseStream, o);
  813. return;
  814. }
  815. w.Write (PrimaryId);
  816. WriteObject (w, val.GetType ().GetElementType (), ctx);
  817. Write7BitEncodedInt (w, val.Length);
  818. for (int i = 0; i < val.Length; i++)
  819. WriteObject (w, val.GetValue (i), ctx);
  820. }
  821. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  822. {
  823. if (token == SecondaryId)
  824. return _binaryFormatter.Deserialize (r.BaseStream);
  825. Type t = (Type) ReadObject (r, ctx);
  826. int len = Read7BitEncodedInt (r);
  827. Array val = Array.CreateInstance (t, len);
  828. for (int i = 0; i < len; i++)
  829. val.SetValue (ReadObject (r, ctx), i);
  830. return val;
  831. }
  832. protected override Type Type {
  833. get { return typeof (Array); }
  834. }
  835. protected override int NumberOfIds {
  836. get { return 2; }
  837. }
  838. }
  839. class FontUnitFormatter : StringFormatter
  840. {
  841. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  842. {
  843. base.Write (w, o.ToString (), ctx);
  844. }
  845. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  846. {
  847. return FontUnit.Parse ((string) base.Read (token, r, ctx));
  848. }
  849. protected override Type Type {
  850. get { return typeof (FontUnit); }
  851. }
  852. }
  853. class UnitFormatter : StringFormatter
  854. {
  855. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  856. {
  857. base.Write (w, o.ToString (), ctx);
  858. }
  859. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  860. {
  861. return Unit.Parse ((string) base.Read (token, r, ctx));
  862. }
  863. protected override Type Type {
  864. get { return typeof (Unit); }
  865. }
  866. }
  867. class TypeConverterFormatter : StringFormatter
  868. {
  869. TypeConverter converter;
  870. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  871. {
  872. w.Write (PrimaryId);
  873. ObjectFormatter.WriteObject (w, o.GetType (), ctx);
  874. string v = (string) converter.ConvertTo (null, Helpers.InvariantCulture,
  875. o, typeof (string));
  876. base.Write (w, v, ctx);
  877. }
  878. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  879. {
  880. Type t = (Type) ObjectFormatter.ReadObject (r, ctx);
  881. converter = TypeDescriptor.GetConverter (t);
  882. token = r.ReadByte ();
  883. string v = (string) base.Read (token, r, ctx);
  884. return converter.ConvertFrom (null, Helpers.InvariantCulture, v);
  885. }
  886. protected override Type Type {
  887. get { return typeof (TypeConverter); }
  888. }
  889. public TypeConverter Converter {
  890. set { converter = value; }
  891. }
  892. }
  893. class BinaryObjectFormatter : ObjectFormatter
  894. {
  895. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  896. {
  897. w.Write (PrimaryId);
  898. MemoryStream ms = new MemoryStream (128);
  899. new BinaryFormatter ().Serialize (ms, o);
  900. byte [] buf = ms.GetBuffer ();
  901. Write7BitEncodedInt (w, buf.Length);
  902. w.Write (buf, 0, buf.Length);
  903. }
  904. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  905. {
  906. int len = Read7BitEncodedInt (r);
  907. byte [] buf = r.ReadBytes (len);
  908. if (buf.Length != len)
  909. throw new Exception ();
  910. return new BinaryFormatter ().Deserialize (new MemoryStream (buf));
  911. }
  912. protected override Type Type {
  913. get { return typeof (object); }
  914. }
  915. }
  916. #endregion
  917. #endregion
  918. }
  919. }