ogre.rb 0.1-i686-linux

Sign up to get free protection for your applications and to get access to all the features.
Files changed (430) hide show
  1. data/README +79 -0
  2. data/Rakefile +288 -0
  3. data/doc_src/ogre.rb +246 -0
  4. data/doc_src/ois.rb +67 -0
  5. data/lib/application.rb +146 -0
  6. data/lib/application_frame_listener.rb +302 -0
  7. data/lib/application_loading_bar.rb +115 -0
  8. data/lib/constants.rb +51 -0
  9. data/lib/method_fixes.rb +42 -0
  10. data/lib/ogre.so +0 -0
  11. data/lib/ruby_ois.so +0 -0
  12. data/ogre.rb +25 -0
  13. data/platform.rb +23 -0
  14. data/samples/Ogre.log +261 -0
  15. data/samples/bsp.rb +76 -0
  16. data/samples/cg.dll +0 -0
  17. data/samples/grass.rb +325 -0
  18. data/samples/js3250.dll +0 -0
  19. data/samples/lighting.rb +138 -0
  20. data/samples/media/materials/programs/Grass.cg +30 -0
  21. data/samples/media/materials/programs/OffsetMapping.cg +97 -0
  22. data/samples/media/materials/programs/OffsetMapping.hlsl +135 -0
  23. data/samples/media/materials/programs/OffsetMappingFp.glsl +69 -0
  24. data/samples/media/materials/programs/OffsetMappingVp.glsl +54 -0
  25. data/samples/media/materials/programs/OffsetMapping_specular.asm +44 -0
  26. data/samples/media/materials/scripts/CloudySky.material +17 -0
  27. data/samples/media/materials/scripts/CubeMapping.material +34 -0
  28. data/samples/media/materials/scripts/Flare.material +17 -0
  29. data/samples/media/materials/scripts/Grass.material +63 -0
  30. data/samples/media/materials/scripts/Knot.material +14 -0
  31. data/samples/media/materials/scripts/MorningSkyBox.material +17 -0
  32. data/samples/media/materials/scripts/Offset.material +124 -0
  33. data/samples/media/materials/scripts/Ogre.material +119 -0
  34. data/samples/media/materials/scripts/RZR-002.material +15 -0
  35. data/samples/media/materials/scripts/Razor.material +14 -0
  36. data/samples/media/materials/scripts/Ribbon.material +19 -0
  37. data/samples/media/materials/scripts/RustySteel.material +14 -0
  38. data/samples/media/materials/scripts/SpaceSkyBox.material +17 -0
  39. data/samples/media/materials/scripts/SpaceSkyPlane.material +17 -0
  40. data/samples/media/materials/scripts/TextureEffects.material +15 -0
  41. data/samples/media/materials/scripts/dragon.material +42 -0
  42. data/samples/media/materials/scripts/smoke.material +18 -0
  43. data/samples/media/materials/textures/GreenSkin.jpg +0 -0
  44. data/samples/media/materials/textures/MtlPlat2.jpg +0 -0
  45. data/samples/media/materials/textures/RZR-002.png +0 -0
  46. data/samples/media/materials/textures/RustedMetal.jpg +0 -0
  47. data/samples/media/materials/textures/RustySteel.jpg +0 -0
  48. data/samples/media/materials/textures/Water02.jpg +0 -0
  49. data/samples/media/materials/textures/WeirdEye.png +0 -0
  50. data/samples/media/materials/textures/clouds.jpg +0 -0
  51. data/samples/media/materials/textures/cursor.png +0 -0
  52. data/samples/media/materials/textures/dirt01.jpg +0 -0
  53. data/samples/media/materials/textures/flare.png +0 -0
  54. data/samples/media/materials/textures/gras_02.png +0 -0
  55. data/samples/media/materials/textures/grass_1024.jpg +0 -0
  56. data/samples/media/materials/textures/ogreborder.png +0 -0
  57. data/samples/media/materials/textures/ogreborderUp.png +0 -0
  58. data/samples/media/materials/textures/ribbonband.png +0 -0
  59. data/samples/media/materials/textures/rockwall.tga +0 -0
  60. data/samples/media/materials/textures/rockwall_NH.tga +0 -0
  61. data/samples/media/materials/textures/smoke.png +0 -0
  62. data/samples/media/materials/textures/smokecolors.png +0 -0
  63. data/samples/media/materials/textures/spacesky.jpg +0 -0
  64. data/samples/media/materials/textures/spheremap.png +0 -0
  65. data/samples/media/materials/textures/texmap2.jpg +0 -0
  66. data/samples/media/models/RZR-002.mesh +0 -0
  67. data/samples/media/models/geosphere4500.mesh +0 -0
  68. data/samples/media/models/geosphere8000.mesh +0 -0
  69. data/samples/media/models/knot.mesh +0 -0
  70. data/samples/media/models/ogrehead.mesh +0 -0
  71. data/samples/media/models/razor.mesh +0 -0
  72. data/samples/media/models/sphere.mesh +0 -0
  73. data/samples/media/overlays/CubeMapping.overlay +139 -0
  74. data/samples/media/packs/OgreCore.zip +0 -0
  75. data/samples/media/packs/chiropteraDM.pk3 +0 -0
  76. data/samples/media/packs/chiropteraDM.txt +99 -0
  77. data/samples/media/packs/cubemap.zip +0 -0
  78. data/samples/media/packs/cubemapsJS.zip +0 -0
  79. data/samples/media/packs/dragon.zip +0 -0
  80. data/samples/media/packs/skybox.zip +0 -0
  81. data/samples/media/particles/smoke.particle +43 -0
  82. data/samples/media.cfg +22 -0
  83. data/samples/navi/Media/NaviDemo.material +60 -0
  84. data/samples/navi/Media/OgreCore.zip +0 -0
  85. data/samples/navi/Media/cerulean.jpg +0 -0
  86. data/samples/navi/Media/clouds.jpg +0 -0
  87. data/samples/navi/Media/controlsNaviMask.png +0 -0
  88. data/samples/navi/Media/grass.jpg +0 -0
  89. data/samples/navi/Media/knot.mesh +0 -0
  90. data/samples/navi/Media/testNaviMask.png +0 -0
  91. data/samples/navi/NaviLocal/Navi.js +136 -0
  92. data/samples/navi/NaviLocal/buttonBg.jpg +0 -0
  93. data/samples/navi/NaviLocal/controls.html +303 -0
  94. data/samples/navi/NaviLocal/knobBg.jpg +0 -0
  95. data/samples/navi/NaviLocal/moo.dropdownmenu.js +87 -0
  96. data/samples/navi/NaviLocal/mootools.v1.1.js +6964 -0
  97. data/samples/navi/NaviLocal/naviLogo.html +32 -0
  98. data/samples/navi/NaviLocal/naviLogo.png +0 -0
  99. data/samples/navi/NaviLocal/pageBg.jpg +0 -0
  100. data/samples/navi/NaviLocal/sliderBg.jpg +0 -0
  101. data/samples/navi/NaviLocal/test.html +5 -0
  102. data/samples/navi/NaviLocal/welcome.html +36 -0
  103. data/samples/navi/NaviLocal/welcome.png +0 -0
  104. data/samples/navi/chrome/chromelist.txt +597 -0
  105. data/samples/navi/chrome/classic.jar +0 -0
  106. data/samples/navi/chrome/classic.manifest +4 -0
  107. data/samples/navi/chrome/comm.jar +0 -0
  108. data/samples/navi/chrome/comm.manifest +2 -0
  109. data/samples/navi/chrome/en-US.jar +0 -0
  110. data/samples/navi/chrome/en-US.manifest +9 -0
  111. data/samples/navi/chrome/toolkit.jar +0 -0
  112. data/samples/navi/chrome/toolkit.manifest +6 -0
  113. data/samples/navi/components/FeedProcessor.js +1825 -0
  114. data/samples/navi/components/alerts.xpt +0 -0
  115. data/samples/navi/components/appshell.xpt +0 -0
  116. data/samples/navi/components/appstartup.xpt +0 -0
  117. data/samples/navi/components/auth.dll +0 -0
  118. data/samples/navi/components/autocomplete.xpt +0 -0
  119. data/samples/navi/components/autoconfig.dll +0 -0
  120. data/samples/navi/components/autoconfig.xpt +0 -0
  121. data/samples/navi/components/caps.xpt +0 -0
  122. data/samples/navi/components/chardet.xpt +0 -0
  123. data/samples/navi/components/chrome.xpt +0 -0
  124. data/samples/navi/components/commandhandler.xpt +0 -0
  125. data/samples/navi/components/commandlines.xpt +0 -0
  126. data/samples/navi/components/composer.xpt +0 -0
  127. data/samples/navi/components/compreg.dat +1474 -0
  128. data/samples/navi/components/content_base.xpt +0 -0
  129. data/samples/navi/components/content_html.xpt +0 -0
  130. data/samples/navi/components/content_htmldoc.xpt +0 -0
  131. data/samples/navi/components/content_xmldoc.xpt +0 -0
  132. data/samples/navi/components/content_xslt.xpt +0 -0
  133. data/samples/navi/components/content_xtf.xpt +0 -0
  134. data/samples/navi/components/directory.xpt +0 -0
  135. data/samples/navi/components/docshell_base.xpt +0 -0
  136. data/samples/navi/components/dom.xpt +0 -0
  137. data/samples/navi/components/dom_base.xpt +0 -0
  138. data/samples/navi/components/dom_canvas.xpt +0 -0
  139. data/samples/navi/components/dom_core.xpt +0 -0
  140. data/samples/navi/components/dom_css.xpt +0 -0
  141. data/samples/navi/components/dom_events.xpt +0 -0
  142. data/samples/navi/components/dom_html.xpt +0 -0
  143. data/samples/navi/components/dom_loadsave.xpt +0 -0
  144. data/samples/navi/components/dom_range.xpt +0 -0
  145. data/samples/navi/components/dom_sidebar.xpt +0 -0
  146. data/samples/navi/components/dom_storage.xpt +0 -0
  147. data/samples/navi/components/dom_stylesheets.xpt +0 -0
  148. data/samples/navi/components/dom_svg.xpt +0 -0
  149. data/samples/navi/components/dom_traversal.xpt +0 -0
  150. data/samples/navi/components/dom_views.xpt +0 -0
  151. data/samples/navi/components/dom_xbl.xpt +0 -0
  152. data/samples/navi/components/dom_xpath.xpt +0 -0
  153. data/samples/navi/components/dom_xul.xpt +0 -0
  154. data/samples/navi/components/downloads.xpt +0 -0
  155. data/samples/navi/components/editor.xpt +0 -0
  156. data/samples/navi/components/embed_base.xpt +0 -0
  157. data/samples/navi/components/extensions.xpt +0 -0
  158. data/samples/navi/components/exthandler.xpt +0 -0
  159. data/samples/navi/components/fastfind.xpt +0 -0
  160. data/samples/navi/components/feeds.xpt +0 -0
  161. data/samples/navi/components/find.xpt +0 -0
  162. data/samples/navi/components/gfx.xpt +0 -0
  163. data/samples/navi/components/gksvgrenderer.xpt +0 -0
  164. data/samples/navi/components/history.xpt +0 -0
  165. data/samples/navi/components/htmlparser.xpt +0 -0
  166. data/samples/navi/components/imglib2.xpt +0 -0
  167. data/samples/navi/components/inspector.xpt +0 -0
  168. data/samples/navi/components/intl.xpt +0 -0
  169. data/samples/navi/components/intlcmpt.xpt +0 -0
  170. data/samples/navi/components/jar.xpt +0 -0
  171. data/samples/navi/components/jsconsole-clhandler.js +170 -0
  172. data/samples/navi/components/jsconsole.xpt +0 -0
  173. data/samples/navi/components/jsdservice.xpt +0 -0
  174. data/samples/navi/components/layout_base.xpt +0 -0
  175. data/samples/navi/components/layout_printing.xpt +0 -0
  176. data/samples/navi/components/layout_xul.xpt +0 -0
  177. data/samples/navi/components/layout_xul_tree.xpt +0 -0
  178. data/samples/navi/components/locale.xpt +0 -0
  179. data/samples/navi/components/lwbrk.xpt +0 -0
  180. data/samples/navi/components/mimetype.xpt +0 -0
  181. data/samples/navi/components/mozbrwsr.xpt +0 -0
  182. data/samples/navi/components/mozfind.xpt +0 -0
  183. data/samples/navi/components/necko.xpt +0 -0
  184. data/samples/navi/components/necko_about.xpt +0 -0
  185. data/samples/navi/components/necko_cache.xpt +0 -0
  186. data/samples/navi/components/necko_cookie.xpt +0 -0
  187. data/samples/navi/components/necko_data.xpt +0 -0
  188. data/samples/navi/components/necko_dns.xpt +0 -0
  189. data/samples/navi/components/necko_file.xpt +0 -0
  190. data/samples/navi/components/necko_ftp.xpt +0 -0
  191. data/samples/navi/components/necko_http.xpt +0 -0
  192. data/samples/navi/components/necko_res.xpt +0 -0
  193. data/samples/navi/components/necko_socket.xpt +0 -0
  194. data/samples/navi/components/necko_strconv.xpt +0 -0
  195. data/samples/navi/components/necko_viewsource.xpt +0 -0
  196. data/samples/navi/components/nsCloseAllWindows.js +143 -0
  197. data/samples/navi/components/nsDefaultCLH.js +231 -0
  198. data/samples/navi/components/nsDictionary.js +148 -0
  199. data/samples/navi/components/nsExtensionManager.js +8497 -0
  200. data/samples/navi/components/nsHelperAppDlg.js +990 -0
  201. data/samples/navi/components/nsInterfaceInfoToIDL.js +590 -0
  202. data/samples/navi/components/nsKillAll.js +200 -0
  203. data/samples/navi/components/nsPostUpdateWin.js +711 -0
  204. data/samples/navi/components/nsProgressDialog.js +949 -0
  205. data/samples/navi/components/nsProxyAutoConfig.js +396 -0
  206. data/samples/navi/components/nsResetPref.js +175 -0
  207. data/samples/navi/components/nsURLFormatter.js +179 -0
  208. data/samples/navi/components/nsUpdateService.js +3074 -0
  209. data/samples/navi/components/nsXULAppInstall.js +301 -0
  210. data/samples/navi/components/nsXmlRpcClient.js +1038 -0
  211. data/samples/navi/components/oji.xpt +0 -0
  212. data/samples/navi/components/passwordmgr.xpt +0 -0
  213. data/samples/navi/components/pipboot.xpt +0 -0
  214. data/samples/navi/components/pipnss.xpt +0 -0
  215. data/samples/navi/components/plugin.xpt +0 -0
  216. data/samples/navi/components/pref.xpt +0 -0
  217. data/samples/navi/components/prefetch.xpt +0 -0
  218. data/samples/navi/components/profile.xpt +0 -0
  219. data/samples/navi/components/progressDlg.xpt +0 -0
  220. data/samples/navi/components/proxyObject.xpt +0 -0
  221. data/samples/navi/components/rdf.xpt +0 -0
  222. data/samples/navi/components/satchel.xpt +0 -0
  223. data/samples/navi/components/saxparser.xpt +0 -0
  224. data/samples/navi/components/shistory.xpt +0 -0
  225. data/samples/navi/components/storage.xpt +0 -0
  226. data/samples/navi/components/toolkitprofile.xpt +0 -0
  227. data/samples/navi/components/transformiix.dll +0 -0
  228. data/samples/navi/components/txmgr.xpt +0 -0
  229. data/samples/navi/components/txtsvc.xpt +0 -0
  230. data/samples/navi/components/uconv.xpt +0 -0
  231. data/samples/navi/components/unicharutil.xpt +0 -0
  232. data/samples/navi/components/universalchardet.dll +0 -0
  233. data/samples/navi/components/update.xpt +0 -0
  234. data/samples/navi/components/uriloader.xpt +0 -0
  235. data/samples/navi/components/urlformatter.xpt +0 -0
  236. data/samples/navi/components/webBrowser_core.xpt +0 -0
  237. data/samples/navi/components/webbrowserpersist.xpt +0 -0
  238. data/samples/navi/components/webshell_idls.xpt +0 -0
  239. data/samples/navi/components/websrvcs.dll +0 -0
  240. data/samples/navi/components/websrvcs.xpt +0 -0
  241. data/samples/navi/components/widget.xpt +0 -0
  242. data/samples/navi/components/windowds.xpt +0 -0
  243. data/samples/navi/components/windowwatcher.xpt +0 -0
  244. data/samples/navi/components/xml-rpc.xpt +0 -0
  245. data/samples/navi/components/xmlextras.dll +0 -0
  246. data/samples/navi/components/xpcom_base.xpt +0 -0
  247. data/samples/navi/components/xpcom_components.xpt +0 -0
  248. data/samples/navi/components/xpcom_ds.xpt +0 -0
  249. data/samples/navi/components/xpcom_io.xpt +0 -0
  250. data/samples/navi/components/xpcom_obsolete.xpt +0 -0
  251. data/samples/navi/components/xpcom_thread.xpt +0 -0
  252. data/samples/navi/components/xpcom_xpti.xpt +0 -0
  253. data/samples/navi/components/xpconnect.xpt +0 -0
  254. data/samples/navi/components/xpinstall.xpt +0 -0
  255. data/samples/navi/components/xpti.dat +1424 -0
  256. data/samples/navi/components/xulapp.xpt +0 -0
  257. data/samples/navi/components/xulapp_setup.xpt +0 -0
  258. data/samples/navi/components/xuldoc.xpt +0 -0
  259. data/samples/navi/components/xulrunner.xpt +0 -0
  260. data/samples/navi/components/xultmpl.xpt +0 -0
  261. data/samples/navi/components/xulutil.dll +0 -0
  262. data/samples/navi/controlsNaviMask.png +0 -0
  263. data/samples/navi/greprefs/all.js +1344 -0
  264. data/samples/navi/greprefs/security-prefs.js +69 -0
  265. data/samples/navi/greprefs/xpinstall.js +2 -0
  266. data/samples/navi/navi_demo.rb +207 -0
  267. data/samples/navi/plugins/NPSWF32.dll +0 -0
  268. data/samples/navi/plugins/flashplayer.xpt +0 -0
  269. data/samples/navi/plugins/npnul32.dll +0 -0
  270. data/samples/navi/plugins.cfg +10 -0
  271. data/samples/navi/res/EditorOverride.css +359 -0
  272. data/samples/navi/res/Thumbs.db +0 -0
  273. data/samples/navi/res/arrow.gif +0 -0
  274. data/samples/navi/res/arrowd.gif +0 -0
  275. data/samples/navi/res/bloatcycle.html +40 -0
  276. data/samples/navi/res/broken-image.gif +0 -0
  277. data/samples/navi/res/charsetData.properties +199 -0
  278. data/samples/navi/res/charsetalias.properties +517 -0
  279. data/samples/navi/res/cmessage.txt +1 -0
  280. data/samples/navi/res/dtd/xhtml11.dtd +300 -0
  281. data/samples/navi/res/entityTables/html40Latin1.properties +146 -0
  282. data/samples/navi/res/entityTables/html40Special.properties +69 -0
  283. data/samples/navi/res/entityTables/html40Symbols.properties +164 -0
  284. data/samples/navi/res/entityTables/htmlEntityVersions.properties +50 -0
  285. data/samples/navi/res/entityTables/transliterate.properties +2367 -0
  286. data/samples/navi/res/fonts/fontEncoding.properties +127 -0
  287. data/samples/navi/res/fonts/fontNameMap.properties +134 -0
  288. data/samples/navi/res/forms.css +531 -0
  289. data/samples/navi/res/grabber.gif +0 -0
  290. data/samples/navi/res/hiddenWindow.html +1 -0
  291. data/samples/navi/res/html/Thumbs.db +0 -0
  292. data/samples/navi/res/html/gopher-audio.gif +0 -0
  293. data/samples/navi/res/html/gopher-binary.gif +0 -0
  294. data/samples/navi/res/html/gopher-find.gif +0 -0
  295. data/samples/navi/res/html/gopher-image.gif +0 -0
  296. data/samples/navi/res/html/gopher-menu.gif +0 -0
  297. data/samples/navi/res/html/gopher-movie.gif +0 -0
  298. data/samples/navi/res/html/gopher-sound.gif +0 -0
  299. data/samples/navi/res/html/gopher-telnet.gif +0 -0
  300. data/samples/navi/res/html/gopher-text.gif +0 -0
  301. data/samples/navi/res/html/gopher-unknown.gif +0 -0
  302. data/samples/navi/res/html.css +478 -0
  303. data/samples/navi/res/langGroups.properties +236 -0
  304. data/samples/navi/res/language.properties +259 -0
  305. data/samples/navi/res/loading-image.gif +0 -0
  306. data/samples/navi/res/quirk.css +282 -0
  307. data/samples/navi/res/samples/Anieyes.gif +0 -0
  308. data/samples/navi/res/samples/Thumbs.db +0 -0
  309. data/samples/navi/res/samples/aform.css +69 -0
  310. data/samples/navi/res/samples/beeptest.html +18 -0
  311. data/samples/navi/res/samples/bform.css +45 -0
  312. data/samples/navi/res/samples/bg.jpg +0 -0
  313. data/samples/navi/res/samples/cform.css +40 -0
  314. data/samples/navi/res/samples/checkboxTest.xul +47 -0
  315. data/samples/navi/res/samples/demoform.css +97 -0
  316. data/samples/navi/res/samples/find.html +97 -0
  317. data/samples/navi/res/samples/gear1.gif +0 -0
  318. data/samples/navi/res/samples/image_props.html +58 -0
  319. data/samples/navi/res/samples/mozform.css +256 -0
  320. data/samples/navi/res/samples/printsetup.html +175 -0
  321. data/samples/navi/res/samples/raptor.jpg +0 -0
  322. data/samples/navi/res/samples/rock_gra.gif +0 -0
  323. data/samples/navi/res/samples/scrollbarTest1.xul +66 -0
  324. data/samples/navi/res/samples/scrollbarTest2.xul +19 -0
  325. data/samples/navi/res/samples/sliderTest1.xul +14 -0
  326. data/samples/navi/res/samples/soundtest.html +20 -0
  327. data/samples/navi/res/samples/test.wav +0 -0
  328. data/samples/navi/res/samples/test0.html +220 -0
  329. data/samples/navi/res/samples/test1.html +84 -0
  330. data/samples/navi/res/samples/test10.html +16 -0
  331. data/samples/navi/res/samples/test11.html +42 -0
  332. data/samples/navi/res/samples/test12.html +79 -0
  333. data/samples/navi/res/samples/test13.html +126 -0
  334. data/samples/navi/res/samples/test14.html +5 -0
  335. data/samples/navi/res/samples/test15.html +5 -0
  336. data/samples/navi/res/samples/test16.html +124 -0
  337. data/samples/navi/res/samples/test2.html +41 -0
  338. data/samples/navi/res/samples/test3.html +126 -0
  339. data/samples/navi/res/samples/test4.html +335 -0
  340. data/samples/navi/res/samples/test5.html +199 -0
  341. data/samples/navi/res/samples/test6.html +335 -0
  342. data/samples/navi/res/samples/test7.html +11 -0
  343. data/samples/navi/res/samples/test8-1.html +66 -0
  344. data/samples/navi/res/samples/test8.html +662 -0
  345. data/samples/navi/res/samples/test8dom.html +64 -0
  346. data/samples/navi/res/samples/test8sca.html +308 -0
  347. data/samples/navi/res/samples/test8siz.html +224 -0
  348. data/samples/navi/res/samples/test8tab.html +9 -0
  349. data/samples/navi/res/samples/test9.html +12 -0
  350. data/samples/navi/res/samples/test9a.html +39 -0
  351. data/samples/navi/res/samples/test9b.html +16 -0
  352. data/samples/navi/res/samples/test_ed.html +5 -0
  353. data/samples/navi/res/samples/test_form.html +34 -0
  354. data/samples/navi/res/samples/test_gfx.html +75 -0
  355. data/samples/navi/res/samples/test_lbox.html +100 -0
  356. data/samples/navi/res/samples/test_pr.html +87 -0
  357. data/samples/navi/res/samples/test_weight.html +45 -0
  358. data/samples/navi/res/samples/toolbarTest1.xul +51 -0
  359. data/samples/navi/res/samples/treeTest1.css +62 -0
  360. data/samples/navi/res/samples/treeTest1.xul +110 -0
  361. data/samples/navi/res/samples/xulTest.css +130 -0
  362. data/samples/navi/res/svg.css +64 -0
  363. data/samples/navi/res/table-add-column-after-active.gif +0 -0
  364. data/samples/navi/res/table-add-column-after-hover.gif +0 -0
  365. data/samples/navi/res/table-add-column-after.gif +0 -0
  366. data/samples/navi/res/table-add-column-before-active.gif +0 -0
  367. data/samples/navi/res/table-add-column-before-hover.gif +0 -0
  368. data/samples/navi/res/table-add-column-before.gif +0 -0
  369. data/samples/navi/res/table-add-row-after-active.gif +0 -0
  370. data/samples/navi/res/table-add-row-after-hover.gif +0 -0
  371. data/samples/navi/res/table-add-row-after.gif +0 -0
  372. data/samples/navi/res/table-add-row-before-active.gif +0 -0
  373. data/samples/navi/res/table-add-row-before-hover.gif +0 -0
  374. data/samples/navi/res/table-add-row-before.gif +0 -0
  375. data/samples/navi/res/table-remove-column-active.gif +0 -0
  376. data/samples/navi/res/table-remove-column-hover.gif +0 -0
  377. data/samples/navi/res/table-remove-column.gif +0 -0
  378. data/samples/navi/res/table-remove-row-active.gif +0 -0
  379. data/samples/navi/res/table-remove-row-hover.gif +0 -0
  380. data/samples/navi/res/table-remove-row.gif +0 -0
  381. data/samples/navi/res/throbber/Thumbs.db +0 -0
  382. data/samples/navi/res/throbber/anim.gif +0 -0
  383. data/samples/navi/res/throbber/anims00.gif +0 -0
  384. data/samples/navi/res/throbber/anims01.gif +0 -0
  385. data/samples/navi/res/throbber/anims02.gif +0 -0
  386. data/samples/navi/res/throbber/anims03.gif +0 -0
  387. data/samples/navi/res/throbber/anims04.gif +0 -0
  388. data/samples/navi/res/throbber/anims05.gif +0 -0
  389. data/samples/navi/res/throbber/anims06.gif +0 -0
  390. data/samples/navi/res/throbber/anims07.gif +0 -0
  391. data/samples/navi/res/throbber/anims08.gif +0 -0
  392. data/samples/navi/res/throbber/anims09.gif +0 -0
  393. data/samples/navi/res/throbber/anims10.gif +0 -0
  394. data/samples/navi/res/throbber/anims11.gif +0 -0
  395. data/samples/navi/res/throbber/anims12.gif +0 -0
  396. data/samples/navi/res/throbber/anims13.gif +0 -0
  397. data/samples/navi/res/throbber/anims14.gif +0 -0
  398. data/samples/navi/res/throbber/anims15.gif +0 -0
  399. data/samples/navi/res/throbber/anims16.gif +0 -0
  400. data/samples/navi/res/throbber/anims17.gif +0 -0
  401. data/samples/navi/res/throbber/anims18.gif +0 -0
  402. data/samples/navi/res/throbber/anims19.gif +0 -0
  403. data/samples/navi/res/throbber/anims20.gif +0 -0
  404. data/samples/navi/res/throbber/anims21.gif +0 -0
  405. data/samples/navi/res/throbber/anims22.gif +0 -0
  406. data/samples/navi/res/throbber/anims23.gif +0 -0
  407. data/samples/navi/res/throbber/anims24.gif +0 -0
  408. data/samples/navi/res/throbber/anims25.gif +0 -0
  409. data/samples/navi/res/throbber/anims26.gif +0 -0
  410. data/samples/navi/res/throbber/anims27.gif +0 -0
  411. data/samples/navi/res/throbber/anims28.gif +0 -0
  412. data/samples/navi/res/throbber/anims29.gif +0 -0
  413. data/samples/navi/res/ua.css +235 -0
  414. data/samples/navi/res/viewer.properties +1 -0
  415. data/samples/navi/res/viewsource.css +118 -0
  416. data/samples/navi/res/wincharset.properties +55 -0
  417. data/samples/navi/resources.cfg +14 -0
  418. data/samples/navi/testNaviMask.png +0 -0
  419. data/samples/ogre.cfg +8 -0
  420. data/samples/plugins.cfg +11 -0
  421. data/samples/quake3settings.cfg +2 -0
  422. data/samples/render_run_log.5796 +891 -0
  423. data/samples/render_to_texture.rb +161 -0
  424. data/samples/resources.cfg +16 -0
  425. data/samples/sky_box.rb +107 -0
  426. data/samples/sky_dome.rb +86 -0
  427. data/samples/sky_plane.rb +27 -0
  428. data/samples/smoke.rb +23 -0
  429. data/samples/work/cube_mapping.rb +686 -0
  430. metadata +500 -0
