~ubuntu-branches/ubuntu/karmic/phppgadmin/karmic

« back to all changes in this revision

Viewing changes to selenium/xpath/dom.js

  • Committer: Bazaar Package Importer
  • Author(s): Peter Eisentraut
  • Date: 2008-12-31 19:32:22 UTC
  • mfrom: (1.3.1 upstream) (8.1.2 sid)
  • mto: (8.1.4 sid)
  • mto: This revision was merged to the branch mainline in revision 17.
  • Revision ID: james.westby@ubuntu.com-20081231193222-swr5hb1fie1enl4l
* New upstream release
  - Fixes local file inclusion vulnerability (CVE-2008-5587) (closes: #508026)
* Removed register_globals from debian/apache.conf (closes: #508026)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// Copyright 2005 Google Inc.
2
 
// All Rights Reserved
3
 
//
4
 
// An XML parse and a minimal DOM implementation that just supportes
5
 
// the subset of the W3C DOM that is used in the XSLT implementation.
6
 
//
7
 
// References: 
8
 
//
9
 
// [DOM] W3C DOM Level 3 Core Specification
10
 
//       <http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/>.
11
 
//
12
 
// 
13
 
// Author: Steffen Meschkat <mesch@google.com>
14
 
 
15
 
// NOTE: The split() method in IE omits empty result strings. This is
16
 
// utterly annoying. So we don't use it here.
17
 
 
18
 
// Resolve entities in XML text fragments. According to the DOM
19
 
// specification, the DOM is supposed to resolve entity references at
20
 
// the API level. I.e. no entity references are passed through the
21
 
// API. See "Entities and the DOM core", p.12, DOM 2 Core
22
 
// Spec. However, different browsers actually pass very different
23
 
// values at the API.
24
 
//
25
 
function xmlResolveEntities(s) {
26
 
 
27
 
  var parts = stringSplit(s, '&');
28
 
 
29
 
  var ret = parts[0];
30
 
  for (var i = 1; i < parts.length; ++i) {
31
 
    var rp = stringSplit(parts[i], ';');
32
 
    if (rp.length == 1) {
33
 
      // no entity reference: just a & but no ;
34
 
      ret += parts[i];
35
 
      continue;
36
 
    }
37
 
    
38
 
    var ch;
39
 
    switch (rp[0]) {
40
 
      case 'lt': 
41
 
        ch = '<';
42
 
        break;
43
 
      case 'gt': 
44
 
        ch = '>';
45
 
        break;
46
 
      case 'amp': 
47
 
        ch = '&';
48
 
        break;
49
 
      case 'quot': 
50
 
        ch = '"';
51
 
        break;
52
 
      case 'apos': 
53
 
        ch = '\'';
54
 
        break;
55
 
      case 'nbsp': 
56
 
        ch = String.fromCharCode(160);
57
 
        break;
58
 
      default:
59
 
        // Cool trick: let the DOM do the entity decoding. We assign
60
 
        // the entity text through non-W3C DOM properties and read it
61
 
        // through the W3C DOM. W3C DOM access is specified to resolve
62
 
        // entities. 
63
 
        var span = window.document.createElement('span');
64
 
        span.innerHTML = '&' + rp[0] + '; ';
65
 
        ch = span.childNodes[0].nodeValue.charAt(0);
66
 
    }
67
 
    ret += ch + rp[1];
68
 
  }
69
 
 
70
 
  return ret;
71
 
}
72
 
 
73
 
 
74
 
// Parses the given XML string with our custom, JavaScript XML parser. Written
75
 
// by Steffen Meschkat (mesch@google.com).
76
 
function xmlParse(xml) {
77
 
  Timer.start('xmlparse');
78
 
  var regex_empty = /\/$/;
79
 
 
80
 
  // See also <http://www.w3.org/TR/REC-xml/#sec-common-syn> for
81
 
  // allowed chars in a tag and attribute name. TODO(mesch): the
82
 
  // following is still not completely correct.
83
 
 
84
 
  var regex_tagname = /^([\w:-]*)/;
85
 
  var regex_attribute = /([\w:-]+)\s?=\s?('([^\']*)'|"([^\"]*)")/g;
86
 
 
87
 
  var xmldoc = new XDocument();
88
 
  var root = xmldoc;
89
 
 
90
 
  // For the record: in Safari, we would create native DOM nodes, but
91
 
  // in Opera that is not possible, because the DOM only allows HTML
92
 
  // element nodes to be created, so we have to do our own DOM nodes.
93
 
 
94
 
  // xmldoc = document.implementation.createDocument('','',null);
95
 
  // root = xmldoc; // .createDocumentFragment();
96
 
  // NOTE(mesch): using the DocumentFragment instead of the Document
97
 
  // crashes my Safari 1.2.4 (v125.12).
98
 
  var stack = [];
99
 
 
100
 
  var parent = root;
101
 
  stack.push(parent);
102
 
 
103
 
  var x = stringSplit(xml, '<');
104
 
  for (var i = 1; i < x.length; ++i) {
105
 
    var xx = stringSplit(x[i], '>');
106
 
    var tag = xx[0];
107
 
    var text = xmlResolveEntities(xx[1] || '');
108
 
 
109
 
    if (tag.charAt(0) == '/') {
110
 
      stack.pop();
111
 
      parent = stack[stack.length-1];
112
 
 
113
 
    } else if (tag.charAt(0) == '?') {
114
 
      // Ignore XML declaration and processing instructions
115
 
    } else if (tag.charAt(0) == '!') {
116
 
      // Ignore notation and comments
117
 
    } else {
118
 
      var empty = tag.match(regex_empty);
119
 
      var tagname = regex_tagname.exec(tag)[1];
120
 
      var node = xmldoc.createElement(tagname);
121
 
 
122
 
      var att;
123
 
      while (att = regex_attribute.exec(tag)) {
124
 
        var val = xmlResolveEntities(att[3] || att[4] || '');
125
 
        node.setAttribute(att[1], val);
126
 
      }
127
 
      
128
 
      if (empty) {
129
 
        parent.appendChild(node);
130
 
      } else {
131
 
        parent.appendChild(node);
132
 
        parent = node;
133
 
        stack.push(node);
134
 
      }
135
 
    }
136
 
 
137
 
    if (text && parent != root) {
138
 
      parent.appendChild(xmldoc.createTextNode(text));
139
 
    }
140
 
  }
141
 
 
142
 
  Timer.end('xmlparse');
143
 
  return root;
144
 
}
145
 
 
146
 
 
147
 
// Our W3C DOM Node implementation. Note we call it XNode because we
148
 
// can't define the identifier Node. We do this mostly for Opera,
149
 
// where we can't reuse the HTML DOM for parsing our own XML, and for
150
 
// Safari, where it is too expensive to have the template processor
151
 
// operate on native DOM nodes.
152
 
function XNode(type, name, value, owner) {
153
 
  this.attributes = [];
154
 
  this.childNodes = [];
155
 
 
156
 
  XNode.init.call(this, type, name, value, owner);
157
 
}
158
 
 
159
 
// Don't call as method, use apply() or call().
160
 
XNode.init = function(type, name, value, owner) {
161
 
  this.nodeType = type - 0;
162
 
  this.nodeName = '' + name;
163
 
  this.nodeValue = '' + value;
164
 
  this.ownerDocument = owner;
165
 
 
166
 
  this.firstChild = null;
167
 
  this.lastChild = null;
168
 
  this.nextSibling = null;
169
 
  this.previousSibling = null;
170
 
  this.parentNode = null;
171
 
}
172
 
 
173
 
XNode.unused_ = [];
174
 
 
175
 
XNode.recycle = function(node) {
176
 
  if (!node) {
177
 
    return;
178
 
  }
179
 
 
180
 
  if (node.constructor == XDocument) {
181
 
    XNode.recycle(node.documentElement);
182
 
    return;
183
 
  }
184
 
 
185
 
  if (node.constructor != this) {
186
 
    return;
187
 
  }
188
 
 
189
 
  XNode.unused_.push(node);
190
 
  for (var a = 0; a < node.attributes.length; ++a) {
191
 
    XNode.recycle(node.attributes[a]);
192
 
  }
193
 
  for (var c = 0; c < node.childNodes.length; ++c) {
194
 
    XNode.recycle(node.childNodes[c]);
195
 
  }
196
 
  node.attributes.length = 0;
197
 
  node.childNodes.length = 0;
198
 
  XNode.init.call(node, 0, '', '', null);
199
 
}
200
 
 
201
 
XNode.create = function(type, name, value, owner) {
202
 
  if (XNode.unused_.length > 0) {
203
 
    var node = XNode.unused_.pop();
204
 
    XNode.init.call(node, type, name, value, owner);
205
 
    return node;
206
 
  } else {
207
 
    return new XNode(type, name, value, owner);
208
 
  }
209
 
}
210
 
 
211
 
XNode.prototype.appendChild = function(node) {
212
 
  // firstChild
213
 
  if (this.childNodes.length == 0) {
214
 
    this.firstChild = node;
215
 
  }
216
 
 
217
 
  // previousSibling
218
 
  node.previousSibling = this.lastChild;
219
 
 
220
 
  // nextSibling
221
 
  node.nextSibling = null;
222
 
  if (this.lastChild) {
223
 
    this.lastChild.nextSibling = node;
224
 
  }
225
 
 
226
 
  // parentNode
227
 
  node.parentNode = this;
228
 
 
229
 
  // lastChild
230
 
  this.lastChild = node;
231
 
 
232
 
  // childNodes
233
 
  this.childNodes.push(node);
234
 
}
235
 
 
236
 
 
237
 
XNode.prototype.replaceChild = function(newNode, oldNode) {
238
 
  if (oldNode == newNode) {
239
 
    return;
240
 
  }
241
 
 
242
 
  for (var i = 0; i < this.childNodes.length; ++i) {
243
 
    if (this.childNodes[i] == oldNode) {
244
 
      this.childNodes[i] = newNode;
245
 
      
246
 
      var p = oldNode.parentNode;
247
 
      oldNode.parentNode = null;
248
 
      newNode.parentNode = p;
249
 
      
250
 
      p = oldNode.previousSibling;
251
 
      oldNode.previousSibling = null;
252
 
      newNode.previousSibling = p;
253
 
      if (newNode.previousSibling) {
254
 
        newNode.previousSibling.nextSibling = newNode;
255
 
      }
256
 
      
257
 
      p = oldNode.nextSibling;
258
 
      oldNode.nextSibling = null;
259
 
      newNode.nextSibling = p;
260
 
      if (newNode.nextSibling) {
261
 
        newNode.nextSibling.previousSibling = newNode;
262
 
      }
263
 
 
264
 
      if (this.firstChild == oldNode) {
265
 
        this.firstChild = newNode;
266
 
      }
267
 
 
268
 
      if (this.lastChild == oldNode) {
269
 
        this.lastChild = newNode;
270
 
      }
271
 
 
272
 
      break;
273
 
    }
274
 
  }
275
 
}
276
 
 
277
 
XNode.prototype.insertBefore = function(newNode, oldNode) {
278
 
  if (oldNode == newNode) {
279
 
    return;
280
 
  }
281
 
 
282
 
  if (oldNode.parentNode != this) {
283
 
    return;
284
 
  }
285
 
 
286
 
  if (newNode.parentNode) {
287
 
    newNode.parentNode.removeChild(newNode);
288
 
  }
289
 
 
290
 
  var newChildren = [];
291
 
  for (var i = 0; i < this.childNodes.length; ++i) {
292
 
    var c = this.childNodes[i];
293
 
    if (c == oldNode) {
294
 
      newChildren.push(newNode);
295
 
 
296
 
      newNode.parentNode = this;
297
 
 
298
 
      newNode.previousSibling = oldNode.previousSibling;
299
 
      oldNode.previousSibling = newNode;
300
 
      if (newNode.previousSibling) {
301
 
        newNode.previousSibling.nextSibling = newNode;
302
 
      }
303
 
      
304
 
      newNode.nextSibling = oldNode;
305
 
 
306
 
      if (this.firstChild == oldNode) {
307
 
        this.firstChild = newNode;
308
 
      }
309
 
    }
310
 
    newChildren.push(c);
311
 
  }
312
 
  this.childNodes = newChildren;
313
 
}
314
 
 
315
 
XNode.prototype.removeChild = function(node) {
316
 
  var newChildren = [];
317
 
  for (var i = 0; i < this.childNodes.length; ++i) {
318
 
    var c = this.childNodes[i];
319
 
    if (c != node) {
320
 
      newChildren.push(c);
321
 
    } else {
322
 
      if (c.previousSibling) {
323
 
        c.previousSibling.nextSibling = c.nextSibling;
324
 
      }
325
 
      if (c.nextSibling) {
326
 
        c.nextSibling.previousSibling = c.previousSibling;
327
 
      }
328
 
      if (this.firstChild == c) {
329
 
        this.firstChild = c.nextSibling;
330
 
      }
331
 
      if (this.lastChild == c) {
332
 
        this.lastChild = c.previousSibling;
333
 
      }
334
 
    }
335
 
  }
336
 
  this.childNodes = newChildren;
337
 
}
338
 
 
339
 
 
340
 
XNode.prototype.hasAttributes = function() {
341
 
  return this.attributes.length > 0;
342
 
}
343
 
 
344
 
 
345
 
XNode.prototype.setAttribute = function(name, value) {
346
 
  for (var i = 0; i < this.attributes.length; ++i) {
347
 
    if (this.attributes[i].nodeName == name) {
348
 
      this.attributes[i].nodeValue = '' + value;
349
 
      return;
350
 
    }
351
 
  }
352
 
  this.attributes.push(new XNode(DOM_ATTRIBUTE_NODE, name, value));
353
 
}
354
 
 
355
 
 
356
 
XNode.prototype.getAttribute = function(name) {
357
 
  for (var i = 0; i < this.attributes.length; ++i) {
358
 
    if (this.attributes[i].nodeName == name) {
359
 
      return this.attributes[i].nodeValue;
360
 
    }
361
 
  }
362
 
  return null;
363
 
}
364
 
 
365
 
XNode.prototype.removeAttribute = function(name) {
366
 
  var a = [];
367
 
  for (var i = 0; i < this.attributes.length; ++i) {
368
 
    if (this.attributes[i].nodeName != name) {
369
 
      a.push(this.attributes[i]);
370
 
    }
371
 
  }
372
 
  this.attributes = a;
373
 
}
374
 
 
375
 
 
376
 
function XDocument() {
377
 
  XNode.call(this, DOM_DOCUMENT_NODE, '#document', null, this);
378
 
  this.documentElement = null;
379
 
}
380
 
 
381
 
XDocument.prototype = new XNode(DOM_DOCUMENT_NODE, '#document');
382
 
 
383
 
XDocument.prototype.clear = function() {
384
 
  XNode.recycle(this.documentElement);
385
 
  this.documentElement = null;
386
 
}
387
 
 
388
 
XDocument.prototype.appendChild = function(node) {
389
 
  XNode.prototype.appendChild.call(this, node);
390
 
  this.documentElement = this.childNodes[0];
391
 
}
392
 
 
393
 
XDocument.prototype.createElement = function(name) {
394
 
  return XNode.create(DOM_ELEMENT_NODE, name, null, this);
395
 
}
396
 
 
397
 
XDocument.prototype.createDocumentFragment = function() {
398
 
  return XNode.create(DOM_DOCUMENT_FRAGMENT_NODE, '#document-fragment',
399
 
                    null, this);
400
 
}
401
 
 
402
 
XDocument.prototype.createTextNode = function(value) {
403
 
  return XNode.create(DOM_TEXT_NODE, '#text', value, this);
404
 
}
405
 
 
406
 
XDocument.prototype.createAttribute = function(name) {
407
 
  return XNode.create(DOM_ATTRIBUTE_NODE, name, null, this);
408
 
}
409
 
 
410
 
XDocument.prototype.createComment = function(data) {
411
 
  return XNode.create(DOM_COMMENT_NODE, '#comment', data, this);
412
 
}
413
 
 
414
 
XNode.prototype.getElementsByTagName = function(name, list) {
415
 
  if (!list) {
416
 
    list = [];
417
 
  }
418
 
 
419
 
  if (this.nodeName == name) {
420
 
    list.push(this);
421
 
  }
422
 
 
423
 
  for (var i = 0; i < this.childNodes.length; ++i) {
424
 
    this.childNodes[i].getElementsByTagName(name, list);
425
 
  }
426
 
 
427
 
  return list;
428
 
}