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.
- data/README +79 -0
- data/Rakefile +288 -0
- data/doc_src/ogre.rb +246 -0
- data/doc_src/ois.rb +67 -0
- data/lib/application.rb +146 -0
- data/lib/application_frame_listener.rb +302 -0
- data/lib/application_loading_bar.rb +115 -0
- data/lib/constants.rb +51 -0
- data/lib/method_fixes.rb +42 -0
- data/lib/ogre.so +0 -0
- data/lib/ruby_ois.so +0 -0
- data/ogre.rb +25 -0
- data/platform.rb +23 -0
- data/samples/Ogre.log +261 -0
- data/samples/bsp.rb +76 -0
- data/samples/cg.dll +0 -0
- data/samples/grass.rb +325 -0
- data/samples/js3250.dll +0 -0
- data/samples/lighting.rb +138 -0
- data/samples/media/materials/programs/Grass.cg +30 -0
- data/samples/media/materials/programs/OffsetMapping.cg +97 -0
- data/samples/media/materials/programs/OffsetMapping.hlsl +135 -0
- data/samples/media/materials/programs/OffsetMappingFp.glsl +69 -0
- data/samples/media/materials/programs/OffsetMappingVp.glsl +54 -0
- data/samples/media/materials/programs/OffsetMapping_specular.asm +44 -0
- data/samples/media/materials/scripts/CloudySky.material +17 -0
- data/samples/media/materials/scripts/CubeMapping.material +34 -0
- data/samples/media/materials/scripts/Flare.material +17 -0
- data/samples/media/materials/scripts/Grass.material +63 -0
- data/samples/media/materials/scripts/Knot.material +14 -0
- data/samples/media/materials/scripts/MorningSkyBox.material +17 -0
- data/samples/media/materials/scripts/Offset.material +124 -0
- data/samples/media/materials/scripts/Ogre.material +119 -0
- data/samples/media/materials/scripts/RZR-002.material +15 -0
- data/samples/media/materials/scripts/Razor.material +14 -0
- data/samples/media/materials/scripts/Ribbon.material +19 -0
- data/samples/media/materials/scripts/RustySteel.material +14 -0
- data/samples/media/materials/scripts/SpaceSkyBox.material +17 -0
- data/samples/media/materials/scripts/SpaceSkyPlane.material +17 -0
- data/samples/media/materials/scripts/TextureEffects.material +15 -0
- data/samples/media/materials/scripts/dragon.material +42 -0
- data/samples/media/materials/scripts/smoke.material +18 -0
- data/samples/media/materials/textures/GreenSkin.jpg +0 -0
- data/samples/media/materials/textures/MtlPlat2.jpg +0 -0
- data/samples/media/materials/textures/RZR-002.png +0 -0
- data/samples/media/materials/textures/RustedMetal.jpg +0 -0
- data/samples/media/materials/textures/RustySteel.jpg +0 -0
- data/samples/media/materials/textures/Water02.jpg +0 -0
- data/samples/media/materials/textures/WeirdEye.png +0 -0
- data/samples/media/materials/textures/clouds.jpg +0 -0
- data/samples/media/materials/textures/cursor.png +0 -0
- data/samples/media/materials/textures/dirt01.jpg +0 -0
- data/samples/media/materials/textures/flare.png +0 -0
- data/samples/media/materials/textures/gras_02.png +0 -0
- data/samples/media/materials/textures/grass_1024.jpg +0 -0
- data/samples/media/materials/textures/ogreborder.png +0 -0
- data/samples/media/materials/textures/ogreborderUp.png +0 -0
- data/samples/media/materials/textures/ribbonband.png +0 -0
- data/samples/media/materials/textures/rockwall.tga +0 -0
- data/samples/media/materials/textures/rockwall_NH.tga +0 -0
- data/samples/media/materials/textures/smoke.png +0 -0
- data/samples/media/materials/textures/smokecolors.png +0 -0
- data/samples/media/materials/textures/spacesky.jpg +0 -0
- data/samples/media/materials/textures/spheremap.png +0 -0
- data/samples/media/materials/textures/texmap2.jpg +0 -0
- data/samples/media/models/RZR-002.mesh +0 -0
- data/samples/media/models/geosphere4500.mesh +0 -0
- data/samples/media/models/geosphere8000.mesh +0 -0
- data/samples/media/models/knot.mesh +0 -0
- data/samples/media/models/ogrehead.mesh +0 -0
- data/samples/media/models/razor.mesh +0 -0
- data/samples/media/models/sphere.mesh +0 -0
- data/samples/media/overlays/CubeMapping.overlay +139 -0
- data/samples/media/packs/OgreCore.zip +0 -0
- data/samples/media/packs/chiropteraDM.pk3 +0 -0
- data/samples/media/packs/chiropteraDM.txt +99 -0
- data/samples/media/packs/cubemap.zip +0 -0
- data/samples/media/packs/cubemapsJS.zip +0 -0
- data/samples/media/packs/dragon.zip +0 -0
- data/samples/media/packs/skybox.zip +0 -0
- data/samples/media/particles/smoke.particle +43 -0
- data/samples/media.cfg +22 -0
- data/samples/navi/Media/NaviDemo.material +60 -0
- data/samples/navi/Media/OgreCore.zip +0 -0
- data/samples/navi/Media/cerulean.jpg +0 -0
- data/samples/navi/Media/clouds.jpg +0 -0
- data/samples/navi/Media/controlsNaviMask.png +0 -0
- data/samples/navi/Media/grass.jpg +0 -0
- data/samples/navi/Media/knot.mesh +0 -0
- data/samples/navi/Media/testNaviMask.png +0 -0
- data/samples/navi/NaviLocal/Navi.js +136 -0
- data/samples/navi/NaviLocal/buttonBg.jpg +0 -0
- data/samples/navi/NaviLocal/controls.html +303 -0
- data/samples/navi/NaviLocal/knobBg.jpg +0 -0
- data/samples/navi/NaviLocal/moo.dropdownmenu.js +87 -0
- data/samples/navi/NaviLocal/mootools.v1.1.js +6964 -0
- data/samples/navi/NaviLocal/naviLogo.html +32 -0
- data/samples/navi/NaviLocal/naviLogo.png +0 -0
- data/samples/navi/NaviLocal/pageBg.jpg +0 -0
- data/samples/navi/NaviLocal/sliderBg.jpg +0 -0
- data/samples/navi/NaviLocal/test.html +5 -0
- data/samples/navi/NaviLocal/welcome.html +36 -0
- data/samples/navi/NaviLocal/welcome.png +0 -0
- data/samples/navi/chrome/chromelist.txt +597 -0
- data/samples/navi/chrome/classic.jar +0 -0
- data/samples/navi/chrome/classic.manifest +4 -0
- data/samples/navi/chrome/comm.jar +0 -0
- data/samples/navi/chrome/comm.manifest +2 -0
- data/samples/navi/chrome/en-US.jar +0 -0
- data/samples/navi/chrome/en-US.manifest +9 -0
- data/samples/navi/chrome/toolkit.jar +0 -0
- data/samples/navi/chrome/toolkit.manifest +6 -0
- data/samples/navi/components/FeedProcessor.js +1825 -0
- data/samples/navi/components/alerts.xpt +0 -0
- data/samples/navi/components/appshell.xpt +0 -0
- data/samples/navi/components/appstartup.xpt +0 -0
- data/samples/navi/components/auth.dll +0 -0
- data/samples/navi/components/autocomplete.xpt +0 -0
- data/samples/navi/components/autoconfig.dll +0 -0
- data/samples/navi/components/autoconfig.xpt +0 -0
- data/samples/navi/components/caps.xpt +0 -0
- data/samples/navi/components/chardet.xpt +0 -0
- data/samples/navi/components/chrome.xpt +0 -0
- data/samples/navi/components/commandhandler.xpt +0 -0
- data/samples/navi/components/commandlines.xpt +0 -0
- data/samples/navi/components/composer.xpt +0 -0
- data/samples/navi/components/compreg.dat +1474 -0
- data/samples/navi/components/content_base.xpt +0 -0
- data/samples/navi/components/content_html.xpt +0 -0
- data/samples/navi/components/content_htmldoc.xpt +0 -0
- data/samples/navi/components/content_xmldoc.xpt +0 -0
- data/samples/navi/components/content_xslt.xpt +0 -0
- data/samples/navi/components/content_xtf.xpt +0 -0
- data/samples/navi/components/directory.xpt +0 -0
- data/samples/navi/components/docshell_base.xpt +0 -0
- data/samples/navi/components/dom.xpt +0 -0
- data/samples/navi/components/dom_base.xpt +0 -0
- data/samples/navi/components/dom_canvas.xpt +0 -0
- data/samples/navi/components/dom_core.xpt +0 -0
- data/samples/navi/components/dom_css.xpt +0 -0
- data/samples/navi/components/dom_events.xpt +0 -0
- data/samples/navi/components/dom_html.xpt +0 -0
- data/samples/navi/components/dom_loadsave.xpt +0 -0
- data/samples/navi/components/dom_range.xpt +0 -0
- data/samples/navi/components/dom_sidebar.xpt +0 -0
- data/samples/navi/components/dom_storage.xpt +0 -0
- data/samples/navi/components/dom_stylesheets.xpt +0 -0
- data/samples/navi/components/dom_svg.xpt +0 -0
- data/samples/navi/components/dom_traversal.xpt +0 -0
- data/samples/navi/components/dom_views.xpt +0 -0
- data/samples/navi/components/dom_xbl.xpt +0 -0
- data/samples/navi/components/dom_xpath.xpt +0 -0
- data/samples/navi/components/dom_xul.xpt +0 -0
- data/samples/navi/components/downloads.xpt +0 -0
- data/samples/navi/components/editor.xpt +0 -0
- data/samples/navi/components/embed_base.xpt +0 -0
- data/samples/navi/components/extensions.xpt +0 -0
- data/samples/navi/components/exthandler.xpt +0 -0
- data/samples/navi/components/fastfind.xpt +0 -0
- data/samples/navi/components/feeds.xpt +0 -0
- data/samples/navi/components/find.xpt +0 -0
- data/samples/navi/components/gfx.xpt +0 -0
- data/samples/navi/components/gksvgrenderer.xpt +0 -0
- data/samples/navi/components/history.xpt +0 -0
- data/samples/navi/components/htmlparser.xpt +0 -0
- data/samples/navi/components/imglib2.xpt +0 -0
- data/samples/navi/components/inspector.xpt +0 -0
- data/samples/navi/components/intl.xpt +0 -0
- data/samples/navi/components/intlcmpt.xpt +0 -0
- data/samples/navi/components/jar.xpt +0 -0
- data/samples/navi/components/jsconsole-clhandler.js +170 -0
- data/samples/navi/components/jsconsole.xpt +0 -0
- data/samples/navi/components/jsdservice.xpt +0 -0
- data/samples/navi/components/layout_base.xpt +0 -0
- data/samples/navi/components/layout_printing.xpt +0 -0
- data/samples/navi/components/layout_xul.xpt +0 -0
- data/samples/navi/components/layout_xul_tree.xpt +0 -0
- data/samples/navi/components/locale.xpt +0 -0
- data/samples/navi/components/lwbrk.xpt +0 -0
- data/samples/navi/components/mimetype.xpt +0 -0
- data/samples/navi/components/mozbrwsr.xpt +0 -0
- data/samples/navi/components/mozfind.xpt +0 -0
- data/samples/navi/components/necko.xpt +0 -0
- data/samples/navi/components/necko_about.xpt +0 -0
- data/samples/navi/components/necko_cache.xpt +0 -0
- data/samples/navi/components/necko_cookie.xpt +0 -0
- data/samples/navi/components/necko_data.xpt +0 -0
- data/samples/navi/components/necko_dns.xpt +0 -0
- data/samples/navi/components/necko_file.xpt +0 -0
- data/samples/navi/components/necko_ftp.xpt +0 -0
- data/samples/navi/components/necko_http.xpt +0 -0
- data/samples/navi/components/necko_res.xpt +0 -0
- data/samples/navi/components/necko_socket.xpt +0 -0
- data/samples/navi/components/necko_strconv.xpt +0 -0
- data/samples/navi/components/necko_viewsource.xpt +0 -0
- data/samples/navi/components/nsCloseAllWindows.js +143 -0
- data/samples/navi/components/nsDefaultCLH.js +231 -0
- data/samples/navi/components/nsDictionary.js +148 -0
- data/samples/navi/components/nsExtensionManager.js +8497 -0
- data/samples/navi/components/nsHelperAppDlg.js +990 -0
- data/samples/navi/components/nsInterfaceInfoToIDL.js +590 -0
- data/samples/navi/components/nsKillAll.js +200 -0
- data/samples/navi/components/nsPostUpdateWin.js +711 -0
- data/samples/navi/components/nsProgressDialog.js +949 -0
- data/samples/navi/components/nsProxyAutoConfig.js +396 -0
- data/samples/navi/components/nsResetPref.js +175 -0
- data/samples/navi/components/nsURLFormatter.js +179 -0
- data/samples/navi/components/nsUpdateService.js +3074 -0
- data/samples/navi/components/nsXULAppInstall.js +301 -0
- data/samples/navi/components/nsXmlRpcClient.js +1038 -0
- data/samples/navi/components/oji.xpt +0 -0
- data/samples/navi/components/passwordmgr.xpt +0 -0
- data/samples/navi/components/pipboot.xpt +0 -0
- data/samples/navi/components/pipnss.xpt +0 -0
- data/samples/navi/components/plugin.xpt +0 -0
- data/samples/navi/components/pref.xpt +0 -0
- data/samples/navi/components/prefetch.xpt +0 -0
- data/samples/navi/components/profile.xpt +0 -0
- data/samples/navi/components/progressDlg.xpt +0 -0
- data/samples/navi/components/proxyObject.xpt +0 -0
- data/samples/navi/components/rdf.xpt +0 -0
- data/samples/navi/components/satchel.xpt +0 -0
- data/samples/navi/components/saxparser.xpt +0 -0
- data/samples/navi/components/shistory.xpt +0 -0
- data/samples/navi/components/storage.xpt +0 -0
- data/samples/navi/components/toolkitprofile.xpt +0 -0
- data/samples/navi/components/transformiix.dll +0 -0
- data/samples/navi/components/txmgr.xpt +0 -0
- data/samples/navi/components/txtsvc.xpt +0 -0
- data/samples/navi/components/uconv.xpt +0 -0
- data/samples/navi/components/unicharutil.xpt +0 -0
- data/samples/navi/components/universalchardet.dll +0 -0
- data/samples/navi/components/update.xpt +0 -0
- data/samples/navi/components/uriloader.xpt +0 -0
- data/samples/navi/components/urlformatter.xpt +0 -0
- data/samples/navi/components/webBrowser_core.xpt +0 -0
- data/samples/navi/components/webbrowserpersist.xpt +0 -0
- data/samples/navi/components/webshell_idls.xpt +0 -0
- data/samples/navi/components/websrvcs.dll +0 -0
- data/samples/navi/components/websrvcs.xpt +0 -0
- data/samples/navi/components/widget.xpt +0 -0
- data/samples/navi/components/windowds.xpt +0 -0
- data/samples/navi/components/windowwatcher.xpt +0 -0
- data/samples/navi/components/xml-rpc.xpt +0 -0
- data/samples/navi/components/xmlextras.dll +0 -0
- data/samples/navi/components/xpcom_base.xpt +0 -0
- data/samples/navi/components/xpcom_components.xpt +0 -0
- data/samples/navi/components/xpcom_ds.xpt +0 -0
- data/samples/navi/components/xpcom_io.xpt +0 -0
- data/samples/navi/components/xpcom_obsolete.xpt +0 -0
- data/samples/navi/components/xpcom_thread.xpt +0 -0
- data/samples/navi/components/xpcom_xpti.xpt +0 -0
- data/samples/navi/components/xpconnect.xpt +0 -0
- data/samples/navi/components/xpinstall.xpt +0 -0
- data/samples/navi/components/xpti.dat +1424 -0
- data/samples/navi/components/xulapp.xpt +0 -0
- data/samples/navi/components/xulapp_setup.xpt +0 -0
- data/samples/navi/components/xuldoc.xpt +0 -0
- data/samples/navi/components/xulrunner.xpt +0 -0
- data/samples/navi/components/xultmpl.xpt +0 -0
- data/samples/navi/components/xulutil.dll +0 -0
- data/samples/navi/controlsNaviMask.png +0 -0
- data/samples/navi/greprefs/all.js +1344 -0
- data/samples/navi/greprefs/security-prefs.js +69 -0
- data/samples/navi/greprefs/xpinstall.js +2 -0
- data/samples/navi/navi_demo.rb +207 -0
- data/samples/navi/plugins/NPSWF32.dll +0 -0
- data/samples/navi/plugins/flashplayer.xpt +0 -0
- data/samples/navi/plugins/npnul32.dll +0 -0
- data/samples/navi/plugins.cfg +10 -0
- data/samples/navi/res/EditorOverride.css +359 -0
- data/samples/navi/res/Thumbs.db +0 -0
- data/samples/navi/res/arrow.gif +0 -0
- data/samples/navi/res/arrowd.gif +0 -0
- data/samples/navi/res/bloatcycle.html +40 -0
- data/samples/navi/res/broken-image.gif +0 -0
- data/samples/navi/res/charsetData.properties +199 -0
- data/samples/navi/res/charsetalias.properties +517 -0
- data/samples/navi/res/cmessage.txt +1 -0
- data/samples/navi/res/dtd/xhtml11.dtd +300 -0
- data/samples/navi/res/entityTables/html40Latin1.properties +146 -0
- data/samples/navi/res/entityTables/html40Special.properties +69 -0
- data/samples/navi/res/entityTables/html40Symbols.properties +164 -0
- data/samples/navi/res/entityTables/htmlEntityVersions.properties +50 -0
- data/samples/navi/res/entityTables/transliterate.properties +2367 -0
- data/samples/navi/res/fonts/fontEncoding.properties +127 -0
- data/samples/navi/res/fonts/fontNameMap.properties +134 -0
- data/samples/navi/res/forms.css +531 -0
- data/samples/navi/res/grabber.gif +0 -0
- data/samples/navi/res/hiddenWindow.html +1 -0
- data/samples/navi/res/html/Thumbs.db +0 -0
- data/samples/navi/res/html/gopher-audio.gif +0 -0
- data/samples/navi/res/html/gopher-binary.gif +0 -0
- data/samples/navi/res/html/gopher-find.gif +0 -0
- data/samples/navi/res/html/gopher-image.gif +0 -0
- data/samples/navi/res/html/gopher-menu.gif +0 -0
- data/samples/navi/res/html/gopher-movie.gif +0 -0
- data/samples/navi/res/html/gopher-sound.gif +0 -0
- data/samples/navi/res/html/gopher-telnet.gif +0 -0
- data/samples/navi/res/html/gopher-text.gif +0 -0
- data/samples/navi/res/html/gopher-unknown.gif +0 -0
- data/samples/navi/res/html.css +478 -0
- data/samples/navi/res/langGroups.properties +236 -0
- data/samples/navi/res/language.properties +259 -0
- data/samples/navi/res/loading-image.gif +0 -0
- data/samples/navi/res/quirk.css +282 -0
- data/samples/navi/res/samples/Anieyes.gif +0 -0
- data/samples/navi/res/samples/Thumbs.db +0 -0
- data/samples/navi/res/samples/aform.css +69 -0
- data/samples/navi/res/samples/beeptest.html +18 -0
- data/samples/navi/res/samples/bform.css +45 -0
- data/samples/navi/res/samples/bg.jpg +0 -0
- data/samples/navi/res/samples/cform.css +40 -0
- data/samples/navi/res/samples/checkboxTest.xul +47 -0
- data/samples/navi/res/samples/demoform.css +97 -0
- data/samples/navi/res/samples/find.html +97 -0
- data/samples/navi/res/samples/gear1.gif +0 -0
- data/samples/navi/res/samples/image_props.html +58 -0
- data/samples/navi/res/samples/mozform.css +256 -0
- data/samples/navi/res/samples/printsetup.html +175 -0
- data/samples/navi/res/samples/raptor.jpg +0 -0
- data/samples/navi/res/samples/rock_gra.gif +0 -0
- data/samples/navi/res/samples/scrollbarTest1.xul +66 -0
- data/samples/navi/res/samples/scrollbarTest2.xul +19 -0
- data/samples/navi/res/samples/sliderTest1.xul +14 -0
- data/samples/navi/res/samples/soundtest.html +20 -0
- data/samples/navi/res/samples/test.wav +0 -0
- data/samples/navi/res/samples/test0.html +220 -0
- data/samples/navi/res/samples/test1.html +84 -0
- data/samples/navi/res/samples/test10.html +16 -0
- data/samples/navi/res/samples/test11.html +42 -0
- data/samples/navi/res/samples/test12.html +79 -0
- data/samples/navi/res/samples/test13.html +126 -0
- data/samples/navi/res/samples/test14.html +5 -0
- data/samples/navi/res/samples/test15.html +5 -0
- data/samples/navi/res/samples/test16.html +124 -0
- data/samples/navi/res/samples/test2.html +41 -0
- data/samples/navi/res/samples/test3.html +126 -0
- data/samples/navi/res/samples/test4.html +335 -0
- data/samples/navi/res/samples/test5.html +199 -0
- data/samples/navi/res/samples/test6.html +335 -0
- data/samples/navi/res/samples/test7.html +11 -0
- data/samples/navi/res/samples/test8-1.html +66 -0
- data/samples/navi/res/samples/test8.html +662 -0
- data/samples/navi/res/samples/test8dom.html +64 -0
- data/samples/navi/res/samples/test8sca.html +308 -0
- data/samples/navi/res/samples/test8siz.html +224 -0
- data/samples/navi/res/samples/test8tab.html +9 -0
- data/samples/navi/res/samples/test9.html +12 -0
- data/samples/navi/res/samples/test9a.html +39 -0
- data/samples/navi/res/samples/test9b.html +16 -0
- data/samples/navi/res/samples/test_ed.html +5 -0
- data/samples/navi/res/samples/test_form.html +34 -0
- data/samples/navi/res/samples/test_gfx.html +75 -0
- data/samples/navi/res/samples/test_lbox.html +100 -0
- data/samples/navi/res/samples/test_pr.html +87 -0
- data/samples/navi/res/samples/test_weight.html +45 -0
- data/samples/navi/res/samples/toolbarTest1.xul +51 -0
- data/samples/navi/res/samples/treeTest1.css +62 -0
- data/samples/navi/res/samples/treeTest1.xul +110 -0
- data/samples/navi/res/samples/xulTest.css +130 -0
- data/samples/navi/res/svg.css +64 -0
- data/samples/navi/res/table-add-column-after-active.gif +0 -0
- data/samples/navi/res/table-add-column-after-hover.gif +0 -0
- data/samples/navi/res/table-add-column-after.gif +0 -0
- data/samples/navi/res/table-add-column-before-active.gif +0 -0
- data/samples/navi/res/table-add-column-before-hover.gif +0 -0
- data/samples/navi/res/table-add-column-before.gif +0 -0
- data/samples/navi/res/table-add-row-after-active.gif +0 -0
- data/samples/navi/res/table-add-row-after-hover.gif +0 -0
- data/samples/navi/res/table-add-row-after.gif +0 -0
- data/samples/navi/res/table-add-row-before-active.gif +0 -0
- data/samples/navi/res/table-add-row-before-hover.gif +0 -0
- data/samples/navi/res/table-add-row-before.gif +0 -0
- data/samples/navi/res/table-remove-column-active.gif +0 -0
- data/samples/navi/res/table-remove-column-hover.gif +0 -0
- data/samples/navi/res/table-remove-column.gif +0 -0
- data/samples/navi/res/table-remove-row-active.gif +0 -0
- data/samples/navi/res/table-remove-row-hover.gif +0 -0
- data/samples/navi/res/table-remove-row.gif +0 -0
- data/samples/navi/res/throbber/Thumbs.db +0 -0
- data/samples/navi/res/throbber/anim.gif +0 -0
- data/samples/navi/res/throbber/anims00.gif +0 -0
- data/samples/navi/res/throbber/anims01.gif +0 -0
- data/samples/navi/res/throbber/anims02.gif +0 -0
- data/samples/navi/res/throbber/anims03.gif +0 -0
- data/samples/navi/res/throbber/anims04.gif +0 -0
- data/samples/navi/res/throbber/anims05.gif +0 -0
- data/samples/navi/res/throbber/anims06.gif +0 -0
- data/samples/navi/res/throbber/anims07.gif +0 -0
- data/samples/navi/res/throbber/anims08.gif +0 -0
- data/samples/navi/res/throbber/anims09.gif +0 -0
- data/samples/navi/res/throbber/anims10.gif +0 -0
- data/samples/navi/res/throbber/anims11.gif +0 -0
- data/samples/navi/res/throbber/anims12.gif +0 -0
- data/samples/navi/res/throbber/anims13.gif +0 -0
- data/samples/navi/res/throbber/anims14.gif +0 -0
- data/samples/navi/res/throbber/anims15.gif +0 -0
- data/samples/navi/res/throbber/anims16.gif +0 -0
- data/samples/navi/res/throbber/anims17.gif +0 -0
- data/samples/navi/res/throbber/anims18.gif +0 -0
- data/samples/navi/res/throbber/anims19.gif +0 -0
- data/samples/navi/res/throbber/anims20.gif +0 -0
- data/samples/navi/res/throbber/anims21.gif +0 -0
- data/samples/navi/res/throbber/anims22.gif +0 -0
- data/samples/navi/res/throbber/anims23.gif +0 -0
- data/samples/navi/res/throbber/anims24.gif +0 -0
- data/samples/navi/res/throbber/anims25.gif +0 -0
- data/samples/navi/res/throbber/anims26.gif +0 -0
- data/samples/navi/res/throbber/anims27.gif +0 -0
- data/samples/navi/res/throbber/anims28.gif +0 -0
- data/samples/navi/res/throbber/anims29.gif +0 -0
- data/samples/navi/res/ua.css +235 -0
- data/samples/navi/res/viewer.properties +1 -0
- data/samples/navi/res/viewsource.css +118 -0
- data/samples/navi/res/wincharset.properties +55 -0
- data/samples/navi/resources.cfg +14 -0
- data/samples/navi/testNaviMask.png +0 -0
- data/samples/ogre.cfg +8 -0
- data/samples/plugins.cfg +11 -0
- data/samples/quake3settings.cfg +2 -0
- data/samples/render_run_log.5796 +891 -0
- data/samples/render_to_texture.rb +161 -0
- data/samples/resources.cfg +16 -0
- data/samples/sky_box.rb +107 -0
- data/samples/sky_dome.rb +86 -0
- data/samples/sky_plane.rb +27 -0
- data/samples/smoke.rb +23 -0
- data/samples/work/cube_mapping.rb +686 -0
- 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, "&");
|
135
|
+
s = s.replace(/>/g, ">");
|
136
|
+
s = s.replace(/</g, "<");
|
137
|
+
s = s.replace(/"/g, """);
|
138
|
+
s = s.replace(/'/g, "'");
|
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
|
+
}
|