ogre.rb 0.1-i686-linux

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }