PageRenderTime 59ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/java/sample/authsub/web/javascript/gdata_condensed.js

http://gdata-java-client.googlecode.com/
JavaScript | 5235 lines | 3217 code | 726 blank | 1292 comment | 629 complexity | 8680b83de9fa03df2564f8ef06ae2ae5 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. /* Copyright (c) 2006 Google Inc.
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. /**
  16. * @fileoverview
  17. * This file contains some common helper functions
  18. */
  19. // Based on <http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/
  20. // core.html#ID-1950641247>
  21. var DOM_ELEMENT_NODE = 1;
  22. var DOM_ATTRIBUTE_NODE = 2;
  23. var DOM_TEXT_NODE = 3;
  24. var DOM_CDATA_SECTION_NODE = 4;
  25. var DOM_ENTITY_REFERENCE_NODE = 5;
  26. var DOM_ENTITY_NODE = 6;
  27. var DOM_PROCESSING_INSTRUCTION_NODE = 7;
  28. var DOM_COMMENT_NODE = 8;
  29. var DOM_DOCUMENT_NODE = 9;
  30. var DOM_DOCUMENT_TYPE_NODE = 10;
  31. var DOM_DOCUMENT_FRAGMENT_NODE = 11;
  32. var DOM_NOTATION_NODE = 12;
  33. //
  34. // regular expression for xsd date-time
  35. //
  36. var UTIL_PARSE_XMLDATE = /(\d{4})-(\d{2})-(\d{2})/;
  37. var UTIL_PARSE_XMLDATETIME =
  38. /(\d{4})-?(\d{2})-?(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.(\d+))(Z)?(([+-])(\d{2}):(\d{2}))?/;
  39. function UTIL_inherits(subClass, superClass) {
  40. subClass.prototype = new superClass();
  41. subClass.prototype.Base = superClass.prototype;
  42. subClass.prototype.constructor = superClass.constructor;
  43. }
  44. /**
  45. * helper to detect if a variable is persistable
  46. * @param toTest the value to test
  47. * @return true if peristable
  48. */
  49. function UTIL_isPersistable(toTest) {
  50. if (typeof(toTest) == 'string') {
  51. if (toTest !== null && toTest.length > 0 ) {
  52. return true;
  53. }
  54. }
  55. return false;
  56. }
  57. /**
  58. * helper to convert a date to RFC3339 string presentation
  59. * @param date {Date} the date to convert
  60. * @return {string} date formatted according to RFC3339
  61. */
  62. function UTIL_dateToRFC3339(dateToConvert) {
  63. var strReturn = null;
  64. strReturn = dateToConvert.getUTCFullYear() + "-" +
  65. UTIL_pad((dateToConvert.getUTCMonth()+1).toString(), 2, "0") + "-" +
  66. UTIL_pad((dateToConvert.getUTCDate()).toString(), 2, "0");
  67. if (dateToConvert.getTime() > 0) {
  68. strReturn += "T" +
  69. UTIL_pad(dateToConvert.getUTCHours().toString(), 2, "0") + ":" +
  70. UTIL_pad(dateToConvert.getUTCMinutes().toString(), 2, "0") + ":" +
  71. UTIL_pad(dateToConvert.getUTCSeconds().toString(), 2, "0");
  72. // convert to hours
  73. var timediff = dateToConvert.getTimezoneOffset();
  74. timediff /= 60;
  75. strReturn += timediff > 0 ? "+" : "-";
  76. strReturn += UTIL_pad(Math.abs(timediff).toFixed(0), 2, "0") + ":00";
  77. }
  78. return strReturn;
  79. }
  80. /**
  81. * helper to convert a string in RFC3339 presentation to a date
  82. * @param dateString the string date value to convert
  83. * @return the date
  84. */
  85. function UTIL_parseXmlDateTime(dateString) {
  86. var d = null;
  87. var dateParts = dateString.match(UTIL_PARSE_XMLDATETIME);
  88. if (dateParts == null) {
  89. //
  90. // if dateTime didn't parse, try date
  91. //
  92. return UTIL_parseXmlDate(dateString);
  93. } else {
  94. d = new Date();
  95. var year = parseInt(dateParts[1],10);
  96. var month = parseInt(dateParts[2],10);
  97. var day = parseInt(dateParts[3],10);
  98. var hour = parseInt(dateParts[4],10);
  99. var min = parseInt(dateParts[5],10);
  100. var sec = parseInt(dateParts[6],10);
  101. if ((dateParts[8] || dateParts[9]) && !(hour==0 && min==0 && sec==0)) {
  102. // utc mode
  103. d.setUTCFullYear(year);
  104. d.setUTCMonth(month-1);
  105. d.setUTCDate(day);
  106. d.setUTCHours(hour);
  107. d.setUTCMinutes(min);
  108. d.setUTCSeconds(sec);
  109. d.setUTCMilliseconds(0);
  110. if (dateParts[8] === 'Z') {
  111. // so the time is in UTC
  112. LOG_TRACE(dateParts[8], "UTIL_parseXmlDateTime", dateString);
  113. } else {
  114. // should be an offset now
  115. var timeOffset = 0;
  116. if (dateParts[10]) {
  117. timeOffset = Number(dateParts[11]) * 60;
  118. timeOffset += Number(dateParts[12]);
  119. timeOffset *= ((dateParts[10] === '-') ? 1 : -1);
  120. }
  121. timeOffset *= 60 * 1000;
  122. d = new Date(Number(d) + timeOffset);
  123. }
  124. //
  125. // BUGBUG - apply +/- bias from part 8
  126. //
  127. } else {
  128. d.setFullYear(year);
  129. d.setMonth(month-1);
  130. d.setDate(day);
  131. d.setHours(hour);
  132. d.setMinutes(min);
  133. d.setSeconds(sec);
  134. d.setMilliseconds(0);
  135. }
  136. }
  137. LOG_TRACE(dateString + "----" + d, "UTIL_parseXmlDateTime", dateString);
  138. return d;
  139. }
  140. /**
  141. * helper to convert a string in RFC3339 presentation to a date
  142. * @param dateString the string date value to convert, no timezone
  143. * @return the date
  144. */
  145. function UTIL_parseXmlDate(dateString) {
  146. var d;
  147. var dateParts = dateString.match(UTIL_PARSE_XMLDATE);
  148. if (dateParts != null) {
  149. d = new Date();
  150. d.setHours(0);
  151. d.setMinutes(0);
  152. d.setSeconds(0);
  153. d.setMilliseconds(0);
  154. var year = parseInt(dateParts[1],10);
  155. var month = parseInt(dateParts[2],10);
  156. var day = parseInt(dateParts[3],10);
  157. d.setFullYear(year);
  158. d.setMonth(month-1);
  159. d.setDate(day);
  160. }
  161. return d;
  162. }
  163. /**
  164. * helper to pad a string with a given char
  165. * @param str the string to pad
  166. * @param length the length to pad to
  167. * @param chr the char to use for padding
  168. * @return the padded string
  169. */
  170. function UTIL_pad(str, length, chr) {
  171. while (length > str.length) {
  172. str = chr + str;
  173. }
  174. return str;
  175. }
  176. /**
  177. * helper to encode a string that is passed in to URL encoding
  178. * this is used for requests to a webserver, so do not use
  179. * encodeUriComponent here
  180. * @param sStr the stirng to encode
  181. * @return the encoded string
  182. */
  183. function UTIL_urlEncodeString(sStr) {
  184. return escape(sStr).
  185. replace(/\+/g, '%2B').
  186. replace(/\"/g,'%22').
  187. replace(/\'/g, '%27').
  188. replace(/\//g,'%2F');
  189. }
  190. /**
  191. * helper to attach an event to a target object
  192. * @param target the object to attach the event to
  193. * @param type the event type
  194. * @param callback the event callback
  195. */
  196. function UTIL_domEventHandler(target, type, callback) {
  197. if (target.addEventListener) {
  198. target.addEventListener(type, callback, false);
  199. } else {
  200. target.attachEvent("on" + type, callback);
  201. }
  202. }
  203. /**
  204. * helper to create a DIV element, currently used for debugging
  205. * @param opt_text the text in the div
  206. * @param opt_className the css class to use
  207. */
  208. function UTIL_domCreateDiv(opt_text, opt_className) {
  209. var el = document.createElement("div");
  210. if (opt_text) {
  211. UTIL_domAppendChild(el, document.createTextNode(opt_text));
  212. }
  213. if (opt_className) {
  214. el.className = opt_className;
  215. }
  216. return el;
  217. }
  218. /**
  219. * helper to append a child in the dom
  220. * @param parent the node to append to
  221. * @param child the node to append
  222. */
  223. function UTIL_domAppendChild(parent, child) {
  224. try {
  225. parent.appendChild(child);
  226. } catch (e) {
  227. LOG_ERROR("UTIL_domAppendChild: " + e);
  228. }
  229. return child;
  230. }
  231. /**
  232. * Applies the given function to each element of the array, preserving
  233. * this, and passing the index.
  234. */
  235. function UTIL_mapExec(array, func) {
  236. for (var i = 0; i < array.length; ++i) {
  237. func.call(this, array[i], i);
  238. }
  239. }
  240. /**
  241. * Returns an array that contains the return value of the given
  242. * function applied to every element of the input array.
  243. */
  244. function UTIL_mapExpr(array, func) {
  245. var ret = [];
  246. for (var i = 0; i < array.length; ++i) {
  247. ret.push(func(array[i]));
  248. }
  249. return ret;
  250. }
  251. /**
  252. * Reverses the given array in place.
  253. */
  254. function UTIL_reverseInplace(array) {
  255. for (var i = 0; i < array.length / 2; ++i) {
  256. var h = array[i];
  257. var ii = array.length - i - 1;
  258. array[i] = array[ii];
  259. array[ii] = h;
  260. }
  261. }
  262. /**
  263. * Shallow-copies an array.
  264. */
  265. function UTIL_copyArray(dst, src) {
  266. for (var i = 0; i < src.length; ++i) {
  267. dst.push(src[i]);
  268. }
  269. }
  270. /**
  271. * Returns the text value of a node; for nodes without children this
  272. * is the nodeValue, for nodes with children this is the concatenation
  273. * of the value of all children.
  274. */
  275. function UTIL_xmlValue(node) {
  276. if (!node) {
  277. return '';
  278. }
  279. var ret = '';
  280. if (node.nodeType == DOM_TEXT_NODE ||
  281. node.nodeType == DOM_CDATA_SECTION_NODE ||
  282. node.nodeType == DOM_ATTRIBUTE_NODE) {
  283. ret += node.nodeValue;
  284. } else if (node.nodeType == DOM_ELEMENT_NODE ||
  285. node.nodeType == DOM_DOCUMENT_NODE ||
  286. node.nodeType == DOM_DOCUMENT_FRAGMENT_NODE) {
  287. for (var i = 0; i < node.childNodes.length; ++i) {
  288. ret += arguments.callee(node.childNodes[i]);
  289. }
  290. }
  291. return ret;
  292. }
  293. /**
  294. * Returns the representation of a node as XML text.
  295. */
  296. function UTIL_xmlText(node, opt_cdata) {
  297. var buf = [];
  298. xmlTextR(node, buf, opt_cdata);
  299. return buf.join('');
  300. }
  301. /**
  302. * worker function for UTIL_xmlText()
  303. */
  304. function xmlTextR(node, buf, cdata) {
  305. if (node.nodeType == DOM_TEXT_NODE) {
  306. buf.push(xmlEscapeText(node.nodeValue));
  307. } else if (node.nodeType == DOM_CDATA_SECTION_NODE) {
  308. if (cdata) {
  309. buf.push(node.nodeValue);
  310. } else {
  311. buf.push('<![CDATA[' + node.nodeValue + ']]>');
  312. }
  313. } else if (node.nodeType == DOM_COMMENT_NODE) {
  314. buf.push('<!--' + node.nodeValue + '-->');
  315. } else if (node.nodeType == DOM_ELEMENT_NODE) {
  316. buf.push('<' + xmlFullNodeName(node));
  317. for (var i = 0; i < node.attributes.length; ++i) {
  318. var a = node.attributes[i];
  319. if (a && a.nodeName && a.nodeValue) {
  320. buf.push(' ' + xmlFullNodeName(a) + '="' +
  321. xmlEscapeAttr(a.nodeValue) + '"');
  322. }
  323. }
  324. if (node.childNodes.length === 0) {
  325. buf.push('/>');
  326. } else {
  327. buf.push('>');
  328. for (i = 0; i < node.childNodes.length; ++i) {
  329. arguments.callee(node.childNodes[i], buf, cdata);
  330. }
  331. buf.push('</' + xmlFullNodeName(node) + '>');
  332. }
  333. } else if (node.nodeType == DOM_DOCUMENT_NODE ||
  334. node.nodeType == DOM_DOCUMENT_FRAGMENT_NODE) {
  335. for (i = 0; i < node.childNodes.length; ++i) {
  336. arguments.callee(node.childNodes[i], buf, cdata);
  337. }
  338. }
  339. }
  340. /**
  341. * helper for xmlTextR
  342. */
  343. function xmlFullNodeName(n) {
  344. if (n.prefix && n.nodeName.indexOf(n.prefix + ':') !== 0) {
  345. return n.prefix + ':' + n.nodeName;
  346. } else {
  347. return n.nodeName;
  348. }
  349. }
  350. /**
  351. * Escape XML special markup chracters: tag delimiter < > and entity
  352. * reference start delimiter &. The escaped string can be used in XML
  353. * text portions (i.e. between tags).
  354. */
  355. function xmlEscapeText(s) {
  356. return ('' + s).replace(/&/g, '&amp;').replace(/</, '&lt;').
  357. replace(/>/, '&gt;');
  358. }
  359. /**
  360. * Escape XML special markup characters: tag delimiter < > entity
  361. * reference start delimiter & and quotes ". The escaped string can be
  362. * used in double quoted XML attribute value portions (i.e. in
  363. * attributes within start tags).
  364. */
  365. function xmlEscapeAttr(s) {
  366. return xmlEscapeText(s).replace(/\"/g, '&quot;');
  367. }
  368. /**
  369. * Escape markup in XML text, but don't touch entity references. The
  370. * escaped string can be used as XML text (i.e. between tags).
  371. */
  372. function xmlEscapeTags(s) {
  373. return s.replace(/</, '&lt;').replace(/>/g, '&gt;');
  374. }
  375. // remove this if you merge
  376. if (window.GD_Loader) {
  377. // continue loading
  378. window.GD_Loader();
  379. }
  380. // end
  381. /* Copyright (c) 2006 Google Inc.
  382. *
  383. * Licensed under the Apache License, Version 2.0 (the "License");
  384. * you may not use this file except in compliance with the License.
  385. * You may obtain a copy of the License at
  386. *
  387. * http://www.apache.org/licenses/LICENSE-2.0
  388. *
  389. * Unless required by applicable law or agreed to in writing, software
  390. * distributed under the License is distributed on an "AS IS" BASIS,
  391. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  392. * See the License for the specific language governing permissions and
  393. * limitations under the License.
  394. */
  395. /**
  396. * @fileoverview
  397. * BrowserDetector (object)
  398. *
  399. * A class for detecting version 5 browsers by the Javascript objects
  400. * they support and not their user agent strings (which can be
  401. * spoofed).
  402. *
  403. * Warning: Though slow to develop, browsers may begin to add
  404. * DOM support in later versions which might require changes to this
  405. * file.
  406. *
  407. * Typical usage:
  408. * Detect = new BrowserDetector();
  409. * if (Detect.IE()) //IE-only code...
  410. */
  411. /**
  412. * @constructor
  413. */
  414. function BrowserDetector() {
  415. //IE 4+
  416. this.IE = function() {
  417. try {
  418. return this.Run(document.all && window.ActiveXObject) !==false;
  419. } catch(e) {
  420. /* IE 5.01 doesn't support the 'contains' object and
  421. fails the first test */
  422. if (document.all) {
  423. return true;
  424. }
  425. return false;
  426. }
  427. };
  428. //IE 5.5+
  429. this.IE_5_5_newer = function(){
  430. try {
  431. return this.Run(this.IE() && Array.prototype.pop)!==false;
  432. } catch(e) {return false;}
  433. };
  434. //IE 5, Macintosh
  435. this.IE_5_Mac = function(){
  436. try {
  437. return(true === undefined);
  438. } catch(e) {
  439. return(
  440. document.all &&
  441. document.getElementById &&
  442. !document.mimeType &&
  443. !window.opera)!==false;
  444. }
  445. };
  446. //Opera 7+
  447. this.OPERA = function(){
  448. try {
  449. return this.Run(document.all && document.contains)!==false;
  450. } catch(e) {return false;}
  451. };
  452. //Gecko, actually Mozilla 1.2+
  453. this.MOZILLA = function() {
  454. try {
  455. return this.Run(
  456. document.implementation &&
  457. document.implementation.createDocument &&
  458. document.evaluate &&
  459. !document.contains )!==false;
  460. } catch(e) {return false;}
  461. };
  462. //Safari
  463. this.SAFARI = function(){
  464. try {
  465. return this.Run(
  466. document.implementation &&
  467. document.implementation.createDocument &&
  468. document.contains)!==false;
  469. } catch(e) {return false;}
  470. };
  471. //Any browser which supports the W3C DOM
  472. this.DOM = function() {
  473. return(document.getElementById);
  474. };
  475. this.Run = function(test) {
  476. if (test===undefined) {
  477. return false;
  478. } else {
  479. return test;
  480. }
  481. };
  482. this.XPathSupport = function() {
  483. return this.IE_5_5_newer() || document.implementation.hasFeature('XPath','3.0');
  484. };
  485. }
  486. var DOM = (document.getElementById);
  487. var Detect;
  488. if (DOM) {
  489. Detect = new BrowserDetector();
  490. }
  491. // remove this if you merge
  492. if (window.GD_Loader) {
  493. // continue loading
  494. window.GD_Loader();
  495. }
  496. // end
  497. /* Copyright (c) 2006 Google Inc.
  498. *
  499. * Licensed under the Apache License, Version 2.0 (the "License");
  500. * you may not use this file except in compliance with the License.
  501. * You may obtain a copy of the License at
  502. *
  503. * http://www.apache.org/licenses/LICENSE-2.0
  504. *
  505. * Unless required by applicable law or agreed to in writing, software
  506. * distributed under the License is distributed on an "AS IS" BASIS,
  507. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  508. * See the License for the specific language governing permissions and
  509. * limitations under the License.
  510. */
  511. //------------------------------------------------------------------------------
  512. function DumpError(msg) {}
  513. function DumpException(msg) {}
  514. //------------------------------------------------------------------------------
  515. // Logging
  516. //------------------------------------------------------------------------------
  517. function LOG_LEVEL() {}
  518. LOG_LEVEL.NONE = 0;
  519. LOG_LEVEL.ERROR = 1;
  520. LOG_LEVEL.DEBUG = 2;
  521. LOG_LEVEL.TRACE = 3;
  522. LOG_LEVEL.ALL = 4;
  523. function DEBUG_ENABLE_CROSSSITE() {}
  524. function DEBUG_CROSSSITE() { return false;}
  525. //------------------------------------------------------------------------------
  526. // Inline log functions
  527. //------------------------------------------------------------------------------
  528. function LOG_CLASS(classDef, name) {}
  529. function LOG(msg, opt_level) {}
  530. function LOG_DEBUG(msg, opt_show) {}
  531. function LOG_ERROR(msg) {}
  532. function LOG_EVENT(msg) {}
  533. function LOG_TRACE(obj, fn, args) {}
  534. function LOG_SEPARATOR(opt_text) {}
  535. function LOG_TIMER_START(name) {}
  536. function LOG_TIMER_STOP(name) {}
  537. function LOG_XML_PRINT(doc, opt_level) {}
  538. function LOG_DUMP_FEED(feed) {}
  539. function VARJ_INC(name) {}
  540. //------------------------------------------------------------------------------
  541. // Inline debug functions
  542. //------------------------------------------------------------------------------
  543. function DBG_ALERT(msg, opt_prefix) {}
  544. function DBG_ASSERT(cond, opt_msg) {}
  545. function DBG_ABSTRACT(obj, fn, args) {}
  546. function DBG_NOT_IMPLEMENTED(str) {}
  547. // remove this if you merge
  548. if (window.GD_Loader) {
  549. // continue loading
  550. window.GD_Loader();
  551. }
  552. // end
  553. /* Copyright (c) 2006 Google Inc.
  554. *
  555. * Licensed under the Apache License, Version 2.0 (the "License");
  556. * you may not use this file except in compliance with the License.
  557. * You may obtain a copy of the License at
  558. *
  559. * http://www.apache.org/licenses/LICENSE-2.0
  560. *
  561. * Unless required by applicable law or agreed to in writing, software
  562. * distributed under the License is distributed on an "AS IS" BASIS,
  563. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  564. * See the License for the specific language governing permissions and
  565. * limitations under the License.
  566. */
  567. /** @filecomment
  568. * transport.js provides the basic server related operations:
  569. * get a feed, create an item, update & delete an item
  570. * we abstract this out, so that a unit test framework based on FILE transport
  571. * can be developed later
  572. */
  573. /** returns the appropriate transportobject based on
  574. * the passed in type
  575. */
  576. function GD_getTransport(transportType) {
  577. switch (transportType) {
  578. case GD_Transport.TRANSPORT_FILE:
  579. // File Transport object
  580. DBG_ALERT("File transport NYI");
  581. return null;
  582. case GD_Transport.TRANSPORT_HTTP:
  583. return new GD_HttpTransport();
  584. case GD_Transport.TRANSPORT_GOOGLECALENDAR:
  585. return new GD_GaiaTransport("cl");
  586. default:
  587. return new GD_GaiaTransport("cl");
  588. }
  589. }
  590. /**
  591. * base transport, for the common things in life
  592. */
  593. function GD_Transport() {
  594. this.userName_ = null;
  595. this.pwd_ = null;
  596. }
  597. GD_Transport.TRANSPORT_FILE = 1;
  598. GD_Transport.TRANSPORT_HTTP = 2;
  599. GD_Transport.TRANSPORT_GOOGLECALENDAR = 3;
  600. GD_Transport.AUTH_HANDLER = "https://www.google.com/accounts/ClientLogin";
  601. GD_Transport.AUTH_HEADER = "Authorization";
  602. GD_Transport.AUTH_HEADERVALUE = "GoogleLogin auth=";
  603. GD_Transport.AUTH_TOKEN = "Auth";
  604. GD_Transport.AUTH_SERVICE = "service=";
  605. GD_Transport.AUTH_SOURCE = "source=desktop_Feed_reader";
  606. GD_Transport.AUTH_USER = "Email=";
  607. GD_Transport.AUTH_PWD = "Passwd=";
  608. GD_Transport.METHOD_OVERRIDE = "X-HTTP-Method-Override";
  609. GD_Transport.NOREDIRECT_HEADER = "X-If-No-Redirect";
  610. GD_Transport.SETCOOKIE_HEADER = "Set-Cookie";
  611. GD_Transport.COOKIE_HEADER = "Cookie";
  612. /**
  613. * set method GD_Transport.userName_
  614. */
  615. GD_Transport.prototype.setUserName = function(stringValue) {
  616. this.userName_ = stringValue;
  617. };
  618. /**
  619. * get method GD_Transport.userName_
  620. */
  621. GD_Transport.prototype.getUserName = function() {
  622. return this.userName_;
  623. };
  624. /**
  625. * set method GD_Transport.pwd_
  626. */
  627. GD_Transport.prototype.setPassword = function(stringValue) {
  628. this.pwd_ = stringValue;
  629. };
  630. /**
  631. * get method GD_Transport.pwd_
  632. */
  633. GD_Transport.prototype.getPassword = function() {
  634. return this.pwd_;
  635. };
  636. /**
  637. * prototype for the GetDocument method
  638. * @param docUri {string} the URI of the XML document to load
  639. * @param opt_callback {function} takes one argument,
  640. * the loaded XMLDocument for the documentUri
  641. */
  642. GD_Transport.prototype.GetDomDocument = function(docUri, opt_callback) {};
  643. /**
  644. * prototype for the InsertEntry method
  645. */
  646. GD_Transport.prototype.InsertEntry = function(feed, entry) {
  647. };
  648. /**
  649. * prototype for the UpdateEntry method
  650. */
  651. GD_Transport.prototype.UpdateEntry = function(entry) {
  652. };
  653. /**
  654. * prototype for the DeleteEntry method
  655. */
  656. GD_Transport.prototype.DeleteEntry = function(entry) {
  657. };
  658. /**
  659. * file transport section, prototype only
  660. */
  661. function GD_FileTransport() {
  662. GD_Transport.call(this);
  663. }
  664. UTIL_inherits(GD_FileTransport, GD_Transport);
  665. GD_FileTransport.prototype.toString = function(opt_verbose) {
  666. return "GD_FileTransport()";
  667. };
  668. /**
  669. * http transport
  670. */
  671. function GD_HttpTransport() {
  672. GD_Transport.call(this);
  673. this.shardingCookie_ = null;
  674. }
  675. UTIL_inherits(GD_HttpTransport, GD_Transport);
  676. GD_HttpTransport.prototype.toString = function(opt_verbose) {
  677. return "GD_HttpTransport()";
  678. };
  679. /**
  680. * set method GD_HttpTransport.shardingCookie_
  681. */
  682. GD_HttpTransport.prototype.setCookie = function(str) {
  683. this.shardingCookie_ = str;
  684. };
  685. /**
  686. * get method GD_HttpTransport.shardingCookie_
  687. */
  688. GD_HttpTransport.prototype.getCookie = function() {
  689. return this.shardingCookie_;
  690. };
  691. /**
  692. * gets the DomDocument for the HTTP transport
  693. * @param docUri {string} the URI of the XML document to load
  694. * @param opt_callback {function} takes one argument,
  695. * the loaded XMLDocument for the documentUri
  696. */
  697. GD_HttpTransport.prototype.GetDomDocument = function(docUri, opt_callback) {
  698. LOG_TRACE(docUri, "GD_HttpTransport => GetDomDocument", null);
  699. var callback = (opt_callback)
  700. ? function(request) { opt_callback.call(null, request.responseXML); }
  701. : undefined;
  702. var params = new XmlHttpParameters("GET", docUri, 200, null, callback);
  703. this.CallXmlHttp(params);
  704. };
  705. /**
  706. * DeleteEntry for the HTTP transport,
  707. * gets the target URI from the passed in entry
  708. */
  709. GD_HttpTransport.prototype.DeleteEntry = function(gdEntry, opt_callBack) {
  710. var deleteUri = gdEntry.getEditUri();
  711. LOG_TRACE(deleteUri, "GD_HttpTransport => DeleteEntry", null);
  712. var params = new XmlHttpParameters("DELETE", deleteUri, 204,
  713. null, opt_callBack);
  714. this.CallXmlHttp(params);
  715. };
  716. /**
  717. * UpdateEntry for the HTTP transport,
  718. * gets the target URI from the passed in entry
  719. */
  720. GD_HttpTransport.prototype.UpdateEntry = function(gdEntry, opt_callBack) {
  721. var updateUri = gdEntry.getEditUri();
  722. LOG_TRACE(updateUri, "GD_HttpTransport => UpdateEntry", null);
  723. var params = new XmlHttpParameters("PUT", updateUri, -1,
  724. gdEntry.save(), opt_callBack);
  725. this.CallXmlHttp(params);
  726. };
  727. /**
  728. * InsertEntry for the HTTP transport,
  729. * sets the target URI from the passed in feed
  730. */
  731. GD_HttpTransport.prototype.InsertEntry = function(ofFeed, gdEntry,
  732. opt_callBack) {
  733. var insertUri = ofFeed.getPostUri();
  734. if (insertUri != null) {
  735. LOG_TRACE(insertUri, "GD_HttpTransport => InsertEntry", null);
  736. var params = new XmlHttpParameters("POST", insertUri, -1,
  737. gdEntry.save(), opt_callBack);
  738. this.CallXmlHttp(params);
  739. }
  740. else {
  741. throw "this is a read only feed";
  742. }
  743. };
  744. /**
  745. * SetHeaders for the HTTP transport,
  746. * just sets the accept content type here
  747. */
  748. GD_HttpTransport.prototype.SetHeaders = function(xmlHttpRequestObject) {
  749. LOG_TRACE("Entering...", "HTTP.SetHeaders", null);
  750. xmlHttpRequestObject.setRequestHeader("Accept", "text/xml");
  751. xmlHttpRequestObject.setRequestHeader("content-type", "application/atom+xml");
  752. xmlHttpRequestObject.setRequestHeader("Cache-Control", "no-cache");
  753. };
  754. /**
  755. * @param params {XmlHttpParameters}
  756. */
  757. GD_HttpTransport.prototype.PrepareAuthentication = function(params) {
  758. this.DoRequest(params);
  759. };
  760. /**
  761. * Bundle a collection of parameters that are used when making an
  762. * XMLHttpRequest. The state of a transaction should be stored in
  763. * the XmlHttpParameters rather than the GD_HttpTransport, as the
  764. * GD_HttpTransport is likely a singleton, so requests it facilitates
  765. * should not share state.
  766. *
  767. * @param verb {string} must be "GET" or "DELETE" or "PUT" or "POST"
  768. * @param uri {string}
  769. * @param allowedStatus {int}
  770. * @param payload {string?}
  771. * @param opt_callback {function} will receive one argument,
  772. * the loaded XMLHttpRequest, and its return value will be ignored
  773. * @param opt_retrying {boolean} indicates whether this is a retry attempt;
  774. * defaults to false
  775. */
  776. function XmlHttpParameters(verb, uri, allowedStatus, payload,
  777. opt_callback, opt_retrying) {
  778. this.verb = verb;
  779. this.uri = uri;
  780. this.allowedStatus = allowedStatus;
  781. this.payload = payload;
  782. this.callback = opt_callback;
  783. this.retrying = !!opt_retrying;
  784. }
  785. /**
  786. * method do create the actual request. This one just calls PrepareAuth
  787. * which will continue calling DoRequest after auth is done
  788. * @param params {XmlHttpParameters}
  789. */
  790. GD_HttpTransport.prototype.CallXmlHttp = function(params) {
  791. try {
  792. LOG_TRACE("Entering...", "CallXmlHttp", null);
  793. this.PrepareAuthentication(params);
  794. } catch (e) {
  795. DBG_ALERT(e.toString());
  796. DBG_ALERT('The exception happened in CallXmlHttp for ' + params.verb +
  797. ' at URI: ' + params.uri);
  798. throw e;
  799. }
  800. LOG_TRACE("Exiting...", "CallXmlHttp", null);
  801. };
  802. /**
  803. * @param params {XmlHttpParameters}
  804. */
  805. GD_HttpTransport.prototype.DoRequest = function(params) {
  806. try {
  807. LOG_TRACE("Entering...", "CallXmlHttp", null);
  808. var xmlRequest = XMLX_getHttpRequest();
  809. var fAsync = false;
  810. if (params.callback) {
  811. xmlRequest.onreadystatechange =
  812. function() { GD_HandleAsyncData(xmlRequest, params); };
  813. fAsync = true;
  814. }
  815. if (DEBUG_CROSSSITE()) {
  816. netscape.security.PrivilegeManager.
  817. enablePrivilege("UniversalBrowserRead");
  818. netscape.security.PrivilegeManager.
  819. enablePrivilege("UniversalBrowserWrite");
  820. }
  821. LOG_TRACE("Using default XlmRequest open", "CallXmlHttp", null);
  822. xmlRequest.open(params.verb, params.uri, fAsync);
  823. // thwart the cache
  824. if (params.verb == "GET") {
  825. xmlRequest.setRequestHeader("If-Modified-Since",
  826. "Sat, 1 Jan 2000 00:00:00 GMT");
  827. }
  828. this.SetHeaders(xmlRequest);
  829. if (xmlRequest.overrideMimeType) {
  830. //only need to do this for mozilla based browsers. IE would throw
  831. xmlRequest.overrideMimeType('text/xml');
  832. }
  833. LOG_TRACE("Sending..." + xmlRequest, "CallXmlHttp", null);
  834. xmlRequest.send(params.payload);
  835. LOG_TRACE("Returned, readyState:" + xmlRequest.readyState,
  836. "CallXmlHttp", null);
  837. if (fAsync === false) {
  838. this.HandleOnXmlRequestFinished(xmlRequest, params);
  839. }
  840. } catch (e) {
  841. DBG_ALERT(e.toString());
  842. DBG_ALERT('The exception happened in CallXmlHttp for ' + params.verb_ +
  843. ' at URI: ' + params.uri_);
  844. throw e;
  845. }
  846. LOG_TRACE("Exiting...", "CallXmlHttp", null);
  847. };
  848. /**
  849. * async callback method
  850. */
  851. function GD_HandleAsyncData(request, params) {
  852. if (request.readyState != 4) {
  853. return;
  854. }
  855. LOG_TRACE("Callback done...", "GD_HandleAsyncData", null);
  856. GoogleDataFactory.getTransport().
  857. HandleOnXmlRequestFinished(request, params);
  858. }
  859. /**
  860. * handling of errors/results of the xmlhttprequest
  861. */
  862. GD_HttpTransport.prototype.HandleOnXmlRequestFinished =
  863. function(xmlRequest, params) {
  864. switch (xmlRequest.readyState) {
  865. case 1:
  866. case 2:
  867. case 3:
  868. DBG_ALERT('Bad Ready State: ' + xmlRequest.status);
  869. return false;
  870. case 4:
  871. if (xmlRequest.status > 299 ||
  872. (params.allowedStatus !== -1 &&
  873. xmlRequest.status != params.allowedStatus)) {
  874. if (params.retrying !== true) {
  875. /*
  876. * this might be a redirect/sharding issue, redo the whole thing
  877. * in javascript you can not handle the 302 return yourself,
  878. * so what happens is we get our auth token, we try to go to the
  879. * server, we get a redirect back now the redirect does not redo
  880. * the "postdata" nor the custom auth header, so it fails with
  881. * 401. Hence, redo it. But only once.
  882. */
  883. if (xmlRequest.status === 401) {
  884. params = true;
  885. this.CallXmlHttp(params);
  886. } else if (xmlRequest.status === 412) {
  887. // the server want's to redirect us to a shard !!
  888. // get the cookie and save it, then retry
  889. var cookie = xmlRequest.getResponseHeader(
  890. GD_Transport.SETCOOKIE_HEADER);
  891. DBG_ASSERT(cookie != null,
  892. "we got no cookie back from the redirection server");
  893. if (cookie != null) {
  894. this.setCookie(cookie);
  895. }
  896. // now retry
  897. params.retrying = true;
  898. this.CallXmlHttp(params);
  899. }
  900. }
  901. DBG_ALERT('Request resulted in a bad status code for the operation: '
  902. + xmlRequest.status + " " + params.allowedStatus);
  903. }
  904. break;
  905. }
  906. if (params.callback) {
  907. LOG_TRACE("calling callback to feed code", "HandleOnXmlRequestFinished",
  908. null);
  909. params.callback.call(null, xmlRequest);
  910. }
  911. }
  912. /**
  913. * Gaia authentication transport.
  914. */
  915. function GD_GaiaTransport(serviceName) {
  916. GD_HttpTransport.call(this);
  917. this.serviceName_ = serviceName;
  918. this.gaiaToken_ = null;
  919. }
  920. UTIL_inherits(GD_GaiaTransport, GD_HttpTransport);
  921. GD_GaiaTransport.prototype.toString = function(opt_verbose) {
  922. return "GD_GaiaTransport() for " + this.serviceName_;
  923. };
  924. /**
  925. * set method GD_GaiaTransport.gaiaToken_
  926. */
  927. GD_GaiaTransport.prototype.setToken = function(string) {
  928. this.gaiaToken_ = string;
  929. };
  930. /**
  931. * get method GD_GaiaTransport.gaiaToken_
  932. */
  933. GD_GaiaTransport.prototype.getToken = function() {
  934. if (/\r|\n/.test(this.gaiaToken_) === true) {
  935. alert("potential attack pattern");
  936. }
  937. return this.gaiaToken_;
  938. };
  939. /**
  940. * function to get an authtoken from the gaia servers
  941. * @param params {XmlHttpParameters}
  942. */
  943. GD_GaiaTransport.prototype.QueryAuthToken = function(params) {
  944. // Create a new request to the authentication URL.
  945. LOG_TRACE("Entering...", "QueryAuthToken()", null);
  946. var token = null;
  947. try {
  948. var xmlRequest = XMLX_getHttpRequest();
  949. var response = null;
  950. // construct the payload
  951. var postData = GD_Transport.AUTH_USER +
  952. encodeURIComponent(this.getUserName()) + "&" +
  953. GD_Transport.AUTH_PWD +
  954. encodeURIComponent(this.getPassword()) + "&" +
  955. GD_Transport.AUTH_SOURCE + "&" +
  956. GD_Transport.AUTH_SERVICE +
  957. encodeURIComponent(this.serviceName_);
  958. LOG_TRACE("postData = " + postData, "QueryAuthToken()", null);
  959. var responseData = null;
  960. var request = xmlRequest;
  961. xmlRequest.onreadystatechange = function() {
  962. GD_GaiaHandleAsyncData(request, params);
  963. }
  964. xmlRequest.open("POST", GD_Transport.AUTH_HANDLER, true);
  965. xmlRequest.setRequestHeader("content-type",
  966. "application/x-www-form-urlencoded");
  967. LOG_TRACE("sending..." + xmlRequest, "QueryAuthToken()", null);
  968. xmlRequest.send(postData);
  969. } catch (e) {
  970. DBG_ALERT(e.toString());
  971. DBG_ALERT('The exception happened in QueryAuthData');
  972. }
  973. };
  974. /**
  975. * callback for the QueryAuthToken
  976. * @param params {XmlHttpParameters}
  977. */
  978. function GD_GaiaHandleAsyncData(request, params) {
  979. LOG_TRACE("Entering callback..", "GD_GaiaHandleAsyncData", null);
  980. if (request.readyState != 4) {
  981. return;
  982. }
  983. GoogleDataFactory.getTransport().HandleOnQueryAuthRequestFinished(
  984. request, params);
  985. LOG_TRACE("QueryAuthCallback done...", "GD_GaiaHandleAsyncData", null);
  986. }
  987. /**
  988. * handling of errors/results of the xmlhttprequest
  989. * @param request {XMLHttpRequest}
  990. * @param params {XmlHttpParameters}
  991. */
  992. GD_GaiaTransport.prototype.HandleOnQueryAuthRequestFinished = function(
  993. request, params) {
  994. var response = null;
  995. var token = null;
  996. LOG_TRACE("Entering...", "HandleOnQueryAuthRequestFinished", null);
  997. if (request.status > 299) {
  998. DBG_ALERT('Bad server response during auth operation: ' +
  999. this.xmlRequest.status);
  1000. DBG_ALERT('body: ' + params.postData);
  1001. } else {
  1002. response = request.responseText;
  1003. }
  1004. DBG_ASSERT(response !== null,
  1005. "we got no data back from the authentication server");
  1006. if (response !== null) {
  1007. // now parse the result
  1008. var result = response.match(/^Auth=(.*)/m);
  1009. DBG_ASSERT(result !== null);
  1010. DBG_ASSERT(result[0] !== null);
  1011. DBG_ASSERT(result[1] !== null);
  1012. if (result !== null) {
  1013. token = result[1];
  1014. }
  1015. }
  1016. LOG_TRACE(token, "HandleOnQueryAuthRequestFinished()", null);
  1017. this.setToken(token);
  1018. // stack needs to unwind, as you can not call from XmlHttp.onreadystate
  1019. // into another xmlHttp object
  1020. window.setTimeout(function() { GD_GaiaContinue(params) }, 0);
  1021. LOG_TRACE("exiting...", "HandleOnQueryAuthRequestFinished", null);
  1022. }
  1023. /**
  1024. * callback for the QueryAuthToken
  1025. */
  1026. function GD_GaiaContinue(params) {
  1027. LOG_TRACE("GD_GaiaContinue...", "GD_GaiaContinue", null);
  1028. GoogleDataFactory.getTransport().DoRequest(params);
  1029. }
  1030. /**
  1031. * check if we need to get a token
  1032. * @returns true if we need to get a token
  1033. */
  1034. GD_GaiaTransport.prototype.NeedToken = function() {
  1035. if (UTIL_isPersistable(this.getUserName()) && this.getToken() == null) {
  1036. return true;
  1037. }
  1038. return false;
  1039. };
  1040. /**
  1041. * if a token is needed, will get one and set it
  1042. */
  1043. GD_GaiaTransport.prototype.PrepareAuthentication = function(params) {
  1044. if (this.NeedToken()) {
  1045. this.QueryAuthToken(params);
  1046. } else {
  1047. this.DoRequest(params);
  1048. }
  1049. };
  1050. /**
  1051. * sets the auth header for Gaia, if we have a token
  1052. * @param xmlHttpRequestObject object to set the header on
  1053. */
  1054. GD_GaiaTransport.prototype.SetHeaders = function(xmlHttpRequestObject) {
  1055. LOG_TRACE("Entering...", "Gaia.SetHeaders", null);
  1056. xmlHttpRequestObject.setRequestHeader(GD_Transport.NOREDIRECT_HEADER, "1");
  1057. if (this.getCookie() !== null) {
  1058. // set a previously stored shard cookie
  1059. LOG_TRACE("setting a stored cookie..." + this.getCookie(),
  1060. "SetHeaders", null);
  1061. xmlHttpRequestObject.setRequestHeader(GD_Transport.COOKIE_HEADER,
  1062. this.getCookie(), null);
  1063. }
  1064. if (this.getToken() !== null) {
  1065. xmlHttpRequestObject.setRequestHeader(GD_Transport.AUTH_HEADER,
  1066. GD_Transport.AUTH_HEADERVALUE + this.getToken());
  1067. }
  1068. this.Base.SetHeaders(xmlHttpRequestObject);
  1069. };
  1070. /**
  1071. * GD_Factory() is used to access the underlying transport layer
  1072. * one instance of the factory exists as a global
  1073. */
  1074. function GD_Factory() {
  1075. this.transPort_ = GD_getTransport(GD_Transport.TRANSPORT_GOOGLECALENDAR);
  1076. };
  1077. // set method GD_Factory.transPort_
  1078. GD_Factory.prototype.setTransport = function(value) {
  1079. this.transPort_ = value;
  1080. };
  1081. // get method GD_Factory.transPort_
  1082. GD_Factory.prototype.getTransport = function() {
  1083. return this.transPort_;
  1084. };
  1085. /**
  1086. * declaration of our global GoogleDataFactory, so that the rest
  1087. * of the code can share this...
  1088. */
  1089. var GoogleDataFactory = new GD_Factory();
  1090. // remove this if you merge
  1091. if (window.GD_Loader) {
  1092. // continue loading
  1093. window.GD_Loader();
  1094. }
  1095. // end
  1096. /* Copyright (c) 2006 Google Inc.
  1097. *
  1098. * Licensed under the Apache License, Version 2.0 (the "License");
  1099. * you may not use this file except in compliance with the License.
  1100. * You may obtain a copy of the License at
  1101. *
  1102. * http://www.apache.org/licenses/LICENSE-2.0
  1103. *
  1104. * Unless required by applicable law or agreed to in writing, software
  1105. * distributed under the License is distributed on an "AS IS" BASIS,
  1106. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  1107. * See the License for the specific language governing permissions and
  1108. * limitations under the License.
  1109. */
  1110. /**
  1111. * @fileoverview
  1112. * this file relies on detect.js to do the browser detection
  1113. * it abstracts a minimal set of xpath methods so that
  1114. * you can do cross browser xpath
  1115. * the code seems to work fine in IE6+, Mozilla, Opera8.5+ and Safari2.0+
  1116. */
  1117. var XMLX_ieProgId_ = undefined;
  1118. /** initialize XMLX_ieProgId_ */
  1119. (function () {
  1120. // Nobody (on the web) is really sure which of the progid's listed is totally
  1121. // necessary. It is known, for instance, that certain installations of IE
  1122. // will not work with only Microsoft.XMLHTTP, as well as with MSXML2.XMLHTTP.
  1123. // Safest course seems to be to do this -- include all known progids for
  1124. // XmlHttp.
  1125. if (typeof XMLHttpRequest == 'undefined' &&
  1126. typeof ActiveXObject != 'undefined') {
  1127. var activeXIdents = [
  1128. "MSXML2.XMLHTTP.5.0", "MSXML2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0",
  1129. "MSXML2.XMLHTTP", "MICROSOFT.XMLHTTP.1.0", "MICROSOFT.XMLHTTP.1",
  1130. "MICROSOFT.XMLHTTP" ];
  1131. for (var i = 0; i < activeXIdents.length; ++i) {
  1132. var candidate = activeXIdents[i];
  1133. try {
  1134. new ActiveXObject(candidate);
  1135. XMLX_ieProgId_ = candidate;
  1136. return;
  1137. } catch (e) {
  1138. // do nothing; try next choice
  1139. }
  1140. }
  1141. // couldn't find any matches
  1142. throw ("Could not create ActiveXObject. ActiveX might be disabled, or " +
  1143. "msxml might not be installed");
  1144. }
  1145. })();
  1146. /**
  1147. * helper function to return the correct XMLHttpRequest() object
  1148. */
  1149. function XMLX_getHttpRequest() {
  1150. if (XMLX_ieProgId_ !== undefined) {
  1151. return new ActiveXObject(XMLX_ieProgId_);
  1152. } else {
  1153. return new XMLHttpRequest();
  1154. }
  1155. };
  1156. /**
  1157. * helper to return a brand new XMLDomDocument
  1158. */
  1159. function XMLX_createDomDocument(optXml) {
  1160. var doc = null;
  1161. if (optXml) {
  1162. if (typeof(optXml) != 'string') {
  1163. optXml = XMLX_serializeNode(optXml);
  1164. }
  1165. }
  1166. if (document.implementation.createDocument) {
  1167. if (optXml) {
  1168. var domParser = new DOMParser();
  1169. doc = domParser.parseFromString(optXml, "text/xml");
  1170. } else {
  1171. doc = document.implementation.createDocument("", "", null);
  1172. }
  1173. } else {
  1174. doc = new ActiveXObject("MSXML.DOMDocument");
  1175. if (optXml) {
  1176. doc.loadXML(optXml);
  1177. }
  1178. }
  1179. DBG_ASSERT(doc !== null, "Could not create a DOM document");
  1180. return doc;
  1181. };
  1182. /**
  1183. * helper to serialize an xmlnode into text
  1184. */
  1185. function XMLX_serializeNode(xmlNode) {
  1186. var text = null;
  1187. try {
  1188. // this is for Gecko based browsers
  1189. LOG_TRACE("Trying serializer", "XMLX_serializeNode", null);
  1190. var xmlSerializer = new XMLSerializer();
  1191. // safari 2.02 seems to work fine with this.
  1192. text = xmlSerializer.serializeToString(xmlNode);
  1193. }
  1194. catch ( e ) {
  1195. try {
  1196. // Internet Explorer.
  1197. LOG_TRACE("Trying IE way to serialize", "XMLX_serializeNode", null);
  1198. text = xmlNode.xml;
  1199. }
  1200. catch (e) {
  1201. // everyone else
  1202. LOG_TRACE("Trying UTIL_xmlText(node)", "XMLX_serializeNode", null);
  1203. text = UTIL_xmlText(xmlNode);
  1204. }
  1205. }
  1206. return text;
  1207. };
  1208. /**
  1209. * encapsulates the xpath methods we are exposing
  1210. */
  1211. function XMLX_getNodes(xmlNode, xpath) {
  1212. DBG_ASSERT(xmlNode, "XML_getNodes: " + xpath);
  1213. LOG_DEBUG("XML_getNodes: " + xpath);
  1214. try {
  1215. var document;
  1216. if (xmlNode.ownerDocument !== null) {
  1217. document = xmlNode.ownerDocument;
  1218. } else {
  1219. document = xmlNode;
  1220. }
  1221. if (Detect.XPathSupport()) {
  1222. if (Detect.IE_5_5_newer()) {
  1223. LOG_DEBUG("XML_getNodes: Inside IE5.5 path");
  1224. document.setProperty("SelectionLanguage", "XPath");
  1225. document.setProperty("SelectionNamespaces", XML.NAMESPACES);
  1226. return xmlNode.selectNodes(xpath);
  1227. } else {
  1228. LOG_DEBUG("XML_getNodes: Inside MOZILLA path");
  1229. var nsResolver = function(prefix){
  1230. var s = XML.NAMESPACE_MAP[prefix];
  1231. if (s) {
  1232. return s;
  1233. } else {
  1234. throw "Unknown prefix: '" + prefix+"'";
  1235. }
  1236. };
  1237. var tempResult = document.evaluate(xpath, xmlNode, nsResolver,
  1238. XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  1239. // now make it an array
  1240. var nodeList = new Array(tempResult.snapshotLength);
  1241. for (var i = 0; i < nodeList.length; ++i) {
  1242. nodeList[i] = tempResult.snapshotItem(i);
  1243. }
  1244. return nodeList;
  1245. }
  1246. } else {
  1247. return XMLX_parse(xmlNode, xpath);
  1248. }
  1249. } catch (e) {
  1250. // LOG_XML_PRINT(xmlNode);
  1251. // this is everyone else
  1252. LOG_DEBUG("XML_getNodes: catch path - " + e.toString());
  1253. return XMLX_parse(xmlNode, xpath);
  1254. }
  1255. };
  1256. /**
  1257. * helper method to call the javascript parser
  1258. */
  1259. function XMLX_parse(xmlNode, xpath) {
  1260. LOG_DEBUG("XML_parse: no xpath support, hence i am here");
  1261. var expr = xpathParse(xpath);
  1262. var ctx = new ExprContext(xmlNode);
  1263. var ret = expr.evaluate(ctx);
  1264. return ret.nodeSetValue();
  1265. }
  1266. /**
  1267. * @param xmlNode the node to search from
  1268. * @xpath the xpath to search for
  1269. * @return the first xmlnode found
  1270. */
  1271. function XMLX_getNode(xmlNode, xpath) {
  1272. var result = XMLX_getNodes(xmlNode, xpath);
  1273. if (result) {
  1274. return result[0];
  1275. }
  1276. return null;
  1277. }
  1278. // remove this if you merge
  1279. if (window.GD_Loader) {
  1280. // continue loading
  1281. window.GD_Loader();
  1282. }
  1283. // end
  1284. /* Copyright (c) 2006 Google Inc.
  1285. *
  1286. * Licensed under the Apache License, Version 2.0 (the "License");
  1287. * you may not use this file except in compliance with the License.
  1288. * You may obtain a copy of the License at
  1289. *
  1290. * http://www.apache.org/licenses/LICENSE-2.0
  1291. *
  1292. * Unless required by applicable law or agreed to in writing, software
  1293. * distributed under the License is distributed on an "AS IS" BASIS,
  1294. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  1295. * See the License for the specific language governing permissions and
  1296. * limitations under the License.
  1297. */
  1298. // All Rights Reserved
  1299. //
  1300. // An XPath parser and evaluator written in JavaScript. The
  1301. // implementation is complete except for functions handling
  1302. // namespaces.
  1303. //
  1304. // Reference: [XPATH] XPath Specification
  1305. // <http://www.w3.org/TR/1999/REC-xpath-19991116>.
  1306. //
  1307. //
  1308. // The API of the parser has several parts:
  1309. //
  1310. // 1. The parser function xpathParse() that takes a string and returns
  1311. // an expession object.
  1312. //
  1313. // 2. The expression object that has an evaluate() method to evaluate the
  1314. // XPath expression it represents. (It is actually a hierarchy of
  1315. // objects that resembles the parse tree, but an application will call
  1316. // evaluate() only on the top node of this hierarchy.)
  1317. //
  1318. // 3. The context object that is passed as an argument to the evaluate()
  1319. // method, which represents the DOM context in which the expression is
  1320. // evaluated.
  1321. //
  1322. // 4. The value object that is returned from evaluate() and represents
  1323. // values of the different types that are defined by XPath (number,
  1324. // string, boolean, and node-set), and allows to convert between them.
  1325. //
  1326. // These parts are near the top of the file, the functions and data
  1327. // that are used internally follow after them.
  1328. //
  1329. function assert(condition) { DBG_ASSERT(condition); }
  1330. // The entry point for the parser.
  1331. //
  1332. // @param expr a string that contains an XPath expression.
  1333. // @return an expression object that can be evaluated with an
  1334. // expression context.
  1335. // right now, only used for safari
  1336. function xpathParse(expr) {
  1337. LOG_DEBUG('XPath parse ' + expr);
  1338. xpathParseInit();
  1339. var cached = xpathCacheLookup(expr);
  1340. if (cached) {
  1341. LOG_DEBUG('XPath ....cached ');
  1342. return cached;
  1343. }
  1344. // Optimize for a few common cases: simple attribute node tests
  1345. // (@id), simple element node tests (page), variable references
  1346. // ($address), numbers (4), multi-step path expressions where each
  1347. // step is a plain element node test
  1348. // (page/overlay/locations/location).
  1349. if (expr.match(/^(\$|@)?\w+$/i)) {
  1350. var ret = makeSimpleExpr(expr);
  1351. xpathParseCache[expr] = ret;
  1352. LOG_DEBUG('XPath ... simple');
  1353. return ret;
  1354. }
  1355. if (expr.match(/^\w+(\/\w+)*$/i)) {
  1356. ret = makeSimpleExpr2(expr);
  1357. xpathParseCache[expr] = ret;
  1358. LOG_DEBUG('XPath ... simple 2 ');
  1359. return ret;
  1360. }
  1361. var cachekey = expr; // expr is modified during parse
  1362. var stack = [];
  1363. var ahead = null;
  1364. var previous = null;
  1365. var done = false;
  1366. var parse_count = 0;
  1367. var lexer_count = 0;
  1368. var reduce_count = 0;
  1369. while (!done) {
  1370. parse_count+=1;
  1371. expr = expr.replace(/^\s*/, '');
  1372. previous = ahead;
  1373. ahead = null;
  1374. var rule = null;
  1375. var match = '';
  1376. for (var i = 0; i < xpathTokenRules.length; ++i) {
  1377. var result = xpathTokenRules[i].re.exec(expr);
  1378. lexer_count+=1;
  1379. if (result && result.length > 0 && result[0].length > match.length) {
  1380. rule = xpathTokenRules[i];
  1381. match = result[0];
  1382. break;
  1383. }
  1384. }
  1385. // Special case: allow operator keywords to be element and
  1386. // variable names.
  1387. // NOTE: The parser resolves conflicts by looking ahead,
  1388. // and this is the only case where we look back to
  1389. // disambiguate. So this is indeed something different, and
  1390. // looking back is usually done in the lexer (via states in the
  1391. // general case, called "start conditions" in flex(1)). Also,the
  1392. // conflict resolution in the parser is not as robust as it could
  1393. // be, so I'd like to keep as much off the parser as possible (all
  1394. // these precedence values should be computed from the grammar
  1395. // rules and possibly associativity declarations, as in bison(1),
  1396. // and not explicitly set.
  1397. if (rule &&
  1398. (rule == TOK_DIV ||
  1399. rule == TOK_MOD ||
  1400. rule == TOK_AND ||
  1401. rule == TOK_OR) &&
  1402. (!previous ||
  1403. previous.tag == TOK_AT ||
  1404. previous.tag == TOK_DSLASH ||
  1405. previous.tag == TOK_SLASH ||
  1406. previous.tag == TOK_AXIS ||
  1407. previous.tag == TOK_DOLLAR)) {
  1408. rule = TOK_QNAME;
  1409. }
  1410. if (rule) {
  1411. expr = expr.substr(match.length);
  1412. LOG_DEBUG('XPath token: parse ' + match + ' -- ' + rule.label);
  1413. ahead = {
  1414. tag: rule,
  1415. match: match,
  1416. prec: rule.prec ? rule.prec : 0, // || 0 is removed by the compiler
  1417. expr: makeTokenExpr(match) };
  1418. } else {
  1419. LOG_DEBUG('XPath DONE');
  1420. done = true;
  1421. }
  1422. while (xpathReduce(stack, ahead)) {
  1423. reduce_count+=1;
  1424. LOG_DEBUG('XPATH stack: ' + stackToString(stack));
  1425. }
  1426. }
  1427. LOG_DEBUG('XPATH stack:' + stackToString(stack));
  1428. if (stack.length != 1) {
  1429. throw 'XPath parse error ' + cachekey + ':\n' + stackToString(stack);
  1430. }
  1431. result = stack[0].expr;
  1432. xpathParseCache[cachekey] = result;
  1433. LOG_DEBUG('XPath parse: ' + parse_count + ' / ' +
  1434. lexer_count + ' / ' + reduce_count);
  1435. return result;
  1436. }
  1437. var xpathParseCache = {};
  1438. function xpathCacheLookup(expr) {
  1439. return xpathParseCache[expr];
  1440. }
  1441. function xpathReduce(stack, ahead) {
  1442. var cand = null;
  1443. if (stack.length > 0) {
  1444. var top = stack[stack.length-1];
  1445. var ruleset = xpathRules[top.tag.key];
  1446. if (ruleset) {
  1447. for (var i = 0; i < ruleset.length; ++i) {
  1448. var rule = ruleset[i];
  1449. var match = xpathMatchStack(stack, rule[1]);
  1450. if (match.length) {
  1451. cand = {
  1452. tag: rule[0],
  1453. rule: rule,
  1454. match: match };
  1455. cand.prec = xpathGrammarPrecedence(cand);
  1456. break;
  1457. }
  1458. }
  1459. }
  1460. }
  1461. var ret;
  1462. if (cand && (!ahead || cand.prec > ahead.prec ||
  1463. (ahead.tag.left && cand.prec >= ahead.prec))) {
  1464. for (i = 0; i < cand.match.matchlength; ++i) {
  1465. stack.pop();
  1466. }
  1467. LOG_DEBUG('reduce ' + cand.tag.label + ' ' + cand.prec +
  1468. ' ahead ' + (ahead ? ahead.tag.label + ' ' + ahead.prec +
  1469. (ahead.tag.left ? ' left' : '') : ' none '));
  1470. var matchexpr = UTIL_mapExpr(cand.match, function(m) { return m.expr; });
  1471. cand.expr = cand.rule[3].apply(null, matchexpr);
  1472. stack.push(cand);
  1473. ret = true;
  1474. } else {
  1475. if (ahead) {
  1476. LOG_DEBUG('shift ' + ahead.tag.label + ' ' + ahead.prec +
  1477. (ahead.tag.left ? ' left' : '') +
  1478. ' over ' + (cand ? cand.tag.label + ' ' +
  1479. cand.prec : ' none'));
  1480. stack.push(ahead);
  1481. }
  1482. ret = false;
  1483. }
  1484. return ret;
  1485. }
  1486. function xpathMatchStack(stack, pattern) {
  1487. // NOTE: The stack matches for variable cardinality are
  1488. // greedy but don't do backtracking. This would be an issue only
  1489. // with rules of the form A* A, i.e. with an element with variable
  1490. // cardinality followed by the same element. Since that doesn't
  1491. // occur in the grammar at hand, all matches on the stack are
  1492. // unambiguous.
  1493. var S = stack.length;
  1494. var P = pattern.length;
  1495. var p, s;
  1496. var match = [];
  1497. match.matchlength = 0;
  1498. var ds = 0;
  1499. for (p = P - 1, s = S - 1; p >= 0 && s >= 0; --p, s -= ds) {
  1500. ds = 0;
  1501. var qmatch = [];
  1502. if (pattern[p] == Q_MM) {
  1503. p -= 1;
  1504. match.push(qmatch);
  1505. while (s - ds >= 0 && stack[s - ds].tag == pattern[p]) {
  1506. qmatch.push(stack[s - ds]);
  1507. ds += 1;
  1508. match.matchlength += 1;
  1509. }
  1510. } else if (pattern[p] == Q_01) {
  1511. p -= 1;
  1512. match.push(qmatch);
  1513. while (s - ds >= 0 && ds < 2 && stack[s - ds].tag == pattern[p]) {
  1514. qmatch.push(stack[s - ds]);
  1515. ds += 1;
  1516. match.matchlength += 1;
  1517. }
  1518. } else if (pattern[p] == Q_1M) {
  1519. p -= 1;
  1520. match.push(qmatch);
  1521. if (stack[s].tag == pattern[p]) {
  1522. while (s - ds >= 0 && stack[s - ds].tag == pattern[p]) {
  1523. qmatch.push(stack[s - ds]);
  1524. ds += 1;
  1525. match.matchlength += 1;
  1526. }
  1527. } else {
  1528. return [];
  1529. }
  1530. } else if (stack[s].tag == pattern[p]) {
  1531. match.push(stack[s]);
  1532. ds += 1;
  1533. match.matchlength += 1;
  1534. } else {
  1535. return [];
  1536. }
  1537. UTIL_reverseInplace(qmatch);
  1538. qmatch.expr = UTIL_mapExpr(qmatch, function(m) { return m.expr; });
  1539. }
  1540. UTIL_reverseInplace(match);
  1541. if (p == -1) {
  1542. return match;
  1543. } else {
  1544. return [];
  1545. }
  1546. }
  1547. function xpathTokenPrecedence(tag) {
  1548. return tag.prec || 2;
  1549. }
  1550. function xpathGrammarPrecedence(frame) {
  1551. var ret = 0;
  1552. if (frame.rule) { /* normal reduce */
  1553. if (frame.rule.length >= 3 && frame.rule[2] >= 0) {
  1554. ret = frame.rule[2];
  1555. } else {
  1556. for (var i = 0; i < frame.rule[1].length; ++i) {
  1557. var p = xpathTokenPrecedence(frame.rule[1][i]);
  1558. ret = Math.max(ret, p);
  1559. }

Large files files are truncated, but you can click here to view the full file