@@ -0,0 +1,1825 @@
1
+ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
+ /* ***** BEGIN LICENSE BLOCK *****
3
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4
+ *
5
+ * The contents of this file are subject to the Mozilla Public License Version
6
+ * 1.1 (the "License"); you may not use this file except in compliance with
7
+ * the License. You may obtain a copy of the License at
8
+ * http://www.mozilla.org/MPL/
9
+ *
10
+ * Software distributed under the License is distributed on an "AS IS" basis,
11
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12
+ * for the specific language governing rights and limitations under the
13
+ * License.
14
+ *
15
+ * The Original Code is mozilla.org code.
16
+ *
17
+ * The Initial Developer of the Original Code is Robert Sayre.
18
+ * Portions created by the Initial Developer are Copyright (C) 2006
19
+ * the Initial Developer. All Rights Reserved.
20
+ *
21
+ * Contributor(s):
22
+ * Ben Goodger <beng@google.com>
23
+ * Myk Melez <myk@mozilla.org>
24
+ *
25
+ * Alternatively, the contents of this file may be used under the terms of
26
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
27
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28
+ * in which case the provisions of the GPL or the LGPL are applicable instead
29
+ * of those above. If you wish to allow use of your version of this file only
30
+ * under the terms of either the GPL or the LGPL, and not to allow others to
31
+ * use your version of this file under the terms of the MPL, indicate your
32
+ * decision by deleting the provisions above and replace them with the notice
33
+ * and other provisions required by the GPL or the LGPL. If you do not delete
34
+ * the provisions above, a recipient may use your version of this file under
35
+ * the terms of any one of the MPL, the GPL or the LGPL.
36
+ *
37
+ * ***** END LICENSE BLOCK ***** */
38
+
39
+ function LOG(str) {
40
+ dump("*** " + str + "\n");
41
+ }
42
+
43
+ const Ci = Components.interfaces;
44
+ const Cc = Components.classes;
45
+ const Cr = Components.results;
46
+
47
+ const IO_CONTRACTID = "@mozilla.org/network/io-service;1"
48
+ const BAG_CONTRACTID = "@mozilla.org/hash-property-bag;1"
49
+ const ARRAY_CONTRACTID = "@mozilla.org/array;1";
50
+ const SAX_CONTRACTID = "@mozilla.org/saxparser/xmlreader;1";
51
+ const UNESCAPE_CONTRACTID = "@mozilla.org/feed-unescapehtml;1";
52
+
53
+ var gIoService = Cc[IO_CONTRACTID].getService(Ci.nsIIOService);
54
+ var gUnescapeHTML = Cc[UNESCAPE_CONTRACTID].
55
+ getService(Ci.nsIScriptableUnescapeHTML);
56
+
57
+ const XMLNS = "http://www.w3.org/XML/1998/namespace";
58
+ const RSS090NS = "http://my.netscape.com/rdf/simple/0.9/";
59
+
60
+ /***** Some general utils *****/
61
+ function strToURI(link, base) {
62
+ var base = base || null;
63
+ try {
64
+ return gIoService.newURI(link, null, base);
65
+ }
66
+ catch(e) {
67
+ return null;
68
+ }
69
+ }
70
+
71
+ function isArray(a) {
72
+ return isObject(a) && a.constructor == Array;
73
+ }
74
+
75
+ function isObject(a) {
76
+ return (a && typeof a == "object") || isFunction(a);
77
+ }
78
+
79
+ function isFunction(a) {
80
+ return typeof a == "function";
81
+ }
82
+
83
+ function isIID(a, iid) {
84
+ var rv = false;
85
+ try {
86
+ a.QueryInterface(iid);
87
+ rv = true;
88
+ }
89
+ catch(e) {
90
+ }
91
+ return rv;
92
+ }
93
+
94
+ function isIArray(a) {
95
+ return isIID(a, Ci.nsIArray);
96
+ }
97
+
98
+ function isIFeedContainer(a) {
99
+ return isIID(a, Ci.nsIFeedContainer);
100
+ }
101
+
102
+ function stripTags(someHTML) {
103
+ return someHTML.replace(/<[^>]+>/g,"");
104
+ }
105
+
106
+ /**
107
+ * Searches through an array of links and returns a JS array
108
+ * of matching property bags.
109
+ */
110
+ const IANA_URI = "http://www.iana.org/assignments/relation/";
111
+ function findAtomLinks(rel, links) {
112
+ var rvLinks = [];
113
+ for (var i = 0; i < links.length; ++i) {
114
+ var linkElement = links.queryElementAt(i, Ci.nsIPropertyBag2);
115
+ // atom:link MUST have @href
116
+ if (bagHasKey(linkElement, "href")) {
117
+ var relAttribute = null;
118
+ if (bagHasKey(linkElement, "rel"))
119
+ relAttribute = linkElement.getPropertyAsAString("rel")
120
+ if ((!relAttribute && rel == "alternate") || relAttribute == rel) {
121
+ rvLinks.push(linkElement);
122
+ continue;
123
+ }
124
+ // catch relations specified by IANA URI
125
+ if (relAttribute == IANA_URI + rel) {
126
+ rvLinks.push(linkElement);
127
+ }
128
+ }
129
+ }
130
+ return rvLinks;
131
+ }
132
+
133
+ function xmlEscape(s) {
134
+ s = s.replace(/&/g, "&amp;");
135
+ s = s.replace(/>/g, "&gt;");
136
+ s = s.replace(/</g, "&lt;");
137
+ s = s.replace(/"/g, "&quot;");
138
+ s = s.replace(/'/g, "&apos;");
139
+ return s;
140
+ }
141
+
142
+ function arrayContains(array, element) {
143
+ for (var i = 0; i < array.length; ++i) {
144
+ if (array[i] == element) {
145
+ return true;
146
+ }
147
+ }
148
+ return false;
149
+ }
150
+
151
+ // XXX add hasKey to nsIPropertyBag
152
+ function bagHasKey(bag, key) {
153
+ try {
154
+ bag.getProperty(key);
155
+ return true;
156
+ }
157
+ catch (e) {
158
+ return false;
159
+ }
160
+ }
161
+
162
+ function makePropGetter(key) {
163
+ return function FeedPropGetter(bag) {
164
+ try {
165
+ return value = bag.getProperty(key);
166
+ }
167
+ catch(e) {
168
+ }
169
+ return null;
170
+ }
171
+ }
172
+
173
+
174
+
175
+ /**
176
+ * XXX Thunderbird's W3C-DTF function
177
+ *
178
+ * Converts a W3C-DTF (subset of ISO 8601) date string to an IETF date
179
+ * string. W3C-DTF is described in this note:
180
+ * http://www.w3.org/TR/NOTE-datetime IETF is obtained via the Date
181
+ * object's toUTCString() method. The object's toString() method is
182
+ * insufficient because it spells out timezones on Win32
183
+ * (f.e. "Pacific Standard Time" instead of "PST"), which Mail doesn't
184
+ * grok. For info, see
185
+ * http://lxr.mozilla.org/mozilla/source/js/src/jsdate.c#1526.
186
+ */
187
+ const HOURS_TO_MINUTES = 60;
188
+ const MINUTES_TO_SECONDS = 60;
189
+ const SECONDS_TO_MILLISECONDS = 1000;
190
+ const MINUTES_TO_MILLISECONDS = MINUTES_TO_SECONDS * SECONDS_TO_MILLISECONDS;
191
+ const HOURS_TO_MILLISECONDS = HOURS_TO_MINUTES * MINUTES_TO_MILLISECONDS;
192
+ function W3CToIETFDate(dateString) {
193
+
194
+ var parts = dateString.match(/(\d\d\d\d)(-(\d\d))?(-(\d\d))?(T(\d\d):(\d\d)(:(\d\d)(\.(\d+))?)?(Z|([+-])(\d\d):(\d\d))?)?/);
195
+
196
+ // Here's an example of a W3C-DTF date string and what .match returns for it.
197
+ //
198
+ // date: 2003-05-30T11:18:50.345-08:00
199
+ // date.match returns array values:
200
+ //
201
+ // 0: 2003-05-30T11:18:50-08:00,
202
+ // 1: 2003,
203
+ // 2: -05,
204
+ // 3: 05,
205
+ // 4: -30,
206
+ // 5: 30,
207
+ // 6: T11:18:50-08:00,
208
+ // 7: 11,
209
+ // 8: 18,
210
+ // 9: :50,
211
+ // 10: 50,
212
+ // 11: .345,
213
+ // 12: 345,
214
+ // 13: -08:00,
215
+ // 14: -,
216
+ // 15: 08,
217
+ // 16: 00
218
+
219
+ // Create a Date object from the date parts. Note that the Date
220
+ // object apparently can't deal with empty string parameters in lieu
221
+ // of numbers, so optional values (like hours, minutes, seconds, and
222
+ // milliseconds) must be forced to be numbers.
223
+ var date = new Date(parts[1], parts[3] - 1, parts[5], parts[7] || 0,
224
+ parts[8] || 0, parts[10] || 0, parts[12] || 0);
225
+
226
+ // We now have a value that the Date object thinks is in the local
227
+ // timezone but which actually represents the date/time in the
228
+ // remote timezone (f.e. the value was "10:00 EST", and we have
229
+ // converted it to "10:00 PST" instead of "07:00 PST"). We need to
230
+ // correct that. To do so, we're going to add the offset between
231
+ // the remote timezone and UTC (to convert the value to UTC), then
232
+ // add the offset between UTC and the local timezone //(to convert
233
+ // the value to the local timezone).
234
+
235
+ // Ironically, W3C-DTF gives us the offset between UTC and the
236
+ // remote timezone rather than the other way around, while the
237
+ // getTimezoneOffset() method of a Date object gives us the offset
238
+ // between the local timezone and UTC rather than the other way
239
+ // around. Both of these are the additive inverse (i.e. -x for x)
240
+ // of what we want, so we have to invert them to use them by
241
+ // multipying by -1 (f.e. if "the offset between UTC and the remote
242
+ // timezone" is -5 hours, then "the offset between the remote
243
+ // timezone and UTC" is -5*-1 = 5 hours).
244
+
245
+ // Note that if the timezone portion of the date/time string is
246
+ // absent (which violates W3C-DTF, although ISO 8601 allows it), we
247
+ // assume the value to be in UTC.
248
+
249
+ // The offset between the remote timezone and UTC in milliseconds.
250
+ var remoteToUTCOffset = 0;
251
+ if (parts[13] && parts[13] != "Z") {
252
+ var direction = (parts[14] == "+" ? 1 : -1);
253
+ if (parts[15])
254
+ remoteToUTCOffset += direction * parts[15] * HOURS_TO_MILLISECONDS;
255
+ if (parts[16])
256
+ remoteToUTCOffset += direction * parts[16] * MINUTES_TO_MILLISECONDS;
257
+ }
258
+ remoteToUTCOffset = remoteToUTCOffset * -1; // invert it
259
+
260
+ // The offset between UTC and the local timezone in milliseconds.
261
+ var UTCToLocalOffset = date.getTimezoneOffset() * MINUTES_TO_MILLISECONDS;
262
+ UTCToLocalOffset = UTCToLocalOffset * -1; // invert it
263
+ date.setTime(date.getTime() + remoteToUTCOffset + UTCToLocalOffset);
264
+
265
+ return date.toUTCString();
266
+ }
267
+
268
+ const RDF_NS = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
269
+ // namespace map
270
+ var gNamespaces = {
271
+ "http://webns.net/mvcb/":"admin",
272
+ "http://backend.userland.com/rss":"",
273
+ "http://blogs.law.harvard.edu/tech/rss":"",
274
+ "http://www.w3.org/2005/Atom":"atom",
275
+ "http://purl.org/atom/ns#":"atom03",
276
+ "http://purl.org/rss/1.0/modules/content/":"content",
277
+ "http://purl.org/dc/elements/1.1/":"dc",
278
+ "http://purl.org/dc/terms/":"dcterms",
279
+ "http://www.w3.org/1999/02/22-rdf-syntax-ns#":"rdf",
280
+ "http://purl.org/rss/1.0/":"rss1",
281
+ "http://my.netscape.com/rdf/simple/0.9/":"rss1",
282
+ "http://wellformedweb.org/CommentAPI/":"wfw",
283
+ "http://purl.org/rss/1.0/modules/wiki/":"wiki",
284
+ "http://www.w3.org/XML/1998/namespace":"xml"
285
+ }
286
+
287
+
288
+ function FeedResult() {}
289
+ FeedResult.prototype = {
290
+ bozo: false,
291
+ doc: null,
292
+ version: null,
293
+ headers: null,
294
+ uri: null,
295
+ stylesheet: null,
296
+
297
+ registerExtensionPrefix: function FR_registerExtensionPrefix(ns, prefix) {
298
+ throw Cr.NS_ERROR_NOT_IMPLEMENTED;
299
+ },
300
+
301
+ QueryInterface: function FR_QI(iid) {
302
+ if (iid.equals(Ci.nsIFeedResult) ||
303
+ iid.equals(Ci.nsISupports))
304
+ return this;
305
+
306
+ throw Cr.NS_ERROR_NOINTERFACE;
307
+ },
308
+ }
309
+
310
+ function Feed() {
311
+ this.subtitle = null;
312
+ this.title = null;
313
+ this.items = Cc[ARRAY_CONTRACTID].createInstance(Ci.nsIMutableArray);
314
+ this.link = null;
315
+ this.id = null;
316
+ this.generator = null;
317
+ this.authors = Cc[ARRAY_CONTRACTID].createInstance(Ci.nsIMutableArray);
318
+ this.contributors = Cc[ARRAY_CONTRACTID].createInstance(Ci.nsIMutableArray);
319
+ this.baseURI = null;
320
+ }
321
+
322
+ Feed.prototype = {
323
+ searchLists: {
324
+ subtitle: ["description","dc:description","rss1:description",
325
+ "atom03:tagline","atom:subtitle"],
326
+ items: ["items","atom03_entries","entries"],
327
+ id: ["atom:id","rdf:about"],
328
+ generator: ["generator"],
329
+ authors : ["authors"],
330
+ contributors: ["contributors"],
331
+ title: ["title","rss1:title", "atom03:title","atom:title"],
332
+ link: [["link",strToURI],["rss1:link",strToURI]],
333
+ categories: ["categories", "dc:subject"],
334
+ rights: ["atom03:rights","atom:rights"],
335
+ cloud: ["cloud"],
336
+ image: ["image", "rss1:image", "atom:logo"],
337
+ textInput: ["textInput", "rss1:textinput"],
338
+ skipDays: ["skipDays"],
339
+ skipHours: ["skipHours"],
340
+ updated: ["pubDate", "lastBuildDate", "atom03:modified", "dc:date",
341
+ "dcterms:modified", "atom:updated"]
342
+ },
343
+
344
+ normalize: function Feed_normalize() {
345
+ fieldsToObj(this, this.searchLists);
346
+ if (this.skipDays)
347
+ this.skipDays = this.skipDays.getProperty("days");
348
+ if (this.skipHours)
349
+ this.skipHours = this.skipHours.getProperty("hours");
350
+
351
+ if (this.updated)
352
+ this.updated = dateParse(this.updated);
353
+
354
+ // Assign Atom link if needed
355
+ if (bagHasKey(this.fields, "links"))
356
+ this._atomLinksToURI();
357
+
358
+ // Resolve relative image links
359
+ if (this.image && bagHasKey(this.image, "url")) {
360
+ this._resolveImageLink();
361
+ }
362
+
363
+ this._resetBagMembersToRawText([this.searchLists.subtitle,
364
+ this.searchLists.title]);
365
+ },
366
+
367
+ _atomLinksToURI: function Feed_linkToURI() {
368
+ var links = this.fields.getPropertyAsInterface("links", Ci.nsIArray);
369
+ var alternates = findAtomLinks("alternate", links);
370
+ if (alternates.length > 0) {
371
+ var href = alternates[0].getPropertyAsAString("href");
372
+ var base;
373
+ if (bagHasKey(alternates[0], "xml:base"))
374
+ base = alternates[0].getPropertyAsAString("xml:base");
375
+ this.link = this._resolveURI(href, base);
376
+ }
377
+ },
378
+
379
+ _resolveImageLink: function Feed_resolveImageLink() {
380
+ var base;
381
+ if (bagHasKey(this.image, "xml:base"))
382
+ base = this.image.getPropertyAsAString("xml:base");
383
+ var url = this._resolveURI(this.image.getPropertyAsAString("url"), base);
384
+ if (url)
385
+ this.image.setPropertyAsAString("url", url.spec);
386
+ },
387
+
388
+ _resolveURI: function Feed_resolveURI(linkSpec, baseSpec) {
389
+ var uri = null;
390
+ try {
391
+ var base = baseSpec ? strToURI(baseSpec, this.baseURI) : this.baseURI;
392
+ uri = strToURI(linkSpec, base);
393
+ }
394
+ catch(e) {
395
+ LOG(e);
396
+ }
397
+
398
+ return uri;
399
+ },
400
+
401
+ // reset the bag to raw contents, not text constructs
402
+ _resetBagMembersToRawText: function Feed_resetBagMembers(fieldLists) {
403
+ for (var i=0; i<fieldLists.length; i++) {
404
+ for (var j=0; j<fieldLists[i].length; j++) {
405
+ if (bagHasKey(this.fields, fieldLists[i][j])) {
406
+ var textConstruct = this.fields.getProperty(fieldLists[i][j]);
407
+ this.fields.setPropertyAsAString(fieldLists[i][j],
408
+ textConstruct.text);
409
+ }
410
+ }
411
+ }
412
+ },
413
+
414
+ QueryInterface: function Feed_QI(iid) {
415
+ if (iid.equals(Ci.nsIFeed) ||
416
+ iid.equals(Ci.nsIFeedContainer) ||
417
+ iid.equals(Ci.nsISupports))
418
+ return this;
419
+ throw Cr.NS_ERROR_NOINTERFACE;
420
+ }
421
+ }
422
+
423
+ function Entry() {
424
+ this.summary = null;
425
+ this.content = null;
426
+ this.title = null;
427
+ this.fields = Cc["@mozilla.org/hash-property-bag;1"].
428
+ createInstance(Ci.nsIWritablePropertyBag2);
429
+ this.link = null;
430
+ this.id = null;
431
+ this.baseURI = null;
432
+ this.updated = null;
433
+ this.published = null;
434
+ this.authors = Cc[ARRAY_CONTRACTID].createInstance(Ci.nsIMutableArray);
435
+ this.contributors = Cc[ARRAY_CONTRACTID].createInstance(Ci.nsIMutableArray);
436
+ }
437
+
438
+ Entry.prototype = {
439
+ fields: null,
440
+ enclosures: null,
441
+ mediaContent: null,
442
+
443
+ searchLists: {
444
+ title: ["title", "rss1:title", "atom03:title", "atom:title"],
445
+ link: [["link",strToURI],["rss1:link",strToURI]],
446
+ id: [["guid", makePropGetter("guid")], "rdf:about",
447
+ "atom03:id", "atom:id"],
448
+ authors : ["authors"],
449
+ contributors: ["contributors"],
450
+ summary: ["description", "rss1:description", "dc:description",
451
+ "atom03:summary", "atom:summary"],
452
+ content: ["content:encoded","atom03:content","atom:content"],
453
+ rights: ["atom03:rights","atom:rights"],
454
+ published: ["atom03:issued", "dcterms:issued", "atom:published"],
455
+ updated: ["pubDate", "atom03:modified", "dc:date", "dcterms:modified",
456
+ "atom:updated"]
457
+ },
458
+
459
+ normalize: function Entry_normalize() {
460
+ fieldsToObj(this, this.searchLists);
461
+
462
+ // Assign Atom link if needed
463
+ if (bagHasKey(this.fields, "links"))
464
+ this._atomLinksToURI();
465
+
466
+ // The link might be a guid w/ permalink=true
467
+ if (!this.link && bagHasKey(this.fields, "guid")) {
468
+ var guid = this.fields.getProperty("guid");
469
+ var isPermaLink = true;
470
+
471
+ if (bagHasKey(guid, "isPermaLink"))
472
+ isPermaLink = guid.getProperty("isPermaLink").toLowerCase() != "false";
473
+
474
+ if (guid && isPermaLink)
475
+ this.link = strToURI(guid.getProperty("guid"));
476
+ }
477
+
478
+ if (this.updated)
479
+ this.updated = dateParse(this.updated);
480
+ if (this.published)
481
+ this.published = dateParse(this.published);
482
+
483
+ this._resetBagMembersToRawText([this.searchLists.content,
484
+ this.searchLists.summary,
485
+ this.searchLists.title]);
486
+ },
487
+
488
+ QueryInterface: function(iid) {
489
+ if (iid.equals(Ci.nsIFeedEntry) ||
490
+ iid.equals(Ci.nsIFeedContainer) ||
491
+ iid.equals(Ci.nsISupports))
492
+ return this;
493
+
494
+ throw Cr.NS_ERROR_NOINTERFACE;
495
+ }
496
+ }
497
+
498
+ Entry.prototype._atomLinksToURI = Feed.prototype._atomLinksToURI;
499
+ Entry.prototype._resolveURI = Feed.prototype._resolveURI;
500
+ Entry.prototype._resetBagMembersToRawText =
501
+ Feed.prototype._resetBagMembersToRawText;
502
+
503
+ // TextConstruct represents and element that could contain (X)HTML
504
+ function TextConstruct() {
505
+ this.lang = null;
506
+ this.base = null;
507
+ this.type = "text";
508
+ this.text = null;
509
+ }
510
+
511
+ TextConstruct.prototype = {
512
+ plainText: function TC_plainText() {
513
+ if (this.type != "text") {
514
+ return gUnescapeHTML.unescape(stripTags(this.text));
515
+ }
516
+ return this.text;
517
+ },
518
+
519
+ createDocumentFragment: function TC_createDocumentFragment(element) {
520
+ if (this.type == "text") {
521
+ var doc = element.ownerDocument;
522
+ var docFragment = doc.createDocumentFragment();
523
+ var node = doc.createTextNode(this.text);
524
+ docFragment.appendChild(node);
525
+ return docFragment;
526
+ }
527
+ var isXML;
528
+ if (this.type == "xhtml")
529
+ isXML = true
530
+ else if (this.type == "html")
531
+ isXML = false;
532
+ else
533
+ return null;
534
+
535
+ return gUnescapeHTML.parseFragment(this.text, isXML, this.base, element);
536
+ },
537
+
538
+ QueryInterface: function(iid) {
539
+ if (iid.equals(Ci.nsIFeedTextConstruct) ||
540
+ iid.equals(Ci.nsISupports))
541
+ return this;
542
+
543
+ throw Cr.NS_ERROR_NOINTERFACE;
544
+ }
545
+ }
546
+
547
+ // Generator represents the software that produced the feed
548
+ function Generator() {
549
+ this.lang = null;
550
+ this.agent = null;
551
+ this.version = null;
552
+ this.uri = null;
553
+
554
+ // nsIFeedElementBase
555
+ this._attributes = null;
556
+ this.baseURI = null;
557
+ }
558
+
559
+ Generator.prototype = {
560
+
561
+ get attributes() {
562
+ return this._attributes;
563
+ },
564
+
565
+ set attributes(value) {
566
+ this._attributes = value;
567
+ this.version = this._attributes.getValueFromName("","version");
568
+ var uriAttribute = this._attributes.getValueFromName("","uri") ||
569
+ this._attributes.getValueFromName("","url");
570
+ this.uri = strToURI(uriAttribute, this.baseURI);
571
+
572
+ // RSS1
573
+ uriAttribute = this._attributes.getValueFromName(RDF_NS,"resource");
574
+ if (uriAttribute) {
575
+ this.agent = uriAttribute;
576
+ this.uri = strToURI(uriAttribute, this.baseURI);
577
+ }
578
+ },
579
+
580
+ QueryInterface: function(iid) {
581
+ if (iid.equals(Ci.nsIFeedGenerator) ||
582
+ iid.equals(Ci.nsIFeedElementBase) ||
583
+ iid.equals(Ci.nsISupports))
584
+ return this;
585
+
586
+ throw Cr.NS_ERROR_NOINTERFACE;
587
+ }
588
+ }
589
+
590
+ function Person() {
591
+ this.name = null;
592
+ this.uri = null;
593
+ this.email = null;
594
+
595
+ // nsIFeedElementBase
596
+ this.attributes = null;
597
+ this.baseURI = null;
598
+ }
599
+
600
+ Person.prototype = {
601
+ QueryInterface: function(iid) {
602
+ if (iid.equals(Ci.nsIFeedPerson) ||
603
+ iid.equals(Ci.nsIFeedElementBase) ||
604
+ iid.equals(Ci.nsISupports))
605
+ return this;
606
+
607
+ throw Cr.NS_ERROR_NOINTERFACE;
608
+ }
609
+ }
610
+
611
+ /**
612
+ * Map a list of fields into properties on a container.
613
+ *
614
+ * @param container An nsIFeedContainer
615
+ * @param fields A list of fields to search for. List members can
616
+ * be a list, in which case the second member is
617
+ * transformation function (like parseInt).
618
+ */
619
+ function fieldsToObj(container, fields) {
620
+ var props,prop,field,searchList;
621
+ for (var key in fields) {
622
+ searchList = fields[key];
623
+ for (var i=0; i < searchList.length; ++i) {
624
+ props = searchList[i];
625
+ prop = null;
626
+ field = isArray(props) ? props[0] : props;
627
+ try {
628
+ prop = container.fields.getProperty(field);
629
+ }
630
+ catch(e) {
631
+ }
632
+ if (prop) {
633
+ prop = isArray(props) ? props[1](prop) : prop;
634
+ container[key] = prop;
635
+ }
636
+ }
637
+ }
638
+ }
639
+
640
+ /**
641
+ * Lower cases an element's localName property
642
+ * @param element A DOM element.
643
+ *
644
+ * @returns The lower case localName property of the specified element
645
+ */
646
+ function LC(element) {
647
+ return element.localName.toLowerCase();
648
+ }
649
+
650
+ // TODO move these post-processor functions
651
+ // create a generator element
652
+ function atomGenerator(s, generator) {
653
+ generator.QueryInterface(Ci.nsIFeedGenerator);
654
+ generator.agent = trimString(s);
655
+ return generator;
656
+ }
657
+
658
+ // post-process atom:logo to create an RSS2-like structure
659
+ function atomLogo(s, logo) {
660
+ logo.setPropertyAsAString("url", trimString(s));
661
+ }
662
+
663
+ // post-process an RSS category, map it to the Atom fields.
664
+ function rssCatTerm(s, cat) {
665
+ // add slash handling?
666
+ cat.setPropertyAsAString("term", trimString(s));
667
+ return cat;
668
+ }
669
+
670
+ // post-process a GUID
671
+ function rssGuid(s, guid) {
672
+ guid.setPropertyAsAString("guid", trimString(s));
673
+ return guid;
674
+ }
675
+
676
+ // post-process an RSS author element
677
+ //
678
+ // It can contain a field like this:
679
+ //
680
+ // <author>lawyer@boyer.net (Lawyer Boyer)</author>
681
+ //
682
+ // or, delightfully, a field like this:
683
+ //
684
+ // <dc:creator>Simon St.Laurent (mailto:simonstl@simonstl.com)</dc:creator>
685
+ //
686
+ // We want to split this up and assign it to corresponding Atom
687
+ // fields.
688
+ //
689
+ function rssAuthor(s,author) {
690
+ author.QueryInterface(Ci.nsIFeedPerson);
691
+ // check for RSS2 string format
692
+ var chars = trimString(s);
693
+ var matches = chars.match(/(.*)\((.*)\)/);
694
+ var emailCheck =
695
+ /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
696
+ if (matches) {
697
+ var match1 = trimString(matches[1]);
698
+ var match2 = trimString(matches[2]);
699
+ if (match2.indexOf("mailto:") == 0)
700
+ match2 = match2.substring(7);
701
+ if (emailCheck.test(match1)) {
702
+ author.email = match1;
703
+ author.name = match2;
704
+ }
705
+ else if (emailCheck.test(match2)) {
706
+ author.email = match2;
707
+ author.name = match1;
708
+ }
709
+ else {
710
+ // put it back together
711
+ author.name = match1 + " (" + match2 + ")";
712
+ }
713
+ }
714
+ else {
715
+ author.name = chars;
716
+ if (chars.indexOf('@'))
717
+ author.email = chars;
718
+ }
719
+ return author;
720
+ }
721
+
722
+ //
723
+ // skipHours and skipDays map to arrays, so we need to change the
724
+ // string to an nsISupports in order to stick it in there.
725
+ //
726
+ function rssArrayElement(s) {
727
+ var str = Cc["@mozilla.org/supports-string;1"].
728
+ createInstance(Ci.nsISupportsString);
729
+ str.data = s;
730
+ str.QueryInterface(Ci.nsISupportsString);
731
+ return str;
732
+ }
733
+
734
+ /***** Some feed utils from TBird *****/
735
+
736
+ /**
737
+ * Tests a RFC822 date against a regex.
738
+ * @param aDateStr A string to test as an RFC822 date.
739
+ *
740
+ * @returns A boolean indicating whether the string is a valid RFC822 date.
741
+ */
742
+ function isValidRFC822Date(aDateStr) {
743
+ var regex = new RegExp(RFC822_RE);
744
+ return regex.test(aDateStr);
745
+ }
746
+
747
+ /**
748
+ * Removes leading and trailing whitespace from a string.
749
+ * @param s The string to trim.
750
+ *
751
+ * @returns A new string with whitespace stripped.
752
+ */
753
+ function trimString(s) {
754
+ return(s.replace(/^\s+/, "").replace(/\s+$/, ""));
755
+ }
756
+
757
+ // Regular expression matching RFC822 dates
758
+ const RFC822_RE = "^(((Mon)|(Tue)|(Wed)|(Thu)|(Fri)|(Sat)|(Sun)), *)?\\d\\d?"
759
+ + " +((Jan)|(Feb)|(Mar)|(Apr)|(May)|(Jun)|(Jul)|(Aug)|(Sep)|(Oct)|(Nov)|(Dec))"
760
+ + " +\\d\\d(\\d\\d)? +\\d\\d:\\d\\d(:\\d\\d)? +(([+-]?\\d\\d\\d\\d)|(UT)|(GMT)"
761
+ + "|(EST)|(EDT)|(CST)|(CDT)|(MST)|(MDT)|(PST)|(PDT)|\\w)$";
762
+
763
+ /**
764
+ * XXX -- need to decide what this should return.
765
+ * XXX -- Is there a Date class usable from C++?
766
+ *
767
+ * Tries tries parsing various date formats.
768
+ * @param dateString
769
+ * A string that is supposedly an RFC822 or RFC3339 date.
770
+ * @returns A Date.toString XXX--fixme
771
+ */
772
+ function dateParse(dateString) {
773
+ var date = trimString(dateString);
774
+
775
+ if (date.search(/^\d\d\d\d/) != -1) //Could be a ISO8601/W3C date
776
+ return W3CToIETFDate(dateString);
777
+
778
+ if (isValidRFC822Date(date))
779
+ return date;
780
+
781
+ if (!isNaN(parseInt(date, 10))) {
782
+ //It's an integer, so maybe it's a timestamp
783
+ var d = new Date(parseInt(date, 10) * 1000);
784
+ var now = new Date();
785
+ var yeardiff = now.getFullYear() - d.getFullYear();
786
+ if ((yeardiff >= 0) && (yeardiff < 3)) {
787
+ // it's quite likely the correct date. 3 years is an arbitrary cutoff,
788
+ // but this is an invalid date format, and there's no way to verify
789
+ // its correctness.
790
+ return d.toString();
791
+ }
792
+ }
793
+ // Can't help.
794
+ return null;
795
+ }
796
+
797
+
798
+ const XHTML_NS = "http://www.w3.org/1999/xhtml";
799
+
800
+ // The XHTMLHandler handles inline XHTML found in things like atom:summary
801
+ function XHTMLHandler(processor, isAtom) {
802
+ this._buf = "";
803
+ this._processor = processor;
804
+ this._depth = 0;
805
+ this._isAtom = isAtom;
806
+ }
807
+
808
+ // The fidelity can be improved here, to allow handling of stuff like
809
+ // SVG and MathML. XXX
810
+ XHTMLHandler.prototype = {
811
+ startDocument: function XH_startDocument() {
812
+ },
813
+ endDocument: function XH_endDocument() {
814
+ },
815
+ startElement: function XH_startElement(uri, localName, qName, attributes) {
816
+ ++this._depth;
817
+
818
+ // RFC4287 requires XHTML to be wrapped in a div that is *not* part of
819
+ // the content. This prevents people from screwing up namespaces, but
820
+ // we need to skip it here.
821
+ if (this._isAtom && this._depth == 1 && localName == "div")
822
+ return;
823
+
824
+ // If it's an XHTML element, record it. Otherwise, it's ignored.
825
+ if (uri == XHTML_NS) {
826
+ this._buf += "<" + localName;
827
+ for (var i=0; i < attributes.length; ++i) {
828
+ // XHTML attributes aren't in a namespace
829
+ if (attributes.getURI(i) == "") {
830
+ this._buf += (" " + attributes.getLocalName(i) + "='" +
831
+ xmlEscape(attributes.getValue(i)) + "'");
832
+ }
833
+ }
834
+ this._buf += ">";
835
+ }
836
+ },
837
+ endElement: function XH_endElement(uri, localName, qName) {
838
+ --this._depth;
839
+
840
+ // We need to skip outer divs in Atom. See comment in startElement.
841
+ if (this._isAtom && this._depth == 0 && localName == "div")
842
+ return;
843
+
844
+ // When we peek too far, go back to the main processor
845
+ if (this._depth < 0) {
846
+ this._processor.returnFromXHTMLHandler(trimString(this._buf),
847
+ uri, localName, qName);
848
+ return;
849
+ }
850
+ // If it's an XHTML element, record it. Otherwise, it's ignored.
851
+ if (uri == XHTML_NS) {
852
+ this._buf += "</" + localName + ">";
853
+ }
854
+ },
855
+ characters: function XH_characters(data) {
856
+ this._buf += xmlEscape(data);
857
+ },
858
+ startPrefixMapping: function XH_startPrefixMapping() {
859
+ },
860
+ endPrefixMapping: function XH_endPrefixMapping() {
861
+ },
862
+ processingInstruction: function XH_processingInstruction() {
863
+ },
864
+ }
865
+
866
+ /**
867
+ * The ExtensionHandler deals with elements we haven't explicitly
868
+ * added to our transition table in the FeedProcessor.
869
+ */
870
+ function ExtensionHandler(processor) {
871
+ this._buf = "";
872
+ this._depth = 0;
873
+ this._hasChildElements = false;
874
+
875
+ // The FeedProcessor
876
+ this._processor = processor;
877
+
878
+ // Fields of the outermost extension element.
879
+ this._localName = null;
880
+ this._uri = null;
881
+ this._qName = null;
882
+ this._attrs = null;
883
+ }
884
+
885
+ ExtensionHandler.prototype = {
886
+ startDocument: function EH_startDocument() {
887
+ },
888
+ endDocument: function EH_endDocument() {
889
+ },
890
+ startElement: function EH_startElement(uri, localName, qName, attrs) {
891
+ ++this._depth;
892
+ var prefix = gNamespaces[uri] ? gNamespaces[uri] + ":" : "";
893
+ var key = prefix + localName;
894
+
895
+ if (this._depth == 1) {
896
+ this._uri = uri;
897
+ this._localName = localName;
898
+ this._qName = qName;
899
+ this._attrs = attrs;
900
+ }
901
+
902
+ // if we descend into another element, we won't send text
903
+ this._hasChildElements = (this._depth > 1);
904
+
905
+ },
906
+ endElement: function EH_endElement(uri, localName, qName) {
907
+ --this._depth;
908
+ if (this._depth == 0) {
909
+ var text = this._hasChildElements ? null : trimString(this._buf);
910
+ this._processor.returnFromExtHandler(this._uri, this._localName,
911
+ text, this._attrs);
912
+ }
913
+ },
914
+ characters: function EH_characters(data) {
915
+ if (!this._hasChildElements)
916
+ this._buf += data;
917
+ },
918
+ startPrefixMapping: function EH_startPrefixMapping() {
919
+ },
920
+ endPrefixMapping: function EH_endPrefixMapping() {
921
+ },
922
+ processingInstruction: function EH_processingInstruction() {
923
+ },
924
+ };
925
+
926
+
927
+ /**
928
+ * ElementInfo is a simple container object that describes
929
+ * some characteristics of a feed element. For example, it
930
+ * says whether an element can be expected to appear more
931
+ * than once inside a given entry or feed.
932
+ */
933
+ function ElementInfo(fieldName, containerClass, closeFunc, isArray) {
934
+ this.fieldName = fieldName;
935
+ this.containerClass = containerClass;
936
+ this.closeFunc = closeFunc;
937
+ this.isArray = isArray;
938
+ this.isWrapper = false;
939
+ }
940
+
941
+ /**
942
+ * FeedElementInfo represents a feed element, usually the root.
943
+ */
944
+ function FeedElementInfo(fieldName, feedVersion) {
945
+ this.isWrapper = false;
946
+ this.fieldName = fieldName;
947
+ this.feedVersion = feedVersion;
948
+ }
949
+
950
+ /**
951
+ * Some feed formats include vestigial wrapper elements that we don't
952
+ * want to include in our object model, but we do need to keep track
953
+ * of during parsing.
954
+ */
955
+ function WrapperElementInfo(fieldName) {
956
+ this.isWrapper = true;
957
+ this.fieldName = fieldName;
958
+ }
959
+
960
+ /***** The Processor *****/
961
+ function FeedProcessor() {
962
+ this._reader = Cc[SAX_CONTRACTID].createInstance(Ci.nsISAXXMLReader);
963
+ this._buf = "";
964
+ this._feed = Cc[BAG_CONTRACTID].createInstance(Ci.nsIWritablePropertyBag2);
965
+ this._handlerStack = [];
966
+ this._xmlBaseStack = []; // sparse array keyed to nesting depth
967
+ this._depth = 0;
968
+ this._state = "START";
969
+ this._result = null;
970
+ this._extensionHandler = null;
971
+ this._xhtmlHandler = null;
972
+
973
+ // The nsIFeedResultListener waiting for the parse results
974
+ this.listener = null;
975
+
976
+ // These elements can contain (X)HTML or plain text.
977
+ // We keep a table here that contains their default treatment
978
+ this._textConstructs = {"atom:title":"text",
979
+ "atom:summary":"text",
980
+ "atom:rights":"text",
981
+ "atom:content":"text",
982
+ "atom:subtitle":"text",
983
+ "description":"html",
984
+ "rss1:description":"html",
985
+ "dc:description":"html",
986
+ "content:encoded":"html",
987
+ "title":"text",
988
+ "rss1:title":"text",
989
+ "atom03:title":"text",
990
+ "atom03:tagline":"text",
991
+ "atom03:summary":"text",
992
+ "atom03:content":"text"};
993
+ this._stack = [];
994
+
995
+ this._trans = {
996
+ "START": {
997
+ //If we hit a root RSS element, treat as RSS2.
998
+ "rss": new FeedElementInfo("RSS2", "rss2"),
999
+
1000
+ // If we hit an RDF element, if could be RSS1, but we can't
1001
+ // verify that until we hit a rss1:channel element.
1002
+ "rdf:RDF": new WrapperElementInfo("RDF"),
1003
+
1004
+ // If we hit a Atom 1.0 element, treat as Atom 1.0.
1005
+ "atom:feed": new FeedElementInfo("Atom", "atom"),
1006
+
1007
+ // Treat as Atom 0.3
1008
+ "atom03:feed": new FeedElementInfo("Atom03", "atom03"),
1009
+ },
1010
+
1011
+ /********* RSS2 **********/
1012
+ "IN_RSS2": {
1013
+ "channel": new WrapperElementInfo("channel")
1014
+ },
1015
+
1016
+ "IN_CHANNEL": {
1017
+ "item": new ElementInfo("items", Cc[ENTRY_CONTRACTID], null, true),
1018
+ "managingEditor": new ElementInfo("authors", Cc[PERSON_CONTRACTID],
1019
+ rssAuthor, true),
1020
+ "dc:creator": new ElementInfo("authors", Cc[PERSON_CONTRACTID],
1021
+ rssAuthor, true),
1022
+ "dc:author": new ElementInfo("authors", Cc[PERSON_CONTRACTID],
1023
+ rssAuthor, true),
1024
+ "dc:contributor": new ElementInfo("contributors", Cc[PERSON_CONTRACTID],
1025
+ rssAuthor, true),
1026
+ "category": new ElementInfo("categories", null, rssCatTerm, true),
1027
+ "cloud": new ElementInfo("cloud", null, null, false),
1028
+ "image": new ElementInfo("image", null, null, false),
1029
+ "textInput": new ElementInfo("textInput", null, null, false),
1030
+ "skipDays": new ElementInfo("skipDays", null, null, false),
1031
+ "skipHours": new ElementInfo("skipHours", null, null, false),
1032
+ "generator": new ElementInfo("generator", Cc[GENERATOR_CONTRACTID],
1033
+ atomGenerator, false),
1034
+ },
1035
+
1036
+ "IN_ITEMS": {
1037
+ "author": new ElementInfo("authors", Cc[PERSON_CONTRACTID],
1038
+ rssAuthor, true),
1039
+ "dc:creator": new ElementInfo("authors", Cc[PERSON_CONTRACTID],
1040
+ rssAuthor, true),
1041
+ "dc:author": new ElementInfo("authors", Cc[PERSON_CONTRACTID],
1042
+ rssAuthor, true),
1043
+ "dc:contributor": new ElementInfo("contributors", Cc[PERSON_CONTRACTID],
1044
+ rssAuthor, true),
1045
+ "category": new ElementInfo("categories", null, rssCatTerm, true),
1046
+ "enclosure": new ElementInfo("enclosure", null, null, true),
1047
+ "guid": new ElementInfo("guid", null, rssGuid, false)
1048
+ },
1049
+
1050
+ "IN_SKIPDAYS": {
1051
+ "day": new ElementInfo("days", null, rssArrayElement, true)
1052
+ },
1053
+
1054
+ "IN_SKIPHOURS":{
1055
+ "hour": new ElementInfo("hours", null, rssArrayElement, true)
1056
+ },
1057
+
1058
+ /********* RSS1 **********/
1059
+ "IN_RDF": {
1060
+ // If we hit a rss1:channel, we can verify that we have RSS1
1061
+ "rss1:channel": new FeedElementInfo("rdf_channel", "rss1"),
1062
+ "rss1:image": new ElementInfo("image", null, null, false),
1063
+ "rss1:textinput": new ElementInfo("textInput", null, null, false),
1064
+ "rss1:item": new ElementInfo("items", Cc[ENTRY_CONTRACTID], null, true),
1065
+ },
1066
+
1067
+ "IN_RDF_CHANNEL": {
1068
+ "admin:generatorAgent": new ElementInfo("generator",
1069
+ Cc[GENERATOR_CONTRACTID],
1070
+ null, false),
1071
+ "dc:creator": new ElementInfo("authors", Cc[PERSON_CONTRACTID],
1072
+ rssAuthor, true),
1073
+ "dc:author": new ElementInfo("authors", Cc[PERSON_CONTRACTID],
1074
+ rssAuthor, true),
1075
+ "dc:contributor": new ElementInfo("contributors", Cc[PERSON_CONTRACTID],
1076
+ rssAuthor, true),
1077
+ },
1078
+
1079
+ /********* ATOM 1.0 **********/
1080
+ "IN_ATOM": {
1081
+ "atom:author": new ElementInfo("authors", Cc[PERSON_CONTRACTID],
1082
+ null, true),
1083
+ "atom:generator": new ElementInfo("generator", Cc[GENERATOR_CONTRACTID],
1084
+ atomGenerator, false),
1085
+ "atom:contributor": new ElementInfo("contributors", Cc[PERSON_CONTRACTID],
1086
+ null, true),
1087
+ "atom:link": new ElementInfo("links", null, null, true),
1088
+ "atom:logo": new ElementInfo("atom:logo", null, atomLogo, false),
1089
+ "atom:entry": new ElementInfo("entries", Cc[ENTRY_CONTRACTID],
1090
+ null, true)
1091
+ },
1092
+
1093
+ "IN_ENTRIES": {
1094
+ "atom:author": new ElementInfo("authors", Cc[PERSON_CONTRACTID],
1095
+ null, true),
1096
+ "atom:contributor": new ElementInfo("contributors", Cc[PERSON_CONTRACTID],
1097
+ null, true),
1098
+ "atom:link": new ElementInfo("links", null, null, true),
1099
+ },
1100
+
1101
+ /********* ATOM 0.3 **********/
1102
+ "IN_ATOM03": {
1103
+ "atom03:author": new ElementInfo("authors", Cc[PERSON_CONTRACTID],
1104
+ null, true),
1105
+ "atom03:contributor": new ElementInfo("contributors",
1106
+ Cc[PERSON_CONTRACTID],
1107
+ null, true),
1108
+ "atom03:link": new ElementInfo("links", null, null, true),
1109
+ "atom03:entry": new ElementInfo("atom03_entries", Cc[ENTRY_CONTRACTID],
1110
+ null, true),
1111
+ "atom03:generator": new ElementInfo("generator", Cc[GENERATOR_CONTRACTID],
1112
+ atomGenerator, false),
1113
+ },
1114
+
1115
+ "IN_ATOM03_ENTRIES": {
1116
+ "atom03:author": new ElementInfo("authors", Cc[PERSON_CONTRACTID],
1117
+ null, true),
1118
+ "atom03:contributor": new ElementInfo("contributors",
1119
+ Cc[PERSON_CONTRACTID],
1120
+ null, true),
1121
+ "atom03:link": new ElementInfo("links", null, null, true),
1122
+ "atom03:entry": new ElementInfo("atom03_entries", Cc[ENTRY_CONTRACTID],
1123
+ null, true)
1124
+ }
1125
+ }
1126
+ }
1127
+
1128
+ // See startElement for a long description of how feeds are processed.
1129
+ FeedProcessor.prototype = {
1130
+
1131
+ // Set ourselves as the SAX handler, and set the base URI
1132
+ _init: function FP_init(uri) {
1133
+ this._reader.contentHandler = this;
1134
+ this._reader.errorHandler = this;
1135
+ this._result = Cc[FR_CONTRACTID].createInstance(Ci.nsIFeedResult);
1136
+ if (uri) {
1137
+ this._result.uri = uri;
1138
+ this._reader.baseURI = uri;
1139
+ this._xmlBaseStack[0] = uri;
1140
+ }
1141
+ },
1142
+
1143
+ // This function is called once we figure out what type of feed
1144
+ // we're dealing with. Some feed types require digging a bit further
1145
+ // than the root.
1146
+ _docVerified: function FP_docVerified(version) {
1147
+ this._result.doc = Cc[FEED_CONTRACTID].createInstance(Ci.nsIFeed);
1148
+ this._result.doc.baseURI =
1149
+ this._xmlBaseStack[this._xmlBaseStack.length - 1];
1150
+ this._result.doc.fields = this._feed;
1151
+ this._result.version = version;
1152
+ },
1153
+
1154
+ // When we're done with the feed, let the listener know what
1155
+ // happened.
1156
+ _sendResult: function FP_sendResult() {
1157
+ try {
1158
+ // Can be null when a non-feed is fed to us
1159
+ if (this._result.doc)
1160
+ this._result.doc.normalize();
1161
+ }
1162
+ catch (e) {
1163
+ LOG("FIXME: " + e);
1164
+ }
1165
+
1166
+ try {
1167
+ if (this.listener != null)
1168
+ this.listener.handleResult(this._result);
1169
+ }
1170
+ finally {
1171
+ this._result = null;
1172
+ this._reader = null;
1173
+ }
1174
+ },
1175
+
1176
+ // Parsing functions
1177
+ parseFromStream: function FP_parseFromStream(stream, uri) {
1178
+ this._init(uri);
1179
+ this._reader.parseFromStream(stream, null, stream.available(),
1180
+ "application/xml");
1181
+ this._reader = null;
1182
+ },
1183
+
1184
+ parseFromString: function FP_parseFromString(inputString, uri) {
1185
+ this._init(uri);
1186
+ this._reader.parseFromString(inputString, "application/xml");
1187
+ this._reader = null;
1188
+ },
1189
+
1190
+ parseAsync: function FP_parseAsync(requestObserver, uri) {
1191
+ this._init(uri);
1192
+ this._reader.parseAsync(requestObserver);
1193
+ },
1194
+
1195
+ // nsIStreamListener
1196
+
1197
+ // The XMLReader will throw sensible exceptions if these get called
1198
+ // out of order.
1199
+ onStartRequest: function FP_onStartRequest(request, context) {
1200
+ this._reader.onStartRequest(request, context);
1201
+ },
1202
+
1203
+ onStopRequest: function FP_onStopRequest(request, context, statusCode) {
1204
+ this._reader.onStopRequest(request, context, statusCode);
1205
+ },
1206
+
1207
+ onDataAvailable:
1208
+ function FP_onDataAvailable(request, context, inputStream, offset, count) {
1209
+ this._reader.onDataAvailable(request, context, inputStream, offset, count);
1210
+ },
1211
+
1212
+ // nsISAXErrorHandler
1213
+
1214
+ // We only care about fatal errors. When this happens, we may have
1215
+ // parsed through the feed metadata and some number of entries. The
1216
+ // listener can still show some of that data if it wants, and we'll
1217
+ // set the bozo bit to indicate we were unable to parse all the way
1218
+ // through.
1219
+ fatalError: function FP_reportError() {
1220
+ this._result.bozo = true;
1221
+ //XXX need to QI to FeedProgressListener
1222
+ this._sendResult();
1223
+ },
1224
+
1225
+ // nsISAXContentHandler
1226
+
1227
+ startDocument: function FP_startDocument() {
1228
+ //LOG("----------");
1229
+ },
1230
+
1231
+ endDocument: function FP_endDocument() {
1232
+ this._sendResult();
1233
+ },
1234
+
1235
+ // The transitions defined above identify elements that contain more
1236
+ // than just text. For example RSS items contain many fields, and so
1237
+ // do Atom authors. The only commonly used elements that contain
1238
+ // mixed content are Atom Text Constructs of type="xhtml", which we
1239
+ // delegate to another handler for cleaning. That leaves a couple
1240
+ // different types of elements to deal with: those that should occur
1241
+ // only once, such as title elements, and those that can occur
1242
+ // multiple times, such as the RSS category element and the Atom
1243
+ // link element. Most of the RSS1/DC elements can occur multiple
1244
+ // times in theory, but in practice, the only ones that do have
1245
+ // analogues in Atom.
1246
+ //
1247
+ // Some elements are also groups of attributes or sub-elements,
1248
+ // while others are simple text fields. For the most part, we don't
1249
+ // have to pay explicit attention to the simple text elements,
1250
+ // unless we want to post-process the resulting string to transform
1251
+ // it into some richer object like a Date or URI.
1252
+ //
1253
+ // Elements that have more sophisticated content models still end up
1254
+ // being dictionaries, whether they are based on attributes like RSS
1255
+ // cloud, sub-elements like Atom author, or even items and
1256
+ // entries. These elements are treated as "containers". It's
1257
+ // theoretically possible for a container to have an attribute with
1258
+ // the same universal name as a sub-element, but none of the feed
1259
+ // formats allow this by default, and I don't of any extension that
1260
+ // works this way.
1261
+ //
1262
+ startElement: function FP_startElement(uri, localName, qName, attributes) {
1263
+ this._buf = "";
1264
+ ++this._depth;
1265
+ var elementInfo;
1266
+
1267
+ //LOG("<" + localName + ">");
1268
+
1269
+ // Check for xml:base
1270
+ var base = attributes.getValueFromName(XMLNS, "base");
1271
+ if (base) {
1272
+ this._xmlBaseStack[this._depth] =
1273
+ strToURI(base, this._xmlBaseStack[this._xmlBaseStack.length - 1]);
1274
+ }
1275
+
1276
+ // To identify the element we're dealing with, we look up the
1277
+ // namespace URI in our gNamespaces dictionary, which will give us
1278
+ // a "canonical" prefix for a namespace URI. For example, this
1279
+ // allows Dublin Core "creator" elements to be consistently mapped
1280
+ // to "dc:creator", for easy field access by consumer code. This
1281
+ // strategy also happens to shorten up our state table.
1282
+ var key = this._prefixForNS(uri) + localName;
1283
+
1284
+ // Check to see if we need to hand this off to our XHTML handler.
1285
+ // The elements we're dealing with will look like this:
1286
+ //
1287
+ // <title type="xhtml">
1288
+ // <div xmlns="http://www.w3.org/1999/xhtml">
1289
+ // A title with <b>bold</b> and <i>italics</i>.
1290
+ // </div>
1291
+ // </title>
1292
+ //
1293
+ // When it returns in returnFromXHTMLHandler, the handler should
1294
+ // give us back a string like this:
1295
+ //
1296
+ // "A title with <b>bold</b> and <i>italics</i>."
1297
+ //
1298
+ // The Atom spec explicitly says the div is not part of the content,
1299
+ // and explicitly allows whitespace collapsing.
1300
+ //
1301
+ if ((this._result.version == "atom" || this._result.version == "atom03") &&
1302
+ this._textConstructs[key] != null) {
1303
+ var type = attributes.getValueFromName("","type");
1304
+ if (type != null && type.indexOf("xhtml") >= 0) {
1305
+ this._xhtmlHandler =
1306
+ new XHTMLHandler(this, (this._result.version == "atom"));
1307
+ this._reader.contentHandler = this._xhtmlHandler;
1308
+ return;
1309
+ }
1310
+ }
1311
+
1312
+ // Check our current state, and see if that state has a defined
1313
+ // transition. For example, this._trans["atom:entry"]["atom:author"]
1314
+ // will have one, and it tells us to add an item to our authors array.
1315
+ if (this._trans[this._state] && this._trans[this._state][key]) {
1316
+ elementInfo = this._trans[this._state][key];
1317
+ }
1318
+ else {
1319
+ // If we don't have a transition, hand off to extension handler
1320
+ this._extensionHandler = new ExtensionHandler(this);
1321
+ this._reader.contentHandler = this._extensionHandler;
1322
+ this._extensionHandler.startElement(uri, localName, qName, attributes);
1323
+ return;
1324
+ }
1325
+
1326
+ // This distinguishes wrappers like 'channel' from elements
1327
+ // we'd actually like to do something with (which will test true).
1328
+ this._handlerStack[this._depth] = elementInfo;
1329
+ if (elementInfo.isWrapper) {
1330
+ this._state = "IN_" + elementInfo.fieldName.toUpperCase();
1331
+ this._stack.push([this._feed, this._state]);
1332
+ }
1333
+ else if (elementInfo.feedVersion) {
1334
+ this._state = "IN_" + elementInfo.fieldName.toUpperCase();
1335
+
1336
+ // Check for the older RSS2 variants
1337
+ if (elementInfo.feedVersion == "rss2")
1338
+ elementInfo.feedVersion = this._findRSSVersion(attributes);
1339
+ else if (uri == RSS090NS)
1340
+ elementInfo.feedVersion = "rss090";
1341
+
1342
+ this._docVerified(elementInfo.feedVersion);
1343
+ this._stack.push([this._feed, this._state]);
1344
+ this._mapAttributes(this._feed, attributes);
1345
+ }
1346
+ else {
1347
+ this._state = this._processComplexElement(elementInfo, attributes);
1348
+ }
1349
+ },
1350
+
1351
+ // In the endElement handler, we decrement the stack and look
1352
+ // for cleanup/transition functions to execute. The second part
1353
+ // of the state transition works as above in startElement, but
1354
+ // the state we're looking for is prefixed with an underscore
1355
+ // to distinguish endElement events from startElement events.
1356
+ endElement: function FP_endElement(uri, localName, qName) {
1357
+ var elementInfo = this._handlerStack[this._depth];
1358
+ //LOG("</" + localName + ">");
1359
+ if (elementInfo && !elementInfo.isWrapper)
1360
+ this._closeComplexElement(elementInfo);
1361
+
1362
+ // cut down xml:base context
1363
+ if (this._xmlBaseStack.length == this._depth + 1)
1364
+ this._xmlBaseStack = this._xmlBaseStack.slice(0, this._depth);
1365
+
1366
+ // our new state is whatever is at the top of the stack now
1367
+ if (this._stack.length > 0)
1368
+ this._state = this._stack[this._stack.length - 1][1];
1369
+ this._handlerStack = this._handlerStack.slice(0, this._depth);
1370
+ --this._depth;
1371
+ },
1372
+
1373
+ // Buffer up character data. The buffer is cleared with every
1374
+ // opening element.
1375
+ characters: function FP_characters(data) {
1376
+ this._buf += data;
1377
+ },
1378
+
1379
+ // TODO: It would be nice to check new prefixes here, and if they
1380
+ // don't conflict with the ones we've defined, throw them in a
1381
+ // dictionary to check.
1382
+ startPrefixMapping: function FP_startPrefixMapping() {
1383
+ },
1384
+ endPrefixMapping: function FP_endPrefixMapping() {
1385
+ },
1386
+ processingInstruction: function FP_processingInstruction(target, data) {
1387
+ if (target == "xml-stylesheet") {
1388
+ var hrefAttribute = data.match(/href=[\"\'](.*?)[\"\']/);
1389
+ if (hrefAttribute && hrefAttribute.length == 2)
1390
+ this._result.stylesheet = gIoService.newURI(hrefAttribute[1], null,
1391
+ this._result.uri);
1392
+ }
1393
+ },
1394
+
1395
+ // end of nsISAXContentHandler
1396
+
1397
+ // Handle our more complicated elements--those that contain
1398
+ // attributes and child elements.
1399
+ _processComplexElement:
1400
+ function FP__processComplexElement(elementInfo, attributes) {
1401
+ var obj, key, prefix;
1402
+
1403
+ // If the container is an entry/item, it'll need to have its
1404
+ // more esoteric properties put in the 'fields' property bag.
1405
+ if (elementInfo.containerClass == Cc[ENTRY_CONTRACTID]) {
1406
+ obj = elementInfo.containerClass.createInstance(Ci.nsIFeedEntry);
1407
+ obj.baseURI = this._xmlBaseStack[this._xmlBaseStack.length - 1];
1408
+ this._mapAttributes(obj.fields, attributes);
1409
+ }
1410
+ else if (elementInfo.containerClass) {
1411
+ obj = elementInfo.containerClass.createInstance(Ci.nsIFeedElementBase);
1412
+ obj.baseURI = this._xmlBaseStack[this._xmlBaseStack.length - 1];
1413
+ obj.attributes = attributes; // just set the SAX attributes
1414
+ }
1415
+ else {
1416
+ obj = Cc[BAG_CONTRACTID].createInstance(Ci.nsIWritablePropertyBag2);
1417
+ this._mapAttributes(obj, attributes);
1418
+ }
1419
+
1420
+ // We should have a container/propertyBag that's had its
1421
+ // attributes processed. Now we need to attach it to its
1422
+ // container.
1423
+ var newProp;
1424
+
1425
+ // First we'll see what's on top of the stack.
1426
+ var container = this._stack[this._stack.length - 1][0];
1427
+
1428
+ // Check to see if it has the property
1429
+ var prop;
1430
+ try {
1431
+ prop = container.getProperty(elementInfo.fieldName);
1432
+ }
1433
+ catch(e) {
1434
+ }
1435
+
1436
+ if (elementInfo.isArray) {
1437
+ if (!prop) {
1438
+ container.setPropertyAsInterface(elementInfo.fieldName,
1439
+ Cc[ARRAY_CONTRACTID].
1440
+ createInstance(Ci.nsIMutableArray));
1441
+ }
1442
+
1443
+ newProp = container.getProperty(elementInfo.fieldName);
1444
+ // XXX This QI should not be necessary, but XPConnect seems to fly
1445
+ // off the handle in the browser, and loses track of the interface
1446
+ // on large files. Bug 335638.
1447
+ newProp.QueryInterface(Ci.nsIMutableArray);
1448
+ newProp.appendElement(obj,false);
1449
+
1450
+ // If new object is an nsIFeedContainer, we want to deal with
1451
+ // its member nsIPropertyBag instead.
1452
+ if (isIFeedContainer(obj))
1453
+ newProp = obj.fields;
1454
+
1455
+ }
1456
+ else {
1457
+ // If it doesn't, set it.
1458
+ if (!prop) {
1459
+ container.setPropertyAsInterface(elementInfo.fieldName,obj);
1460
+ }
1461
+ newProp = container.getProperty(elementInfo.fieldName);
1462
+ }
1463
+
1464
+ // make our new state name, and push the property onto the stack
1465
+ var newState = "IN_" + elementInfo.fieldName.toUpperCase();
1466
+ this._stack.push([newProp, newState, obj]);
1467
+ return newState;
1468
+ },
1469
+
1470
+ // Sometimes we need reconcile the element content with the object
1471
+ // model for a given feed. We use helper functions to do the
1472
+ // munging, but we need to identify array types here, so the munging
1473
+ // happens only to the last element of an array.
1474
+ _closeComplexElement: function FP__closeComplexElement(elementInfo) {
1475
+ var stateTuple = this._stack.pop();
1476
+ var container = stateTuple[0];
1477
+ var containerParent = stateTuple[2];
1478
+ var element = null;
1479
+ var isArray = isIArray(container);
1480
+
1481
+ // If it's an array and we have to post-process,
1482
+ // grab the last element
1483
+ if (isArray)
1484
+ element = container.queryElementAt(container.length - 1, Ci.nsISupports);
1485
+ else
1486
+ element = container;
1487
+
1488
+ // Run the post-processing function if there is one.
1489
+ if (elementInfo.closeFunc)
1490
+ element = elementInfo.closeFunc(this._buf, element);
1491
+
1492
+ // If an nsIFeedContainer was on top of the stack,
1493
+ // we need to normalize it
1494
+ if (elementInfo.containerClass == Cc[ENTRY_CONTRACTID])
1495
+ containerParent.normalize();
1496
+
1497
+ // If it's an array, re-set the last element
1498
+ if (isArray)
1499
+ container.replaceElementAt(element, container.length - 1, false);
1500
+ },
1501
+
1502
+ _prefixForNS: function FP_prefixForNS(uri) {
1503
+ if (!uri)
1504
+ return "";
1505
+ var prefix = gNamespaces[uri];
1506
+ if (prefix)
1507
+ return prefix + ":";
1508
+ if (uri.toLowerCase().indexOf("http://backend.userland.com") == 0)
1509
+ return "";
1510
+ else
1511
+ return null;
1512
+ },
1513
+
1514
+ _mapAttributes: function FP__mapAttributes(bag, attributes) {
1515
+ // Cycle through the attributes, and set our properties using the
1516
+ // prefix:localNames we find in our namespace dictionary.
1517
+ for (var i = 0; i < attributes.length; ++i) {
1518
+ var key = this._prefixForNS(attributes.getURI(i)) + attributes.getLocalName(i);
1519
+ var val = attributes.getValue(i);
1520
+ bag.setPropertyAsAString(key, val);
1521
+ }
1522
+ },
1523
+
1524
+ // Only for RSS2esque formats
1525
+ _findRSSVersion: function FP__findRSSVersion(attributes) {
1526
+ var versionAttr = trimString(attributes.getValueFromName("", "version"));
1527
+ var versions = { "0.91":"rss091",
1528
+ "0.92":"rss092",
1529
+ "0.93":"rss093",
1530
+ "0.94":"rss094" }
1531
+ if (versions[versionAttr])
1532
+ return versions[versionAttr];
1533
+ if (versionAttr.substr(0,2) != "2.")
1534
+ return "rssUnknown";
1535
+ return "rss2";
1536
+ },
1537
+
1538
+ // unknown element values are returned here. See startElement above
1539
+ // for how this works.
1540
+ returnFromExtHandler:
1541
+ function FP_returnExt(uri, localName, chars, attributes) {
1542
+ --this._depth;
1543
+
1544
+ // take control of the SAX events
1545
+ this._reader.contentHandler = this;
1546
+ if (localName == null && chars == null)
1547
+ return;
1548
+
1549
+ // we don't take random elements inside rdf:RDF
1550
+ if (this._state == "IN_RDF")
1551
+ return;
1552
+
1553
+ // Grab the top of the stack
1554
+ var top = this._stack[this._stack.length - 1];
1555
+ if (!top)
1556
+ return;
1557
+
1558
+ var container = top[0];
1559
+ // Grab the last element if it's an array
1560
+ if (isIArray(container)) {
1561
+ var contract = this._handlerStack[this._depth].containerClass;
1562
+ // check if it's something specific, but not an entry
1563
+ if (contract && contract != Cc[ENTRY_CONTRACTID]) {
1564
+ var el = container.queryElementAt(container.length - 1,
1565
+ Ci.nsIFeedElementBase);
1566
+ // XXX there must be a way to flatten these interfaces
1567
+ if (contract == Cc[PERSON_CONTRACTID])
1568
+ el.QueryInterface(Ci.nsIFeedPerson);
1569
+ else
1570
+ return; // don't know about this interface
1571
+
1572
+ var propName = localName;
1573
+ var prefix = gNamespaces[uri];
1574
+
1575
+ // synonyms
1576
+ if ((uri == "" ||
1577
+ prefix &&
1578
+ ((prefix.indexOf("atom") > -1) ||
1579
+ (prefix.indexOf("rss") > -1))) &&
1580
+ (propName == "url" || propName == "href"))
1581
+ propName = "uri";
1582
+
1583
+ try {
1584
+ if (el[propName] !== "undefined") {
1585
+ var propValue = chars;
1586
+ // convert URI-bearing values to an nsIURI
1587
+ if (propName == "uri") {
1588
+ var base = this._xmlBaseStack[this._xmlBaseStack.length - 1];
1589
+ propValue = strToURI(chars, base);
1590
+ }
1591
+ el[propName] = propValue;
1592
+ }
1593
+ }
1594
+ catch(e) {
1595
+ // ignore XPConnect errors
1596
+ }
1597
+ // the rest of the function deals with entry- and feed-level stuff
1598
+ return;
1599
+ }
1600
+ else {
1601
+ container = container.queryElementAt(container.length - 1,
1602
+ Ci.nsIWritablePropertyBag2);
1603
+ }
1604
+ }
1605
+
1606
+ // Make the buffer our new property
1607
+ var propName = this._prefixForNS(uri) + localName;
1608
+
1609
+ // But, it could be something containing HTML. If so,
1610
+ // we need to know about that.
1611
+ if (this._textConstructs[propName] != null &&
1612
+ this._handlerStack[this._depth].containerClass !== null) {
1613
+ var newProp = Cc[TEXTCONSTRUCT_CONTRACTID].
1614
+ createInstance(Ci.nsIFeedTextConstruct);
1615
+ newProp.text = chars;
1616
+ // Look up the default type in our table
1617
+ var type = this._textConstructs[propName];
1618
+ var typeAttribute = attributes.getValueFromName("","type");
1619
+ if (this._result.version == "atom" && typeAttribute != null) {
1620
+ type = typeAttribute;
1621
+ }
1622
+ else if (this._result.version == "atom03" && typeAttribute != null) {
1623
+ if (typeAttribute.toLowerCase().indexOf("xhtml") >= 0) {
1624
+ type = "xhtml";
1625
+ }
1626
+ else if (typeAttribute.toLowerCase().indexOf("html") >= 0) {
1627
+ type = "html";
1628
+ }
1629
+ else if (typeAttribute.toLowerCase().indexOf("text") >= 0) {
1630
+ type = "text";
1631
+ }
1632
+ }
1633
+
1634
+ // If it's rss feed-level description, it's not supposed to have html
1635
+ if (this._result.version.indexOf("rss") >= 0 &&
1636
+ this._handlerStack[this._depth].containerClass != ENTRY_CONTRACTID) {
1637
+ type = "text";
1638
+ }
1639
+
1640
+ newProp.type = type;
1641
+ newProp.base = this._xmlBaseStack[this._xmlBaseStack.length - 1];
1642
+ container.setPropertyAsInterface(propName, newProp);
1643
+ }
1644
+ else {
1645
+ container.setPropertyAsAString(propName, chars);
1646
+ }
1647
+
1648
+ },
1649
+
1650
+ // Sometimes, we'll hand off SAX handling duties to an XHTMLHandler
1651
+ // (see above) that will scrape out non-XHTML stuff, normalize
1652
+ // namespaces, and remove the wrapper div from Atom 1.0. When the
1653
+ // XHTMLHandler is done, it'll callback here.
1654
+ returnFromXHTMLHandler:
1655
+ function FP_returnFromXHTMLHandler(chars, uri, localName, qName) {
1656
+ // retake control of the SAX content events
1657
+ this._reader.contentHandler = this;
1658
+
1659
+ // Grab the top of the stack
1660
+ var top = this._stack[this._stack.length - 1];
1661
+ if (!top)
1662
+ return;
1663
+ var container = top[0];
1664
+
1665
+ // Assign the property
1666
+ var newProp = newProp = Cc[TEXTCONSTRUCT_CONTRACTID].
1667
+ createInstance(Ci.nsIFeedTextConstruct);
1668
+ newProp.text = chars;
1669
+ newProp.type = "xhtml";
1670
+ newProp.base = this._xmlBaseStack[this._xmlBaseStack.length - 1];
1671
+ container.setPropertyAsInterface(this._prefixForNS(uri) + localName,
1672
+ newProp);
1673
+
1674
+ // XHTML will cause us to peek too far. The XHTML handler will
1675
+ // send us an end element to call. RFC4287-valid feeds allow a
1676
+ // more graceful way to handle this. Unfortunately, we can't count
1677
+ // on compliance at this point.
1678
+ this.endElement(uri, localName, qName);
1679
+ },
1680
+
1681
+ // nsISupports
1682
+ QueryInterface: function FP_QueryInterface(iid) {
1683
+ if (iid.equals(Ci.nsIFeedProcessor) ||
1684
+ iid.equals(Ci.nsISAXContentHandler) ||
1685
+ iid.equals(Ci.nsISAXErrorHandler) ||
1686
+ iid.equals(Ci.nsIStreamListener) ||
1687
+ iid.equals(Ci.nsIRequestObserver) ||
1688
+ iid.equals(Ci.nsISupports))
1689
+ return this;
1690
+
1691
+ throw Cr.NS_ERROR_NOINTERFACE;
1692
+ },
1693
+ }
1694
+
1695
+ const FP_CONTRACTID = "@mozilla.org/feed-processor;1";
1696
+ const FP_CLASSID = Components.ID("{26acb1f0-28fc-43bc-867a-a46aabc85dd4}");
1697
+ const FP_CLASSNAME = "Feed Processor";
1698
+ const FR_CONTRACTID = "@mozilla.org/feed-result;1";
1699
+ const FR_CLASSID = Components.ID("{072a5c3d-30c6-4f07-b87f-9f63d51403f2}");
1700
+ const FR_CLASSNAME = "Feed Result";
1701
+ const FEED_CONTRACTID = "@mozilla.org/feed;1";
1702
+ const FEED_CLASSID = Components.ID("{5d0cfa97-69dd-4e5e-ac84-f253162e8f9a}");
1703
+ const FEED_CLASSNAME = "Feed";
1704
+ const ENTRY_CONTRACTID = "@mozilla.org/feed-entry;1";
1705
+ const ENTRY_CLASSID = Components.ID("{8e4444ff-8e99-4bdd-aa7f-fb3c1c77319f}");
1706
+ const ENTRY_CLASSNAME = "Feed Entry";
1707
+ const TEXTCONSTRUCT_CONTRACTID = "@mozilla.org/feed-textconstruct;1";
1708
+ const TEXTCONSTRUCT_CLASSID =
1709
+ Components.ID("{b992ddcd-3899-4320-9909-924b3e72c922}");
1710
+ const TEXTCONSTRUCT_CLASSNAME = "Feed Text Construct";
1711
+ const GENERATOR_CONTRACTID = "@mozilla.org/feed-generator;1";
1712
+ const GENERATOR_CLASSID =
1713
+ Components.ID("{414af362-9ad8-4296-898e-62247f25a20e}");
1714
+ const GENERATOR_CLASSNAME = "Feed Generator";
1715
+ const PERSON_CONTRACTID = "@mozilla.org/feed-person;1";
1716
+ const PERSON_CLASSID = Components.ID("{95c963b7-20b2-11db-92f6-001422106990}");
1717
+ const PERSON_CLASSNAME = "Feed Person";
1718
+
1719
+ function GenericComponentFactory(ctor) {
1720
+ this._ctor = ctor;
1721
+ }
1722
+
1723
+ GenericComponentFactory.prototype = {
1724
+
1725
+ _ctor: null,
1726
+
1727
+ // nsIFactory
1728
+ createInstance: function(outer, iid) {
1729
+ if (outer != null)
1730
+ throw Cr.NS_ERROR_NO_AGGREGATION;
1731
+ return (new this._ctor()).QueryInterface(iid);
1732
+ },
1733
+
1734
+ // nsISupports
1735
+ QueryInterface: function(iid) {
1736
+ if (iid.equals(Ci.nsIFactory) ||
1737
+ iid.equals(Ci.nsISupports))
1738
+ return this;
1739
+ throw Cr.NS_ERROR_NO_INTERFACE;
1740
+ },
1741
+
1742
+ };
1743
+
1744
+ var Module = {
1745
+ QueryInterface: function(iid) {
1746
+ if (iid.equals(Ci.nsIModule) ||
1747
+ iid.equals(Ci.nsISupports))
1748
+ return this;
1749
+
1750
+ throw Cr.NS_ERROR_NO_INTERFACE;
1751
+ },
1752
+
1753
+ getClassObject: function(cm, cid, iid) {
1754
+ if (!iid.equals(Ci.nsIFactory))
1755
+ throw Cr.NS_ERROR_NOT_IMPLEMENTED;
1756
+
1757
+ if (cid.equals(FP_CLASSID))
1758
+ return new GenericComponentFactory(FeedProcessor);
1759
+ if (cid.equals(FR_CLASSID))
1760
+ return new GenericComponentFactory(FeedResult);
1761
+ if (cid.equals(FEED_CLASSID))
1762
+ return new GenericComponentFactory(Feed);
1763
+ if (cid.equals(ENTRY_CLASSID))
1764
+ return new GenericComponentFactory(Entry);
1765
+ if (cid.equals(TEXTCONSTRUCT_CLASSID))
1766
+ return new GenericComponentFactory(TextConstruct);
1767
+ if (cid.equals(GENERATOR_CLASSID))
1768
+ return new GenericComponentFactory(Generator);
1769
+ if (cid.equals(PERSON_CLASSID))
1770
+ return new GenericComponentFactory(Person);
1771
+
1772
+ throw Cr.NS_ERROR_NO_INTERFACE;
1773
+ },
1774
+
1775
+ registerSelf: function(cm, file, location, type) {
1776
+ var cr = cm.QueryInterface(Ci.nsIComponentRegistrar);
1777
+ // Feed Processor
1778
+ cr.registerFactoryLocation(FP_CLASSID, FP_CLASSNAME,
1779
+ FP_CONTRACTID, file, location, type);
1780
+ // Feed Result
1781
+ cr.registerFactoryLocation(FR_CLASSID, FR_CLASSNAME,
1782
+ FR_CONTRACTID, file, location, type);
1783
+ // Feed
1784
+ cr.registerFactoryLocation(FEED_CLASSID, FEED_CLASSNAME,
1785
+ FEED_CONTRACTID, file, location, type);
1786
+ // Entry
1787
+ cr.registerFactoryLocation(ENTRY_CLASSID, ENTRY_CLASSNAME,
1788
+ ENTRY_CONTRACTID, file, location, type);
1789
+ // Text Construct
1790
+ cr.registerFactoryLocation(TEXTCONSTRUCT_CLASSID, TEXTCONSTRUCT_CLASSNAME,
1791
+ TEXTCONSTRUCT_CONTRACTID, file, location, type);
1792
+ // Generator
1793
+ cr.registerFactoryLocation(GENERATOR_CLASSID, GENERATOR_CLASSNAME,
1794
+ GENERATOR_CONTRACTID, file, location, type);
1795
+ // Person
1796
+ cr.registerFactoryLocation(PERSON_CLASSID, PERSON_CLASSNAME,
1797
+ PERSON_CONTRACTID, file, location, type);
1798
+ },
1799
+
1800
+ unregisterSelf: function(cm, location, type) {
1801
+ var cr = cm.QueryInterface(Ci.nsIComponentRegistrar);
1802
+ // Feed Processor
1803
+ cr.unregisterFactoryLocation(FP_CLASSID, location);
1804
+ // Feed Result
1805
+ cr.unregisterFactoryLocation(FR_CLASSID, location);
1806
+ // Feed
1807
+ cr.unregisterFactoryLocation(FEED_CLASSID, location);
1808
+ // Entry
1809
+ cr.unregisterFactoryLocation(ENTRY_CLASSID, location);
1810
+ // Text Construct
1811
+ cr.unregisterFactoryLocation(TEXTCONSTRUCT_CLASSID, location);
1812
+ // Generator
1813
+ cr.unregisterFactoryLocation(GENERATOR_CLASSID, location);
1814
+ // Person
1815
+ cr.unregisterFactoryLocation(PERSON_CLASSID, location);
1816
+ },
1817
+
1818
+ canUnload: function(cm) {
1819
+ return true;
1820
+ },
1821
+ };
1822
+
1823
+ function NSGetModule(cm, file) {
1824
+ return Module;
1825
+ }