Posted in ColdFusion | Posted on 01-27-2010 | 2,661 views
While working on a ColdFusion Builder extension (no, not that one) I ran into a bug that caused the response dialog to constantly return an 'invalid XML' error. An Adobe engineer discovered that the issue was with the cfdump tag I had in the extension code, but didn't explain why that was the cause. I did a quick test and saw what the problem was.
First, consider the following simple template:
2
3done
As you can see, I've got a cfdump that is directed to the file system. This is a handy trick when you are working with CFM files that are Ajax bound, or in the case of ColdFusion Builder, happen between the IDE and the server. When you view this in the browser, you should see -- and done, right? (With some whitespace of course.) However, this is what you get:
2
3
4 table.cfdump_wddx,
5 table.cfdump_xml,
6 table.cfdump_struct,
7 table.cfdump_varundefined,
8 table.cfdump_array,
9 table.cfdump_query,
10 table.cfdump_cfc,
11 table.cfdump_object,
12 table.cfdump_binary,
13 table.cfdump_udf,
14 table.cfdump_udfbody,
15 table.cfdump_udfarguments {
16 font-size: xx-small;
17 font-family: verdana, arial, helvetica, sans-serif;
18 cell-spacing: 2px;
19 }
20
21 table.cfdump_wddx th,
22 table.cfdump_xml th,
23 table.cfdump_struct th,
24 table.cfdump_varundefined th,
25 table.cfdump_array th,
26 table.cfdump_query th,
27 table.cfdump_cfc th,
28 table.cfdump_object th,
29 table.cfdump_binary th,
30 table.cfdump_udf th,
31 table.cfdump_udfbody th,
32 table.cfdump_udfarguments th {
33 text-align: left;
34 color: white;
35 padding: 5px;
36 }
37
38 table.cfdump_wddx td,
39 table.cfdump_xml td,
40 table.cfdump_struct td,
41 table.cfdump_varundefined td,
42 table.cfdump_array td,
43 table.cfdump_query td,
44 table.cfdump_cfc td,
45 table.cfdump_object td,
46 table.cfdump_binary td,
47 table.cfdump_udf td,
48 table.cfdump_udfbody td,
49 table.cfdump_udfarguments td {
50 padding: 3px;
51 background-color: #ffffff;
52 vertical-align : top;
53 }
54
55 table.cfdump_wddx {
56 background-color: #000000;
57 }
58 table.cfdump_wddx th.wddx {
59 background-color: #444444;
60 }
61
62
63 table.cfdump_xml {
64 background-color: #888888;
65 }
66 table.cfdump_xml th.xml {
67 background-color: #aaaaaa;
68 }
69 table.cfdump_xml td.xml {
70 background-color: #dddddd;
71 }
72
73 table.cfdump_struct {
74 background-color: #0000cc ;
75 }
76 table.cfdump_struct th.struct {
77 background-color: #4444cc ;
78 }
79 table.cfdump_struct td.struct {
80 background-color: #ccddff;
81 }
82
83 table.cfdump_varundefined {
84 background-color: #CC3300 ;
85 }
86 table.cfdump_varundefined th.varundefined {
87 background-color: #CC3300 ;
88 }
89 table.cfdump_varundefined td.varundefined {
90 background-color: #ccddff;
91 }
92
93 table.cfdump_array {
94 background-color: #006600 ;
95 }
96 table.cfdump_array th.array {
97 background-color: #009900 ;
98 }
99 table.cfdump_array td.array {
100 background-color: #ccffcc ;
101 }
102
103 table.cfdump_query {
104 background-color: #884488 ;
105 }
106 table.cfdump_query th.query {
107 background-color: #aa66aa ;
108 }
109 table.cfdump_query td.query {
110 background-color: #ffddff ;
111 }
112
113
114 table.cfdump_cfc {
115 background-color: #ff0000;
116 }
117 table.cfdump_cfc th.cfc{
118 background-color: #ff4444;
119 }
120 table.cfdump_cfc td.cfc {
121 background-color: #ffcccc;
122 }
123
124
125 table.cfdump_object {
126 background-color : #ff0000;
127 }
128 table.cfdump_object th.object{
129 background-color: #ff4444;
130 }
131
132 table.cfdump_binary {
133 background-color : #eebb00;
134 }
135 table.cfdump_binary th.binary {
136 background-color: #ffcc44;
137 }
138 table.cfdump_binary td {
139 font-size: x-small;
140 }
141 table.cfdump_udf {
142 background-color: #aa4400;
143 }
144 table.cfdump_udf th.udf {
145 background-color: #cc6600;
146 }
147 table.cfdump_udfarguments {
148 background-color: #dddddd;
149 cell-spacing: 3;
150 }
151 table.cfdump_udfarguments th {
152 background-color: #eeeeee;
153 color: #000000;
154 }
155
156</style> <script language="javascript">
157
158
159// for queries we have more than one td element to collapse/expand
160 var expand = "open";
161
162 dump = function( obj ) {
163 var out = "" ;
164 if ( typeof obj == "object" ) {
165 for ( key in obj ) {
166 if ( typeof obj[key] != "function" ) out += key + ': ' + obj[key] + '<br>' ;
167 }
168 }
169 }
170
171
172 cfdump_toggleRow = function(source) {
173 //target is the right cell
174 if(document.all) target = source.parentElement.cells[1];
175 else {
176 var element = null;
177 var vLen = source.parentNode.childNodes.length;
178 for(var i=vLen-1;i>0;i--){
179 if(source.parentNode.childNodes[i].nodeType == 1){
180 element = source.parentNode.childNodes[i];
181 break;
182 }
183 }
184 if(element == null)
185 target = source.parentNode.lastChild;
186 else
187 target = element;
188 }
189 //target = source.parentNode.lastChild ;
190 cfdump_toggleTarget( target, cfdump_toggleSource( source ) ) ;
191 }
192
193 cfdump_toggleXmlDoc = function(source) {
194
195 var caption = source.innerHTML.split( ' [' ) ;
196
197 // toggle source (header)
198 if ( source.style.fontStyle == 'italic' ) {
199 // closed -> short
200 source.style.fontStyle = 'normal' ;
201 source.innerHTML = caption[0] + ' [short version]' ;
202 source.title = 'click to maximize' ;
203 switchLongToState = 'closed' ;
204 switchShortToState = 'open' ;
205 } else if ( source.innerHTML.indexOf('[short version]') != -1 ) {
206 // short -> full
207 source.innerHTML = caption[0] + ' [long version]' ;
208 source.title = 'click to collapse' ;
209 switchLongToState = 'open' ;
210 switchShortToState = 'closed' ;
211 } else {
212 // full -> closed
213 source.style.fontStyle = 'italic' ;
214 source.title = 'click to expand' ;
215 source.innerHTML = caption[0] ;
216 switchLongToState = 'closed' ;
217 switchShortToState = 'closed' ;
218 }
219
220 // Toggle the target (everething below the header row).
221 // First two rows are XMLComment and XMLRoot - they are part
222 // of the long dump, the rest are direct children - part of the
223 // short dump
224 if(document.all) {
225 var table = source.parentElement.parentElement ;
226 for ( var i = 1; i < table.rows.length; i++ ) {
227 target = table.rows[i] ;
228 if ( i < 3 ) cfdump_toggleTarget( target, switchLongToState ) ;
229 else cfdump_toggleTarget( target, switchShortToState ) ;
230 }
231 }
232 else {
233 var table = source.parentNode.parentNode ;
234 var row = 1;
235 for ( var i = 1; i < table.childNodes.length; i++ ) {
236 target = table.childNodes[i] ;
237 if( target.style ) {
238 if ( row < 3 ) {
239 cfdump_toggleTarget( target, switchLongToState ) ;
240 } else {
241 cfdump_toggleTarget( target, switchShortToState ) ;
242 }
243 row++;
244 }
245 }
246 }
247 }
248
249 cfdump_toggleTable = function(source) {
250
251 var switchToState = cfdump_toggleSource( source ) ;
252 if(document.all) {
253 var table = source.parentElement.parentElement ;
254 for ( var i = 1; i < table.rows.length; i++ ) {
255 target = table.rows[i] ;
256 cfdump_toggleTarget( target, switchToState ) ;
257 }
258 }
259 else {
260 var table = source.parentNode.parentNode ;
261 for ( var i = 1; i < table.childNodes.length; i++ ) {
262 target = table.childNodes[i] ;
263 if(target.style) {
264 cfdump_toggleTarget( target, switchToState ) ;
265 }
266 }
267 }
268 }
269
270 cfdump_toggleSource = function( source ) {
271 if ( source.style.fontStyle == 'italic' || source.style.fontStyle == null) {
272 source.style.fontStyle = 'normal' ;
273 source.title = 'click to collapse' ;
274 return 'open' ;
275 } else {
276 source.style.fontStyle = 'italic' ;
277 source.title = 'click to expand' ;
278 return 'closed' ;
279 }
280 }
281
282 cfdump_toggleTarget = function( target, switchToState ) {
283 if ( switchToState == 'open' ) target.style.display = '' ;
284 else target.style.display = 'none' ;
285 }
286
287 // collapse all td elements for queries
288 cfdump_toggleRow_qry = function(source) {
289 expand = (source.title == "click to collapse") ? "closed" : "open";
290 if(document.all) {
291 var nbrChildren = source.parentElement.cells.length;
292 if(nbrChildren > 1){
293 for(i=nbrChildren-1;i>0;i--){
294 target = source.parentElement.cells[i];
295 cfdump_toggleTarget( target,expand ) ;
296 cfdump_toggleSource_qry(source);
297 }
298 }
299 else {
300 //target is the right cell
301 target = source.parentElement.cells[1];
302 cfdump_toggleTarget( target, cfdump_toggleSource( source ) ) ;
303 }
304 }
305 else{
306 var target = null;
307 var vLen = source.parentNode.childNodes.length;
308 for(var i=vLen-1;i>1;i--){
309 if(source.parentNode.childNodes[i].nodeType == 1){
310 target = source.parentNode.childNodes[i];
311 cfdump_toggleTarget( target,expand );
312 cfdump_toggleSource_qry(source);
313 }
314 }
315 if(target == null){
316 //target is the last cell
317 target = source.parentNode.lastChild;
318 cfdump_toggleTarget( target, cfdump_toggleSource( source ) ) ;
319 }
320 }
321 }
322
323 cfdump_toggleSource_qry = function(source) {
324 if(expand == "closed"){
325 source.title = "click to expand";
326 source.style.fontStyle = "italic";
327 }
328 else{
329 source.title = "click to collapse";
330 source.style.fontStyle = "normal";
331 }
332 }
333
334</script> -
335
336done
As you can see, the CSS and JavaScript used by cfdump "leaked" out into the page result. It is also correctly stored in the HTML file so that part isn't broken. This only involves the HTML format of the dump. If you switch the format to text, then nothing is output (except one white space character).
If you want to make use of cfdump like this and are building anything that is supposed to return only XML or JSON, then you can wrap your dump in cfsilent tags. It doesn't impact the output to the file and it correctly hides the CSS/JavaScript.
I reported this as bug 81819. Please vote for it!


table.cfdump_udfarguments {
background-color: #dddddd;
cell-spacing: 3;
}
cell-spacing?