ObjectStateFormatter.cs 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060
  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-2008 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.GetSection ("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. return new HMACSHA1 (algoKey);
  103. }
  104. static int ValidateInput (HashAlgorithm algo, byte [] data, int offset, int size)
  105. {
  106. if (algo == null)
  107. throw new HttpException ("Unable to validate data.");
  108. int hash_size = algo.HashSize / 8;
  109. if (size != 0 && size < hash_size)
  110. throw new HttpException ("Unable to validate data.");
  111. int data_length = size - hash_size;
  112. MemoryStream data_stream = new MemoryStream (data, offset, data_length, false, false);
  113. byte [] hash = algo.ComputeHash (data_stream);
  114. for (int i = 0; i < hash_size; i++) {
  115. if (hash [i] != data [data_length + i])
  116. throw new HttpException ("Unable to validate data.");
  117. }
  118. return data_length;
  119. }
  120. public object Deserialize (Stream inputStream)
  121. {
  122. if (inputStream == null)
  123. throw new ArgumentNullException ("inputStream");
  124. return DeserializeObject (new BinaryReader (inputStream));
  125. }
  126. public object Deserialize (string inputString)
  127. {
  128. if (inputString == null)
  129. throw new ArgumentNullException ("inputString");
  130. #if NET_2_0
  131. if (inputString.Length == 0)
  132. throw new ArgumentNullException ("inputString");
  133. #else
  134. if (inputString == "")
  135. return "";
  136. #endif
  137. byte [] buffer = Convert.FromBase64String (inputString);
  138. int length;
  139. if (buffer == null || (length = buffer.Length) == 0)
  140. throw new ArgumentNullException ("inputString");
  141. if (page != null && EnableMac)
  142. length = ValidateInput (GetAlgo (), buffer, 0, length);
  143. #if NET_2_0
  144. bool isEncrypted = ((int)buffer [--length] == 1)? true : false;
  145. #endif
  146. Stream ms = new MemoryStream (buffer, 0, length, false, false);
  147. #if NET_2_0
  148. if (isEncrypted)
  149. ms = new CryptoStream (ms, page.GetCryptoTransform (CryptoStreamMode.Read), CryptoStreamMode.Read);
  150. #endif
  151. return Deserialize (ms);
  152. }
  153. public string Serialize (object stateGraph)
  154. {
  155. if (stateGraph == null)
  156. return "";
  157. MemoryStream ms = new MemoryStream ();
  158. Stream output = ms;
  159. #if NET_2_0
  160. bool needEncryption = page == null ? false : page.NeedViewStateEncryption;
  161. if (needEncryption){
  162. output = new CryptoStream (output, page.GetCryptoTransform (CryptoStreamMode.Write), CryptoStreamMode.Write);
  163. }
  164. #endif
  165. Serialize (output, stateGraph);
  166. #if NET_2_0
  167. ms.WriteByte((byte)(needEncryption? 1 : 0));
  168. #endif
  169. #if TRACE
  170. ms.WriteTo (File.OpenWrite (Path.GetTempFileName ()));
  171. #endif
  172. if (EnableMac && ms.Length > 0) {
  173. HashAlgorithm algo = GetAlgo ();
  174. if (algo != null) {
  175. byte [] hash = algo.ComputeHash (ms.GetBuffer (), 0, (int) ms.Length);
  176. ms.Write (hash, 0, hash.Length);
  177. }
  178. }
  179. return Convert.ToBase64String (ms.GetBuffer (), 0, (int) ms.Length);
  180. }
  181. public void Serialize (Stream outputStream, object stateGraph)
  182. {
  183. if (outputStream == null)
  184. throw new ArgumentNullException ("outputStream");
  185. if (stateGraph == null)
  186. throw new ArgumentNullException ("stateGraph");
  187. SerializeValue (new BinaryWriter (outputStream), stateGraph);
  188. }
  189. void SerializeValue (BinaryWriter w, object o)
  190. {
  191. ObjectFormatter.WriteObject (w, o, new WriterContext ());
  192. }
  193. object DeserializeObject (BinaryReader r)
  194. {
  195. return ObjectFormatter.ReadObject (r, new ReaderContext ());
  196. }
  197. #region IFormatter
  198. object IFormatter.Deserialize (Stream serializationStream)
  199. {
  200. return Deserialize (serializationStream);
  201. }
  202. void IFormatter.Serialize (Stream serializationStream, object stateGraph)
  203. {
  204. Serialize (serializationStream, stateGraph);
  205. }
  206. SerializationBinder IFormatter.Binder {
  207. get { return null; }
  208. set { }
  209. }
  210. StreamingContext IFormatter.Context {
  211. get { return new StreamingContext (StreamingContextStates.All); }
  212. set { }
  213. }
  214. ISurrogateSelector IFormatter.SurrogateSelector {
  215. get { return null; }
  216. set { }
  217. }
  218. #endregion
  219. #region Object Readers/Writers
  220. class WriterContext
  221. {
  222. Hashtable cache;
  223. short nextKey = 0;
  224. short key = 0;
  225. public short Key {
  226. get { return key; }
  227. }
  228. public bool RegisterCache (object o)
  229. {
  230. if (nextKey == short.MaxValue)
  231. return false;
  232. if (cache == null) {
  233. cache = new Hashtable ();
  234. cache.Add (o, key = nextKey++);
  235. return false;
  236. }
  237. object posKey = cache [o];
  238. if (posKey == null) {
  239. cache.Add (o, key = nextKey++);
  240. return false;
  241. }
  242. key = (short) posKey;
  243. return true;
  244. }
  245. }
  246. class ReaderContext
  247. {
  248. ArrayList cache;
  249. public void CacheItem (object o)
  250. {
  251. if (cache == null)
  252. cache = new ArrayList ();
  253. cache.Add (o);
  254. }
  255. public object GetCache (short key)
  256. {
  257. return cache [key];
  258. }
  259. }
  260. abstract class ObjectFormatter
  261. {
  262. static readonly Hashtable writeMap = new Hashtable ();
  263. static ObjectFormatter [] readMap = new ObjectFormatter [256];
  264. static BinaryObjectFormatter binaryObjectFormatter;
  265. static TypeFormatter typeFormatter;
  266. static EnumFormatter enumFormatter;
  267. static SingleRankArrayFormatter singleRankArrayFormatter;
  268. static TypeConverterFormatter typeConverterFormatter;
  269. static ObjectFormatter ()
  270. {
  271. new StringFormatter ().Register ();
  272. new Int64Formatter ().Register ();
  273. new Int32Formatter ().Register ();
  274. new Int16Formatter ().Register ();
  275. new ByteFormatter ().Register ();
  276. new BooleanFormatter ().Register ();
  277. new CharFormatter ().Register ();
  278. new DateTimeFormatter ().Register ();
  279. new PairFormatter ().Register ();
  280. new TripletFormatter ().Register ();
  281. new ArrayListFormatter ().Register ();
  282. new HashtableFormatter ().Register ();
  283. new ObjectArrayFormatter ().Register ();
  284. new UnitFormatter ().Register ();
  285. new FontUnitFormatter ().Register ();
  286. new ColorFormatter ().Register ();
  287. enumFormatter = new EnumFormatter ();
  288. enumFormatter.Register ();
  289. typeFormatter = new TypeFormatter ();
  290. typeFormatter.Register ();
  291. singleRankArrayFormatter = new SingleRankArrayFormatter ();
  292. singleRankArrayFormatter.Register ();
  293. typeConverterFormatter = new TypeConverterFormatter ();
  294. typeConverterFormatter.Register ();
  295. binaryObjectFormatter = new BinaryObjectFormatter ();
  296. binaryObjectFormatter.Register ();
  297. }
  298. // 0 == null
  299. static byte nextId = 1;
  300. public ObjectFormatter ()
  301. {
  302. PrimaryId = nextId ++;
  303. if (NumberOfIds == 1)
  304. return;
  305. SecondaryId = nextId ++;
  306. if (NumberOfIds == 2)
  307. return;
  308. TertiaryId = nextId ++;
  309. if (NumberOfIds == 3)
  310. return;
  311. throw new Exception ();
  312. }
  313. protected readonly byte PrimaryId, SecondaryId = 255, TertiaryId = 255;
  314. protected abstract void Write (BinaryWriter w, object o, WriterContext ctx);
  315. protected abstract object Read (byte token, BinaryReader r, ReaderContext ctx);
  316. protected abstract Type Type { get; }
  317. protected virtual int NumberOfIds { get { return 1; } }
  318. public virtual void Register ()
  319. {
  320. writeMap [Type] = this;
  321. readMap [PrimaryId] = this;
  322. if (SecondaryId != 255) {
  323. readMap [SecondaryId] = this;
  324. if (TertiaryId != 255)
  325. readMap [TertiaryId] = this;
  326. }
  327. }
  328. public static void WriteObject (BinaryWriter w, object o, WriterContext ctx)
  329. {
  330. #if TRACE
  331. if (o != null) {
  332. Trace.WriteLine (String.Format ("Writing {0} (type: {1})", o, o.GetType ()));
  333. Trace.Indent ();
  334. } else {
  335. Trace.WriteLine ("Writing null");
  336. }
  337. long pos = w.BaseStream.Position;
  338. #endif
  339. if (o == null) {
  340. w.Write ((byte) 0);
  341. return;
  342. }
  343. Type t = o.GetType ();
  344. #if TRACE
  345. Trace.WriteLine (String.Format ("Looking up formatter for type {0}", t));
  346. #endif
  347. ObjectFormatter fmt = writeMap [t] as ObjectFormatter;
  348. #if TRACE
  349. Trace.WriteLine (String.Format ("Formatter from writeMap: '{0}'", fmt));
  350. #endif
  351. if (fmt == null) {
  352. // Handle abstract types here
  353. if (o is Type)
  354. fmt = typeFormatter;
  355. else if (t.IsEnum)
  356. fmt = enumFormatter;
  357. else if (t.IsArray && ((Array) o).Rank == 1)
  358. fmt = singleRankArrayFormatter;
  359. else {
  360. TypeConverter converter;
  361. converter = TypeDescriptor.GetConverter (o);
  362. #if TRACE
  363. Trace.WriteLine (String.Format ("Type converter: '{0}' (to string: {1}; from {2}: {3})",
  364. converter,
  365. converter != null ? converter.CanConvertTo (typeof (string)) : false,
  366. t,
  367. converter != null ? converter.CanConvertFrom (t) : false));
  368. #endif
  369. if (converter == null ||
  370. !converter.CanConvertTo (typeof (string)) ||
  371. !converter.CanConvertFrom (t)) {
  372. fmt = binaryObjectFormatter;
  373. } else {
  374. typeConverterFormatter.Converter = converter;
  375. fmt = typeConverterFormatter;
  376. }
  377. }
  378. }
  379. #if TRACE
  380. Trace.WriteLine (String.Format ("Writing with formatter '{0}'", fmt.GetType ()));
  381. #endif
  382. fmt.Write (w, o, ctx);
  383. #if TRACE
  384. Trace.Unindent ();
  385. Trace.WriteLine (String.Format ("Wrote {0} (type: {1}) {2} bytes", o, o.GetType (), w.BaseStream.Position - pos));
  386. #endif
  387. }
  388. public static object ReadObject (BinaryReader r, ReaderContext ctx)
  389. {
  390. byte sig = r.ReadByte ();
  391. if (sig == 0)
  392. return null;
  393. return readMap [sig].Read (sig, r, ctx);
  394. }
  395. protected void Write7BitEncodedInt (BinaryWriter w, int value)
  396. {
  397. do {
  398. int high = (value >> 7) & 0x01ffffff;
  399. byte b = (byte)(value & 0x7f);
  400. if (high != 0)
  401. b = (byte)(b | 0x80);
  402. w.Write(b);
  403. value = high;
  404. } while(value != 0);
  405. }
  406. protected int Read7BitEncodedInt (BinaryReader r)
  407. {
  408. int ret = 0;
  409. int shift = 0;
  410. byte b;
  411. do {
  412. b = r.ReadByte();
  413. ret = ret | ((b & 0x7f) << shift);
  414. shift += 7;
  415. } while ((b & 0x80) == 0x80);
  416. return ret;
  417. }
  418. }
  419. #region Primitive Formatters
  420. class StringFormatter : ObjectFormatter
  421. {
  422. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  423. {
  424. if (ctx.RegisterCache (o)) {
  425. w.Write (SecondaryId);
  426. w.Write (ctx.Key);
  427. } else {
  428. w.Write (PrimaryId);
  429. w.Write ((string)o);
  430. }
  431. }
  432. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  433. {
  434. if (token == PrimaryId) {
  435. string s = r.ReadString ();
  436. ctx.CacheItem (s);
  437. return s;
  438. } else {
  439. return ctx.GetCache (r.ReadInt16 ());
  440. }
  441. }
  442. protected override Type Type {
  443. get { return typeof (string); }
  444. }
  445. protected override int NumberOfIds {
  446. get { return 2; }
  447. }
  448. }
  449. class Int64Formatter : ObjectFormatter
  450. {
  451. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  452. {
  453. w.Write (PrimaryId);
  454. w.Write ((long)o);
  455. }
  456. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  457. {
  458. return r.ReadInt64 ();
  459. }
  460. protected override Type Type {
  461. get { return typeof (long); }
  462. }
  463. }
  464. class Int32Formatter : ObjectFormatter
  465. {
  466. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  467. {
  468. int i = (int) o;
  469. if ((int)(byte) i == i) {
  470. w.Write (SecondaryId);
  471. w.Write ((byte) i);
  472. } else {
  473. w.Write (PrimaryId);
  474. w.Write (i);
  475. }
  476. }
  477. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  478. {
  479. if (token == PrimaryId)
  480. return r.ReadInt32 ();
  481. else
  482. return (int) r.ReadByte ();
  483. }
  484. protected override Type Type {
  485. get { return typeof (int); }
  486. }
  487. protected override int NumberOfIds {
  488. get { return 2; }
  489. }
  490. }
  491. class Int16Formatter : ObjectFormatter
  492. {
  493. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  494. {
  495. w.Write (PrimaryId);
  496. w.Write ((short)o);
  497. }
  498. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  499. {
  500. return r.ReadInt16 ();
  501. }
  502. protected override Type Type {
  503. get { return typeof (short); }
  504. }
  505. }
  506. class ByteFormatter : ObjectFormatter
  507. {
  508. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  509. {
  510. w.Write (PrimaryId);
  511. w.Write ((byte)o);
  512. }
  513. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  514. {
  515. return r.ReadByte ();
  516. }
  517. protected override Type Type {
  518. get { return typeof (byte); }
  519. }
  520. }
  521. class BooleanFormatter : ObjectFormatter
  522. {
  523. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  524. {
  525. if ((bool)o == true)
  526. w.Write (PrimaryId);
  527. else
  528. w.Write (SecondaryId);
  529. }
  530. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  531. {
  532. return token == PrimaryId;
  533. }
  534. protected override Type Type {
  535. get { return typeof (bool); }
  536. }
  537. protected override int NumberOfIds {
  538. get { return 2; }
  539. }
  540. }
  541. class CharFormatter : ObjectFormatter
  542. {
  543. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  544. {
  545. w.Write (PrimaryId);
  546. w.Write ((char) o);
  547. }
  548. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  549. {
  550. return r.ReadChar ();
  551. }
  552. protected override Type Type {
  553. get { return typeof (char); }
  554. }
  555. }
  556. class DateTimeFormatter : ObjectFormatter
  557. {
  558. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  559. {
  560. w.Write (PrimaryId);
  561. w.Write (((DateTime) o).Ticks);
  562. }
  563. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  564. {
  565. return new DateTime (r.ReadInt64 ());
  566. }
  567. protected override Type Type {
  568. get { return typeof (DateTime); }
  569. }
  570. }
  571. class PairFormatter : ObjectFormatter
  572. {
  573. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  574. {
  575. Pair p = (Pair) o;
  576. w.Write (PrimaryId);
  577. WriteObject (w, p.First, ctx);
  578. WriteObject (w, p.Second, ctx);
  579. }
  580. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  581. {
  582. Pair p = new Pair ();
  583. p.First = ReadObject (r, ctx);
  584. p.Second = ReadObject (r, ctx);
  585. return p;
  586. }
  587. protected override Type Type {
  588. get { return typeof (Pair); }
  589. }
  590. }
  591. class TripletFormatter : ObjectFormatter
  592. {
  593. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  594. {
  595. Triplet t = (Triplet) o;
  596. w.Write (PrimaryId);
  597. WriteObject (w, t.First, ctx);
  598. WriteObject (w, t.Second, ctx);
  599. WriteObject (w, t.Third, ctx);
  600. }
  601. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  602. {
  603. Triplet t = new Triplet ();
  604. t.First = ReadObject (r, ctx);
  605. t.Second = ReadObject (r, ctx);
  606. t.Third = ReadObject (r, ctx);
  607. return t;
  608. }
  609. protected override Type Type {
  610. get { return typeof (Triplet); }
  611. }
  612. }
  613. class ArrayListFormatter : ObjectFormatter
  614. {
  615. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  616. {
  617. ArrayList l = (ArrayList) o;
  618. w.Write (PrimaryId);
  619. Write7BitEncodedInt (w, l.Count);
  620. for (int i = 0; i < l.Count; i++)
  621. WriteObject (w, l [i], ctx);
  622. }
  623. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  624. {
  625. int len = Read7BitEncodedInt (r);
  626. ArrayList l = new ArrayList (len);
  627. for (int i = 0; i < len; i++)
  628. l.Add (ReadObject (r, ctx));
  629. return l;
  630. }
  631. protected override Type Type {
  632. get { return typeof (ArrayList); }
  633. }
  634. }
  635. class HashtableFormatter : ObjectFormatter
  636. {
  637. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  638. {
  639. Hashtable ht = (Hashtable) o;
  640. w.Write (PrimaryId);
  641. Write7BitEncodedInt (w, ht.Count);
  642. foreach (DictionaryEntry de in ht) {
  643. WriteObject (w, de.Key, ctx);
  644. WriteObject (w, de.Value, ctx);
  645. }
  646. }
  647. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  648. {
  649. int len = Read7BitEncodedInt (r);
  650. Hashtable ht = new Hashtable (len);
  651. for (int i = 0; i < len; i++) {
  652. object key = ReadObject (r, ctx);
  653. object val = ReadObject (r, ctx);
  654. ht.Add (key, val);
  655. }
  656. return ht;
  657. }
  658. protected override Type Type {
  659. get { return typeof (Hashtable); }
  660. }
  661. }
  662. class ObjectArrayFormatter : ObjectFormatter
  663. {
  664. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  665. {
  666. object [] val = (object []) o;
  667. w.Write (PrimaryId);
  668. Write7BitEncodedInt (w, val.Length);
  669. for (int i = 0; i < val.Length; i++)
  670. WriteObject (w, val [i], ctx);
  671. }
  672. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  673. {
  674. int len = Read7BitEncodedInt (r);
  675. object [] ret = new object [len];
  676. for (int i = 0; i < len; i++)
  677. ret [i] = ReadObject (r, ctx);
  678. return ret;
  679. }
  680. protected override Type Type {
  681. get { return typeof (object []); }
  682. }
  683. }
  684. #endregion
  685. #region System.Web Optimizations
  686. class ColorFormatter : ObjectFormatter
  687. {
  688. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  689. {
  690. Color c = (Color) o;
  691. if (c.IsEmpty || c.IsKnownColor) {
  692. w.Write (SecondaryId);
  693. if (c.IsEmpty)
  694. w.Write (-1); //isempty marker
  695. else
  696. w.Write ((int) c.ToKnownColor ());
  697. } else {
  698. w.Write (PrimaryId);
  699. w.Write (c.ToArgb ());
  700. }
  701. }
  702. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  703. {
  704. int value = r.ReadInt32 ();
  705. if (token == PrimaryId)
  706. return Color.FromArgb (value);
  707. else {
  708. if (value == -1) //isempty marker
  709. return Color.Empty;
  710. return Color.FromKnownColor ((KnownColor)value);
  711. }
  712. }
  713. protected override Type Type {
  714. get { return typeof (Color); }
  715. }
  716. protected override int NumberOfIds {
  717. get { return 2; }
  718. }
  719. }
  720. #endregion
  721. #region Special Formatters
  722. class EnumFormatter : ObjectFormatter
  723. {
  724. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  725. {
  726. object value = Convert.ChangeType (o, ((Enum) o).GetTypeCode ());
  727. w.Write (PrimaryId);
  728. WriteObject (w, o.GetType (), ctx);
  729. WriteObject (w, value, ctx);
  730. }
  731. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  732. {
  733. Type t = (Type) ReadObject (r, ctx);
  734. object value = ReadObject (r, ctx);
  735. return Enum.ToObject (t, value);
  736. }
  737. protected override Type Type {
  738. get { return typeof (Enum); }
  739. }
  740. }
  741. class TypeFormatter : ObjectFormatter
  742. {
  743. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  744. {
  745. if (ctx.RegisterCache (o)) {
  746. w.Write (SecondaryId);
  747. w.Write (ctx.Key);
  748. } else {
  749. w.Write (PrimaryId);
  750. w.Write (((Type) o).FullName);
  751. // We should cache the name of the assembly
  752. w.Write (((Type) o).Assembly.FullName);
  753. }
  754. }
  755. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  756. {
  757. if (token == PrimaryId) {
  758. string type = r.ReadString ();
  759. string assembly = r.ReadString ();
  760. Type t = Assembly.Load (assembly).GetType (type);
  761. ctx.CacheItem (t);
  762. return t;
  763. } else {
  764. return ctx.GetCache (r.ReadInt16 ());
  765. }
  766. }
  767. protected override Type Type {
  768. get { return typeof (Type); }
  769. }
  770. protected override int NumberOfIds {
  771. get { return 2; }
  772. }
  773. }
  774. class SingleRankArrayFormatter : ObjectFormatter
  775. {
  776. readonly BinaryFormatter _binaryFormatter = new BinaryFormatter ();
  777. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  778. {
  779. Array val = (Array) o;
  780. if (val.GetType ().GetElementType ().IsPrimitive) {
  781. w.Write (SecondaryId);
  782. _binaryFormatter.Serialize (w.BaseStream, o);
  783. return;
  784. }
  785. w.Write (PrimaryId);
  786. WriteObject (w, val.GetType ().GetElementType (), ctx);
  787. Write7BitEncodedInt (w, val.Length);
  788. for (int i = 0; i < val.Length; i++)
  789. WriteObject (w, val.GetValue (i), ctx);
  790. }
  791. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  792. {
  793. if (token == SecondaryId)
  794. return _binaryFormatter.Deserialize (r.BaseStream);
  795. Type t = (Type) ReadObject (r, ctx);
  796. int len = Read7BitEncodedInt (r);
  797. Array val = Array.CreateInstance (t, len);
  798. for (int i = 0; i < len; i++)
  799. val.SetValue (ReadObject (r, ctx), i);
  800. return val;
  801. }
  802. protected override Type Type {
  803. get { return typeof (Array); }
  804. }
  805. protected override int NumberOfIds {
  806. get { return 2; }
  807. }
  808. }
  809. class FontUnitFormatter : StringFormatter
  810. {
  811. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  812. {
  813. base.Write (w, o.ToString (), ctx);
  814. }
  815. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  816. {
  817. return FontUnit.Parse ((string) base.Read (token, r, ctx));
  818. }
  819. protected override Type Type {
  820. get { return typeof (FontUnit); }
  821. }
  822. }
  823. class UnitFormatter : StringFormatter
  824. {
  825. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  826. {
  827. base.Write (w, o.ToString (), ctx);
  828. }
  829. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  830. {
  831. return Unit.Parse ((string) base.Read (token, r, ctx));
  832. }
  833. protected override Type Type {
  834. get { return typeof (Unit); }
  835. }
  836. }
  837. class TypeConverterFormatter : StringFormatter
  838. {
  839. TypeConverter converter;
  840. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  841. {
  842. w.Write (PrimaryId);
  843. ObjectFormatter.WriteObject (w, o.GetType (), ctx);
  844. string v = (string) converter.ConvertTo (null, CultureInfo.InvariantCulture,
  845. o, typeof (string));
  846. base.Write (w, v, ctx);
  847. }
  848. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  849. {
  850. Type t = (Type) ObjectFormatter.ReadObject (r, ctx);
  851. converter = TypeDescriptor.GetConverter (t);
  852. token = r.ReadByte ();
  853. string v = (string) base.Read (token, r, ctx);
  854. return converter.ConvertFrom (null, CultureInfo.InvariantCulture, v);
  855. }
  856. protected override Type Type {
  857. get { return typeof (TypeConverter); }
  858. }
  859. public TypeConverter Converter {
  860. set { converter = value; }
  861. }
  862. }
  863. class BinaryObjectFormatter : ObjectFormatter
  864. {
  865. protected override void Write (BinaryWriter w, object o, WriterContext ctx)
  866. {
  867. w.Write (PrimaryId);
  868. MemoryStream ms = new MemoryStream (128);
  869. new BinaryFormatter ().Serialize (ms, o);
  870. byte [] buf = ms.GetBuffer ();
  871. Write7BitEncodedInt (w, buf.Length);
  872. w.Write (buf, 0, buf.Length);
  873. }
  874. protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
  875. {
  876. int len = Read7BitEncodedInt (r);
  877. byte [] buf = r.ReadBytes (len);
  878. if (buf.Length != len)
  879. throw new Exception ();
  880. return new BinaryFormatter ().Deserialize (new MemoryStream (buf));
  881. }
  882. protected override Type Type {
  883. get { return typeof (object); }
  884. }
  885. }
  886. #endregion
  887. #endregion
  888. }
  889. }