1: public override void Write(byte[] buffer, int offset, int count)
2: { 3: // If we are not capturing script blocks anymore, just redirect to response stream
4: if (!this.captureScripts)
5: { 6: this.responseStream.Write(buffer, offset, count);
7: return;
8: }
9:
10: /*
11: * Script and HTML can be in one of the following combinations in the specified buffer:
12: * .....<script ....>.....</script>.....
13: * <script ....>.....</script>.....
14: * <script ....>.....</script>
15: * <script ....>.....</script> .....
16: * ....<script ....>.....
17: * <script ....>.....
18: * .....</script>.....
19: * .....</script>
20: * <script>.....
21: * .... </script>
22: * ......
23: * Here, "...." means html content between and outside script tags
24: */
25:
26: char[] content = this.encoding.GetChars(buffer, offset, count);
27:
28: int scriptTagStart = 0;
29: int lastScriptTagEnd = 0;
30: bool scriptTagStarted = false;
31:
32: for (int pos = 0; pos < content.Length; pos++)
33: { 34: // See if tag start
35: char c = content[pos];
36: if (c == '<')
37: { 38: int tagStart = pos;
39: // Check if it's a tag ending
40: if (content[pos+1] == '/')
41: { 42: pos+=2; // go past the </
43:
44: // See if script tag is ending
45: if (isScriptTag(content, pos))
46: { 47: /// Script tag just ended. Get the whole script
48: /// and store in buffer
49: pos = pos + "script>".Length;
50: scriptBlocks.Append(content, scriptTagStart, pos - scriptTagStart);
51: scriptBlocks.Append(Environment.NewLine);
52: lastScriptTagEnd = pos;
53:
54: scriptTagStarted = false;
55: continue;
56: }
57: else if (isBodyTag(content, pos))
58: { 59: /// body tag has just end. Time for rendering all the script
60: /// blocks we have suppressed so far and stop capturing script blocks
61:
62: if (this.scriptBlocks.Length > 0)
63: { 64: // Render all pending html output till now
65: this.WriteOutput(content, lastScriptTagEnd, tagStart - lastScriptTagEnd);
66:
67: // Render the script blocks
68: byte[] scriptBytes = this.encoding.GetBytes(this.scriptBlocks.ToString());
69: this.responseStream.Write(scriptBytes, 0, scriptBytes.Length);
70:
71: // Stop capturing for script blocks
72: this.captureScripts = false;
73:
74: // Write from the body tag start to the end of the inut buffer and return
75: // from the function. We are done.
76: this.WriteOutput(content, tagStart, content.Length - tagStart);
77: return;
78: }
79: }
80: else
81: { 82: // some other tag's closing. safely skip one character as smallest
83: // html tag is one character e.g. <b>. just an optimization to save one loop
84: pos++;
85: }
86: }
87: else
88: { 89: if (isScriptTag(content, pos+1))
90: { 91: /// Script tag started. Record the position as we will
92: /// capture the whole script tag including its content
93: /// and store in an internal buffer.
94: scriptTagStart = pos;
95:
96: // Write html content since last script tag closing upto this script tag
97: this.WriteOutput(content, lastScriptTagEnd, scriptTagStart - lastScriptTagEnd);
98:
99: // Skip the tag start to save some loops
100: pos += "<script".Length;
101:
102: scriptTagStarted = true;
103: }
104: else
105: { 106: // some other tag started
107: // safely skip 2 character because the smallest tag is one character e.g. <b>
108: // just an optimization to eliminate one loop
109: pos++;
110: }
111: }
112: }
113: }
114:
115: // If a script tag is partially sent to buffer, then the remaining content
116: // is part of the last script block
117: if (scriptTagStarted)
118: { 119:
120: this.scriptBlocks.Append(content, scriptTagStart, content.Length - scriptTagStart);
121: }
122: else
123: { 124: /// Render the characters since the last script tag ending
125: this.WriteOutput(content, lastScriptTagEnd, content.Length - lastScriptTagEnd);
126: }
127: }