ObjectStateFormatter.cs 25 KB

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