[Lutinweb-commits] r48 - in trunk/lutinrss/src/main/webapp/fckeditor/editor: _source/classes _source/commandclasses _source/internals css/behaviors css/images dialog/common dialog/common/images dialog/fck_about dialog/fck_about/sponsors dialog/fck_docprops dialog/fck_flash dialog/fck_image dialog/fck_link dialog/fck_select dialog/fck_spellerpages dialog/fck_spellerpages/spellerpages dialog/fck_spellerpages/spellerpages/server-scripts dialog/fck_template dialog/fck_template/images filemanager/browser fileman
Author: tchemit Date: 2008-05-18 11:54:29 +0000 (Sun, 18 May 2008) New Revision: 48 Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckcontextmenu.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckdataprocessor.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckdocumentfragment_gecko.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckdocumentfragment_ie.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckdomrange.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckdomrange_gecko.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckdomrange_ie.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckdomrangeiterator.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckeditingarea.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckelementpath.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckenterkey.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckevents.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckhtmliterator.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckicon.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckiecleanup.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckimagepreloader.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckkeystrokehandler.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckmenublock.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckmenublockpanel.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckmenuitem.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckpanel.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckplugin.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckspecialcombo.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckstyle.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbar.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarbreak_gecko.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarbreak_ie.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarbutton.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarbuttonui.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarfontformatcombo.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarfontscombo.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarfontsizecombo.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarpanelbutton.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarspecialcombo.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarstylecombo.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckw3crange.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckxml.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckxml_gecko.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckxml_ie.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fck_othercommands.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckblockquotecommand.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckcorestylecommand.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckfitwindow.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckindentcommands.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckjustifycommands.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fcklistcommands.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fcknamedcommand.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckpasteplaintextcommand.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckpastewordcommand.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckremoveformatcommand.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckshowblocks.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckspellcheckcommand_gecko.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckspellcheckcommand_ie.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckstylecommand.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fcktablecommand.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fcktextcolorcommand.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fck.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fck_contextmenu.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fck_gecko.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fck_ie.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckbrowserinfo.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckcodeformatter.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckcommands.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckconfig.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckdebug.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckdialog.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckdocumentprocessor.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckdomtools.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcklanguagemanager.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcklisthandler.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcklistslib.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckplugins.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckregexlib.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckselection.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckselection_gecko.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckselection_ie.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckstyles.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcktablehandler.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcktablehandler_gecko.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcktablehandler_ie.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcktoolbaritems.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcktoolbarset.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcktools.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcktools_gecko.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcktools_ie.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckundo.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckurlparams.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckxhtml.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckxhtml_gecko.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckxhtml_ie.js trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckxhtmlentities.js trunk/lutinrss/src/main/webapp/fckeditor/editor/css/behaviors/disablehandles.htc trunk/lutinrss/src/main/webapp/fckeditor/editor/css/behaviors/showtableborders.htc trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/block_address.png trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/block_blockquote.png trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/block_div.png trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/block_h1.png trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/block_h2.png trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/block_h3.png trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/block_h4.png trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/block_h5.png trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/block_h6.png trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/block_p.png trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/block_pre.png trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/fck_anchor.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/fck_flashlogo.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/fck_hiddenfield.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/fck_pagebreak.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/fck_plugin.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/common/fck_dialog_common.css trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/common/fck_dialog_common.js trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/common/images/ trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/common/images/locked.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/common/images/reset.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/common/images/unlocked.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_about/logo_fckeditor.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_about/logo_fredck.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_about/sponsors/ trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_about/sponsors/spellchecker_net.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_docprops/fck_document_preview.html trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_flash/fck_flash.js trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_flash/fck_flash_preview.html trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_image/fck_image.js trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_image/fck_image_preview.html trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_link/fck_link.js trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_select/fck_select.js trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/ trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/blank.html trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/controlWindow.js trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/controls.html trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/server-scripts/ trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/server-scripts/spellchecker.cfm trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/server-scripts/spellchecker.php trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/server-scripts/spellchecker.pl trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/spellChecker.js trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/spellchecker.html trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/spellerStyle.css trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/wordWindow.js trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_template/images/ trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_template/images/template1.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_template/images/template2.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_template/images/template3.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/browser.css trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/browser.html trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/frmactualfolder.html trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/frmcreatefolder.html trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/frmfolders.html trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/frmresourceslist.html trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/frmresourcetype.html trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/frmupload.html trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/ButtonArrow.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/Folder.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/Folder32.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/FolderOpened.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/FolderOpened32.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/FolderUp.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/ai.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/avi.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/bmp.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/cs.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/default.icon.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/dll.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/doc.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/exe.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/fla.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/gif.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/htm.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/html.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/jpg.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/js.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/mdb.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/mp3.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/pdf.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/png.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/ppt.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/rdp.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/swf.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/swt.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/txt.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/vsd.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/xls.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/xml.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/zip.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/ai.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/avi.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/bmp.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/cs.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/default.icon.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/dll.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/doc.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/exe.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/fla.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/gif.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/htm.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/html.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/jpg.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/js.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/mdb.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/mp3.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/pdf.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/png.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/ppt.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/rdp.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/swf.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/swt.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/txt.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/vsd.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/xls.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/xml.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/zip.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/spacer.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/js/ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/js/common.js trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/js/fckxml.js trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/asp/ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/asp/basexml.asp trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/asp/class_upload.asp trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/asp/commands.asp trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/asp/config.asp trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/asp/connector.asp trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/asp/io.asp trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/asp/upload.asp trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/asp/util.asp trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/aspx/ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/aspx/config.ascx trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/aspx/connector.aspx trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/aspx/upload.aspx trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/ImageObject.cfc trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/cf5_connector.cfm trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/cf5_upload.cfm trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/cf_basexml.cfm trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/cf_commands.cfm trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/cf_connector.cfm trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/cf_io.cfm trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/cf_upload.cfm trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/cf_util.cfm trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/config.cfm trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/connector.cfm trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/image.cfc trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/upload.cfm trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/lasso/ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/lasso/config.lasso trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/lasso/connector.lasso trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/lasso/upload.lasso trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/perl/ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/perl/basexml.pl trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/perl/commands.pl trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/perl/connector.cgi trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/perl/io.pl trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/perl/upload.cgi trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/perl/upload_fck.pl trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/perl/util.pl trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/php/ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/php/basexml.php trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/php/commands.php trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/php/config.php trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/php/connector.php trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/php/io.php trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/php/phpcompat.php trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/php/upload.php trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/php/util.php trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/config.py trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/connector.py trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/fckcommands.py trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/fckconnector.py trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/fckoutput.py trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/fckutil.py trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/htaccess.txt trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/upload.py trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/wsgi.py trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/zope.py trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/test.html trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/uploadtest.html trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/ trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/angel_smile.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/angry_smile.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/broken_heart.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/cake.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/confused_smile.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/cry_smile.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/devil_smile.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/embaressed_smile.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/envelope.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/heart.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/kiss.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/lightbulb.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/omg_smile.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/regular_smile.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/sad_smile.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/shades_smile.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/teeth_smile.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/thumbs_down.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/thumbs_up.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/tounge_smile.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/whatchutalkingabout_smile.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/wink_smile.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/plugins/bbcode/_sample/sample.config.js trunk/lutinrss/src/main/webapp/fckeditor/editor/plugins/bbcode/_sample/sample.html trunk/lutinrss/src/main/webapp/fckeditor/editor/plugins/placeholder/lang/de.js trunk/lutinrss/src/main/webapp/fckeditor/editor/plugins/placeholder/lang/en.js trunk/lutinrss/src/main/webapp/fckeditor/editor/plugins/placeholder/lang/es.js trunk/lutinrss/src/main/webapp/fckeditor/editor/plugins/placeholder/lang/fr.js trunk/lutinrss/src/main/webapp/fckeditor/editor/plugins/placeholder/lang/it.js trunk/lutinrss/src/main/webapp/fckeditor/editor/plugins/placeholder/lang/pl.js trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/fck_dialog.css trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/fck_dialog_ie6.js trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/fck_editor.css trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/fck_strip.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/ trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/dialog.sides.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/dialog.sides.png trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/dialog.sides.rtl.png trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/sprites.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/sprites.png trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/toolbar.arrowright.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/toolbar.buttonarrow.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/toolbar.collapse.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/toolbar.end.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/toolbar.expand.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/toolbar.separator.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/toolbar.start.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/fck_dialog.css trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/fck_dialog_ie6.js trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/fck_editor.css trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/fck_strip.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/ trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/dialog.sides.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/dialog.sides.png trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/dialog.sides.rtl.png trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/sprites.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/sprites.png trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/toolbar.arrowright.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/toolbar.bg.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/toolbar.buttonarrow.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/toolbar.collapse.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/toolbar.end.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/toolbar.expand.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/toolbar.separator.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/toolbar.start.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/fck_dialog.css trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/fck_dialog_ie6.js trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/fck_editor.css trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/fck_strip.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/ trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/dialog.sides.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/dialog.sides.png trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/dialog.sides.rtl.png trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/sprites.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/sprites.png trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/toolbar.arrowright.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/toolbar.buttonarrow.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/toolbar.buttonbg.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/toolbar.collapse.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/toolbar.end.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/toolbar.expand.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/toolbar.separator.gif trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/toolbar.start.gif Log: import fckeditor 2.6 for test Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckcontextmenu.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckcontextmenu.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckcontextmenu.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,214 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKContextMenu Class: renders an control a context menu. + */ + +var FCKContextMenu = function( parentWindow, langDir ) +{ + this.CtrlDisable = false ; + + var oPanel = this._Panel = new FCKPanel( parentWindow ) ; + oPanel.AppendStyleSheet( FCKConfig.SkinEditorCSS ) ; + oPanel.IsContextMenu = true ; + + // The FCKTools.DisableSelection doesn't seems to work to avoid dragging of the icons in Mozilla + // so we stop the start of the dragging + if ( FCKBrowserInfo.IsGecko ) + oPanel.Document.addEventListener( 'draggesture', function(e) {e.preventDefault(); return false;}, true ) ; + + var oMenuBlock = this._MenuBlock = new FCKMenuBlock() ; + oMenuBlock.Panel = oPanel ; + oMenuBlock.OnClick = FCKTools.CreateEventListener( FCKContextMenu_MenuBlock_OnClick, this ) ; + + this._Redraw = true ; +} + + +FCKContextMenu.prototype.SetMouseClickWindow = function( mouseClickWindow ) +{ + if ( !FCKBrowserInfo.IsIE ) + { + this._Document = mouseClickWindow.document ; + if ( FCKBrowserInfo.IsOpera && !( 'oncontextmenu' in document.createElement('foo') ) ) + { + this._Document.addEventListener( 'mousedown', FCKContextMenu_Document_OnMouseDown, false ) ; + this._Document.addEventListener( 'mouseup', FCKContextMenu_Document_OnMouseUp, false ) ; + } + this._Document.addEventListener( 'contextmenu', FCKContextMenu_Document_OnContextMenu, false ) ; + } +} + +/** + The customData parameter is just a value that will be send to the command that is executed, + so it's possible to reuse the same command for several items just by assigning different data for each one. +*/ +FCKContextMenu.prototype.AddItem = function( name, label, iconPathOrStripInfoArrayOrIndex, isDisabled, customData ) +{ + var oItem = this._MenuBlock.AddItem( name, label, iconPathOrStripInfoArrayOrIndex, isDisabled, customData ) ; + this._Redraw = true ; + return oItem ; +} + +FCKContextMenu.prototype.AddSeparator = function() +{ + this._MenuBlock.AddSeparator() ; + this._Redraw = true ; +} + +FCKContextMenu.prototype.RemoveAllItems = function() +{ + this._MenuBlock.RemoveAllItems() ; + this._Redraw = true ; +} + +FCKContextMenu.prototype.AttachToElement = function( element ) +{ + if ( FCKBrowserInfo.IsIE ) + FCKTools.AddEventListenerEx( element, 'contextmenu', FCKContextMenu_AttachedElement_OnContextMenu, this ) ; + else + element._FCKContextMenu = this ; +} + +function FCKContextMenu_Document_OnContextMenu( e ) +{ + var el = e.target ; + + while ( el ) + { + if ( el._FCKContextMenu ) + { + if ( el._FCKContextMenu.CtrlDisable && ( e.ctrlKey || e.metaKey ) ) + return true ; + + FCKTools.CancelEvent( e ) ; + FCKContextMenu_AttachedElement_OnContextMenu( e, el._FCKContextMenu, el ) ; + return false ; + } + el = el.parentNode ; + } + return true ; +} + +var FCKContextMenu_OverrideButton ; + +function FCKContextMenu_Document_OnMouseDown( e ) +{ + if( !e || e.button != 2 ) + return false ; + + var el = e.target ; + + while ( el ) + { + if ( el._FCKContextMenu ) + { + if ( el._FCKContextMenu.CtrlDisable && ( e.ctrlKey || e.metaKey ) ) + return true ; + + var overrideButton = FCKContextMenu_OverrideButton ; + if( !overrideButton ) + { + var doc = FCKTools.GetElementDocument( e.target ) ; + overrideButton = FCKContextMenu_OverrideButton = doc.createElement('input') ; + overrideButton.type = 'button' ; + var buttonHolder = doc.createElement('p') ; + doc.body.appendChild( buttonHolder ) ; + buttonHolder.appendChild( overrideButton ) ; + } + + overrideButton.style.cssText = 'position:absolute;top:' + ( e.clientY - 2 ) + + 'px;left:' + ( e.clientX - 2 ) + + 'px;width:5px;height:5px;opacity:0.01' ; + } + el = el.parentNode ; + } + return false ; +} + +function FCKContextMenu_Document_OnMouseUp( e ) +{ + var overrideButton = FCKContextMenu_OverrideButton ; + + if ( overrideButton ) + { + var parent = overrideButton.parentNode ; + parent.parentNode.removeChild( parent ) ; + FCKContextMenu_OverrideButton = undefined ; + + if( e && e.button == 2 ) + { + FCKContextMenu_Document_OnContextMenu( e ) ; + return false ; + } + } + return true ; +} + +function FCKContextMenu_AttachedElement_OnContextMenu( ev, fckContextMenu, el ) +{ + if ( fckContextMenu.CtrlDisable && ( ev.ctrlKey || ev.metaKey ) ) + return true ; + + var eTarget = el || this ; + + if ( fckContextMenu.OnBeforeOpen ) + fckContextMenu.OnBeforeOpen.call( fckContextMenu, eTarget ) ; + + if ( fckContextMenu._MenuBlock.Count() == 0 ) + return false ; + + if ( fckContextMenu._Redraw ) + { + fckContextMenu._MenuBlock.Create( fckContextMenu._Panel.MainNode ) ; + fckContextMenu._Redraw = false ; + } + + // This will avoid that the content of the context menu can be dragged in IE + // as the content of the panel is recreated we need to do it every time + FCKTools.DisableSelection( fckContextMenu._Panel.Document.body ) ; + + var x = 0 ; + var y = 0 ; + if ( FCKBrowserInfo.IsIE ) + { + x = ev.screenX ; + y = ev.screenY ; + } + else if ( FCKBrowserInfo.IsSafari ) + { + x = ev.clientX ; + y = ev.clientY ; + } + else + { + x = ev.pageX ; + y = ev.pageY ; + } + fckContextMenu._Panel.Show( x, y, ev.currentTarget || null ) ; + + return false ; +} + +function FCKContextMenu_MenuBlock_OnClick( menuItem, contextMenu ) +{ + contextMenu._Panel.Hide() ; + FCKTools.RunFunction( contextMenu.OnItemClick, contextMenu, menuItem ) ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckdataprocessor.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckdataprocessor.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckdataprocessor.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,119 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * The Data Processor is responsible for transforming the input and output data + * in the editor. For more info: + * http://dev.fckeditor.net/wiki/Components/DataProcessor + * + * The default implementation offers the base XHTML compatibility features of + * FCKeditor. Further Data Processors may be implemented for other purposes. + * + */ + +var FCKDataProcessor = function() +{} + +FCKDataProcessor.prototype = +{ + /* + * Returns a string representing the HTML format of "data". The returned + * value will be loaded in the editor. + * The HTML must be from <html> to </html>, including <head>, <body> and + * eventually the DOCTYPE. + * Note: HTML comments may already be part of the data because of the + * pre-processing made with ProtectedSource. + * @param {String} data The data to be converted in the + * DataProcessor specific format. + */ + ConvertToHtml : function( data ) + { + // The default data processor must handle two different cases depending + // on the FullPage setting. Custom Data Processors will not be + // compatible with FullPage, much probably. + if ( FCKConfig.FullPage ) + { + // Save the DOCTYPE. + FCK.DocTypeDeclaration = data.match( FCKRegexLib.DocTypeTag ) ; + + // Check if the <body> tag is available. + if ( !FCKRegexLib.HasBodyTag.test( data ) ) + data = '<body>' + data + '</body>' ; + + // Check if the <html> tag is available. + if ( !FCKRegexLib.HtmlOpener.test( data ) ) + data = '<html dir="' + FCKConfig.ContentLangDirection + '">' + data + '</html>' ; + + // Check if the <head> tag is available. + if ( !FCKRegexLib.HeadOpener.test( data ) ) + data = data.replace( FCKRegexLib.HtmlOpener, '$&<head><title></title></head>' ) ; + + return data ; + } + else + { + var html = + FCKConfig.DocType + + '<html dir="' + FCKConfig.ContentLangDirection + '"' ; + + // On IE, if you are using a DOCTYPE different of HTML 4 (like + // XHTML), you must force the vertical scroll to show, otherwise + // the horizontal one may appear when the page needs vertical scrolling. + // TODO : Check it with IE7 and make it IE6- if it is the case. + if ( FCKBrowserInfo.IsIE && FCKConfig.DocType.length > 0 && !FCKRegexLib.Html4DocType.test( FCKConfig.DocType ) ) + html += ' style="overflow-y: scroll"' ; + + html += '><head><title></title></head>' + + '<body' + FCKConfig.GetBodyAttributes() + '>' + + data + + '</body></html>' ; + + return html ; + } + }, + + /* + * Converts a DOM (sub-)tree to a string in the data format. + * @param {Object} rootNode The node that contains the DOM tree to be + * converted to the data format. + * @param {Boolean} excludeRoot Indicates that the root node must not + * be included in the conversion, only its children. + * @param {Boolean} format Indicates that the data must be formatted + * for human reading. Not all Data Processors may provide it. + */ + ConvertToDataFormat : function( rootNode, excludeRoot, ignoreIfEmptyParagraph, format ) + { + var data = FCKXHtml.GetXHTML( rootNode, !excludeRoot, format ) ; + + if ( ignoreIfEmptyParagraph && FCKRegexLib.EmptyOutParagraph.test( data ) ) + return '' ; + + return data ; + }, + + /* + * Makes any necessary changes to a piece of HTML for insertion in the + * editor selection position. + * @param {String} html The HTML to be fixed. + */ + FixHtml : function( html ) + { + return html ; + } +} ; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckdocumentfragment_gecko.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckdocumentfragment_gecko.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckdocumentfragment_gecko.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,46 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * This is a generic Document Fragment object. It is not intended to provide + * the W3C implementation, but is a way to fix the missing of a real Document + * Fragment in IE (where document.createDocumentFragment() returns a normal + * document instead), giving a standard interface for it. + * (IE Implementation) + */ + +var FCKDocumentFragment = function( parentDocument, baseDocFrag ) +{ + this.RootNode = baseDocFrag || parentDocument.createDocumentFragment() ; +} + +FCKDocumentFragment.prototype = +{ + + // Append the contents of this Document Fragment to another element. + AppendTo : function( targetNode ) + { + targetNode.appendChild( this.RootNode ) ; + }, + + InsertAfterNode : function( existingNode ) + { + FCKDomTools.InsertAfterNode( existingNode, this.RootNode ) ; + } +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckdocumentfragment_ie.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckdocumentfragment_ie.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckdocumentfragment_ie.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,58 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * This is a generic Document Fragment object. It is not intended to provide + * the W3C implementation, but is a way to fix the missing of a real Document + * Fragment in IE (where document.createDocumentFragment() returns a normal + * document instead), giving a standard interface for it. + * (IE Implementation) + */ + +var FCKDocumentFragment = function( parentDocument ) +{ + this._Document = parentDocument ; + this.RootNode = parentDocument.createElement( 'div' ) ; +} + +// Append the contents of this Document Fragment to another node. +FCKDocumentFragment.prototype = +{ + + AppendTo : function( targetNode ) + { + FCKDomTools.MoveChildren( this.RootNode, targetNode ) ; + }, + + AppendHtml : function( html ) + { + var eTmpDiv = this._Document.createElement( 'div' ) ; + eTmpDiv.innerHTML = html ; + FCKDomTools.MoveChildren( eTmpDiv, this.RootNode ) ; + }, + + InsertAfterNode : function( existingNode ) + { + var eRoot = this.RootNode ; + var eLast ; + + while( ( eLast = eRoot.lastChild ) ) + FCKDomTools.InsertAfterNode( existingNode, eRoot.removeChild( eLast ) ) ; + } +} ; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckdomrange.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckdomrange.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckdomrange.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,918 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Class for working with a selection range, much like the W3C DOM Range, but + * it is not intended to be an implementation of the W3C interface. + */ + +var FCKDomRange = function( sourceWindow ) +{ + this.Window = sourceWindow ; + this._Cache = {} ; +} + +FCKDomRange.prototype = +{ + + _UpdateElementInfo : function() + { + var innerRange = this._Range ; + + if ( !innerRange ) + this.Release( true ) ; + else + { + // For text nodes, the node itself is the StartNode. + var eStart = innerRange.startContainer ; + var eEnd = innerRange.endContainer ; + + var oElementPath = new FCKElementPath( eStart ) ; + this.StartNode = eStart.nodeType == 3 ? eStart : eStart.childNodes[ innerRange.startOffset ] ; + this.StartContainer = eStart ; + this.StartBlock = oElementPath.Block ; + this.StartBlockLimit = oElementPath.BlockLimit ; + + if ( eStart != eEnd ) + oElementPath = new FCKElementPath( eEnd ) ; + + // The innerRange.endContainer[ innerRange.endOffset ] is not + // usually part of the range, but the marker for the range end. So, + // let's get the previous available node as the real end. + var eEndNode = eEnd ; + if ( innerRange.endOffset == 0 ) + { + while ( eEndNode && !eEndNode.previousSibling ) + eEndNode = eEndNode.parentNode ; + + if ( eEndNode ) + eEndNode = eEndNode.previousSibling ; + } + else if ( eEndNode.nodeType == 1 ) + eEndNode = eEndNode.childNodes[ innerRange.endOffset - 1 ] ; + + this.EndNode = eEndNode ; + this.EndContainer = eEnd ; + this.EndBlock = oElementPath.Block ; + this.EndBlockLimit = oElementPath.BlockLimit ; + } + + this._Cache = {} ; + }, + + CreateRange : function() + { + return new FCKW3CRange( this.Window.document ) ; + }, + + DeleteContents : function() + { + if ( this._Range ) + { + this._Range.deleteContents() ; + this._UpdateElementInfo() ; + } + }, + + ExtractContents : function() + { + if ( this._Range ) + { + var docFrag = this._Range.extractContents() ; + this._UpdateElementInfo() ; + return docFrag ; + } + return null ; + }, + + CheckIsCollapsed : function() + { + if ( this._Range ) + return this._Range.collapsed ; + + return false ; + }, + + Collapse : function( toStart ) + { + if ( this._Range ) + this._Range.collapse( toStart ) ; + + this._UpdateElementInfo() ; + }, + + Clone : function() + { + var oClone = FCKTools.CloneObject( this ) ; + + if ( this._Range ) + oClone._Range = this._Range.cloneRange() ; + + return oClone ; + }, + + MoveToNodeContents : function( targetNode ) + { + if ( !this._Range ) + this._Range = this.CreateRange() ; + + this._Range.selectNodeContents( targetNode ) ; + + this._UpdateElementInfo() ; + }, + + MoveToElementStart : function( targetElement ) + { + this.SetStart(targetElement,1) ; + this.SetEnd(targetElement,1) ; + }, + + // Moves to the first editing point inside a element. For example, in a + // element tree like "<p><b><i></i></b> Text</p>", the start editing point + // is "<p><b><i>^</i></b> Text</p>" (inside <i>). + MoveToElementEditStart : function( targetElement ) + { + var editableElement ; + + while ( targetElement && targetElement.nodeType == 1 ) + { + if ( FCKDomTools.CheckIsEditable( targetElement ) ) + editableElement = targetElement ; + else if ( editableElement ) + break ; // If we already found an editable element, stop the loop. + + targetElement = targetElement.firstChild ; + } + + if ( editableElement ) + this.MoveToElementStart( editableElement ) ; + }, + + InsertNode : function( node ) + { + if ( this._Range ) + this._Range.insertNode( node ) ; + }, + + CheckIsEmpty : function() + { + if ( this.CheckIsCollapsed() ) + return true ; + + // Inserts the contents of the range in a div tag. + var eToolDiv = this.Window.document.createElement( 'div' ) ; + this._Range.cloneContents().AppendTo( eToolDiv ) ; + + FCKDomTools.TrimNode( eToolDiv ) ; + + return ( eToolDiv.innerHTML.length == 0 ) ; + }, + + /** + * Checks if the start boundary of the current range is "visually" (like a + * selection caret) at the beginning of the block. It means that some + * things could be brefore the range, like spaces or empty inline elements, + * but it would still be considered at the beginning of the block. + */ + CheckStartOfBlock : function() + { + var cache = this._Cache ; + var bIsStartOfBlock = cache.IsStartOfBlock ; + + if ( bIsStartOfBlock != undefined ) + return bIsStartOfBlock ; + + // Take the block reference. + var block = this.StartBlock || this.StartBlockLimit ; + + var container = this._Range.startContainer ; + var offset = this._Range.startOffset ; + var currentNode ; + + if ( offset > 0 ) + { + // First, check the start container. If it is a text node, get the + // substring of the node value before the range offset. + if ( container.nodeType == 3 ) + { + var textValue = container.nodeValue.substr( 0, offset ).Trim() ; + + // If we have some text left in the container, we are not at + // the end for the block. + if ( textValue.length != 0 ) + return cache.IsStartOfBlock = false ; + } + else + currentNode = container.childNodes[ offset - 1 ] ; + } + + // We'll not have a currentNode if the container was a text node, or + // the offset is zero. + if ( !currentNode ) + currentNode = FCKDomTools.GetPreviousSourceNode( container, true, null, block ) ; + + while ( currentNode ) + { + switch ( currentNode.nodeType ) + { + case 1 : + // It's not an inline element. + if ( !FCKListsLib.InlineChildReqElements[ currentNode.nodeName.toLowerCase() ] ) + return cache.IsStartOfBlock = false ; + + break ; + + case 3 : + // It's a text node with real text. + if ( currentNode.nodeValue.Trim().length > 0 ) + return cache.IsStartOfBlock = false ; + } + + currentNode = FCKDomTools.GetPreviousSourceNode( currentNode, false, null, block ) ; + } + + return cache.IsStartOfBlock = true ; + }, + + /** + * Checks if the end boundary of the current range is "visually" (like a + * selection caret) at the end of the block. It means that some things + * could be after the range, like spaces, empty inline elements, or a + * single <br>, but it would still be considered at the end of the block. + */ + CheckEndOfBlock : function( refreshSelection ) + { + var isEndOfBlock = this._Cache.IsEndOfBlock ; + + if ( isEndOfBlock != undefined ) + return isEndOfBlock ; + + // Take the block reference. + var block = this.EndBlock || this.EndBlockLimit ; + + var container = this._Range.endContainer ; + var offset = this._Range.endOffset ; + var currentNode ; + + // First, check the end container. If it is a text node, get the + // substring of the node value after the range offset. + if ( container.nodeType == 3 ) + { + var textValue = container.nodeValue ; + if ( offset < textValue.length ) + { + textValue = textValue.substr( offset ) ; + + // If we have some text left in the container, we are not at + // the end for the block. + if ( textValue.Trim().length != 0 ) + return this._Cache.IsEndOfBlock = false ; + } + } + else + currentNode = container.childNodes[ offset ] ; + + // We'll not have a currentNode if the container was a text node, of + // the offset is out the container children limits (after it probably). + if ( !currentNode ) + currentNode = FCKDomTools.GetNextSourceNode( container, true, null, block ) ; + + var hadBr = false ; + + while ( currentNode ) + { + switch ( currentNode.nodeType ) + { + case 1 : + var nodeName = currentNode.nodeName.toLowerCase() ; + + // It's an inline element. + if ( FCKListsLib.InlineChildReqElements[ nodeName ] ) + break ; + + // It is the first <br> found. + if ( nodeName == 'br' && !hadBr ) + { + hadBr = true ; + break ; + } + + return this._Cache.IsEndOfBlock = false ; + + case 3 : + // It's a text node with real text. + if ( currentNode.nodeValue.Trim().length > 0 ) + return this._Cache.IsEndOfBlock = false ; + } + + currentNode = FCKDomTools.GetNextSourceNode( currentNode, false, null, block ) ; + } + + if ( refreshSelection ) + this.Select() ; + + return this._Cache.IsEndOfBlock = true ; + }, + + // This is an "intrusive" way to create a bookmark. It includes <span> tags + // in the range boundaries. The advantage of it is that it is possible to + // handle DOM mutations when moving back to the bookmark. + // Attention: the inclusion of nodes in the DOM is a design choice and + // should not be changed as there are other points in the code that may be + // using those nodes to perform operations. See GetBookmarkNode. + // For performance, includeNodes=true if intended to SelectBookmark. + CreateBookmark : function( includeNodes ) + { + // Create the bookmark info (random IDs). + var oBookmark = + { + StartId : (new Date()).valueOf() + Math.floor(Math.random()*1000) + 'S', + EndId : (new Date()).valueOf() + Math.floor(Math.random()*1000) + 'E' + } ; + + var oDoc = this.Window.document ; + var eStartSpan ; + var eEndSpan ; + var oClone ; + + // For collapsed ranges, add just the start marker. + if ( !this.CheckIsCollapsed() ) + { + eEndSpan = oDoc.createElement( 'span' ) ; + eEndSpan.style.display = 'none' ; + eEndSpan.id = oBookmark.EndId ; + eEndSpan.setAttribute( '_fck_bookmark', true ) ; + + // For IE, it must have something inside, otherwise it may be + // removed during DOM operations. +// if ( FCKBrowserInfo.IsIE ) + eEndSpan.innerHTML = ' ' ; + + oClone = this.Clone() ; + oClone.Collapse( false ) ; + oClone.InsertNode( eEndSpan ) ; + } + + eStartSpan = oDoc.createElement( 'span' ) ; + eStartSpan.style.display = 'none' ; + eStartSpan.id = oBookmark.StartId ; + eStartSpan.setAttribute( '_fck_bookmark', true ) ; + + // For IE, it must have something inside, otherwise it may be removed + // during DOM operations. +// if ( FCKBrowserInfo.IsIE ) + eStartSpan.innerHTML = ' ' ; + + oClone = this.Clone() ; + oClone.Collapse( true ) ; + oClone.InsertNode( eStartSpan ) ; + + if ( includeNodes ) + { + oBookmark.StartNode = eStartSpan ; + oBookmark.EndNode = eEndSpan ; + } + + // Update the range position. + if ( eEndSpan ) + { + this.SetStart( eStartSpan, 4 ) ; + this.SetEnd( eEndSpan, 3 ) ; + } + else + this.MoveToPosition( eStartSpan, 4 ) ; + + return oBookmark ; + }, + + // This one should be a part of a hypothetic "bookmark" object. + GetBookmarkNode : function( bookmark, start ) + { + var doc = this.Window.document ; + + if ( start ) + return bookmark.StartNode || doc.getElementById( bookmark.StartId ) ; + else + return bookmark.EndNode || doc.getElementById( bookmark.EndId ) ; + }, + + MoveToBookmark : function( bookmark, preserveBookmark ) + { + var eStartSpan = this.GetBookmarkNode( bookmark, true ) ; + var eEndSpan = this.GetBookmarkNode( bookmark, false ) ; + + this.SetStart( eStartSpan, 3 ) ; + + if ( !preserveBookmark ) + FCKDomTools.RemoveNode( eStartSpan ) ; + + // If collapsed, the end span will not be available. + if ( eEndSpan ) + { + this.SetEnd( eEndSpan, 3 ) ; + + if ( !preserveBookmark ) + FCKDomTools.RemoveNode( eEndSpan ) ; + } + else + this.Collapse( true ) ; + + this._UpdateElementInfo() ; + }, + + // Non-intrusive bookmark algorithm + CreateBookmark2 : function() + { + // If there is no range then get out of here. + // It happens on initial load in Safari #962 and if the editor it's hidden also in Firefox + if ( ! this._Range ) + return { "Start" : 0, "End" : 0 } ; + + // First, we record down the offset values + var bookmark = + { + "Start" : [ this._Range.startOffset ], + "End" : [ this._Range.endOffset ] + } ; + // Since we're treating the document tree as normalized, we need to backtrack the text lengths + // of previous text nodes into the offset value. + var curStart = this._Range.startContainer.previousSibling ; + var curEnd = this._Range.endContainer.previousSibling ; + + // Also note that the node that we use for "address base" would change during backtracking. + var addrStart = this._Range.startContainer ; + var addrEnd = this._Range.endContainer ; + while ( curStart && curStart.nodeType == 3 ) + { + bookmark.Start[0] += curStart.length ; + addrStart = curStart ; + curStart = curStart.previousSibling ; + } + while ( curEnd && curEnd.nodeType == 3 ) + { + bookmark.End[0] += curEnd.length ; + addrEnd = curEnd ; + curEnd = curEnd.previousSibling ; + } + + // If the object pointed to by the startOffset and endOffset are text nodes, we need + // to backtrack and add in the text offset to the bookmark addresses. + if ( addrStart.nodeType == 1 && addrStart.childNodes[bookmark.Start[0]] && addrStart.childNodes[bookmark.Start[0]].nodeType == 3 ) + { + var curNode = addrStart.childNodes[bookmark.Start[0]] ; + var offset = 0 ; + while ( curNode.previousSibling && curNode.previousSibling.nodeType == 3 ) + { + curNode = curNode.previousSibling ; + offset += curNode.length ; + } + addrStart = curNode ; + bookmark.Start[0] = offset ; + } + if ( addrEnd.nodeType == 1 && addrEnd.childNodes[bookmark.End[0]] && addrEnd.childNodes[bookmark.End[0]].nodeType == 3 ) + { + var curNode = addrEnd.childNodes[bookmark.End[0]] ; + var offset = 0 ; + while ( curNode.previousSibling && curNode.previousSibling.nodeType == 3 ) + { + curNode = curNode.previousSibling ; + offset += curNode.length ; + } + addrEnd = curNode ; + bookmark.End[0] = offset ; + } + + // Then, we record down the precise position of the container nodes + // by walking up the DOM tree and counting their childNode index + bookmark.Start = FCKDomTools.GetNodeAddress( addrStart, true ).concat( bookmark.Start ) ; + bookmark.End = FCKDomTools.GetNodeAddress( addrEnd, true ).concat( bookmark.End ) ; + return bookmark; + }, + + MoveToBookmark2 : function( bookmark ) + { + // Reverse the childNode counting algorithm in CreateBookmark2() + var curStart = FCKDomTools.GetNodeFromAddress( this.Window.document, bookmark.Start.slice( 0, -1 ), true ) ; + var curEnd = FCKDomTools.GetNodeFromAddress( this.Window.document, bookmark.End.slice( 0, -1 ), true ) ; + + // Generate the W3C Range object and update relevant data + this.Release( true ) ; + this._Range = new FCKW3CRange( this.Window.document ) ; + var startOffset = bookmark.Start[ bookmark.Start.length - 1 ] ; + var endOffset = bookmark.End[ bookmark.End.length - 1 ] ; + while ( curStart.nodeType == 3 && startOffset > curStart.length ) + { + if ( ! curStart.nextSibling || curStart.nextSibling.nodeType != 3 ) + break ; + startOffset -= curStart.length ; + curStart = curStart.nextSibling ; + } + while ( curEnd.nodeType == 3 && endOffset > curEnd.length ) + { + if ( ! curEnd.nextSibling || curEnd.nextSibling.nodeType != 3 ) + break ; + endOffset -= curEnd.length ; + curEnd = curEnd.nextSibling ; + } + this._Range.setStart( curStart, startOffset ) ; + this._Range.setEnd( curEnd, endOffset ) ; + this._UpdateElementInfo() ; + }, + + MoveToPosition : function( targetElement, position ) + { + this.SetStart( targetElement, position ) ; + this.Collapse( true ) ; + }, + + /* + * Moves the position of the start boundary of the range to a specific position + * relatively to a element. + * @position: + * 1 = After Start <target>^contents</target> + * 2 = Before End <target>contents^</target> + * 3 = Before Start ^<target>contents</target> + * 4 = After End <target>contents</target>^ + */ + SetStart : function( targetElement, position, noInfoUpdate ) + { + var oRange = this._Range ; + if ( !oRange ) + oRange = this._Range = this.CreateRange() ; + + switch( position ) + { + case 1 : // After Start <target>^contents</target> + oRange.setStart( targetElement, 0 ) ; + break ; + + case 2 : // Before End <target>contents^</target> + oRange.setStart( targetElement, targetElement.childNodes.length ) ; + break ; + + case 3 : // Before Start ^<target>contents</target> + oRange.setStartBefore( targetElement ) ; + break ; + + case 4 : // After End <target>contents</target>^ + oRange.setStartAfter( targetElement ) ; + } + + if ( !noInfoUpdate ) + this._UpdateElementInfo() ; + }, + + /* + * Moves the position of the start boundary of the range to a specific position + * relatively to a element. + * @position: + * 1 = After Start <target>^contents</target> + * 2 = Before End <target>contents^</target> + * 3 = Before Start ^<target>contents</target> + * 4 = After End <target>contents</target>^ + */ + SetEnd : function( targetElement, position, noInfoUpdate ) + { + var oRange = this._Range ; + if ( !oRange ) + oRange = this._Range = this.CreateRange() ; + + switch( position ) + { + case 1 : // After Start <target>^contents</target> + oRange.setEnd( targetElement, 0 ) ; + break ; + + case 2 : // Before End <target>contents^</target> + oRange.setEnd( targetElement, targetElement.childNodes.length ) ; + break ; + + case 3 : // Before Start ^<target>contents</target> + oRange.setEndBefore( targetElement ) ; + break ; + + case 4 : // After End <target>contents</target>^ + oRange.setEndAfter( targetElement ) ; + } + + if ( !noInfoUpdate ) + this._UpdateElementInfo() ; + }, + + Expand : function( unit ) + { + var oNode, oSibling ; + + switch ( unit ) + { + // Expand the range to include all inline parent elements if we are + // are in their boundary limits. + // For example (where [ ] are the range limits): + // Before => Some <b>[<i>Some sample text]</i></b>. + // After => Some [<b><i>Some sample text</i></b>]. + case 'inline_elements' : + // Expand the start boundary. + if ( this._Range.startOffset == 0 ) + { + oNode = this._Range.startContainer ; + + if ( oNode.nodeType != 1 ) + oNode = oNode.previousSibling ? null : oNode.parentNode ; + + if ( oNode ) + { + while ( FCKListsLib.InlineNonEmptyElements[ oNode.nodeName.toLowerCase() ] ) + { + this._Range.setStartBefore( oNode ) ; + + if ( oNode != oNode.parentNode.firstChild ) + break ; + + oNode = oNode.parentNode ; + } + } + } + + // Expand the end boundary. + oNode = this._Range.endContainer ; + var offset = this._Range.endOffset ; + + if ( ( oNode.nodeType == 3 && offset >= oNode.nodeValue.length ) || ( oNode.nodeType == 1 && offset >= oNode.childNodes.length ) || ( oNode.nodeType != 1 && oNode.nodeType != 3 ) ) + { + if ( oNode.nodeType != 1 ) + oNode = oNode.nextSibling ? null : oNode.parentNode ; + + if ( oNode ) + { + while ( FCKListsLib.InlineNonEmptyElements[ oNode.nodeName.toLowerCase() ] ) + { + this._Range.setEndAfter( oNode ) ; + + if ( oNode != oNode.parentNode.lastChild ) + break ; + + oNode = oNode.parentNode ; + } + } + } + + break ; + + case 'block_contents' : + case 'list_contents' : + var boundarySet = FCKListsLib.BlockBoundaries ; + if ( unit == 'list_contents' || FCKConfig.EnterMode == 'br' ) + boundarySet = FCKListsLib.ListBoundaries ; + + if ( this.StartBlock && FCKConfig.EnterMode != 'br' && unit == 'block_contents' ) + this.SetStart( this.StartBlock, 1 ) ; + else + { + // Get the start node for the current range. + oNode = this._Range.startContainer ; + + // If it is an element, get the node right before of it (in source order). + if ( oNode.nodeType == 1 ) + { + var lastNode = oNode.childNodes[ this._Range.startOffset ] ; + if ( lastNode ) + oNode = FCKDomTools.GetPreviousSourceNode( lastNode, true ) ; + else + oNode = oNode.lastChild || oNode ; + } + + // We must look for the left boundary, relative to the range + // start, which is limited by a block element. + while ( oNode + && ( oNode.nodeType != 1 + || ( oNode != this.StartBlockLimit + && !boundarySet[ oNode.nodeName.toLowerCase() ] ) ) ) + { + this._Range.setStartBefore( oNode ) ; + oNode = oNode.previousSibling || oNode.parentNode ; + } + } + + if ( this.EndBlock && FCKConfig.EnterMode != 'br' && unit == 'block_contents' && this.EndBlock.nodeName.toLowerCase() != 'li' ) + this.SetEnd( this.EndBlock, 2 ) ; + else + { + oNode = this._Range.endContainer ; + if ( oNode.nodeType == 1 ) + oNode = oNode.childNodes[ this._Range.endOffset ] || oNode.lastChild ; + + // We must look for the right boundary, relative to the range + // end, which is limited by a block element. + while ( oNode + && ( oNode.nodeType != 1 + || ( oNode != this.StartBlockLimit + && !boundarySet[ oNode.nodeName.toLowerCase() ] ) ) ) + { + this._Range.setEndAfter( oNode ) ; + oNode = oNode.nextSibling || oNode.parentNode ; + } + + // In EnterMode='br', the end <br> boundary element must + // be included in the expanded range. + if ( oNode && oNode.nodeName.toLowerCase() == 'br' ) + this._Range.setEndAfter( oNode ) ; + } + + this._UpdateElementInfo() ; + } + }, + + /** + * Split the block element for the current range. It deletes the contents + * of the range and splits the block in the collapsed position, resulting + * in two sucessive blocks. The range is then positioned in the middle of + * them. + * + * It returns and object with the following properties: + * - PreviousBlock : a reference to the block element that preceeds + * the range after the split. + * - NextBlock : a reference to the block element that follows the + * range after the split. + * - WasStartOfBlock : a boolean indicating that the range was + * originaly at the start of the block. + * - WasEndOfBlock : a boolean indicating that the range was originaly + * at the end of the block. + * + * If the range was originaly at the start of the block, no split will happen + * and the PreviousBlock value will be null. The same is valid for the + * NextBlock value if the range was at the end of the block. + */ + SplitBlock : function( forceBlockTag ) + { + var blockTag = forceBlockTag || FCKConfig.EnterMode ; + + if ( !this._Range ) + this.MoveToSelection() ; + + // The range boundaries must be in the same "block limit" element. + if ( this.StartBlockLimit == this.EndBlockLimit ) + { + // Get the current blocks. + var eStartBlock = this.StartBlock ; + var eEndBlock = this.EndBlock ; + var oElementPath = null ; + + if ( blockTag != 'br' ) + { + if ( !eStartBlock ) + { + eStartBlock = this.FixBlock( true, blockTag ) ; + eEndBlock = this.EndBlock ; // FixBlock may have fixed the EndBlock too. + } + + if ( !eEndBlock ) + eEndBlock = this.FixBlock( false, blockTag ) ; + } + + // Get the range position. + var bIsStartOfBlock = ( eStartBlock != null && this.CheckStartOfBlock() ) ; + var bIsEndOfBlock = ( eEndBlock != null && this.CheckEndOfBlock() ) ; + + // Delete the current contents. + if ( !this.CheckIsEmpty() ) + this.DeleteContents() ; + + if ( eStartBlock && eEndBlock && eStartBlock == eEndBlock ) + { + if ( bIsEndOfBlock ) + { + oElementPath = new FCKElementPath( this.StartContainer ) ; + this.MoveToPosition( eEndBlock, 4 ) ; + eEndBlock = null ; + } + else if ( bIsStartOfBlock ) + { + oElementPath = new FCKElementPath( this.StartContainer ) ; + this.MoveToPosition( eStartBlock, 3 ) ; + eStartBlock = null ; + } + else + { + // Extract the contents of the block from the selection point to the end of its contents. + this.SetEnd( eStartBlock, 2 ) ; + var eDocFrag = this.ExtractContents() ; + + // Duplicate the block element after it. + eEndBlock = eStartBlock.cloneNode( false ) ; + eEndBlock.removeAttribute( 'id', false ) ; + + // Place the extracted contents in the duplicated block. + eDocFrag.AppendTo( eEndBlock ) ; + + FCKDomTools.InsertAfterNode( eStartBlock, eEndBlock ) ; + + this.MoveToPosition( eStartBlock, 4 ) ; + + // In Gecko, the last child node must be a bogus <br>. + // Note: bogus <br> added under <ul> or <ol> would cause lists to be incorrectly rendered. + if ( FCKBrowserInfo.IsGecko && + ! eStartBlock.nodeName.IEquals( ['ul', 'ol'] ) ) + FCKTools.AppendBogusBr( eStartBlock ) ; + } + } + + return { + PreviousBlock : eStartBlock, + NextBlock : eEndBlock, + WasStartOfBlock : bIsStartOfBlock, + WasEndOfBlock : bIsEndOfBlock, + ElementPath : oElementPath + } ; + } + + return null ; + }, + + // Transform a block without a block tag in a valid block (orphan text in the body or td, usually). + FixBlock : function( isStart, blockTag ) + { + // Bookmark the range so we can restore it later. + var oBookmark = this.CreateBookmark() ; + + // Collapse the range to the requested ending boundary. + this.Collapse( isStart ) ; + + // Expands it to the block contents. + this.Expand( 'block_contents' ) ; + + // Create the fixed block. + var oFixedBlock = this.Window.document.createElement( blockTag ) ; + + // Move the contents of the temporary range to the fixed block. + this.ExtractContents().AppendTo( oFixedBlock ) ; + FCKDomTools.TrimNode( oFixedBlock ) ; + + // Insert the fixed block into the DOM. + this.InsertNode( oFixedBlock ) ; + + // Move the range back to the bookmarked place. + this.MoveToBookmark( oBookmark ) ; + + return oFixedBlock ; + }, + + Release : function( preserveWindow ) + { + if ( !preserveWindow ) + this.Window = null ; + + this.StartNode = null ; + this.StartContainer = null ; + this.StartBlock = null ; + this.StartBlockLimit = null ; + this.EndNode = null ; + this.EndContainer = null ; + this.EndBlock = null ; + this.EndBlockLimit = null ; + this._Range = null ; + this._Cache = null ; + }, + + CheckHasRange : function() + { + return !!this._Range ; + }, + + GetTouchedStartNode : function() + { + var range = this._Range ; + var container = range.startContainer ; + + if ( range.collapsed || container.nodeType != 1 ) + return container ; + + return container.childNodes[ range.startOffset ] || container ; + }, + + GetTouchedEndNode : function() + { + var range = this._Range ; + var container = range.endContainer ; + + if ( range.collapsed || container.nodeType != 1 ) + return container ; + + return container.childNodes[ range.endOffset - 1 ] || container ; + } +} ; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckdomrange_gecko.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckdomrange_gecko.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckdomrange_gecko.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,104 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Class for working with a selection range, much like the W3C DOM Range, but + * it is not intended to be an implementation of the W3C interface. + * (Gecko Implementation) + */ + +FCKDomRange.prototype.MoveToSelection = function() +{ + this.Release( true ) ; + + var oSel = this.Window.getSelection() ; + + if ( oSel && oSel.rangeCount > 0 ) + { + this._Range = FCKW3CRange.CreateFromRange( this.Window.document, oSel.getRangeAt(0) ) ; + this._UpdateElementInfo() ; + } + else + if ( this.Window.document ) + this.MoveToElementStart( this.Window.document.body ) ; +} + +FCKDomRange.prototype.Select = function() +{ + var oRange = this._Range ; + if ( oRange ) + { + var startContainer = oRange.startContainer ; + + // If we have a collapsed range, inside an empty element, we must add + // something to it, otherwise the caret will not be visible. + if ( oRange.collapsed && startContainer.nodeType == 1 && startContainer.childNodes.length == 0 ) + startContainer.appendChild( oRange._Document.createTextNode('') ) ; + + var oDocRange = this.Window.document.createRange() ; + oDocRange.setStart( startContainer, oRange.startOffset ) ; + + try + { + oDocRange.setEnd( oRange.endContainer, oRange.endOffset ) ; + } + catch ( e ) + { + // There is a bug in Firefox implementation (it would be too easy + // otherwise). The new start can't be after the end (W3C says it can). + // So, let's create a new range and collapse it to the desired point. + if ( e.toString().Contains( 'NS_ERROR_ILLEGAL_VALUE' ) ) + { + oRange.collapse( true ) ; + oDocRange.setEnd( oRange.endContainer, oRange.endOffset ) ; + } + else + throw( e ) ; + } + + var oSel = this.Window.getSelection() ; + oSel.removeAllRanges() ; + + // We must add a clone otherwise Firefox will have rendering issues. + oSel.addRange( oDocRange ) ; + } +} + +// Not compatible with bookmark created with CreateBookmark2. +// The bookmark nodes will be deleted from the document. +FCKDomRange.prototype.SelectBookmark = function( bookmark ) +{ + var domRange = this.Window.document.createRange() ; + + var startNode = this.GetBookmarkNode( bookmark, true ) ; + var endNode = this.GetBookmarkNode( bookmark, false ) ; + + domRange.setStart( startNode.parentNode, FCKDomTools.GetIndexOf( startNode ) ) ; + FCKDomTools.RemoveNode( startNode ) ; + + if ( endNode ) + { + domRange.setEnd( endNode.parentNode, FCKDomTools.GetIndexOf( endNode ) ) ; + FCKDomTools.RemoveNode( endNode ) ; + } + + var selection = this.Window.getSelection() ; + selection.removeAllRanges() ; + selection.addRange( domRange ) ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckdomrange_ie.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckdomrange_ie.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckdomrange_ie.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,199 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Class for working with a selection range, much like the W3C DOM Range, but + * it is not intended to be an implementation of the W3C interface. + * (IE Implementation) + */ + +FCKDomRange.prototype.MoveToSelection = function() +{ + this.Release( true ) ; + + this._Range = new FCKW3CRange( this.Window.document ) ; + + var oSel = this.Window.document.selection ; + + if ( oSel.type != 'Control' ) + { + var eMarkerStart = this._GetSelectionMarkerTag( true ) ; + var eMarkerEnd = this._GetSelectionMarkerTag( false ) ; + + if ( !eMarkerStart && !eMarkerEnd ) + { + this._Range.setStart( this.Window.document.body, 0 ) ; + this._UpdateElementInfo() ; + return ; + } + + // Set the start boundary. + this._Range.setStart( eMarkerStart.parentNode, FCKDomTools.GetIndexOf( eMarkerStart ) ) ; + eMarkerStart.parentNode.removeChild( eMarkerStart ) ; + + // Set the end boundary. + this._Range.setEnd( eMarkerEnd.parentNode, FCKDomTools.GetIndexOf( eMarkerEnd ) ) ; + eMarkerEnd.parentNode.removeChild( eMarkerEnd ) ; + + this._UpdateElementInfo() ; + } + else + { + var oControl = oSel.createRange().item(0) ; + + if ( oControl ) + { + this._Range.setStartBefore( oControl ) ; + this._Range.setEndAfter( oControl ) ; + this._UpdateElementInfo() ; + } + } +} + +FCKDomRange.prototype.Select = function( forceExpand ) +{ + if ( this._Range ) + this.SelectBookmark( this.CreateBookmark( true ), forceExpand ) ; +} + +// Not compatible with bookmark created with CreateBookmark2. +// The bookmark nodes will be deleted from the document. +FCKDomRange.prototype.SelectBookmark = function( bookmark, forceExpand ) +{ + var bIsCollapsed = this.CheckIsCollapsed() ; + var bIsStartMakerAlone ; + var dummySpan ; + + // Create marker tags for the start and end boundaries. + var eStartMarker = this.GetBookmarkNode( bookmark, true ) ; + + if ( !eStartMarker ) + return ; + + var eEndMarker ; + if ( !bIsCollapsed ) + eEndMarker = this.GetBookmarkNode( bookmark, false ) ; + + // Create the main range which will be used for the selection. + var oIERange = this.Window.document.body.createTextRange() ; + + // Position the range at the start boundary. + oIERange.moveToElementText( eStartMarker ) ; + oIERange.moveStart( 'character', 1 ) ; + + if ( eEndMarker ) + { + // Create a tool range for the end. + var oIERangeEnd = this.Window.document.body.createTextRange() ; + + // Position the tool range at the end. + oIERangeEnd.moveToElementText( eEndMarker ) ; + + // Move the end boundary of the main range to match the tool range. + oIERange.setEndPoint( 'EndToEnd', oIERangeEnd ) ; + oIERange.moveEnd( 'character', -1 ) ; + } + else + { + bIsStartMakerAlone = ( forceExpand || !eStartMarker.previousSibling || eStartMarker.previousSibling.nodeName.toLowerCase() == 'br' ) && !eStartMarker.nextSibing ; + + // Append a temporary <span></span> before the selection. + // This is needed to avoid IE destroying selections inside empty + // inline elements, like <b></b> (#253). + // It is also needed when placing the selection right after an inline + // element to avoid the selection moving inside of it. + dummySpan = this.Window.document.createElement( 'span' ) ; + dummySpan.innerHTML = '' ; // Zero Width No-Break Space (U+FEFF). See #1359. + eStartMarker.parentNode.insertBefore( dummySpan, eStartMarker ) ; + + if ( bIsStartMakerAlone ) + { + // To expand empty blocks or line spaces after <br>, we need + // instead to have any char, which will be later deleted using the + // selection. + // \ufeff = Zero Width No-Break Space (U+FEFF). See #1359. + eStartMarker.parentNode.insertBefore( this.Window.document.createTextNode( '\ufeff' ), eStartMarker ) ; + } + } + + if ( !this._Range ) + this._Range = this.CreateRange() ; + + // Remove the markers (reset the position, because of the changes in the DOM tree). + this._Range.setStartBefore( eStartMarker ) ; + eStartMarker.parentNode.removeChild( eStartMarker ) ; + + if ( bIsCollapsed ) + { + if ( bIsStartMakerAlone ) + { + // Move the selection start to include the temporary . + oIERange.moveStart( 'character', -1 ) ; + + oIERange.select() ; + + // Remove our temporary stuff. + this.Window.document.selection.clear() ; + } + else + oIERange.select() ; + + FCKDomTools.RemoveNode( dummySpan ) ; + } + else + { + this._Range.setEndBefore( eEndMarker ) ; + eEndMarker.parentNode.removeChild( eEndMarker ) ; + oIERange.select() ; + } +} + +FCKDomRange.prototype._GetSelectionMarkerTag = function( toStart ) +{ + var doc = this.Window.document ; + var selection = doc.selection ; + + // Get a range for the start boundary. + var oRange ; + + // IE may throw an "unspecified error" on some cases (it happened when + // loading _samples/default.html), so try/catch. + try + { + oRange = selection.createRange() ; + } + catch (e) + { + return null ; + } + + // IE might take the range object to the main window instead of inside the editor iframe window. + // This is known to happen when the editor window has not been selected before (See #933). + // We need to avoid that. + if ( oRange.parentElement().document != doc ) + return null ; + + oRange.collapse( toStart === true ) ; + + // Paste a marker element at the collapsed range and get it from the DOM. + var sMarkerId = 'fck_dom_range_temp_' + (new Date()).valueOf() + '_' + Math.floor(Math.random()*1000) ; + oRange.pasteHTML( '<span id="' + sMarkerId + '"></span>' ) ; + + return doc.getElementById( sMarkerId ) ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckdomrangeiterator.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckdomrangeiterator.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckdomrangeiterator.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,327 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * This class can be used to interate through nodes inside a range. + * + * During interation, the provided range can become invalid, due to document + * mutations, so CreateBookmark() used to restore it after processing, if + * needed. + */ + +var FCKDomRangeIterator = function( range ) +{ + /** + * The FCKDomRange object that marks the interation boundaries. + */ + this.Range = range ; + + /** + * Indicates that <br> elements must be used as paragraph boundaries. + */ + this.ForceBrBreak = false ; + + /** + * Guarantees that the iterator will always return "real" block elements. + * If "false", elements like <li>, <th> and <td> are returned. If "true", a + * dedicated block element block element will be created inside those + * elements to hold the selected content. + */ + this.EnforceRealBlocks = false ; +} + +FCKDomRangeIterator.CreateFromSelection = function( targetWindow ) +{ + var range = new FCKDomRange( targetWindow ) ; + range.MoveToSelection() ; + return new FCKDomRangeIterator( range ) ; +} + +FCKDomRangeIterator.prototype = +{ + /** + * Get the next paragraph element. It automatically breaks the document + * when necessary to generate block elements for the paragraphs. + */ + GetNextParagraph : function() + { + // The block element to be returned. + var block ; + + // The range object used to identify the paragraph contents. + var range ; + + // Indicated that the current element in the loop is the last one. + var isLast ; + + // Instructs to cleanup remaining BRs. + var removePreviousBr ; + var removeLastBr ; + + var boundarySet = this.ForceBrBreak ? FCKListsLib.ListBoundaries : FCKListsLib.BlockBoundaries ; + + // This is the first iteration. Let's initialize it. + if ( !this._LastNode ) + { + var range = this.Range.Clone() ; + range.Expand( this.ForceBrBreak ? 'list_contents' : 'block_contents' ) ; + + this._NextNode = range.GetTouchedStartNode() ; + this._LastNode = range.GetTouchedEndNode() ; + + // Let's reuse this variable. + range = null ; + } + + var currentNode = this._NextNode ; + var lastNode = this._LastNode ; + + this._NextNode = null ; + + while ( currentNode ) + { + // closeRange indicates that a paragraph boundary has been found, + // so the range can be closed. + var closeRange = false ; + + // includeNode indicates that the current node is good to be part + // of the range. By default, any non-element node is ok for it. + var includeNode = ( currentNode.nodeType != 1 ) ; + + var continueFromSibling = false ; + + // If it is an element node, let's check if it can be part of the + // range. + if ( !includeNode ) + { + var nodeName = currentNode.nodeName.toLowerCase() ; + + if ( boundarySet[ nodeName ] && ( !FCKBrowserInfo.IsIE || currentNode.scopeName == 'HTML' ) ) + { + // <br> boundaries must be part of the range. It will + // happen only if ForceBrBreak. + if ( nodeName == 'br' ) + includeNode = true ; + else if ( !range && currentNode.childNodes.length == 0 && nodeName != 'hr' ) + { + // If we have found an empty block, and haven't started + // the range yet, it means we must return this block. + block = currentNode ; + isLast = currentNode == lastNode ; + break ; + } + + // The range must finish right before the boundary, + // including possibly skipped empty spaces. (#1603) + if ( range ) + { + range.SetEnd( currentNode, 3, true ) ; + + // The found boundary must be set as the next one at this + // point. (#1717) + if ( nodeName != 'br' ) + this._NextNode = currentNode ; + } + + closeRange = true ; + } + else + { + // If we have child nodes, let's check them. + if ( currentNode.firstChild ) + { + // If we don't have a range yet, let's start it. + if ( !range ) + { + range = new FCKDomRange( this.Range.Window ) ; + range.SetStart( currentNode, 3, true ) ; + } + + currentNode = currentNode.firstChild ; + continue ; + } + includeNode = true ; + } + } + else if ( currentNode.nodeType == 3 ) + { + // Ignore normal whitespaces (i.e. not including or + // other unicode whitespaces) before/after a block node. + if ( /^[\r\n\t ]+$/.test( currentNode.nodeValue ) ) + includeNode = false ; + } + + // The current node is good to be part of the range and we are + // starting a new range, initialize it first. + if ( includeNode && !range ) + { + range = new FCKDomRange( this.Range.Window ) ; + range.SetStart( currentNode, 3, true ) ; + } + + // The last node has been found. + isLast = ( ( !closeRange || includeNode ) && currentNode == lastNode ) ; +// isLast = ( currentNode == lastNode && ( currentNode.nodeType != 1 || currentNode.childNodes.length == 0 ) ) ; + + // If we are in an element boundary, let's check if it is time + // to close the range, otherwise we include the parent within it. + if ( range && !closeRange ) + { + while ( !currentNode.nextSibling && !isLast ) + { + var parentNode = currentNode.parentNode ; + + if ( boundarySet[ parentNode.nodeName.toLowerCase() ] ) + { + closeRange = true ; + isLast = isLast || ( parentNode == lastNode ) ; + break ; + } + + currentNode = parentNode ; + includeNode = true ; + isLast = ( currentNode == lastNode ) ; + continueFromSibling = true ; + } + } + + // Now finally include the node. + if ( includeNode ) + range.SetEnd( currentNode, 4, true ) ; + + // We have found a block boundary. Let's close the range and move out of the + // loop. + if ( ( closeRange || isLast ) && range ) + { + range._UpdateElementInfo() ; + + if ( range.StartNode == range.EndNode + && range.StartNode.parentNode == range.StartBlockLimit + && range.StartNode.getAttribute && range.StartNode.getAttribute( '_fck_bookmark' ) ) + range = null ; + else + break ; + } + + if ( isLast ) + break ; + + currentNode = FCKDomTools.GetNextSourceNode( currentNode, continueFromSibling, null, lastNode ) ; + } + + // Now, based on the processed range, look for (or create) the block to be returned. + if ( !block ) + { + // If no range has been found, this is the end. + if ( !range ) + { + this._NextNode = null ; + return null ; + } + + block = range.StartBlock ; + + if ( !block + && !this.EnforceRealBlocks + && range.StartBlockLimit.nodeName.IEquals( 'DIV', 'TH', 'TD' ) + && range.CheckStartOfBlock() + && range.CheckEndOfBlock() ) + { + block = range.StartBlockLimit ; + } + else if ( !block || ( this.EnforceRealBlocks && block.nodeName.toLowerCase() == 'li' ) ) + { + // Create the fixed block. + block = this.Range.Window.document.createElement( FCKConfig.EnterMode == 'p' ? 'p' : 'div' ) ; + + // Move the contents of the temporary range to the fixed block. + range.ExtractContents().AppendTo( block ) ; + FCKDomTools.TrimNode( block ) ; + + // Insert the fixed block into the DOM. + range.InsertNode( block ) ; + + removePreviousBr = true ; + removeLastBr = true ; + } + else if ( block.nodeName.toLowerCase() != 'li' ) + { + // If the range doesn't includes the entire contents of the + // block, we must split it, isolating the range in a dedicated + // block. + if ( !range.CheckStartOfBlock() || !range.CheckEndOfBlock() ) + { + // The resulting block will be a clone of the current one. + block = block.cloneNode( false ) ; + + // Extract the range contents, moving it to the new block. + range.ExtractContents().AppendTo( block ) ; + FCKDomTools.TrimNode( block ) ; + + // Split the block. At this point, the range will be in the + // right position for our intents. + var splitInfo = range.SplitBlock() ; + + removePreviousBr = !splitInfo.WasStartOfBlock ; + removeLastBr = !splitInfo.WasEndOfBlock ; + + // Insert the new block into the DOM. + range.InsertNode( block ) ; + } + } + else if ( !isLast ) + { + // LIs are returned as is, with all their children (due to the + // nested lists). But, the next node is the node right after + // the current range, which could be an <li> child (nested + // lists) or the next sibling <li>. + + this._NextNode = block == lastNode ? null : FCKDomTools.GetNextSourceNode( range.EndNode, true, null, lastNode ) ; + return block ; + } + } + + if ( removePreviousBr ) + { + var previousSibling = block.previousSibling ; + if ( previousSibling && previousSibling.nodeType == 1 ) + { + if ( previousSibling.nodeName.toLowerCase() == 'br' ) + previousSibling.parentNode.removeChild( previousSibling ) ; + else if ( previousSibling.lastChild && previousSibling.lastChild.nodeName.IEquals( 'br' ) ) + previousSibling.removeChild( previousSibling.lastChild ) ; + } + } + + if ( removeLastBr ) + { + var lastChild = block.lastChild ; + if ( lastChild && lastChild.nodeType == 1 && lastChild.nodeName.toLowerCase() == 'br' ) + block.removeChild( lastChild ) ; + } + + // Get a reference for the next element. This is important because the + // above block can be removed or changed, so we can rely on it for the + // next interation. + if ( !this._NextNode ) + this._NextNode = ( isLast || block == lastNode ) ? null : FCKDomTools.GetNextSourceNode( block, true, null, lastNode ) ; + + return block ; + } +} ; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckeditingarea.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckeditingarea.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckeditingarea.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,362 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKEditingArea Class: renders an editable area. + */ + +/** + * @constructor + * @param {String} targetElement The element that will hold the editing area. Any child element present in the target will be deleted. + */ +var FCKEditingArea = function( targetElement ) +{ + this.TargetElement = targetElement ; + this.Mode = FCK_EDITMODE_WYSIWYG ; + + if ( FCK.IECleanup ) + FCK.IECleanup.AddItem( this, FCKEditingArea_Cleanup ) ; +} + + +/** + * @param {String} html The complete HTML for the page, including DOCTYPE and the <html> tag. + */ +FCKEditingArea.prototype.Start = function( html, secondCall ) +{ + var eTargetElement = this.TargetElement ; + var oTargetDocument = FCKTools.GetElementDocument( eTargetElement ) ; + + // Remove all child nodes from the target. + while( eTargetElement.firstChild ) + eTargetElement.removeChild( eTargetElement.firstChild ) ; + + if ( this.Mode == FCK_EDITMODE_WYSIWYG ) + { + // For FF, document.domain must be set only when different, otherwhise + // we'll strangely have "Permission denied" issues. + if ( FCK_IS_CUSTOM_DOMAIN ) + html = '<script>document.domain="' + FCK_RUNTIME_DOMAIN + '";</script>' + html ; + + // IE has a bug with the <base> tag... it must have a </base> closer, + // otherwise the all successive tags will be set as children nodes of the <base>. + if ( FCKBrowserInfo.IsIE ) + html = html.replace( /(<base[^>]*?)\s*\/?>(?!\s*<\/base>)/gi, '$1></base>' ) ; + else if ( !secondCall ) + { + // Gecko moves some tags out of the body to the head, so we must use + // innerHTML to set the body contents (SF BUG 1526154). + + // Extract the BODY contents from the html. + var oMatchBefore = html.match( FCKRegexLib.BeforeBody ) ; + var oMatchAfter = html.match( FCKRegexLib.AfterBody ) ; + + if ( oMatchBefore && oMatchAfter ) + { + var sBody = html.substr( oMatchBefore[1].length, + html.length - oMatchBefore[1].length - oMatchAfter[1].length ) ; // This is the BODY tag contents. + + html = + oMatchBefore[1] + // This is the HTML until the <body...> tag, inclusive. + ' ' + + oMatchAfter[1] ; // This is the HTML from the </body> tag, inclusive. + + // If nothing in the body, place a BOGUS tag so the cursor will appear. + if ( FCKBrowserInfo.IsGecko && ( sBody.length == 0 || FCKRegexLib.EmptyParagraph.test( sBody ) ) ) + sBody = '<br type="_moz">' ; + + this._BodyHTML = sBody ; + + } + else + this._BodyHTML = html ; // Invalid HTML input. + } + + // Create the editing area IFRAME. + var oIFrame = this.IFrame = oTargetDocument.createElement( 'iframe' ) ; + + // IE: Avoid JavaScript errors thrown by the editing are source (like tags events). + // See #1055. + var sOverrideError = '<script type="text/javascript" _fcktemp="true">window.onerror=function(){return true;};</script>' ; + + oIFrame.frameBorder = 0 ; + oIFrame.width = oIFrame.height = '100%' ; + + if ( FCK_IS_CUSTOM_DOMAIN && FCKBrowserInfo.IsIE ) + { + window._FCKHtmlToLoad = sOverrideError + html ; + oIFrame.src = 'javascript:void( (function(){' + + 'document.open() ;' + + 'document.domain="' + document.domain + '" ;' + + 'document.write( window.parent._FCKHtmlToLoad );' + + 'document.close() ;' + + 'window.parent._FCKHtmlToLoad = null ;' + + '})() )' ; + } + else if ( !FCKBrowserInfo.IsGecko ) + { + // Firefox will render the tables inside the body in Quirks mode if the + // source of the iframe is set to javascript. see #515 + oIFrame.src = 'javascript:void(0)' ; + } + + // Append the new IFRAME to the target. For IE, it must be done after + // setting the "src", to avoid the "secure/unsecure" message under HTTPS. + eTargetElement.appendChild( oIFrame ) ; + + // Get the window and document objects used to interact with the newly created IFRAME. + this.Window = oIFrame.contentWindow ; + + // IE: Avoid JavaScript errors thrown by the editing are source (like tags events). + // TODO: This error handler is not being fired. + // this.Window.onerror = function() { alert( 'Error!' ) ; return true ; } + + if ( !FCK_IS_CUSTOM_DOMAIN || !FCKBrowserInfo.IsIE ) + { + var oDoc = this.Window.document ; + + oDoc.open() ; + oDoc.write( sOverrideError + html ) ; + oDoc.close() ; + } + + if ( FCKBrowserInfo.IsAIR ) + FCKAdobeAIR.EditingArea_Start( oDoc, html ) ; + + // Firefox 1.0.x is buggy... ohh yes... so let's do it two times and it + // will magically work. + if ( FCKBrowserInfo.IsGecko10 && !secondCall ) + { + this.Start( html, true ) ; + return ; + } + + if ( oIFrame.readyState && oIFrame.readyState != 'completed' ) + { + var editArea = this ; + ( oIFrame.onreadystatechange = function() + { + if ( oIFrame.readyState == 'complete' ) + { + oIFrame.onreadystatechange = null ; + editArea.Window._FCKEditingArea = editArea ; + FCKEditingArea_CompleteStart.call( editArea.Window ) ; + } + // It happened that IE changed the state to "complete" after the + // "if" and before the "onreadystatechange" assignement, making we + // lost the event call, so we do a manual call just to be sure. + } )() ; + } + else + { + this.Window._FCKEditingArea = this ; + + // FF 1.0.x is buggy... we must wait a lot to enable editing because + // sometimes the content simply disappears, for example when pasting + // "bla1!<img src='some_url'>!bla2" in the source and then switching + // back to design. + if ( FCKBrowserInfo.IsGecko10 ) + this.Window.setTimeout( FCKEditingArea_CompleteStart, 500 ) ; + else + FCKEditingArea_CompleteStart.call( this.Window ) ; + } + } + else + { + var eTextarea = this.Textarea = oTargetDocument.createElement( 'textarea' ) ; + eTextarea.className = 'SourceField' ; + eTextarea.dir = 'ltr' ; + FCKDomTools.SetElementStyles( eTextarea, + { + width : '100%', + height : '100%', + border : 'none', + resize : 'none', + outline : 'none' + } ) ; + eTargetElement.appendChild( eTextarea ) ; + + eTextarea.value = html ; + + // Fire the "OnLoad" event. + FCKTools.RunFunction( this.OnLoad ) ; + } +} + +// "this" here is FCKEditingArea.Window +function FCKEditingArea_CompleteStart() +{ + // On Firefox, the DOM takes a little to become available. So we must wait for it in a loop. + if ( !this.document.body ) + { + this.setTimeout( FCKEditingArea_CompleteStart, 50 ) ; + return ; + } + + var oEditorArea = this._FCKEditingArea ; + + // Save this reference to be re-used later. + oEditorArea.Document = oEditorArea.Window.document ; + + oEditorArea.MakeEditable() ; + + // Fire the "OnLoad" event. + FCKTools.RunFunction( oEditorArea.OnLoad ) ; +} + +FCKEditingArea.prototype.MakeEditable = function() +{ + var oDoc = this.Document ; + + if ( FCKBrowserInfo.IsIE ) + { + // Kludge for #141 and #523 + oDoc.body.disabled = true ; + oDoc.body.contentEditable = true ; + oDoc.body.removeAttribute( "disabled" ) ; + + /* The following commands don't throw errors, but have no effect. + oDoc.execCommand( 'AutoDetect', false, false ) ; + oDoc.execCommand( 'KeepSelection', false, true ) ; + */ + } + else + { + try + { + // Disable Firefox 2 Spell Checker. + oDoc.body.spellcheck = ( this.FFSpellChecker !== false ) ; + + if ( this._BodyHTML ) + { + oDoc.body.innerHTML = this._BodyHTML ; + this._BodyHTML = null ; + } + + oDoc.designMode = 'on' ; + + // Tell Gecko (Firefox 1.5+) to enable or not live resizing of objects (by Alfonso Martinez) + oDoc.execCommand( 'enableObjectResizing', false, !FCKConfig.DisableObjectResizing ) ; + + // Disable the standard table editing features of Firefox. + oDoc.execCommand( 'enableInlineTableEditing', false, !FCKConfig.DisableFFTableHandles ) ; + } + catch (e) + { + // In Firefox if the iframe is initially hidden it can't be set to designMode and it raises an exception + // So we set up a DOM Mutation event Listener on the HTML, as it will raise several events when the document is visible again + FCKTools.AddEventListener( this.Window.frameElement, 'DOMAttrModified', FCKEditingArea_Document_AttributeNodeModified ) ; + } + + } +} + +// This function processes the notifications of the DOM Mutation event on the document +// We use it to know that the document will be ready to be editable again (or we hope so) +function FCKEditingArea_Document_AttributeNodeModified( evt ) +{ + var editingArea = evt.currentTarget.contentWindow._FCKEditingArea ; + + // We want to run our function after the events no longer fire, so we can know that it's a stable situation + if ( editingArea._timer ) + window.clearTimeout( editingArea._timer ) ; + + editingArea._timer = FCKTools.SetTimeout( FCKEditingArea_MakeEditableByMutation, 1000, editingArea ) ; +} + +// This function ideally should be called after the document is visible, it does clean up of the +// mutation tracking and tries again to make the area editable. +function FCKEditingArea_MakeEditableByMutation() +{ + // Clean up + delete this._timer ; + // Now we don't want to keep on getting this event + FCKTools.RemoveEventListener( this.Window.frameElement, 'DOMAttrModified', FCKEditingArea_Document_AttributeNodeModified ) ; + // Let's try now to set the editing area editable + // If it fails it will set up the Mutation Listener again automatically + this.MakeEditable() ; +} + +FCKEditingArea.prototype.Focus = function() +{ + try + { + if ( this.Mode == FCK_EDITMODE_WYSIWYG ) + { + if ( FCKBrowserInfo.IsIE ) + this._FocusIE() ; + else + this.Window.focus() ; + } + else + { + var oDoc = FCKTools.GetElementDocument( this.Textarea ) ; + if ( (!oDoc.hasFocus || oDoc.hasFocus() ) && oDoc.activeElement == this.Textarea ) + return ; + + this.Textarea.focus() ; + } + } + catch(e) {} +} + +FCKEditingArea.prototype._FocusIE = function() +{ + // In IE it can happen that the document is in theory focused but the + // active element is outside of it. + this.Document.body.setActive() ; + + this.Window.focus() ; + + // Kludge for #141... yet more code to workaround IE bugs + var range = this.Document.selection.createRange() ; + + var parentNode = range.parentElement() ; + var parentTag = parentNode.nodeName.toLowerCase() ; + + // Only apply the fix when in a block, and the block is empty. + if ( parentNode.childNodes.length > 0 || + !( FCKListsLib.BlockElements[parentTag] || + FCKListsLib.NonEmptyBlockElements[parentTag] ) ) + { + return ; + } + + // Force the selection to happen, in this way we guarantee the focus will + // be there. + range = new FCKDomRange( this.Window ) ; + range.MoveToElementEditStart( parentNode ) ; + range.Select() ; +} + +function FCKEditingArea_Cleanup() +{ + if ( this.Document ) + this.Document.body.innerHTML = "" ; + this.TargetElement = null ; + this.IFrame = null ; + this.Document = null ; + this.Textarea = null ; + + if ( this.Window ) + { + this.Window._FCKEditingArea = null ; + this.Window = null ; + } +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckelementpath.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckelementpath.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckelementpath.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,89 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Manages the DOM ascensors element list of a specific DOM node + * (limited to body, inclusive). + */ + +var FCKElementPath = function( lastNode ) +{ + var eBlock = null ; + var eBlockLimit = null ; + + var aElements = new Array() ; + + var e = lastNode ; + while ( e ) + { + if ( e.nodeType == 1 ) + { + if ( !this.LastElement ) + this.LastElement = e ; + + var sElementName = e.nodeName.toLowerCase() ; + if ( FCKBrowserInfo.IsIE && e.scopeName != 'HTML' ) + sElementName = e.scopeName.toLowerCase() + ':' + sElementName ; + + if ( !eBlockLimit ) + { + if ( !eBlock && FCKListsLib.PathBlockElements[ sElementName ] != null ) + eBlock = e ; + + if ( FCKListsLib.PathBlockLimitElements[ sElementName ] != null ) + { + // DIV is considered the Block, if no block is available (#525) + // and if it doesn't contain other blocks. + if ( !eBlock && sElementName == 'div' && !FCKElementPath._CheckHasBlock( e ) ) + eBlock = e ; + else + eBlockLimit = e ; + } + } + + aElements.push( e ) ; + + if ( sElementName == 'body' ) + break ; + } + e = e.parentNode ; + } + + this.Block = eBlock ; + this.BlockLimit = eBlockLimit ; + this.Elements = aElements ; +} + +/** + * Check if an element contains any block element. + */ +FCKElementPath._CheckHasBlock = function( element ) +{ + var childNodes = element.childNodes ; + + for ( var i = 0, count = childNodes.length ; i < count ; i++ ) + { + var child = childNodes[i] ; + + if ( child.nodeType == 1 && FCKListsLib.BlockElements[ child.nodeName.toLowerCase() ] ) + return true ; + } + + return false ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckenterkey.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckenterkey.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckenterkey.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,667 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Controls the [Enter] keystroke behavior in a document. + */ + +/* + * Constructor. + * @targetDocument : the target document. + * @enterMode : the behavior for the <Enter> keystroke. + * May be "p", "div", "br". Default is "p". + * @shiftEnterMode : the behavior for the <Shift>+<Enter> keystroke. + * May be "p", "div", "br". Defaults to "br". + */ +var FCKEnterKey = function( targetWindow, enterMode, shiftEnterMode, tabSpaces ) +{ + this.Window = targetWindow ; + this.EnterMode = enterMode || 'p' ; + this.ShiftEnterMode = shiftEnterMode || 'br' ; + + // Setup the Keystroke Handler. + var oKeystrokeHandler = new FCKKeystrokeHandler( false ) ; + oKeystrokeHandler._EnterKey = this ; + oKeystrokeHandler.OnKeystroke = FCKEnterKey_OnKeystroke ; + + oKeystrokeHandler.SetKeystrokes( [ + [ 13 , 'Enter' ], + [ SHIFT + 13, 'ShiftEnter' ], + [ 9 , 'Tab' ], + [ 8 , 'Backspace' ], + [ CTRL + 8 , 'CtrlBackspace' ], + [ 46 , 'Delete' ] + ] ) ; + + if ( tabSpaces > 0 ) + { + this.TabText = '' ; + while ( tabSpaces-- > 0 ) + this.TabText += '\xa0' ; + } + + oKeystrokeHandler.AttachToElement( targetWindow.document ) ; +} + + +function FCKEnterKey_OnKeystroke( keyCombination, keystrokeValue ) +{ + var oEnterKey = this._EnterKey ; + + try + { + switch ( keystrokeValue ) + { + case 'Enter' : + return oEnterKey.DoEnter() ; + break ; + case 'ShiftEnter' : + return oEnterKey.DoShiftEnter() ; + break ; + case 'Backspace' : + return oEnterKey.DoBackspace() ; + break ; + case 'Delete' : + return oEnterKey.DoDelete() ; + break ; + case 'Tab' : + return oEnterKey.DoTab() ; + break ; + case 'CtrlBackspace' : + return oEnterKey.DoCtrlBackspace() ; + break ; + } + } + catch (e) + { + // If for any reason we are not able to handle it, go + // ahead with the browser default behavior. + } + + return false ; +} + +/* + * Executes the <Enter> key behavior. + */ +FCKEnterKey.prototype.DoEnter = function( mode, hasShift ) +{ + // Save an undo snapshot before doing anything + FCKUndo.SaveUndoStep() ; + + this._HasShift = ( hasShift === true ) ; + + var parentElement = FCKSelection.GetParentElement() ; + var parentPath = new FCKElementPath( parentElement ) ; + var sMode = mode || this.EnterMode ; + + if ( sMode == 'br' || parentPath.Block && parentPath.Block.tagName.toLowerCase() == 'pre' ) + return this._ExecuteEnterBr() ; + else + return this._ExecuteEnterBlock( sMode ) ; +} + +/* + * Executes the <Shift>+<Enter> key behavior. + */ +FCKEnterKey.prototype.DoShiftEnter = function() +{ + return this.DoEnter( this.ShiftEnterMode, true ) ; +} + +/* + * Executes the <Backspace> key behavior. + */ +FCKEnterKey.prototype.DoBackspace = function() +{ + var bCustom = false ; + + // Get the current selection. + var oRange = new FCKDomRange( this.Window ) ; + oRange.MoveToSelection() ; + + // Kludge for #247 + if ( FCKBrowserInfo.IsIE && this._CheckIsAllContentsIncluded( oRange, this.Window.document.body ) ) + { + this._FixIESelectAllBug( oRange ) ; + return true ; + } + + var isCollapsed = oRange.CheckIsCollapsed() ; + + if ( !isCollapsed ) + { + // Bug #327, Backspace with an img selection would activate the default action in IE. + // Let's override that with our logic here. + if ( FCKBrowserInfo.IsIE && this.Window.document.selection.type.toLowerCase() == "control" ) + { + var controls = this.Window.document.selection.createRange() ; + for ( var i = controls.length - 1 ; i >= 0 ; i-- ) + { + var el = controls.item( i ) ; + el.parentNode.removeChild( el ) ; + } + return true ; + } + + return false ; + } + + var oStartBlock = oRange.StartBlock ; + var oEndBlock = oRange.EndBlock ; + + // The selection boundaries must be in the same "block limit" element + if ( oRange.StartBlockLimit == oRange.EndBlockLimit && oStartBlock && oEndBlock ) + { + if ( !isCollapsed ) + { + var bEndOfBlock = oRange.CheckEndOfBlock() ; + + oRange.DeleteContents() ; + + if ( oStartBlock != oEndBlock ) + { + oRange.SetStart(oEndBlock,1) ; + oRange.SetEnd(oEndBlock,1) ; + +// if ( bEndOfBlock ) +// oEndBlock.parentNode.removeChild( oEndBlock ) ; + } + + oRange.Select() ; + + bCustom = ( oStartBlock == oEndBlock ) ; + } + + if ( oRange.CheckStartOfBlock() ) + { + var oCurrentBlock = oRange.StartBlock ; + + var ePrevious = FCKDomTools.GetPreviousSourceElement( oCurrentBlock, true, [ 'BODY', oRange.StartBlockLimit.nodeName ], ['UL','OL'] ) ; + + bCustom = this._ExecuteBackspace( oRange, ePrevious, oCurrentBlock ) ; + } + else if ( FCKBrowserInfo.IsGeckoLike ) + { + // Firefox and Opera (#1095) loose the selection when executing + // CheckStartOfBlock, so we must reselect. + oRange.Select() ; + } + } + + oRange.Release() ; + return bCustom ; +} + +FCKEnterKey.prototype.DoCtrlBackspace = function() +{ + FCKUndo.SaveUndoStep() ; + var oRange = new FCKDomRange( this.Window ) ; + oRange.MoveToSelection() ; + if ( FCKBrowserInfo.IsIE && this._CheckIsAllContentsIncluded( oRange, this.Window.document.body ) ) + { + this._FixIESelectAllBug( oRange ) ; + return true ; + } + return false ; +} + +FCKEnterKey.prototype._ExecuteBackspace = function( range, previous, currentBlock ) +{ + var bCustom = false ; + + // We could be in a nested LI. + if ( !previous && currentBlock && currentBlock.nodeName.IEquals( 'LI' ) && currentBlock.parentNode.parentNode.nodeName.IEquals( 'LI' ) ) + { + this._OutdentWithSelection( currentBlock, range ) ; + return true ; + } + + if ( previous && previous.nodeName.IEquals( 'LI' ) ) + { + var oNestedList = FCKDomTools.GetLastChild( previous, ['UL','OL'] ) ; + + while ( oNestedList ) + { + previous = FCKDomTools.GetLastChild( oNestedList, 'LI' ) ; + oNestedList = FCKDomTools.GetLastChild( previous, ['UL','OL'] ) ; + } + } + + if ( previous && currentBlock ) + { + // If we are in a LI, and the previous block is not an LI, we must outdent it. + if ( currentBlock.nodeName.IEquals( 'LI' ) && !previous.nodeName.IEquals( 'LI' ) ) + { + this._OutdentWithSelection( currentBlock, range ) ; + return true ; + } + + // Take a reference to the parent for post processing cleanup. + var oCurrentParent = currentBlock.parentNode ; + + var sPreviousName = previous.nodeName.toLowerCase() ; + if ( FCKListsLib.EmptyElements[ sPreviousName ] != null || sPreviousName == 'table' ) + { + FCKDomTools.RemoveNode( previous ) ; + bCustom = true ; + } + else + { + // Remove the current block. + FCKDomTools.RemoveNode( currentBlock ) ; + + // Remove any empty tag left by the block removal. + while ( oCurrentParent.innerHTML.Trim().length == 0 ) + { + var oParent = oCurrentParent.parentNode ; + oParent.removeChild( oCurrentParent ) ; + oCurrentParent = oParent ; + } + + // Cleanup the previous and the current elements. + FCKDomTools.LTrimNode( currentBlock ) ; + FCKDomTools.RTrimNode( previous ) ; + + // Append a space to the previous. + // Maybe it is not always desirable... + // previous.appendChild( this.Window.document.createTextNode( ' ' ) ) ; + + // Set the range to the end of the previous element and bookmark it. + range.SetStart( previous, 2, true ) ; + range.Collapse( true ) ; + var oBookmark = range.CreateBookmark( true ) ; + + // Move the contents of the block to the previous element and delete it. + // But for some block types (e.g. table), moving the children to the previous block makes no sense. + // So a check is needed. (See #1081) + if ( ! currentBlock.tagName.IEquals( [ 'TABLE' ] ) ) + FCKDomTools.MoveChildren( currentBlock, previous ) ; + + // Place the selection at the bookmark. + range.SelectBookmark( oBookmark ) ; + + bCustom = true ; + } + } + + return bCustom ; +} + +/* + * Executes the <Delete> key behavior. + */ +FCKEnterKey.prototype.DoDelete = function() +{ + // Save an undo snapshot before doing anything + // This is to conform with the behavior seen in MS Word + FCKUndo.SaveUndoStep() ; + + // The <Delete> has the same effect as the <Backspace>, so we have the same + // results if we just move to the next block and apply the same <Backspace> logic. + + var bCustom = false ; + + // Get the current selection. + var oRange = new FCKDomRange( this.Window ) ; + oRange.MoveToSelection() ; + + // Kludge for #247 + if ( FCKBrowserInfo.IsIE && this._CheckIsAllContentsIncluded( oRange, this.Window.document.body ) ) + { + this._FixIESelectAllBug( oRange ) ; + return true ; + } + + // There is just one special case for collapsed selections at the end of a block. + if ( oRange.CheckIsCollapsed() && oRange.CheckEndOfBlock( FCKBrowserInfo.IsGeckoLike ) ) + { + var oCurrentBlock = oRange.StartBlock ; + var eCurrentCell = FCKTools.GetElementAscensor( oCurrentBlock, 'td' ); + + var eNext = FCKDomTools.GetNextSourceElement( oCurrentBlock, true, [ oRange.StartBlockLimit.nodeName ], + ['UL','OL','TR'], true ) ; + + // Bug #1323 : if we're in a table cell, and the next node belongs to a different cell, then don't + // delete anything. + if ( eCurrentCell ) + { + var eNextCell = FCKTools.GetElementAscensor( eNext, 'td' ); + if ( eNextCell != eCurrentCell ) + return true ; + } + + bCustom = this._ExecuteBackspace( oRange, oCurrentBlock, eNext ) ; + } + + oRange.Release() ; + return bCustom ; +} + +/* + * Executes the <Tab> key behavior. + */ +FCKEnterKey.prototype.DoTab = function() +{ + var oRange = new FCKDomRange( this.Window ); + oRange.MoveToSelection() ; + + // If the user pressed <tab> inside a table, we should give him the default behavior ( moving between cells ) + // instead of giving him more non-breaking spaces. (Bug #973) + var node = oRange._Range.startContainer ; + while ( node ) + { + if ( node.nodeType == 1 ) + { + var tagName = node.tagName.toLowerCase() ; + if ( tagName == "tr" || tagName == "td" || tagName == "th" || tagName == "tbody" || tagName == "table" ) + return false ; + else + break ; + } + node = node.parentNode ; + } + + if ( this.TabText ) + { + oRange.DeleteContents() ; + oRange.InsertNode( this.Window.document.createTextNode( this.TabText ) ) ; + oRange.Collapse( false ) ; + oRange.Select() ; + } + return true ; +} + +FCKEnterKey.prototype._ExecuteEnterBlock = function( blockTag, range ) +{ + // Get the current selection. + var oRange = range || new FCKDomRange( this.Window ) ; + + var oSplitInfo = oRange.SplitBlock( blockTag ) ; + + if ( oSplitInfo ) + { + // Get the current blocks. + var ePreviousBlock = oSplitInfo.PreviousBlock ; + var eNextBlock = oSplitInfo.NextBlock ; + + var bIsStartOfBlock = oSplitInfo.WasStartOfBlock ; + var bIsEndOfBlock = oSplitInfo.WasEndOfBlock ; + + // If there is one block under a list item, modify the split so that the list item gets split as well. (Bug #1647) + if ( eNextBlock ) + { + if ( eNextBlock.parentNode.nodeName.IEquals( 'li' ) ) + { + FCKDomTools.BreakParent( eNextBlock, eNextBlock.parentNode ) ; + FCKDomTools.MoveNode( eNextBlock, eNextBlock.nextSibling, true ) ; + } + } + else if ( ePreviousBlock && ePreviousBlock.parentNode.nodeName.IEquals( 'li' ) ) + { + FCKDomTools.BreakParent( ePreviousBlock, ePreviousBlock.parentNode ) ; + oRange.MoveToElementEditStart( ePreviousBlock.nextSibling ); + FCKDomTools.MoveNode( ePreviousBlock, ePreviousBlock.previousSibling ) ; + } + + // If we have both the previous and next blocks, it means that the + // boundaries were on separated blocks, or none of them where on the + // block limits (start/end). + if ( !bIsStartOfBlock && !bIsEndOfBlock ) + { + // If the next block is an <li> with another list tree as the first child + // We'll need to append a placeholder or the list item wouldn't be editable. (Bug #1420) + if ( eNextBlock.nodeName.IEquals( 'li' ) && eNextBlock.firstChild + && eNextBlock.firstChild.nodeName.IEquals( ['ul', 'ol'] ) ) + eNextBlock.insertBefore( FCKTools.GetElementDocument( eNextBlock ).createTextNode( '\xa0' ), eNextBlock.firstChild ) ; + // Move the selection to the end block. + if ( eNextBlock ) + oRange.MoveToElementEditStart( eNextBlock ) ; + } + else + { + if ( bIsStartOfBlock && bIsEndOfBlock && ePreviousBlock.tagName.toUpperCase() == 'LI' ) + { + oRange.MoveToElementStart( ePreviousBlock ) ; + this._OutdentWithSelection( ePreviousBlock, oRange ) ; + oRange.Release() ; + return true ; + } + + var eNewBlock ; + + if ( ePreviousBlock ) + { + var sPreviousBlockTag = ePreviousBlock.tagName.toUpperCase() ; + + // If is a header tag, or we are in a Shift+Enter (#77), + // create a new block element (later in the code). + if ( !this._HasShift && !(/^H[1-6]$/).test( sPreviousBlockTag ) ) + { + // Otherwise, duplicate the previous block. + eNewBlock = FCKDomTools.CloneElement( ePreviousBlock ) ; + } + } + else if ( eNextBlock ) + eNewBlock = FCKDomTools.CloneElement( eNextBlock ) ; + + if ( !eNewBlock ) + eNewBlock = this.Window.document.createElement( blockTag ) ; + + // Recreate the inline elements tree, which was available + // before the hitting enter, so the same styles will be + // available in the new block. + var elementPath = oSplitInfo.ElementPath ; + if ( elementPath ) + { + for ( var i = 0, len = elementPath.Elements.length ; i < len ; i++ ) + { + var element = elementPath.Elements[i] ; + + if ( element == elementPath.Block || element == elementPath.BlockLimit ) + break ; + + if ( FCKListsLib.InlineChildReqElements[ element.nodeName.toLowerCase() ] ) + { + element = FCKDomTools.CloneElement( element ) ; + FCKDomTools.MoveChildren( eNewBlock, element ) ; + eNewBlock.appendChild( element ) ; + } + } + } + + if ( FCKBrowserInfo.IsGeckoLike ) + FCKTools.AppendBogusBr( eNewBlock ) ; + + oRange.InsertNode( eNewBlock ) ; + + // This is tricky, but to make the new block visible correctly + // we must select it. + if ( FCKBrowserInfo.IsIE ) + { + // Move the selection to the new block. + oRange.MoveToElementEditStart( eNewBlock ) ; + oRange.Select() ; + } + + // Move the selection to the new block. + oRange.MoveToElementEditStart( bIsStartOfBlock && !bIsEndOfBlock ? eNextBlock : eNewBlock ) ; + } + + if ( FCKBrowserInfo.IsSafari ) + FCKDomTools.ScrollIntoView( eNextBlock || eNewBlock, false ) ; + else if ( FCKBrowserInfo.IsGeckoLike ) + ( eNextBlock || eNewBlock ).scrollIntoView( false ) ; + + oRange.Select() ; + } + + // Release the resources used by the range. + oRange.Release() ; + + return true ; +} + +FCKEnterKey.prototype._ExecuteEnterBr = function( blockTag ) +{ + // Get the current selection. + var oRange = new FCKDomRange( this.Window ) ; + oRange.MoveToSelection() ; + + // The selection boundaries must be in the same "block limit" element. + if ( oRange.StartBlockLimit == oRange.EndBlockLimit ) + { + oRange.DeleteContents() ; + + // Get the new selection (it is collapsed at this point). + oRange.MoveToSelection() ; + + var bIsStartOfBlock = oRange.CheckStartOfBlock() ; + var bIsEndOfBlock = oRange.CheckEndOfBlock() ; + + var sStartBlockTag = oRange.StartBlock ? oRange.StartBlock.tagName.toUpperCase() : '' ; + + var bHasShift = this._HasShift ; + var bIsPre = false ; + + if ( !bHasShift && sStartBlockTag == 'LI' ) + return this._ExecuteEnterBlock( null, oRange ) ; + + // If we are at the end of a header block. + if ( !bHasShift && bIsEndOfBlock && (/^H[1-6]$/).test( sStartBlockTag ) ) + { + // Insert a BR after the current paragraph. + FCKDomTools.InsertAfterNode( oRange.StartBlock, this.Window.document.createElement( 'br' ) ) ; + + // The space is required by Gecko only to make the cursor blink. + if ( FCKBrowserInfo.IsGecko ) + FCKDomTools.InsertAfterNode( oRange.StartBlock, this.Window.document.createTextNode( '' ) ) ; + + // IE and Gecko have different behaviors regarding the position. + oRange.SetStart( oRange.StartBlock.nextSibling, FCKBrowserInfo.IsIE ? 3 : 1 ) ; + } + else + { + var eLineBreak ; + bIsPre = sStartBlockTag.IEquals( 'pre' ) ; + if ( bIsPre ) + eLineBreak = this.Window.document.createTextNode( FCKBrowserInfo.IsIE ? '\r' : '\n' ) ; + else + eLineBreak = this.Window.document.createElement( 'br' ) ; + + oRange.InsertNode( eLineBreak ) ; + + // The space is required by Gecko only to make the cursor blink. + if ( FCKBrowserInfo.IsGecko ) + FCKDomTools.InsertAfterNode( eLineBreak, this.Window.document.createTextNode( '' ) ) ; + + // If we are at the end of a block, we must be sure the bogus node is available in that block. + if ( bIsEndOfBlock && FCKBrowserInfo.IsGeckoLike ) + FCKTools.AppendBogusBr( eLineBreak.parentNode ) ; + + if ( FCKBrowserInfo.IsIE ) + oRange.SetStart( eLineBreak, 4 ) ; + else + oRange.SetStart( eLineBreak.nextSibling, 1 ) ; + + if ( ! FCKBrowserInfo.IsIE ) + { + var dummy = null ; + if ( FCKBrowserInfo.IsOpera ) + dummy = this.Window.document.createElement( 'span' ) ; + else + dummy = this.Window.document.createElement( 'br' ) ; + + eLineBreak.parentNode.insertBefore( dummy, eLineBreak.nextSibling ) ; + + if ( FCKBrowserInfo.IsSafari ) + FCKDomTools.ScrollIntoView( dummy, false ) ; + else + dummy.scrollIntoView( false ) ; + + dummy.parentNode.removeChild( dummy ) ; + } + } + + // This collapse guarantees the cursor will be blinking. + oRange.Collapse( true ) ; + + oRange.Select( bIsPre ) ; + } + + // Release the resources used by the range. + oRange.Release() ; + + return true ; +} + +// Outdents a LI, maintaining the selection defined on a range. +FCKEnterKey.prototype._OutdentWithSelection = function( li, range ) +{ + var oBookmark = range.CreateBookmark() ; + + FCKListHandler.OutdentListItem( li ) ; + + range.MoveToBookmark( oBookmark ) ; + range.Select() ; +} + +// Is all the contents under a node included by a range? +FCKEnterKey.prototype._CheckIsAllContentsIncluded = function( range, node ) +{ + var startOk = false ; + var endOk = false ; + + /* + FCKDebug.Output( 'sc='+range.StartContainer.nodeName+ + ',so='+range._Range.startOffset+ + ',ec='+range.EndContainer.nodeName+ + ',eo='+range._Range.endOffset ) ; + */ + if ( range.StartContainer == node || range.StartContainer == node.firstChild ) + startOk = ( range._Range.startOffset == 0 ) ; + + if ( range.EndContainer == node || range.EndContainer == node.lastChild ) + { + var nodeLength = range.EndContainer.nodeType == 3 ? range.EndContainer.length : range.EndContainer.childNodes.length ; + endOk = ( range._Range.endOffset == nodeLength ) ; + } + + return startOk && endOk ; +} + +// Kludge for #247 +FCKEnterKey.prototype._FixIESelectAllBug = function( range ) +{ + var doc = this.Window.document ; + doc.body.innerHTML = '' ; + var editBlock ; + if ( FCKConfig.EnterMode.IEquals( ['div', 'p'] ) ) + { + editBlock = doc.createElement( FCKConfig.EnterMode ) ; + doc.body.appendChild( editBlock ) ; + } + else + editBlock = doc.body ; + + range.MoveToNodeContents( editBlock ) ; + range.Collapse( true ) ; + range.Select() ; + range.Release() ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckevents.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckevents.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckevents.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,71 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKEvents Class: used to handle events is a advanced way. + */ + +var FCKEvents = function( eventsOwner ) +{ + this.Owner = eventsOwner ; + this._RegisteredEvents = new Object() ; +} + +FCKEvents.prototype.AttachEvent = function( eventName, functionPointer ) +{ + var aTargets ; + + if ( !( aTargets = this._RegisteredEvents[ eventName ] ) ) + this._RegisteredEvents[ eventName ] = [ functionPointer ] ; + else + { + // Check that the event handler isn't already registered with the same listener + // It doesn't detect function pointers belonging to an object (at least in Gecko) + if ( aTargets.IndexOf( functionPointer ) == -1 ) + aTargets.push( functionPointer ) ; + } +} + +FCKEvents.prototype.FireEvent = function( eventName, params ) +{ + var bReturnValue = true ; + + var oCalls = this._RegisteredEvents[ eventName ] ; + + if ( oCalls ) + { + for ( var i = 0 ; i < oCalls.length ; i++ ) + { + try + { + bReturnValue = ( oCalls[ i ]( this.Owner, params ) && bReturnValue ) ; + } + catch(e) + { + // Ignore the following error. It may happen if pointing to a + // script not anymore available (#934): + // -2146823277 = Can't execute code from a freed script + if ( e.number != -2146823277 ) + throw e ; + } + } + } + + return bReturnValue ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckhtmliterator.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckhtmliterator.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckhtmliterator.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,142 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * This class can be used to interate through nodes inside a range. + * + * During interation, the provided range can become invalid, due to document + * mutations, so CreateBookmark() used to restore it after processing, if + * needed. + */ + +var FCKHtmlIterator = function( source ) +{ + this._sourceHtml = source ; +} +FCKHtmlIterator.prototype = +{ + Next : function() + { + var sourceHtml = this._sourceHtml ; + if ( sourceHtml == null ) + return null ; + + var match = FCKRegexLib.HtmlTag.exec( sourceHtml ) ; + var isTag = false ; + var value = "" ; + if ( match ) + { + if ( match.index > 0 ) + { + value = sourceHtml.substr( 0, match.index ) ; + this._sourceHtml = sourceHtml.substr( match.index ) ; + } + else + { + isTag = true ; + value = match[0] ; + this._sourceHtml = sourceHtml.substr( match[0].length ) ; + } + } + else + { + value = sourceHtml ; + this._sourceHtml = null ; + } + return { 'isTag' : isTag, 'value' : value } ; + }, + + Each : function( func ) + { + var chunk ; + while ( ( chunk = this.Next() ) ) + func( chunk.isTag, chunk.value ) ; + } +} ; +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * This class can be used to interate through nodes inside a range. + * + * During interation, the provided range can become invalid, due to document + * mutations, so CreateBookmark() used to restore it after processing, if + * needed. + */ + +var FCKHtmlIterator = function( source ) +{ + this._sourceHtml = source ; +} +FCKHtmlIterator.prototype = +{ + Next : function() + { + var sourceHtml = this._sourceHtml ; + if ( sourceHtml == null ) + return null ; + + var match = FCKRegexLib.HtmlTag.exec( sourceHtml ) ; + var isTag = false ; + var value = "" ; + if ( match ) + { + if ( match.index > 0 ) + { + value = sourceHtml.substr( 0, match.index ) ; + this._sourceHtml = sourceHtml.substr( match.index ) ; + } + else + { + isTag = true ; + value = match[0] ; + this._sourceHtml = sourceHtml.substr( match[0].length ) ; + } + } + else + { + value = sourceHtml ; + this._sourceHtml = null ; + } + return { 'isTag' : isTag, 'value' : value } ; + }, + + Each : function( func ) + { + var chunk ; + while ( ( chunk = this.Next() ) ) + func( chunk.isTag, chunk.value ) ; + } +} ; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckicon.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckicon.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckicon.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,103 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKIcon Class: renders an icon from a single image, a strip or even a + * spacer. + */ + +var FCKIcon = function( iconPathOrStripInfoArray ) +{ + var sTypeOf = iconPathOrStripInfoArray ? typeof( iconPathOrStripInfoArray ) : 'undefined' ; + switch ( sTypeOf ) + { + case 'number' : + this.Path = FCKConfig.SkinPath + 'fck_strip.gif' ; + this.Size = 16 ; + this.Position = iconPathOrStripInfoArray ; + break ; + + case 'undefined' : + this.Path = FCK_SPACER_PATH ; + break ; + + case 'string' : + this.Path = iconPathOrStripInfoArray ; + break ; + + default : + // It is an array in the format [ StripFilePath, IconSize, IconPosition ] + this.Path = iconPathOrStripInfoArray[0] ; + this.Size = iconPathOrStripInfoArray[1] ; + this.Position = iconPathOrStripInfoArray[2] ; + } +} + +FCKIcon.prototype.CreateIconElement = function( document ) +{ + var eIcon, eIconImage ; + + if ( this.Position ) // It is using an icons strip image. + { + var sPos = '-' + ( ( this.Position - 1 ) * this.Size ) + 'px' ; + + if ( FCKBrowserInfo.IsIE ) + { + // <div class="TB_Button_Image"><img src="strip.gif" style="top:-16px"></div> + + eIcon = document.createElement( 'DIV' ) ; + + eIconImage = eIcon.appendChild( document.createElement( 'IMG' ) ) ; + eIconImage.src = this.Path ; + eIconImage.style.top = sPos ; + } + else + { + // <img class="TB_Button_Image" src="spacer.gif" style="background-position: 0px -16px;background-image: url(strip.gif);"> + + eIcon = document.createElement( 'IMG' ) ; + eIcon.src = FCK_SPACER_PATH ; + eIcon.style.backgroundPosition = '0px ' + sPos ; + eIcon.style.backgroundImage = 'url("' + this.Path + '")' ; + } + } + else // It is using a single icon image. + { + if ( FCKBrowserInfo.IsIE ) + { + // IE makes the button 1px higher if using the <img> directly, so we + // are changing to the <div> system to clip the image correctly. + eIcon = document.createElement( 'DIV' ) ; + + eIconImage = eIcon.appendChild( document.createElement( 'IMG' ) ) ; + eIconImage.src = this.Path ? this.Path : FCK_SPACER_PATH ; + } + else + { + // This is not working well with IE. See notes above. + // <img class="TB_Button_Image" src="smiley.gif"> + eIcon = document.createElement( 'IMG' ) ; + eIcon.src = this.Path ? this.Path : FCK_SPACER_PATH ; + } + } + + eIcon.className = 'TB_Button_Image' ; + + return eIcon ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckiecleanup.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckiecleanup.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckiecleanup.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,68 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKIECleanup Class: a generic class used as a tool to remove IE leaks. + */ + +var FCKIECleanup = function( attachWindow ) +{ + // If the attachWindow already have a cleanup object, just use that one. + if ( attachWindow._FCKCleanupObj ) + this.Items = attachWindow._FCKCleanupObj.Items ; + else + { + this.Items = new Array() ; + + attachWindow._FCKCleanupObj = this ; + FCKTools.AddEventListenerEx( attachWindow, 'unload', FCKIECleanup_Cleanup ) ; +// attachWindow.attachEvent( 'onunload', FCKIECleanup_Cleanup ) ; + } +} + +FCKIECleanup.prototype.AddItem = function( dirtyItem, cleanupFunction ) +{ + this.Items.push( [ dirtyItem, cleanupFunction ] ) ; +} + +function FCKIECleanup_Cleanup() +{ + if ( !this._FCKCleanupObj || !window.FCKUnloadFlag ) + return ; + + var aItems = this._FCKCleanupObj.Items ; + + while ( aItems.length > 0 ) + { + + // It is important to remove from the end to the beginning (pop()), + // because of the order things get created in the editor. In the code, + // elements in deeper position in the DOM are placed at the end of the + // cleanup function, so we must cleanup then first, otherwise IE could + // throw some crazy memory errors (IE bug). + var oItem = aItems.pop() ; + if ( oItem ) + oItem[1].call( oItem[0] ) ; + } + + this._FCKCleanupObj = null ; + + if ( CollectGarbage ) + CollectGarbage() ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckimagepreloader.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckimagepreloader.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckimagepreloader.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,64 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Preload a list of images, firing an event when complete. + */ + +var FCKImagePreloader = function() +{ + this._Images = new Array() ; +} + +FCKImagePreloader.prototype = +{ + AddImages : function( images ) + { + if ( typeof( images ) == 'string' ) + images = images.split( ';' ) ; + + this._Images = this._Images.concat( images ) ; + }, + + Start : function() + { + var aImages = this._Images ; + this._PreloadCount = aImages.length ; + + for ( var i = 0 ; i < aImages.length ; i++ ) + { + var eImg = document.createElement( 'img' ) ; + FCKTools.AddEventListenerEx( eImg, 'load', _FCKImagePreloader_OnImage, this ) ; + FCKTools.AddEventListenerEx( eImg, 'error', _FCKImagePreloader_OnImage, this ) ; + eImg.src = aImages[i] ; + + _FCKImagePreloader_ImageCache.push( eImg ) ; + } + } +}; + +// All preloaded images must be placed in a global array, otherwise the preload +// magic will not happen. +var _FCKImagePreloader_ImageCache = new Array() ; + +function _FCKImagePreloader_OnImage( ev, imagePreloader ) +{ + if ( (--imagePreloader._PreloadCount) == 0 && imagePreloader.OnComplete ) + imagePreloader.OnComplete() ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckkeystrokehandler.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckkeystrokehandler.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckkeystrokehandler.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,141 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Control keyboard keystroke combinations. + */ + +var FCKKeystrokeHandler = function( cancelCtrlDefaults ) +{ + this.Keystrokes = new Object() ; + this.CancelCtrlDefaults = ( cancelCtrlDefaults !== false ) ; +} + +/* + * Listen to keystroke events in an element or DOM document object. + * @target: The element or document to listen to keystroke events. + */ +FCKKeystrokeHandler.prototype.AttachToElement = function( target ) +{ + // For newer browsers, it is enough to listen to the keydown event only. + // Some browsers instead, don't cancel key events in the keydown, but in the + // keypress. So we must do a longer trip in those cases. + FCKTools.AddEventListenerEx( target, 'keydown', _FCKKeystrokeHandler_OnKeyDown, this ) ; + if ( FCKBrowserInfo.IsGecko10 || FCKBrowserInfo.IsOpera || ( FCKBrowserInfo.IsGecko && FCKBrowserInfo.IsMac ) ) + FCKTools.AddEventListenerEx( target, 'keypress', _FCKKeystrokeHandler_OnKeyPress, this ) ; +} + +/* + * Sets a list of keystrokes. It can receive either a single array or "n" + * arguments, each one being an array of 1 or 2 elemenst. The first element + * is the keystroke combination, and the second is the value to assign to it. + * If the second element is missing, the keystroke definition is removed. + */ +FCKKeystrokeHandler.prototype.SetKeystrokes = function() +{ + // Look through the arguments. + for ( var i = 0 ; i < arguments.length ; i++ ) + { + var keyDef = arguments[i] ; + + // If the configuration for the keystrokes is missing some element or has any extra comma + // this item won't be valid, so skip it and keep on processing. + if ( !keyDef ) + continue ; + + if ( typeof( keyDef[0] ) == 'object' ) // It is an array with arrays defining the keystrokes. + this.SetKeystrokes.apply( this, keyDef ) ; + else + { + if ( keyDef.length == 1 ) // If it has only one element, remove the keystroke. + delete this.Keystrokes[ keyDef[0] ] ; + else // Otherwise add it. + this.Keystrokes[ keyDef[0] ] = keyDef[1] === true ? true : keyDef ; + } + } +} + +function _FCKKeystrokeHandler_OnKeyDown( ev, keystrokeHandler ) +{ + // Get the key code. + var keystroke = ev.keyCode || ev.which ; + + // Combine it with the CTRL, SHIFT and ALT states. + var keyModifiers = 0 ; + + if ( ev.ctrlKey || ev.metaKey ) + keyModifiers += CTRL ; + + if ( ev.shiftKey ) + keyModifiers += SHIFT ; + + if ( ev.altKey ) + keyModifiers += ALT ; + + var keyCombination = keystroke + keyModifiers ; + + var cancelIt = keystrokeHandler._CancelIt = false ; + + // Look for its definition availability. + var keystrokeValue = keystrokeHandler.Keystrokes[ keyCombination ] ; + +// FCKDebug.Output( 'KeyDown: ' + keyCombination + ' - Value: ' + keystrokeValue ) ; + + // If the keystroke is defined + if ( keystrokeValue ) + { + // If the keystroke has been explicitly set to "true" OR calling the + // "OnKeystroke" event, it doesn't return "true", the default behavior + // must be preserved. + if ( keystrokeValue === true || !( keystrokeHandler.OnKeystroke && keystrokeHandler.OnKeystroke.apply( keystrokeHandler, keystrokeValue ) ) ) + return true ; + + cancelIt = true ; + } + + // By default, it will cancel all combinations with the CTRL key only (except positioning keys). + if ( cancelIt || ( keystrokeHandler.CancelCtrlDefaults && keyModifiers == CTRL && ( keystroke < 33 || keystroke > 40 ) ) ) + { + keystrokeHandler._CancelIt = true ; + + if ( ev.preventDefault ) + return ev.preventDefault() ; + + ev.returnValue = false ; + ev.cancelBubble = true ; + return false ; + } + + return true ; +} + +function _FCKKeystrokeHandler_OnKeyPress( ev, keystrokeHandler ) +{ + if ( keystrokeHandler._CancelIt ) + { +// FCKDebug.Output( 'KeyPress Cancel', 'Red') ; + + if ( ev.preventDefault ) + return ev.preventDefault() ; + + return false ; + } + + return true ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckmenublock.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckmenublock.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckmenublock.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,153 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Renders a list of menu items. + */ + +var FCKMenuBlock = function() +{ + this._Items = new Array() ; +} + + +FCKMenuBlock.prototype.Count = function() +{ + return this._Items.length ; +} + +FCKMenuBlock.prototype.AddItem = function( name, label, iconPathOrStripInfoArrayOrIndex, isDisabled, customData ) +{ + var oItem = new FCKMenuItem( this, name, label, iconPathOrStripInfoArrayOrIndex, isDisabled, customData ) ; + + oItem.OnClick = FCKTools.CreateEventListener( FCKMenuBlock_Item_OnClick, this ) ; + oItem.OnActivate = FCKTools.CreateEventListener( FCKMenuBlock_Item_OnActivate, this ) ; + + this._Items.push( oItem ) ; + + return oItem ; +} + +FCKMenuBlock.prototype.AddSeparator = function() +{ + this._Items.push( new FCKMenuSeparator() ) ; +} + +FCKMenuBlock.prototype.RemoveAllItems = function() +{ + this._Items = new Array() ; + + var eItemsTable = this._ItemsTable ; + if ( eItemsTable ) + { + while ( eItemsTable.rows.length > 0 ) + eItemsTable.deleteRow( 0 ) ; + } +} + +FCKMenuBlock.prototype.Create = function( parentElement ) +{ + if ( !this._ItemsTable ) + { + if ( FCK.IECleanup ) + FCK.IECleanup.AddItem( this, FCKMenuBlock_Cleanup ) ; + + this._Window = FCKTools.GetElementWindow( parentElement ) ; + + var oDoc = FCKTools.GetElementDocument( parentElement ) ; + + var eTable = parentElement.appendChild( oDoc.createElement( 'table' ) ) ; + eTable.cellPadding = 0 ; + eTable.cellSpacing = 0 ; + + FCKTools.DisableSelection( eTable ) ; + + var oMainElement = eTable.insertRow(-1).insertCell(-1) ; + oMainElement.className = 'MN_Menu' ; + + var eItemsTable = this._ItemsTable = oMainElement.appendChild( oDoc.createElement( 'table' ) ) ; + eItemsTable.cellPadding = 0 ; + eItemsTable.cellSpacing = 0 ; + } + + for ( var i = 0 ; i < this._Items.length ; i++ ) + this._Items[i].Create( this._ItemsTable ) ; +} + +/* Events */ + +function FCKMenuBlock_Item_OnClick( clickedItem, menuBlock ) +{ + if ( menuBlock.Hide ) + menuBlock.Hide() ; + + FCKTools.RunFunction( menuBlock.OnClick, menuBlock, [ clickedItem ] ) ; +} + +function FCKMenuBlock_Item_OnActivate( menuBlock ) +{ + var oActiveItem = menuBlock._ActiveItem ; + + if ( oActiveItem && oActiveItem != this ) + { + // Set the focus to this menu block window (to fire OnBlur on opened panels). + if ( !FCKBrowserInfo.IsIE && oActiveItem.HasSubMenu && !this.HasSubMenu ) + { + menuBlock._Window.focus() ; + + // Due to the event model provided by Opera, we need to set + // HasFocus here as the above focus() call will not fire the focus + // event in the panel immediately (#1200). + menuBlock.Panel.HasFocus = true ; + } + + oActiveItem.Deactivate() ; + } + + menuBlock._ActiveItem = this ; +} + +function FCKMenuBlock_Cleanup() +{ + this._Window = null ; + this._ItemsTable = null ; +} + +// ################# // + +var FCKMenuSeparator = function() +{} + +FCKMenuSeparator.prototype.Create = function( parentTable ) +{ + var oDoc = FCKTools.GetElementDocument( parentTable ) ; + + var r = parentTable.insertRow(-1) ; + + var eCell = r.insertCell(-1) ; + eCell.className = 'MN_Separator MN_Icon' ; + + eCell = r.insertCell(-1) ; + eCell.className = 'MN_Separator' ; + eCell.appendChild( oDoc.createElement( 'DIV' ) ).className = 'MN_Separator_Line' ; + + eCell = r.insertCell(-1) ; + eCell.className = 'MN_Separator' ; + eCell.appendChild( oDoc.createElement( 'DIV' ) ).className = 'MN_Separator_Line' ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckmenublockpanel.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckmenublockpanel.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckmenublockpanel.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,54 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * This class is a menu block that behaves like a panel. It's a mix of the + * FCKMenuBlock and FCKPanel classes. + */ + +var FCKMenuBlockPanel = function() +{ + // Call the "base" constructor. + FCKMenuBlock.call( this ) ; +} + +FCKMenuBlockPanel.prototype = new FCKMenuBlock() ; + + +// Override the create method. +FCKMenuBlockPanel.prototype.Create = function() +{ + var oPanel = this.Panel = ( this.Parent && this.Parent.Panel ? this.Parent.Panel.CreateChildPanel() : new FCKPanel() ) ; + oPanel.AppendStyleSheet( FCKConfig.SkinEditorCSS ) ; + + // Call the "base" implementation. + FCKMenuBlock.prototype.Create.call( this, oPanel.MainNode ) ; +} + +FCKMenuBlockPanel.prototype.Show = function( x, y, relElement ) +{ + if ( !this.Panel.CheckIsOpened() ) + this.Panel.Show( x, y, relElement ) ; +} + +FCKMenuBlockPanel.prototype.Hide = function() +{ + if ( this.Panel.CheckIsOpened() ) + this.Panel.Hide() ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckmenuitem.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckmenuitem.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckmenuitem.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,161 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Defines and renders a menu items in a menu block. + */ + +var FCKMenuItem = function( parentMenuBlock, name, label, iconPathOrStripInfoArray, isDisabled, customData ) +{ + this.Name = name ; + this.Label = label || name ; + this.IsDisabled = isDisabled ; + + this.Icon = new FCKIcon( iconPathOrStripInfoArray ) ; + + this.SubMenu = new FCKMenuBlockPanel() ; + this.SubMenu.Parent = parentMenuBlock ; + this.SubMenu.OnClick = FCKTools.CreateEventListener( FCKMenuItem_SubMenu_OnClick, this ) ; + this.CustomData = customData ; + + if ( FCK.IECleanup ) + FCK.IECleanup.AddItem( this, FCKMenuItem_Cleanup ) ; +} + + +FCKMenuItem.prototype.AddItem = function( name, label, iconPathOrStripInfoArrayOrIndex, isDisabled, customData ) +{ + this.HasSubMenu = true ; + return this.SubMenu.AddItem( name, label, iconPathOrStripInfoArrayOrIndex, isDisabled, customData ) ; +} + +FCKMenuItem.prototype.AddSeparator = function() +{ + this.SubMenu.AddSeparator() ; +} + +FCKMenuItem.prototype.Create = function( parentTable ) +{ + var bHasSubMenu = this.HasSubMenu ; + + var oDoc = FCKTools.GetElementDocument( parentTable ) ; + + // Add a row in the table to hold the menu item. + var r = this.MainElement = parentTable.insertRow(-1) ; + r.className = this.IsDisabled ? 'MN_Item_Disabled' : 'MN_Item' ; + + // Set the row behavior. + if ( !this.IsDisabled ) + { + FCKTools.AddEventListenerEx( r, 'mouseover', FCKMenuItem_OnMouseOver, [ this ] ) ; + FCKTools.AddEventListenerEx( r, 'click', FCKMenuItem_OnClick, [ this ] ) ; + + if ( !bHasSubMenu ) + FCKTools.AddEventListenerEx( r, 'mouseout', FCKMenuItem_OnMouseOut, [ this ] ) ; + } + + // Create the icon cell. + var eCell = r.insertCell(-1) ; + eCell.className = 'MN_Icon' ; + eCell.appendChild( this.Icon.CreateIconElement( oDoc ) ) ; + + // Create the label cell. + eCell = r.insertCell(-1) ; + eCell.className = 'MN_Label' ; + eCell.noWrap = true ; + eCell.appendChild( oDoc.createTextNode( this.Label ) ) ; + + // Create the arrow cell and setup the sub menu panel (if needed). + eCell = r.insertCell(-1) ; + if ( bHasSubMenu ) + { + eCell.className = 'MN_Arrow' ; + + // The arrow is a fixed size image. + var eArrowImg = eCell.appendChild( oDoc.createElement( 'IMG' ) ) ; + eArrowImg.src = FCK_IMAGES_PATH + 'arrow_' + FCKLang.Dir + '.gif' ; + eArrowImg.width = 4 ; + eArrowImg.height = 7 ; + + this.SubMenu.Create() ; + this.SubMenu.Panel.OnHide = FCKTools.CreateEventListener( FCKMenuItem_SubMenu_OnHide, this ) ; + } +} + +FCKMenuItem.prototype.Activate = function() +{ + this.MainElement.className = 'MN_Item_Over' ; + + if ( this.HasSubMenu ) + { + // Show the child menu block. The ( +2, -2 ) correction is done because + // of the padding in the skin. It is not a good solution because one + // could change the skin and so the final result would not be accurate. + // For now it is ok because we are controlling the skin. + this.SubMenu.Show( this.MainElement.offsetWidth + 2, -2, this.MainElement ) ; + } + + FCKTools.RunFunction( this.OnActivate, this ) ; +} + +FCKMenuItem.prototype.Deactivate = function() +{ + this.MainElement.className = 'MN_Item' ; + + if ( this.HasSubMenu ) + this.SubMenu.Hide() ; +} + +/* Events */ + +function FCKMenuItem_SubMenu_OnClick( clickedItem, listeningItem ) +{ + FCKTools.RunFunction( listeningItem.OnClick, listeningItem, [ clickedItem ] ) ; +} + +function FCKMenuItem_SubMenu_OnHide( menuItem ) +{ + menuItem.Deactivate() ; +} + +function FCKMenuItem_OnClick( ev, menuItem ) +{ + if ( menuItem.HasSubMenu ) + menuItem.Activate() ; + else + { + menuItem.Deactivate() ; + FCKTools.RunFunction( menuItem.OnClick, menuItem, [ menuItem ] ) ; + } +} + +function FCKMenuItem_OnMouseOver( ev, menuItem ) +{ + menuItem.Activate() ; +} + +function FCKMenuItem_OnMouseOut( ev, menuItem ) +{ + menuItem.Deactivate() ; +} + +function FCKMenuItem_Cleanup() +{ + this.MainElement = null ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckpanel.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckpanel.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckpanel.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,385 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Component that creates floating panels. It is used by many + * other components, like the toolbar items, context menu, etc... + */ + +var FCKPanel = function( parentWindow ) +{ + this.IsRTL = ( FCKLang.Dir == 'rtl' ) ; + this.IsContextMenu = false ; + this._LockCounter = 0 ; + + this._Window = parentWindow || window ; + + var oDocument ; + + if ( FCKBrowserInfo.IsIE ) + { + // Create the Popup that will hold the panel. + // The popup has to be created before playing with domain hacks, see #1666. + this._Popup = this._Window.createPopup() ; + + // this._Window cannot be accessed while playing with domain hacks, but local variable is ok. + // See #1666. + var pDoc = this._Window.document ; + + // This is a trick to IE6 (not IE7). The original domain must be set + // before creating the popup, so we are able to take a refence to the + // document inside of it, and the set the proper domain for it. (#123) + if ( FCK_IS_CUSTOM_DOMAIN && !FCKBrowserInfo.IsIE7 ) + { + pDoc.domain = FCK_ORIGINAL_DOMAIN ; + document.domain = FCK_ORIGINAL_DOMAIN ; + } + + oDocument = this.Document = this._Popup.document ; + + // Set the proper domain inside the popup. + if ( FCK_IS_CUSTOM_DOMAIN ) + { + oDocument.domain = FCK_RUNTIME_DOMAIN ; + pDoc.domain = FCK_RUNTIME_DOMAIN ; + document.domain = FCK_RUNTIME_DOMAIN ; + } + + FCK.IECleanup.AddItem( this, FCKPanel_Cleanup ) ; + } + else + { + var oIFrame = this._IFrame = this._Window.document.createElement('iframe') ; + oIFrame.src = 'javascript:void(0)' ; + oIFrame.allowTransparency = true ; + oIFrame.frameBorder = '0' ; + oIFrame.scrolling = 'no' ; + oIFrame.width = oIFrame.height = 0 ; + FCKDomTools.SetElementStyles( oIFrame, + { + position : 'absolute', + zIndex : FCKConfig.FloatingPanelsZIndex + } ) ; + + this._Window.document.body.appendChild( oIFrame ) ; + + var oIFrameWindow = oIFrame.contentWindow ; + + oDocument = this.Document = oIFrameWindow.document ; + + // Workaround for Safari 12256. Ticket #63 + var sBase = '' ; + if ( FCKBrowserInfo.IsSafari ) + sBase = '<base href="' + window.document.location + '">' ; + + // Initialize the IFRAME document body. + oDocument.open() ; + oDocument.write( '<html><head>' + sBase + '<\/head><body style="margin:0px;padding:0px;"><\/body><\/html>' ) ; + oDocument.close() ; + + if( FCKBrowserInfo.IsAIR ) + FCKAdobeAIR.Panel_Contructor( oDocument, window.document.location ) ; + + FCKTools.AddEventListenerEx( oIFrameWindow, 'focus', FCKPanel_Window_OnFocus, this ) ; + FCKTools.AddEventListenerEx( oIFrameWindow, 'blur', FCKPanel_Window_OnBlur, this ) ; + } + + oDocument.dir = FCKLang.Dir ; + + FCKTools.AddEventListener( oDocument, 'contextmenu', FCKTools.CancelEvent ) ; + + + // Create the main DIV that is used as the panel base. + this.MainNode = oDocument.body.appendChild( oDocument.createElement('DIV') ) ; + + // The "float" property must be set so Firefox calculates the size correctly. + this.MainNode.style.cssFloat = this.IsRTL ? 'right' : 'left' ; +} + + +FCKPanel.prototype.AppendStyleSheet = function( styleSheet ) +{ + FCKTools.AppendStyleSheet( this.Document, styleSheet ) ; +} + +FCKPanel.prototype.Preload = function( x, y, relElement ) +{ + // The offsetWidth and offsetHeight properties are not available if the + // element is not visible. So we must "show" the popup with no size to + // be able to use that values in the second call (IE only). + if ( this._Popup ) + this._Popup.show( x, y, 0, 0, relElement ) ; +} + +FCKPanel.prototype.Show = function( x, y, relElement, width, height ) +{ + var iMainWidth ; + var eMainNode = this.MainNode ; + + if ( this._Popup ) + { + // The offsetWidth and offsetHeight properties are not available if the + // element is not visible. So we must "show" the popup with no size to + // be able to use that values in the second call. + this._Popup.show( x, y, 0, 0, relElement ) ; + + // The following lines must be place after the above "show", otherwise it + // doesn't has the desired effect. + FCKDomTools.SetElementStyles( eMainNode, + { + width : width ? width + 'px' : '', + height : height ? height + 'px' : '' + } ) ; + + iMainWidth = eMainNode.offsetWidth ; + + if ( this.IsRTL ) + { + if ( this.IsContextMenu ) + x = x - iMainWidth + 1 ; + else if ( relElement ) + x = ( x * -1 ) + relElement.offsetWidth - iMainWidth ; + } + + // Second call: Show the Popup at the specified location, with the correct size. + this._Popup.show( x, y, iMainWidth, eMainNode.offsetHeight, relElement ) ; + + if ( this.OnHide ) + { + if ( this._Timer ) + CheckPopupOnHide.call( this, true ) ; + + this._Timer = FCKTools.SetInterval( CheckPopupOnHide, 100, this ) ; + } + } + else + { + // Do not fire OnBlur while the panel is opened. + if ( typeof( FCK.ToolbarSet.CurrentInstance.FocusManager ) != 'undefined' ) + FCK.ToolbarSet.CurrentInstance.FocusManager.Lock() ; + + if ( this.ParentPanel ) + { + this.ParentPanel.Lock() ; + + // Due to a bug on FF3, we must ensure that the parent panel will + // blur (#1584). + FCKPanel_Window_OnBlur( null, this.ParentPanel ) ; + } + + // Toggle the iframe scrolling attribute to prevent the panel + // scrollbars from disappearing in FF Mac. (#191) + if ( FCKBrowserInfo.IsGecko && FCKBrowserInfo.IsMac ) + { + this._IFrame.scrolling = '' ; + FCKTools.RunFunction( function(){ this._IFrame.scrolling = 'no'; }, this ) ; + } + + // Be sure we'll not have more than one Panel opened at the same time. + // Do not unlock focus manager here because we're displaying another floating panel + // instead of returning the editor to a "no panel" state (Bug #1514). + if ( FCK.ToolbarSet.CurrentInstance.GetInstanceObject( 'FCKPanel' )._OpenedPanel && + FCK.ToolbarSet.CurrentInstance.GetInstanceObject( 'FCKPanel' )._OpenedPanel != this ) + FCK.ToolbarSet.CurrentInstance.GetInstanceObject( 'FCKPanel' )._OpenedPanel.Hide( false, true ) ; + + FCKDomTools.SetElementStyles( eMainNode, + { + width : width ? width + 'px' : '', + height : height ? height + 'px' : '' + } ) ; + + iMainWidth = eMainNode.offsetWidth ; + + if ( !width ) this._IFrame.width = 1 ; + if ( !height ) this._IFrame.height = 1 ; + + // This is weird... but with Firefox, we must get the offsetWidth before + // setting the _IFrame size (which returns "0"), and then after that, + // to return the correct width. Remove the first step and it will not + // work when the editor is in RTL. + // + // The "|| eMainNode.firstChild.offsetWidth" part has been added + // for Opera compatibility (see #570). + iMainWidth = eMainNode.offsetWidth || eMainNode.firstChild.offsetWidth ; + + // Base the popup coordinates upon the coordinates of relElement. + var oPos = FCKTools.GetDocumentPosition( this._Window, + relElement.nodeType == 9 ? + ( FCKTools.IsStrictMode( relElement ) ? relElement.documentElement : relElement.body ) : + relElement ) ; + + // Minus the offsets provided by any positioned parent element of the panel iframe. + var positionedAncestor = FCKDomTools.GetPositionedAncestor( this._IFrame.parentNode ) ; + if ( positionedAncestor ) + { + var nPos = FCKTools.GetDocumentPosition( FCKTools.GetElementWindow( positionedAncestor ), positionedAncestor ) ; + oPos.x -= nPos.x ; + oPos.y -= nPos.y ; + } + + if ( this.IsRTL && !this.IsContextMenu ) + x = ( x * -1 ) ; + + x += oPos.x ; + y += oPos.y ; + + if ( this.IsRTL ) + { + if ( this.IsContextMenu ) + x = x - iMainWidth + 1 ; + else if ( relElement ) + x = x + relElement.offsetWidth - iMainWidth ; + } + else + { + var oViewPaneSize = FCKTools.GetViewPaneSize( this._Window ) ; + var oScrollPosition = FCKTools.GetScrollPosition( this._Window ) ; + + var iViewPaneHeight = oViewPaneSize.Height + oScrollPosition.Y ; + var iViewPaneWidth = oViewPaneSize.Width + oScrollPosition.X ; + + if ( ( x + iMainWidth ) > iViewPaneWidth ) + x -= x + iMainWidth - iViewPaneWidth ; + + if ( ( y + eMainNode.offsetHeight ) > iViewPaneHeight ) + y -= y + eMainNode.offsetHeight - iViewPaneHeight ; + } + + // Set the context menu DIV in the specified location. + FCKDomTools.SetElementStyles( this._IFrame, + { + left : x + 'px', + top : y + 'px' + } ) ; + + // Move the focus to the IFRAME so we catch the "onblur". + this._IFrame.contentWindow.focus() ; + this._IsOpened = true ; + + var me = this ; + this._resizeTimer = setTimeout( function() + { + var iWidth = eMainNode.offsetWidth || eMainNode.firstChild.offsetWidth ; + var iHeight = eMainNode.offsetHeight ; + me._IFrame.width = iWidth ; + me._IFrame.height = iHeight ; + + }, 0 ) ; + + FCK.ToolbarSet.CurrentInstance.GetInstanceObject( 'FCKPanel' )._OpenedPanel = this ; + } + + FCKTools.RunFunction( this.OnShow, this ) ; +} + +FCKPanel.prototype.Hide = function( ignoreOnHide, ignoreFocusManagerUnlock ) +{ + if ( this._Popup ) + this._Popup.hide() ; + else + { + if ( !this._IsOpened || this._LockCounter > 0 ) + return ; + + // Enable the editor to fire the "OnBlur". + if ( typeof( FCKFocusManager ) != 'undefined' && !ignoreFocusManagerUnlock ) + FCKFocusManager.Unlock() ; + + // It is better to set the sizes to 0, otherwise Firefox would have + // rendering problems. + this._IFrame.width = this._IFrame.height = 0 ; + + this._IsOpened = false ; + + if ( this._resizeTimer ) + { + clearTimeout( this._resizeTimer ) ; + this._resizeTimer = null ; + } + + if ( this.ParentPanel ) + this.ParentPanel.Unlock() ; + + if ( !ignoreOnHide ) + FCKTools.RunFunction( this.OnHide, this ) ; + } +} + +FCKPanel.prototype.CheckIsOpened = function() +{ + if ( this._Popup ) + return this._Popup.isOpen ; + else + return this._IsOpened ; +} + +FCKPanel.prototype.CreateChildPanel = function() +{ + var oWindow = this._Popup ? FCKTools.GetDocumentWindow( this.Document ) : this._Window ; + + var oChildPanel = new FCKPanel( oWindow ) ; + oChildPanel.ParentPanel = this ; + + return oChildPanel ; +} + +FCKPanel.prototype.Lock = function() +{ + this._LockCounter++ ; +} + +FCKPanel.prototype.Unlock = function() +{ + if ( --this._LockCounter == 0 && !this.HasFocus ) + this.Hide() ; +} + +/* Events */ + +function FCKPanel_Window_OnFocus( e, panel ) +{ + panel.HasFocus = true ; +} + +function FCKPanel_Window_OnBlur( e, panel ) +{ + panel.HasFocus = false ; + + if ( panel._LockCounter == 0 ) + FCKTools.RunFunction( panel.Hide, panel ) ; +} + +function CheckPopupOnHide( forceHide ) +{ + if ( forceHide || !this._Popup.isOpen ) + { + window.clearInterval( this._Timer ) ; + this._Timer = null ; + + FCKTools.RunFunction( this.OnHide, this ) ; + } +} + +function FCKPanel_Cleanup() +{ + this._Popup = null ; + this._Window = null ; + this.Document = null ; + this.MainNode = null ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckplugin.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckplugin.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckplugin.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,56 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKPlugin Class: Represents a single plugin. + */ + +var FCKPlugin = function( name, availableLangs, basePath ) +{ + this.Name = name ; + this.BasePath = basePath ? basePath : FCKConfig.PluginsPath ; + this.Path = this.BasePath + name + '/' ; + + if ( !availableLangs || availableLangs.length == 0 ) + this.AvailableLangs = new Array() ; + else + this.AvailableLangs = availableLangs.split(',') ; +} + +FCKPlugin.prototype.Load = function() +{ + // Load the language file, if defined. + if ( this.AvailableLangs.length > 0 ) + { + var sLang ; + + // Check if the plugin has the language file for the active language. + if ( this.AvailableLangs.IndexOf( FCKLanguageManager.ActiveLanguage.Code ) >= 0 ) + sLang = FCKLanguageManager.ActiveLanguage.Code ; + else + // Load the default language file (first one) if the current one is not available. + sLang = this.AvailableLangs[0] ; + + // Add the main plugin script. + LoadScript( this.Path + 'lang/' + sLang + '.js' ) ; + } + + // Add the main plugin script. + LoadScript( this.Path + 'fckplugin.js' ) ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckspecialcombo.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckspecialcombo.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckspecialcombo.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,376 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKSpecialCombo Class: represents a special combo. + */ + +var FCKSpecialCombo = function( caption, fieldWidth, panelWidth, panelMaxHeight, parentWindow ) +{ + // Default properties values. + this.FieldWidth = fieldWidth || 100 ; + this.PanelWidth = panelWidth || 150 ; + this.PanelMaxHeight = panelMaxHeight || 150 ; + this.Label = ' ' ; + this.Caption = caption ; + this.Tooltip = caption ; + this.Style = FCK_TOOLBARITEM_ICONTEXT ; + + this.Enabled = true ; + + this.Items = new Object() ; + + this._Panel = new FCKPanel( parentWindow || window ) ; + this._Panel.AppendStyleSheet( FCKConfig.SkinEditorCSS ) ; + this._PanelBox = this._Panel.MainNode.appendChild( this._Panel.Document.createElement( 'DIV' ) ) ; + this._PanelBox.className = 'SC_Panel' ; + this._PanelBox.style.width = this.PanelWidth + 'px' ; + + this._PanelBox.innerHTML = '<table cellpadding="0" cellspacing="0" width="100%" style="TABLE-LAYOUT: fixed"><tr><td nowrap></td></tr></table>' ; + + this._ItemsHolderEl = this._PanelBox.getElementsByTagName('TD')[0] ; + + if ( FCK.IECleanup ) + FCK.IECleanup.AddItem( this, FCKSpecialCombo_Cleanup ) ; + +// this._Panel.StyleSheet = FCKConfig.SkinPath + 'fck_contextmenu.css' ; +// this._Panel.Create() ; +// this._Panel.PanelDiv.className += ' SC_Panel' ; +// this._Panel.PanelDiv.innerHTML = '<table cellpadding="0" cellspacing="0" width="100%" style="TABLE-LAYOUT: fixed"><tr><td nowrap></td></tr></table>' ; +// this._ItemsHolderEl = this._Panel.PanelDiv.getElementsByTagName('TD')[0] ; +} + +function FCKSpecialCombo_ItemOnMouseOver() +{ + this.className += ' SC_ItemOver' ; +} + +function FCKSpecialCombo_ItemOnMouseOut() +{ + this.className = this.originalClass ; +} + +function FCKSpecialCombo_ItemOnClick( ev, specialCombo, itemId ) +{ + this.className = this.originalClass ; + + specialCombo._Panel.Hide() ; + + specialCombo.SetLabel( this.FCKItemLabel ) ; + + if ( typeof( specialCombo.OnSelect ) == 'function' ) + specialCombo.OnSelect( itemId, this ) ; +} + +FCKSpecialCombo.prototype.ClearItems = function () +{ + if ( this.Items ) + this.Items = {} ; + + var itemsholder = this._ItemsHolderEl ; + while ( itemsholder.firstChild ) + itemsholder.removeChild( itemsholder.firstChild ) ; +} + +FCKSpecialCombo.prototype.AddItem = function( id, html, label, bgColor ) +{ + // <div class="SC_Item" onmouseover="this.className='SC_Item SC_ItemOver';" onmouseout="this.className='SC_Item';"><b>Bold 1</b></div> + var oDiv = this._ItemsHolderEl.appendChild( this._Panel.Document.createElement( 'DIV' ) ) ; + oDiv.className = oDiv.originalClass = 'SC_Item' ; + oDiv.innerHTML = html ; + oDiv.FCKItemLabel = label || id ; + oDiv.Selected = false ; + + // In IE, the width must be set so the borders are shown correctly when the content overflows. + if ( FCKBrowserInfo.IsIE ) + oDiv.style.width = '100%' ; + + if ( bgColor ) + oDiv.style.backgroundColor = bgColor ; + + FCKTools.AddEventListenerEx( oDiv, 'mouseover', FCKSpecialCombo_ItemOnMouseOver ) ; + FCKTools.AddEventListenerEx( oDiv, 'mouseout', FCKSpecialCombo_ItemOnMouseOut ) ; + FCKTools.AddEventListenerEx( oDiv, 'click', FCKSpecialCombo_ItemOnClick, [ this, id ] ) ; + + this.Items[ id.toString().toLowerCase() ] = oDiv ; + + return oDiv ; +} + +FCKSpecialCombo.prototype.SelectItem = function( item ) +{ + if ( typeof item == 'string' ) + item = this.Items[ item.toString().toLowerCase() ] ; + + if ( item ) + { + item.className = item.originalClass = 'SC_ItemSelected' ; + item.Selected = true ; + } +} + +FCKSpecialCombo.prototype.SelectItemByLabel = function( itemLabel, setLabel ) +{ + for ( var id in this.Items ) + { + var oDiv = this.Items[id] ; + + if ( oDiv.FCKItemLabel == itemLabel ) + { + oDiv.className = oDiv.originalClass = 'SC_ItemSelected' ; + oDiv.Selected = true ; + + if ( setLabel ) + this.SetLabel( itemLabel ) ; + } + } +} + +FCKSpecialCombo.prototype.DeselectAll = function( clearLabel ) +{ + for ( var i in this.Items ) + { + if ( !this.Items[i] ) continue; + this.Items[i].className = this.Items[i].originalClass = 'SC_Item' ; + this.Items[i].Selected = false ; + } + + if ( clearLabel ) + this.SetLabel( '' ) ; +} + +FCKSpecialCombo.prototype.SetLabelById = function( id ) +{ + id = id ? id.toString().toLowerCase() : '' ; + + var oDiv = this.Items[ id ] ; + this.SetLabel( oDiv ? oDiv.FCKItemLabel : '' ) ; +} + +FCKSpecialCombo.prototype.SetLabel = function( text ) +{ + text = ( !text || text.length == 0 ) ? ' ' : text ; + + if ( text == this.Label ) + return ; + + this.Label = text ; + + var labelEl = this._LabelEl ; + if ( labelEl ) + { + labelEl.innerHTML = text ; + + // It may happen that the label is some HTML, including tags. This + // would be a problem because when the user click on those tags, the + // combo will get the selection from the editing area. So we must + // disable any kind of selection here. + FCKTools.DisableSelection( labelEl ) ; + } +} + +FCKSpecialCombo.prototype.SetEnabled = function( isEnabled ) +{ + this.Enabled = isEnabled ; + + // In IE it can happen when the page is reloaded that _OuterTable is null, so check its existence + if ( this._OuterTable ) + this._OuterTable.className = isEnabled ? '' : 'SC_FieldDisabled' ; +} + +FCKSpecialCombo.prototype.Create = function( targetElement ) +{ + var oDoc = FCKTools.GetElementDocument( targetElement ) ; + var eOuterTable = this._OuterTable = targetElement.appendChild( oDoc.createElement( 'TABLE' ) ) ; + eOuterTable.cellPadding = 0 ; + eOuterTable.cellSpacing = 0 ; + + eOuterTable.insertRow(-1) ; + + var sClass ; + var bShowLabel ; + + switch ( this.Style ) + { + case FCK_TOOLBARITEM_ONLYICON : + sClass = 'TB_ButtonType_Icon' ; + bShowLabel = false; + break ; + case FCK_TOOLBARITEM_ONLYTEXT : + sClass = 'TB_ButtonType_Text' ; + bShowLabel = false; + break ; + case FCK_TOOLBARITEM_ICONTEXT : + bShowLabel = true; + break ; + } + + if ( this.Caption && this.Caption.length > 0 && bShowLabel ) + { + var oCaptionCell = eOuterTable.rows[0].insertCell(-1) ; + oCaptionCell.innerHTML = this.Caption ; + oCaptionCell.className = 'SC_FieldCaption' ; + } + + // Create the main DIV element. + var oField = FCKTools.AppendElement( eOuterTable.rows[0].insertCell(-1), 'div' ) ; + if ( bShowLabel ) + { + oField.className = 'SC_Field' ; + oField.style.width = this.FieldWidth + 'px' ; + oField.innerHTML = '<table width="100%" cellpadding="0" cellspacing="0" style="TABLE-LAYOUT: fixed;"><tbody><tr><td class="SC_FieldLabel"><label> </label></td><td class="SC_FieldButton"> </td></tr></tbody></table>' ; + + this._LabelEl = oField.getElementsByTagName('label')[0] ; // Memory Leak + this._LabelEl.innerHTML = this.Label ; + } + else + { + oField.className = 'TB_Button_Off' ; + //oField.innerHTML = '<span className="SC_FieldCaption">' + this.Caption + '<table cellpadding="0" cellspacing="0" style="TABLE-LAYOUT: fixed;"><tbody><tr><td class="SC_FieldButton" style="border-left: none;"> </td></tr></tbody></table>' ; + //oField.innerHTML = '<table cellpadding="0" cellspacing="0" style="TABLE-LAYOUT: fixed;"><tbody><tr><td class="SC_FieldButton" style="border-left: none;"> </td></tr></tbody></table>' ; + + // Gets the correct CSS class to use for the specified style (param). + oField.innerHTML = '<table title="' + this.Tooltip + '" class="' + sClass + '" cellspacing="0" cellpadding="0" border="0">' + + '<tr>' + + //'<td class="TB_Icon"><img src="' + FCKConfig.SkinPath + 'toolbar/' + this.Command.Name.toLowerCase() + '.gif" width="21" height="21"></td>' + + '<td><img class="TB_Button_Padding" src="' + FCK_SPACER_PATH + '" /></td>' + + '<td class="TB_Text">' + this.Caption + '</td>' + + '<td><img class="TB_Button_Padding" src="' + FCK_SPACER_PATH + '" /></td>' + + '<td class="TB_ButtonArrow"><img src="' + FCKConfig.SkinPath + 'images/toolbar.buttonarrow.gif" width="5" height="3"></td>' + + '<td><img class="TB_Button_Padding" src="' + FCK_SPACER_PATH + '" /></td>' + + '</tr>' + + '</table>' ; + } + + + // Events Handlers + + FCKTools.AddEventListenerEx( oField, 'mouseover', FCKSpecialCombo_OnMouseOver, this ) ; + FCKTools.AddEventListenerEx( oField, 'mouseout', FCKSpecialCombo_OnMouseOut, this ) ; + FCKTools.AddEventListenerEx( oField, 'click', FCKSpecialCombo_OnClick, this ) ; + + FCKTools.DisableSelection( this._Panel.Document.body ) ; +} + +function FCKSpecialCombo_Cleanup() +{ + this._LabelEl = null ; + this._OuterTable = null ; + this._ItemsHolderEl = null ; + this._PanelBox = null ; + + if ( this.Items ) + { + for ( var key in this.Items ) + this.Items[key] = null ; + } +} + +function FCKSpecialCombo_OnMouseOver( ev, specialCombo ) +{ + if ( specialCombo.Enabled ) + { + switch ( specialCombo.Style ) + { + case FCK_TOOLBARITEM_ONLYICON : + this.className = 'TB_Button_On_Over'; + break ; + case FCK_TOOLBARITEM_ONLYTEXT : + this.className = 'TB_Button_On_Over'; + break ; + case FCK_TOOLBARITEM_ICONTEXT : + this.className = 'SC_Field SC_FieldOver' ; + break ; + } + } +} + +function FCKSpecialCombo_OnMouseOut( ev, specialCombo ) +{ + switch ( specialCombo.Style ) + { + case FCK_TOOLBARITEM_ONLYICON : + this.className = 'TB_Button_Off'; + break ; + case FCK_TOOLBARITEM_ONLYTEXT : + this.className = 'TB_Button_Off'; + break ; + case FCK_TOOLBARITEM_ICONTEXT : + this.className='SC_Field' ; + break ; + } +} + +function FCKSpecialCombo_OnClick( e, specialCombo ) +{ + // For Mozilla we must stop the event propagation to avoid it hiding + // the panel because of a click outside of it. +// if ( e ) +// { +// e.stopPropagation() ; +// FCKPanelEventHandlers.OnDocumentClick( e ) ; +// } + + if ( specialCombo.Enabled ) + { + var oPanel = specialCombo._Panel ; + var oPanelBox = specialCombo._PanelBox ; + var oItemsHolder = specialCombo._ItemsHolderEl ; + var iMaxHeight = specialCombo.PanelMaxHeight ; + + if ( specialCombo.OnBeforeClick ) + specialCombo.OnBeforeClick( specialCombo ) ; + + // This is a tricky thing. We must call the "Load" function, otherwise + // it will not be possible to retrieve "oItemsHolder.offsetHeight" (IE only). + if ( FCKBrowserInfo.IsIE ) + oPanel.Preload( 0, this.offsetHeight, this ) ; + + if ( oItemsHolder.offsetHeight > iMaxHeight ) +// { + oPanelBox.style.height = iMaxHeight + 'px' ; + +// if ( FCKBrowserInfo.IsGecko ) +// oPanelBox.style.overflow = '-moz-scrollbars-vertical' ; +// } + else + oPanelBox.style.height = '' ; + +// oPanel.PanelDiv.style.width = specialCombo.PanelWidth + 'px' ; + + oPanel.Show( 0, this.offsetHeight, this ) ; + } + +// return false ; +} + +/* +Sample Combo Field HTML output: + +<div class="SC_Field" style="width: 80px;"> + <table width="100%" cellpadding="0" cellspacing="0" style="table-layout: fixed;"> + <tbody> + <tr> + <td class="SC_FieldLabel"><label> </label></td> + <td class="SC_FieldButton"> </td> + </tr> + </tbody> + </table> +</div> +*/ Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckstyle.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckstyle.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckstyle.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,1443 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKStyle Class: contains a style definition, and all methods to work with + * the style in a document. + */ + +/** + * @param {Object} styleDesc A "style descriptor" object, containing the raw + * style definition in the following format: + * '<style name>' : { + * Element : '<element name>', + * Attributes : { + * '<att name>' : '<att value>', + * ... + * }, + * Styles : { + * '<style name>' : '<style value>', + * ... + * }, + * Overrides : '<element name>'|{ + * Element : '<element name>', + * Attributes : { + * '<att name>' : '<att value>'|/<att regex>/ + * }, + * Styles : { + * '<style name>' : '<style value>'|/<style regex>/ + * }, + * } + * } + */ +var FCKStyle = function( styleDesc ) +{ + this.Element = ( styleDesc.Element || 'span' ).toLowerCase() ; + this._StyleDesc = styleDesc ; +} + +FCKStyle.prototype = +{ + /** + * Get the style type, based on its element name: + * - FCK_STYLE_BLOCK (0): Block Style + * - FCK_STYLE_INLINE (1): Inline Style + * - FCK_STYLE_OBJECT (2): Object Style + */ + GetType : function() + { + var type = this.GetType_$ ; + + if ( type != undefined ) + return type ; + + var elementName = this.Element ; + + if ( elementName == '#' || FCKListsLib.StyleBlockElements[ elementName ] ) + type = FCK_STYLE_BLOCK ; + else if ( FCKListsLib.StyleObjectElements[ elementName ] ) + type = FCK_STYLE_OBJECT ; + else + type = FCK_STYLE_INLINE ; + + return ( this.GetType_$ = type ) ; + }, + + /** + * Apply the style to the current selection. + */ + ApplyToSelection : function( targetWindow ) + { + // Create a range for the current selection. + var range = new FCKDomRange( targetWindow ) ; + range.MoveToSelection() ; + + this.ApplyToRange( range, true ) ; + }, + + /** + * Apply the style to a FCKDomRange. + */ + ApplyToRange : function( range, selectIt, updateRange ) + { + // ApplyToRange is not valid for FCK_STYLE_OBJECT types. + // Use ApplyToObject instead. + + switch ( this.GetType() ) + { + case FCK_STYLE_BLOCK : + this.ApplyToRange = this._ApplyBlockStyle ; + break ; + case FCK_STYLE_INLINE : + this.ApplyToRange = this._ApplyInlineStyle ; + break ; + default : + return ; + } + + this.ApplyToRange( range, selectIt, updateRange ) ; + }, + + /** + * Apply the style to an object. Valid for FCK_STYLE_BLOCK types only. + */ + ApplyToObject : function( objectElement ) + { + if ( !objectElement ) + return ; + + this.BuildElement( null, objectElement ) ; + }, + + /** + * Remove the style from the current selection. + */ + RemoveFromSelection : function( targetWindow ) + { + // Create a range for the current selection. + var range = new FCKDomRange( targetWindow ) ; + range.MoveToSelection() ; + + this.RemoveFromRange( range, true ) ; + }, + + /** + * Remove the style from a FCKDomRange. Block type styles will have no + * effect. + */ + RemoveFromRange : function( range, selectIt, updateRange ) + { + var bookmark ; + + // Create the attribute list to be used later for element comparisons. + var styleAttribs = this._GetAttribsForComparison() ; + var styleOverrides = this._GetOverridesForComparison() ; + + // If collapsed, we are removing all conflicting styles from the range + // parent tree. + if ( range.CheckIsCollapsed() ) + { + // Bookmark the range so we can re-select it after processing. + var bookmark = range.CreateBookmark( true ) ; + + // Let's start from the bookmark <span> parent. + var bookmarkStart = range.GetBookmarkNode( bookmark, true ) ; + + var path = new FCKElementPath( bookmarkStart.parentNode ) ; + + // While looping through the path, we'll be saving references to + // parent elements if the range is in one of their boundaries. In + // this way, we are able to create a copy of those elements when + // removing a style if the range is in a boundary limit (see #1270). + var boundaryElements = [] ; + + // Check if the range is in the boundary limits of an element + // (related to #1270). + var isBoundaryRight = !FCKDomTools.GetNextSibling( bookmarkStart ) ; + var isBoundary = isBoundaryRight || !FCKDomTools.GetPreviousSibling( bookmarkStart ) ; + + // This is the last element to be removed in the boundary situation + // described at #1270. + var lastBoundaryElement ; + var boundaryLimitIndex = -1 ; + + for ( var i = 0 ; i < path.Elements.length ; i++ ) + { + var pathElement = path.Elements[i] ; + if ( this.CheckElementRemovable( pathElement ) ) + { + if ( isBoundary + && !FCKDomTools.CheckIsEmptyElement( pathElement, + function( el ) + { + return ( el != bookmarkStart ) ; + } ) + ) + { + lastBoundaryElement = pathElement ; + + // We'll be continuously including elements in the + // boundaryElements array, but only those added before + // setting lastBoundaryElement must be used later, so + // let's mark the current index here. + boundaryLimitIndex = boundaryElements.length - 1 ; + } + else + { + var pathElementName = pathElement.nodeName.toLowerCase() ; + + if ( pathElementName == this.Element ) + { + // Remove any attribute that conflict with this style, no + // matter their values. + for ( var att in styleAttribs ) + { + if ( FCKDomTools.HasAttribute( pathElement, att ) ) + { + switch ( att ) + { + case 'style' : + this._RemoveStylesFromElement( pathElement ) ; + break ; + + case 'class' : + // The 'class' element value must match (#1318). + if ( FCKDomTools.GetAttributeValue( pathElement, att ) != this.GetFinalAttributeValue( att ) ) + continue ; + + default : + FCKDomTools.RemoveAttribute( pathElement, att ) ; + } + } + } + } + + // Remove overrides defined to the same element name. + this._RemoveOverrides( pathElement, styleOverrides[ pathElementName ] ) ; + + // Remove the element if no more attributes are available and it's an inline style element + if ( this.GetType() == FCK_STYLE_INLINE) + this._RemoveNoAttribElement( pathElement ) ; + } + } + else if ( isBoundary ) + boundaryElements.push( pathElement ) ; + + // Check if we are still in a boundary (at the same side). + isBoundary = isBoundary && ( ( isBoundaryRight && !FCKDomTools.GetNextSibling( pathElement ) ) || ( !isBoundaryRight && !FCKDomTools.GetPreviousSibling( pathElement ) ) ) ; + + // If we are in an element that is not anymore a boundary, or + // we are at the last element, let's move things outside the + // boundary (if available). + if ( lastBoundaryElement && ( !isBoundary || ( i == path.Elements.length - 1 ) ) ) + { + // Remove the bookmark node from the DOM. + var currentElement = FCKDomTools.RemoveNode( bookmarkStart ) ; + + // Build the collapsed group of elements that are not + // removed by this style, but share the boundary. + // (see comment 1 and 2 at #1270) + for ( var j = 0 ; j <= boundaryLimitIndex ; j++ ) + { + var newElement = FCKDomTools.CloneElement( boundaryElements[j] ) ; + newElement.appendChild( currentElement ) ; + currentElement = newElement ; + } + + // Re-insert the bookmark node (and the collapsed elements) + // in the DOM, in the new position next to the styled element. + if ( isBoundaryRight ) + FCKDomTools.InsertAfterNode( lastBoundaryElement, currentElement ) ; + else + lastBoundaryElement.parentNode.insertBefore( currentElement, lastBoundaryElement ) ; + + isBoundary = false ; + lastBoundaryElement = null ; + } + } + + // Re-select the original range. + if ( selectIt ) + range.SelectBookmark( bookmark ) ; + + if ( updateRange ) + range.MoveToBookmark( bookmark ) ; + + return ; + } + + // Expand the range, if inside inline element boundaries. + range.Expand( 'inline_elements' ) ; + + // Bookmark the range so we can re-select it after processing. + bookmark = range.CreateBookmark( true ) ; + + // The style will be applied within the bookmark boundaries. + var startNode = range.GetBookmarkNode( bookmark, true ) ; + var endNode = range.GetBookmarkNode( bookmark, false ) ; + + range.Release( true ) ; + + // We need to check the selection boundaries (bookmark spans) to break + // the code in a way that we can properly remove partially selected nodes. + // For example, removing a <b> style from + // <b>This is [some text</b> to show <b>the] problem</b> + // ... where [ and ] represent the selection, must result: + // <b>This is </b>[some text to show the]<b> problem</b> + // The strategy is simple, we just break the partial nodes before the + // removal logic, having something that could be represented this way: + // <b>This is </b>[<b>some text</b> to show <b>the</b>]<b> problem</b> + + // Let's start checking the start boundary. + var path = new FCKElementPath( startNode ) ; + var pathElements = path.Elements ; + var pathElement ; + + for ( var i = 1 ; i < pathElements.length ; i++ ) + { + pathElement = pathElements[i] ; + + if ( pathElement == path.Block || pathElement == path.BlockLimit ) + break ; + + // If this element can be removed (even partially). + if ( this.CheckElementRemovable( pathElement ) ) + FCKDomTools.BreakParent( startNode, pathElement, range ) ; + } + + // Now the end boundary. + path = new FCKElementPath( endNode ) ; + pathElements = path.Elements ; + + for ( var i = 1 ; i < pathElements.length ; i++ ) + { + pathElement = pathElements[i] ; + + if ( pathElement == path.Block || pathElement == path.BlockLimit ) + break ; + + elementName = pathElement.nodeName.toLowerCase() ; + + // If this element can be removed (even partially). + if ( this.CheckElementRemovable( pathElement ) ) + FCKDomTools.BreakParent( endNode, pathElement, range ) ; + } + + // Navigate through all nodes between the bookmarks. + var currentNode = FCKDomTools.GetNextSourceNode( startNode, true ) ; + + while ( currentNode ) + { + // Cache the next node to be processed. Do it now, because + // currentNode may be removed. + var nextNode = FCKDomTools.GetNextSourceNode( currentNode ) ; + + // Remove elements nodes that match with this style rules. + if ( currentNode.nodeType == 1 ) + { + var elementName = currentNode.nodeName.toLowerCase() ; + + var mayRemove = ( elementName == this.Element ) ; + if ( mayRemove ) + { + // Remove any attribute that conflict with this style, no matter + // their values. + for ( var att in styleAttribs ) + { + if ( FCKDomTools.HasAttribute( currentNode, att ) ) + { + switch ( att ) + { + case 'style' : + this._RemoveStylesFromElement( currentNode ) ; + break ; + + case 'class' : + // The 'class' element value must match (#1318). + if ( FCKDomTools.GetAttributeValue( currentNode, att ) != this.GetFinalAttributeValue( att ) ) + continue ; + + default : + FCKDomTools.RemoveAttribute( currentNode, att ) ; + } + } + } + } + else + mayRemove = !!styleOverrides[ elementName ] ; + + if ( mayRemove ) + { + // Remove overrides defined to the same element name. + this._RemoveOverrides( currentNode, styleOverrides[ elementName ] ) ; + + // Remove the element if no more attributes are available. + this._RemoveNoAttribElement( currentNode ) ; + } + } + + // If we have reached the end of the selection, stop looping. + if ( nextNode == endNode ) + break ; + + currentNode = nextNode ; + } + + this._FixBookmarkStart( startNode ) ; + + // Re-select the original range. + if ( selectIt ) + range.SelectBookmark( bookmark ) ; + + if ( updateRange ) + range.MoveToBookmark( bookmark ) ; + }, + + /** + * Checks if an element, or any of its attributes, is removable by the + * current style definition. + */ + CheckElementRemovable : function( element, fullMatch ) + { + if ( !element ) + return false ; + + var elementName = element.nodeName.toLowerCase() ; + + // If the element name is the same as the style name. + if ( elementName == this.Element ) + { + // If no attributes are defined in the element. + if ( !fullMatch && !FCKDomTools.HasAttributes( element ) ) + return true ; + + // If any attribute conflicts with the style attributes. + var attribs = this._GetAttribsForComparison() ; + var allMatched = ( attribs._length == 0 ) ; + for ( var att in attribs ) + { + if ( att == '_length' ) + continue ; + + if ( this._CompareAttributeValues( att, FCKDomTools.GetAttributeValue( element, att ), ( this.GetFinalAttributeValue( att ) || '' ) ) ) + { + allMatched = true ; + if ( !fullMatch ) + break ; + } + else + { + allMatched = false ; + if ( fullMatch ) + return false ; + } + } + if ( allMatched ) + return true ; + } + + // Check if the element can be somehow overriden. + var override = this._GetOverridesForComparison()[ elementName ] ; + if ( override ) + { + // If no attributes have been defined, remove the element. + if ( !( attribs = override.Attributes ) ) // Only one "=" + return true ; + + for ( var i = 0 ; i < attribs.length ; i++ ) + { + var attName = attribs[i][0] ; + if ( FCKDomTools.HasAttribute( element, attName ) ) + { + var attValue = attribs[i][1] ; + + // Remove the attribute if: + // - The override definition value is null ; + // - The override definition valie is a string that + // matches the attribute value exactly. + // - The override definition value is a regex that + // has matches in the attribute value. + if ( attValue == null || + ( typeof attValue == 'string' && FCKDomTools.GetAttributeValue( element, attName ) == attValue ) || + attValue.test( FCKDomTools.GetAttributeValue( element, attName ) ) ) + return true ; + } + } + } + + return false ; + }, + + /** + * Get the style state for an element path. Returns "true" if the element + * is active in the path. + */ + CheckActive : function( elementPath ) + { + switch ( this.GetType() ) + { + case FCK_STYLE_BLOCK : + return this.CheckElementRemovable( elementPath.Block || elementPath.BlockLimit, true ) ; + + case FCK_STYLE_INLINE : + + var elements = elementPath.Elements ; + + for ( var i = 0 ; i < elements.length ; i++ ) + { + var element = elements[i] ; + + if ( element == elementPath.Block || element == elementPath.BlockLimit ) + continue ; + + if ( this.CheckElementRemovable( element, true ) ) + return true ; + } + } + return false ; + }, + + /** + * Removes an inline style from inside an element tree. The element node + * itself is not checked or removed, only the child tree inside of it. + */ + RemoveFromElement : function( element ) + { + var attribs = this._GetAttribsForComparison() ; + var overrides = this._GetOverridesForComparison() ; + + // Get all elements with the same name. + var innerElements = element.getElementsByTagName( this.Element ) ; + + for ( var i = innerElements.length - 1 ; i >= 0 ; i-- ) + { + var innerElement = innerElements[i] ; + + // Remove any attribute that conflict with this style, no matter + // their values. + for ( var att in attribs ) + { + if ( FCKDomTools.HasAttribute( innerElement, att ) ) + { + switch ( att ) + { + case 'style' : + this._RemoveStylesFromElement( innerElement ) ; + break ; + + case 'class' : + // The 'class' element value must match (#1318). + if ( FCKDomTools.GetAttributeValue( innerElement, att ) != this.GetFinalAttributeValue( att ) ) + continue ; + + default : + FCKDomTools.RemoveAttribute( innerElement, att ) ; + } + } + } + + // Remove overrides defined to the same element name. + this._RemoveOverrides( innerElement, overrides[ this.Element ] ) ; + + // Remove the element if no more attributes are available. + this._RemoveNoAttribElement( innerElement ) ; + } + + // Now remove any other element with different name that is + // defined to be overriden. + for ( var overrideElement in overrides ) + { + if ( overrideElement != this.Element ) + { + // Get all elements. + innerElements = element.getElementsByTagName( overrideElement ) ; + + for ( var i = innerElements.length - 1 ; i >= 0 ; i-- ) + { + var innerElement = innerElements[i] ; + this._RemoveOverrides( innerElement, overrides[ overrideElement ] ) ; + this._RemoveNoAttribElement( innerElement ) ; + } + } + } + }, + + _RemoveStylesFromElement : function( element ) + { + var elementStyle = element.style.cssText ; + var pattern = this.GetFinalStyleValue() ; + + if ( elementStyle.length > 0 && pattern.length == 0 ) + return ; + + pattern = '(^|;)\\s*(' + + pattern.replace( /\s*([^ ]+):.*?(;|$)/g, '$1|' ).replace( /\|$/, '' ) + + '):[^;]+' ; + + var regex = new RegExp( pattern, 'gi' ) ; + + elementStyle = elementStyle.replace( regex, '' ).Trim() ; + + if ( elementStyle.length == 0 || elementStyle == ';' ) + FCKDomTools.RemoveAttribute( element, 'style' ) ; + else + element.style.cssText = elementStyle.replace( regex, '' ) ; + }, + + /** + * Remove all attributes that are defined to be overriden, + */ + _RemoveOverrides : function( element, override ) + { + var attributes = override && override.Attributes ; + + if ( attributes ) + { + for ( var i = 0 ; i < attributes.length ; i++ ) + { + var attName = attributes[i][0] ; + + if ( FCKDomTools.HasAttribute( element, attName ) ) + { + var attValue = attributes[i][1] ; + + // Remove the attribute if: + // - The override definition value is null ; + // - The override definition valie is a string that + // matches the attribute value exactly. + // - The override definition value is a regex that + // has matches in the attribute value. + if ( attValue == null || + ( attValue.test && attValue.test( FCKDomTools.GetAttributeValue( element, attName ) ) ) || + ( typeof attValue == 'string' && FCKDomTools.GetAttributeValue( element, attName ) == attValue ) ) + FCKDomTools.RemoveAttribute( element, attName ) ; + } + } + } + }, + + /** + * If the element has no more attributes, remove it. + */ + _RemoveNoAttribElement : function( element ) + { + // If no more attributes remained in the element, remove it, + // leaving its children. + if ( !FCKDomTools.HasAttributes( element ) ) + { + // Removing elements may open points where merging is possible, + // so let's cache the first and last nodes for later checking. + var firstChild = element.firstChild ; + var lastChild = element.lastChild ; + + FCKDomTools.RemoveNode( element, true ) ; + + // Check the cached nodes for merging. + this._MergeSiblings( firstChild ) ; + + if ( firstChild != lastChild ) + this._MergeSiblings( lastChild ) ; + } + }, + + /** + * Creates a DOM element for this style object. + */ + BuildElement : function( targetDoc, element ) + { + // Create the element. + var el = element || targetDoc.createElement( this.Element ) ; + + // Assign all defined attributes. + var attribs = this._StyleDesc.Attributes ; + var attValue ; + if ( attribs ) + { + for ( var att in attribs ) + { + attValue = this.GetFinalAttributeValue( att ) ; + + if ( att.toLowerCase() == 'class' ) + el.className = attValue ; + else + el.setAttribute( att, attValue ) ; + } + } + + // Assign the style attribute. + if ( this._GetStyleText().length > 0 ) + el.style.cssText = this.GetFinalStyleValue() ; + + return el ; + }, + + _CompareAttributeValues : function( attName, valueA, valueB ) + { + if ( attName == 'style' && valueA && valueB ) + { + valueA = valueA.replace( /;$/, '' ).toLowerCase() ; + valueB = valueB.replace( /;$/, '' ).toLowerCase() ; + } + + // Return true if they match or if valueA is null and valueB is an empty string + return ( valueA == valueB || ( ( valueA === null || valueA === '' ) && ( valueB === null || valueB === '' ) ) ) + }, + + GetFinalAttributeValue : function( attName ) + { + var attValue = this._StyleDesc.Attributes ; + var attValue = attValue ? attValue[ attName ] : null ; + + if ( !attValue && attName == 'style' ) + return this.GetFinalStyleValue() ; + + if ( attValue && this._Variables ) + // Using custom Replace() to guarantee the correct scope. + attValue = attValue.Replace( FCKRegexLib.StyleVariableAttName, this._GetVariableReplace, this ) ; + + return attValue ; + }, + + GetFinalStyleValue : function() + { + var attValue = this._GetStyleText() ; + + if ( attValue.length > 0 && this._Variables ) + { + // Using custom Replace() to guarantee the correct scope. + attValue = attValue.Replace( FCKRegexLib.StyleVariableAttName, this._GetVariableReplace, this ) ; + attValue = FCKTools.NormalizeCssText( attValue ) ; + } + + return attValue ; + }, + + _GetVariableReplace : function() + { + // The second group in the regex is the variable name. + return this._Variables[ arguments[2] ] || arguments[0] ; + }, + + /** + * Set the value of a variable attribute or style, to be used when + * appliying the style. + */ + SetVariable : function( name, value ) + { + var variables = this._Variables ; + + if ( !variables ) + variables = this._Variables = {} ; + + this._Variables[ name ] = value ; + }, + + /** + * Converting from a PRE block to a non-PRE block in formatting operations. + */ + _FromPre : function( doc, block, newBlock ) + { + var innerHTML = block.innerHTML ; + + // Trim the first and last linebreaks immediately after and before <pre>, </pre>, + // if they exist. + // This is done because the linebreaks are not rendered. + innerHTML = innerHTML.replace( /(\r\n|\r)/g, '\n' ) ; + innerHTML = innerHTML.replace( /^[ \t]*\n/, '' ) ; + innerHTML = innerHTML.replace( /\n$/, '' ) ; + + // 1. Convert spaces or tabs at the beginning or at the end to + innerHTML = innerHTML.replace( /^[ \t]+|[ \t]+$/g, function( match, offset, s ) + { + if ( match.length == 1 ) // one space, preserve it + return ' ' ; + else if ( offset == 0 ) // beginning of block + return new Array( match.length ).join( ' ' ) + ' ' ; + else // end of block + return ' ' + new Array( match.length ).join( ' ' ) ; + } ) ; + + // 2. Convert \n to <BR>. + // 3. Convert contiguous (i.e. non-singular) spaces or tabs to + var htmlIterator = new FCKHtmlIterator( innerHTML ) ; + var results = [] ; + htmlIterator.Each( function( isTag, value ) + { + if ( !isTag ) + { + value = value.replace( /\n/g, '<BR>' ) ; + value = value.replace( /[ \t]{2,}/g, + function ( match ) + { + return new Array( match.length ).join( ' ' ) + ' ' ; + } ) ; + } + results.push( value ) ; + } ) ; + newBlock.innerHTML = results.join( '' ) ; + return newBlock ; + }, + + /** + * Converting from a non-PRE block to a PRE block in formatting operations. + */ + _ToPre : function( doc, block, newBlock ) + { + // Handle converting from a regular block to a <pre> block. + var innerHTML = block.innerHTML.Trim() ; + + // 1. Delete ANSI whitespaces immediately before and after <BR> because they are not visible. + // 2. Mark down any <BR /> nodes here so they can be turned into \n in the next step and avoid being compressed. + innerHTML = innerHTML.replace( /[ \t\r\n]*(<br[^>]*>)[ \t\r\n]*/gi, '<BR />' ) ; + + // 3. Compress other ANSI whitespaces since they're only visible as one single space previously. + // 4. Convert to spaces since is no longer needed in <PRE>. + // 5. Convert any <BR /> to \n. This must not be done earlier because the \n would then get compressed. + var htmlIterator = new FCKHtmlIterator( innerHTML ) ; + var results = [] ; + htmlIterator.Each( function( isTag, value ) + { + if ( !isTag ) + value = value.replace( /([ \t\n\r]+| )/g, ' ' ) ; + else if ( isTag && value == '<BR />' ) + value = '\n' ; + results.push( value ) ; + } ) ; + + // Assigning innerHTML to <PRE> in IE causes all linebreaks to be reduced to spaces. + // Assigning outerHTML to <PRE> in IE doesn't work if the <PRE> isn't contained in another node + // since the node reference is changed after outerHTML assignment. + // So, we need some hacks to workaround IE bugs here. + if ( FCKBrowserInfo.IsIE ) + { + var temp = doc.createElement( 'div' ) ; + temp.appendChild( newBlock ) ; + newBlock.outerHTML = '<PRE>\n' + results.join( '' ) + '</PRE>' ; + newBlock = temp.removeChild( temp.firstChild ) ; + } + else + newBlock.innerHTML = results.join( '' ) ; + return newBlock ; + }, + + /** + * Apply an inline style to a FCKDomRange. + * + * TODO + * - Implement the "#" style handling. + * - Properly handle block containers like <div> and <blockquote>. + */ + _ApplyBlockStyle : function( range, selectIt, updateRange ) + { + // Bookmark the range so we can re-select it after processing. + var bookmark ; + + if ( selectIt ) + bookmark = range.CreateBookmark() ; + + var iterator = new FCKDomRangeIterator( range ) ; + iterator.EnforceRealBlocks = true ; + + var block ; + var doc = range.Window.document ; + + var preBlocks = [] ; + var convertedPreBlocks = [] ; + + while( ( block = iterator.GetNextParagraph() ) ) // Only one = + { + // Create the new node right before the current one. + var newBlock = this.BuildElement( doc ) ; + + // Move everything from the current node to the new one. + var newBlockIsPre = newBlock.nodeName.IEquals( 'pre' ) ; + var blockIsPre = block.nodeName.IEquals( 'pre' ) ; + if ( newBlockIsPre && !blockIsPre ) + { + newBlock = this._ToPre( doc, block, newBlock ) ; + preBlocks.push( newBlock ) ; + } + else if ( !newBlockIsPre && blockIsPre ) + { + newBlock = this._FromPre( doc, block, newBlock ) ; + convertedPreBlocks.push( newBlock ) ; + } + else // Convering from a regular block to another regular block. + FCKDomTools.MoveChildren( block, newBlock ) ; + + // Replace the current block. + block.parentNode.insertBefore( newBlock, block ) ; + FCKDomTools.RemoveNode( block ) ; + } + + // Merge adjacent <PRE> blocks for #1229. + for ( var i = 0 ; i < preBlocks.length - 1 ; i++ ) + { + // Check if the next block in HTML equals the next <PRE> block generated. + if ( FCKDomTools.GetNextSourceElement( preBlocks[i], true, [], [], true ) != preBlocks[i+1] ) + continue ; + + // Merge the upper <PRE> block's content into the lower <PRE> block. + // Remove the upper <PRE> block. + preBlocks[i+1].innerHTML = preBlocks[i].innerHTML + '\n\n' + preBlocks[i+1].innerHTML ; + FCKDomTools.RemoveNode( preBlocks[i] ) ; + } + + // Split converted <PRE> blocks for #1229. + for ( var i = 0 ; i < convertedPreBlocks.length ; i++ ) + { + var currentBlock = convertedPreBlocks[i] ; + var lastNewBlock = null ; + for ( var j = 0 ; j < currentBlock.childNodes.length ; j++ ) + { + var cursor = currentBlock.childNodes[j] ; + + // If we have two <BR>s, and they're not at the beginning or the end, + // then we'll split up the contents following them into another block. + if ( cursor.nodeName.IEquals( 'br' ) && j != 0 && j != currentBlock.childNodes.length - 2 + && cursor.nextSibling && cursor.nextSibling.nodeName.IEquals( 'br' ) ) + { + FCKDomTools.RemoveNode( cursor.nextSibling ) ; + FCKDomTools.RemoveNode( cursor ) ; + j-- ; // restart at current index at next iteration + lastNewBlock = FCKDomTools.InsertAfterNode( lastNewBlock || currentBlock, doc.createElement( currentBlock.nodeName ) ) ; + continue ; + } + + if ( lastNewBlock ) + { + FCKDomTools.MoveNode( cursor, lastNewBlock ) ; + j-- ; // restart at current index at next iteration + } + } + } + + // Re-select the original range. + if ( selectIt ) + range.SelectBookmark( bookmark ) ; + + if ( updateRange ) + range.MoveToBookmark( bookmark ) ; + }, + + /** + * Apply an inline style to a FCKDomRange. + * + * TODO + * - Merge elements, when applying styles to similar elements that enclose + * the entire selection, outputing: + * <span style="color: #ff0000; background-color: #ffffff">XYZ</span> + * instead of: + * <span style="color: #ff0000;"><span style="background-color: #ffffff">XYZ</span></span> + */ + _ApplyInlineStyle : function( range, selectIt, updateRange ) + { + var doc = range.Window.document ; + + if ( range.CheckIsCollapsed() ) + { + // Create the element to be inserted in the DOM. + var collapsedElement = this.BuildElement( doc ) ; + range.InsertNode( collapsedElement ) ; + range.MoveToPosition( collapsedElement, 2 ) ; + range.Select() ; + + return ; + } + + // The general idea here is navigating through all nodes inside the + // current selection, working on distinct range blocks, defined by the + // DTD compatibility between the style element and the nodes inside the + // ranges. + // + // For example, suppose we have the following selection (where [ and ] + // are the boundaries), and we apply a <b> style there: + // + // <p>Here we [have <b>some</b> text.<p> + // <p>And some here] here.</p> + // + // Two different ranges will be detected: + // + // "have <b>some</b> text." + // "And some here" + // + // Both ranges will be extracted, moved to a <b> element, and + // re-inserted, resulting in the following output: + // + // <p>Here we [<b>have some text.</b><p> + // <p><b>And some here</b>] here.</p> + // + // Note that the <b> element at <b>some</b> is also removed because it + // is not needed anymore. + + var elementName = this.Element ; + + // Get the DTD definition for the element. Defaults to "span". + var elementDTD = FCK.DTD[ elementName ] || FCK.DTD.span ; + + // Create the attribute list to be used later for element comparisons. + var styleAttribs = this._GetAttribsForComparison() ; + var styleNode ; + + // Expand the range, if inside inline element boundaries. + range.Expand( 'inline_elements' ) ; + + // Bookmark the range so we can re-select it after processing. + var bookmark = range.CreateBookmark( true ) ; + + // The style will be applied within the bookmark boundaries. + var startNode = range.GetBookmarkNode( bookmark, true ) ; + var endNode = range.GetBookmarkNode( bookmark, false ) ; + + // We'll be reusing the range to apply the styles. So, release it here + // to indicate that it has not been initialized. + range.Release( true ) ; + + // Let's start the nodes lookup from the node right after the bookmark + // span. + var currentNode = FCKDomTools.GetNextSourceNode( startNode, true ) ; + + while ( currentNode ) + { + var applyStyle = false ; + + var nodeType = currentNode.nodeType ; + var nodeName = nodeType == 1 ? currentNode.nodeName.toLowerCase() : null ; + + // Check if the current node can be a child of the style element. + if ( !nodeName || elementDTD[ nodeName ] ) + { + // Check if the style element can be a child of the current + // node parent or if the element is not defined in the DTD. + if ( ( FCK.DTD[ currentNode.parentNode.nodeName.toLowerCase() ] || FCK.DTD.span )[ elementName ] || !FCK.DTD[ elementName ] ) + { + // This node will be part of our range, so if it has not + // been started, place its start right before the node. + if ( !range.CheckHasRange() ) + range.SetStart( currentNode, 3 ) ; + + // Non element nodes, or empty elements can be added + // completely to the range. + if ( nodeType != 1 || currentNode.childNodes.length == 0 ) + { + var includedNode = currentNode ; + var parentNode = includedNode.parentNode ; + + // This node is about to be included completelly, but, + // if this is the last node in its parent, we must also + // check if the parent itself can be added completelly + // to the range. + while ( includedNode == parentNode.lastChild + && elementDTD[ parentNode.nodeName.toLowerCase() ] ) + { + includedNode = parentNode ; + } + + range.SetEnd( includedNode, 4 ) ; + + // If the included node is the last node in its parent + // and its parent can't be inside the style node, apply + // the style immediately. + if ( includedNode == includedNode.parentNode.lastChild && !elementDTD[ includedNode.parentNode.nodeName.toLowerCase() ] ) + applyStyle = true ; + } + else + { + // Element nodes will not be added directly. We need to + // check their children because the selection could end + // inside the node, so let's place the range end right + // before the element. + range.SetEnd( currentNode, 3 ) ; + } + } + else + applyStyle = true ; + } + else + applyStyle = true ; + + // Get the next node to be processed. + currentNode = FCKDomTools.GetNextSourceNode( currentNode ) ; + + // If we have reached the end of the selection, just apply the + // style ot the range, and stop looping. + if ( currentNode == endNode ) + { + currentNode = null ; + applyStyle = true ; + } + + // Apply the style if we have something to which apply it. + if ( applyStyle && range.CheckHasRange() && !range.CheckIsCollapsed() ) + { + // Build the style element, based on the style object definition. + styleNode = this.BuildElement( doc ) ; + + // Move the contents of the range to the style element. + range.ExtractContents().AppendTo( styleNode ) ; + + // If it is not empty. + if ( styleNode.innerHTML.RTrim().length > 0 ) + { + // Insert it in the range position (it is collapsed after + // ExtractContents. + range.InsertNode( styleNode ) ; + + // Here we do some cleanup, removing all duplicated + // elements from the style element. + this.RemoveFromElement( styleNode ) ; + + // Let's merge our new style with its neighbors, if possible. + this._MergeSiblings( styleNode, this._GetAttribsForComparison() ) ; + + // As the style system breaks text nodes constantly, let's normalize + // things for performance. + // With IE, some paragraphs get broken when calling normalize() + // repeatedly. Also, for IE, we must normalize body, not documentElement. + // IE is also known for having a "crash effect" with normalize(). + // We should try to normalize with IE too in some way, somewhere. + if ( !FCKBrowserInfo.IsIE ) + styleNode.normalize() ; + } + + // Style applied, let's release the range, so it gets marked to + // re-initialization in the next loop. + range.Release( true ) ; + } + } + + this._FixBookmarkStart( startNode ) ; + + // Re-select the original range. + if ( selectIt ) + range.SelectBookmark( bookmark ) ; + + if ( updateRange ) + range.MoveToBookmark( bookmark ) ; + }, + + _FixBookmarkStart : function( startNode ) + { + // After appliying or removing an inline style, the start boundary of + // the selection must be placed inside all inline elements it is + // bordering. + var startSibling ; + while ( ( startSibling = startNode.nextSibling ) ) // Only one "=". + { + if ( startSibling.nodeType == 1 + && FCKListsLib.InlineNonEmptyElements[ startSibling.nodeName.toLowerCase() ] ) + { + // If it is an empty inline element, we can safely remove it. + if ( !startSibling.firstChild ) + FCKDomTools.RemoveNode( startSibling ) ; + else + FCKDomTools.MoveNode( startNode, startSibling, true ) ; + continue ; + } + + // Empty text nodes can be safely removed to not disturb. + if ( startSibling.nodeType == 3 && startSibling.length == 0 ) + { + FCKDomTools.RemoveNode( startSibling ) ; + continue ; + } + + break ; + } + }, + + /** + * Merge an element with its similar siblings. + * "attribs" is and object computed with _CreateAttribsForComparison. + */ + _MergeSiblings : function( element, attribs ) + { + if ( !element || element.nodeType != 1 || !FCKListsLib.InlineNonEmptyElements[ element.nodeName.toLowerCase() ] ) + return ; + + this._MergeNextSibling( element, attribs ) ; + this._MergePreviousSibling( element, attribs ) ; + }, + + /** + * Merge an element with its similar siblings after it. + * "attribs" is and object computed with _CreateAttribsForComparison. + */ + _MergeNextSibling : function( element, attribs ) + { + // Check the next sibling. + var sibling = element.nextSibling ; + + // Check if the next sibling is a bookmark element. In this case, jump it. + var hasBookmark = ( sibling && sibling.nodeType == 1 && sibling.getAttribute( '_fck_bookmark' ) ) ; + if ( hasBookmark ) + sibling = sibling.nextSibling ; + + if ( sibling && sibling.nodeType == 1 && sibling.nodeName == element.nodeName ) + { + if ( !attribs ) + attribs = this._CreateElementAttribsForComparison( element ) ; + + if ( this._CheckAttributesMatch( sibling, attribs ) ) + { + // Save the last child to be checked too (to merge things like <b><i></i></b><b><i></i></b>). + var innerSibling = element.lastChild ; + + if ( hasBookmark ) + FCKDomTools.MoveNode( element.nextSibling, element ) ; + + // Move contents from the sibling. + FCKDomTools.MoveChildren( sibling, element ) ; + FCKDomTools.RemoveNode( sibling ) ; + + // Now check the last inner child (see two comments above). + if ( innerSibling ) + this._MergeNextSibling( innerSibling ) ; + } + } + }, + + /** + * Merge an element with its similar siblings before it. + * "attribs" is and object computed with _CreateAttribsForComparison. + */ + _MergePreviousSibling : function( element, attribs ) + { + // Check the previous sibling. + var sibling = element.previousSibling ; + + // Check if the previous sibling is a bookmark element. In this case, jump it. + var hasBookmark = ( sibling && sibling.nodeType == 1 && sibling.getAttribute( '_fck_bookmark' ) ) ; + if ( hasBookmark ) + sibling = sibling.previousSibling ; + + if ( sibling && sibling.nodeType == 1 && sibling.nodeName == element.nodeName ) + { + if ( !attribs ) + attribs = this._CreateElementAttribsForComparison( element ) ; + + if ( this._CheckAttributesMatch( sibling, attribs ) ) + { + // Save the first child to be checked too (to merge things like <b><i></i></b><b><i></i></b>). + var innerSibling = element.firstChild ; + + if ( hasBookmark ) + FCKDomTools.MoveNode( element.previousSibling, element, true ) ; + + // Move contents to the sibling. + FCKDomTools.MoveChildren( sibling, element, true ) ; + FCKDomTools.RemoveNode( sibling ) ; + + // Now check the first inner child (see two comments above). + if ( innerSibling ) + this._MergePreviousSibling( innerSibling ) ; + } + } + }, + + /** + * Build the cssText based on the styles definition. + */ + _GetStyleText : function() + { + var stylesDef = this._StyleDesc.Styles ; + + // Builds the StyleText. + var stylesText = ( this._StyleDesc.Attributes ? this._StyleDesc.Attributes['style'] || '' : '' ) ; + + if ( stylesText.length > 0 ) + stylesText += ';' ; + + for ( var style in stylesDef ) + stylesText += style + ':' + stylesDef[style] + ';' ; + + // Browsers make some changes to the style when applying them. So, here + // we normalize it to the browser format. We'll not do that if there + // are variables inside the style. + if ( stylesText.length > 0 && !( /#\(/.test( stylesText ) ) ) + { + stylesText = FCKTools.NormalizeCssText( stylesText ) ; + } + + return (this._GetStyleText = function() { return stylesText ; })() ; + }, + + /** + * Get the the collection used to compare the attributes defined in this + * style with attributes in an element. All information in it is lowercased. + */ + _GetAttribsForComparison : function() + { + // If we have already computed it, just return it. + var attribs = this._GetAttribsForComparison_$ ; + if ( attribs ) + return attribs ; + + attribs = new Object() ; + + // Loop through all defined attributes. + var styleAttribs = this._StyleDesc.Attributes ; + if ( styleAttribs ) + { + for ( var styleAtt in styleAttribs ) + { + attribs[ styleAtt.toLowerCase() ] = styleAttribs[ styleAtt ].toLowerCase() ; + } + } + + // Includes the style definitions. + if ( this._GetStyleText().length > 0 ) + { + attribs['style'] = this._GetStyleText().toLowerCase() ; + } + + // Appends the "length" information to the object. + FCKTools.AppendLengthProperty( attribs, '_length' ) ; + + // Return it, saving it to the next request. + return ( this._GetAttribsForComparison_$ = attribs ) ; + }, + + /** + * Get the the collection used to compare the elements and attributes, + * defined in this style overrides, with other element. All information in + * it is lowercased. + */ + _GetOverridesForComparison : function() + { + // If we have already computed it, just return it. + var overrides = this._GetOverridesForComparison_$ ; + if ( overrides ) + return overrides ; + + overrides = new Object() ; + + var overridesDesc = this._StyleDesc.Overrides ; + + if ( overridesDesc ) + { + // The override description can be a string, object or array. + // Internally, well handle arrays only, so transform it if needed. + if ( !FCKTools.IsArray( overridesDesc ) ) + overridesDesc = [ overridesDesc ] ; + + // Loop through all override definitions. + for ( var i = 0 ; i < overridesDesc.length ; i++ ) + { + var override = overridesDesc[i] ; + var elementName ; + var overrideEl ; + var attrs ; + + // If can be a string with the element name. + if ( typeof override == 'string' ) + elementName = override.toLowerCase() ; + // Or an object. + else + { + elementName = override.Element ? override.Element.toLowerCase() : this.Element ; + attrs = override.Attributes ; + } + + // We can have more than one override definition for the same + // element name, so we attempt to simply append information to + // it if it already exists. + overrideEl = overrides[ elementName ] || ( overrides[ elementName ] = {} ) ; + + if ( attrs ) + { + // The returning attributes list is an array, because we + // could have different override definitions for the same + // attribute name. + var overrideAttrs = ( overrideEl.Attributes = overrideEl.Attributes || new Array() ) ; + for ( var attName in attrs ) + { + // Each item in the attributes array is also an array, + // where [0] is the attribute name and [1] is the + // override value. + overrideAttrs.push( [ attName.toLowerCase(), attrs[ attName ] ] ) ; + } + } + } + } + + return ( this._GetOverridesForComparison_$ = overrides ) ; + }, + + /* + * Create and object containing all attributes specified in an element, + * added by a "_length" property. All values are lowercased. + */ + _CreateElementAttribsForComparison : function( element ) + { + var attribs = new Object() ; + var attribsCount = 0 ; + + for ( var i = 0 ; i < element.attributes.length ; i++ ) + { + var att = element.attributes[i] ; + + if ( att.specified ) + { + attribs[ att.nodeName.toLowerCase() ] = FCKDomTools.GetAttributeValue( element, att ).toLowerCase() ; + attribsCount++ ; + } + } + + attribs._length = attribsCount ; + + return attribs ; + }, + + /** + * Checks is the element attributes have a perfect match with the style + * attributes. + */ + _CheckAttributesMatch : function( element, styleAttribs ) + { + // Loop through all specified attributes. The same number of + // attributes must be found and their values must match to + // declare them as equal. + + var elementAttrbs = element.attributes ; + var matchCount = 0 ; + + for ( var i = 0 ; i < elementAttrbs.length ; i++ ) + { + var att = elementAttrbs[i] ; + if ( att.specified ) + { + var attName = att.nodeName.toLowerCase() ; + var styleAtt = styleAttribs[ attName ] ; + + // The attribute is not defined in the style. + if ( !styleAtt ) + break ; + + // The values are different. + if ( styleAtt != FCKDomTools.GetAttributeValue( element, att ).toLowerCase() ) + break ; + + matchCount++ ; + } + } + + return ( matchCount == styleAttribs._length ) ; + } +} ; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbar.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbar.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbar.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,103 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKToolbar Class: represents a toolbar in the toolbarset. It is a group of + * toolbar items. + */ + +var FCKToolbar = function() +{ + this.Items = new Array() ; +} + +FCKToolbar.prototype.AddItem = function( item ) +{ + return this.Items[ this.Items.length ] = item ; +} + +FCKToolbar.prototype.AddButton = function( name, label, tooltip, iconPathOrStripInfoArrayOrIndex, style, state ) +{ + if ( typeof( iconPathOrStripInfoArrayOrIndex ) == 'number' ) + iconPathOrStripInfoArrayOrIndex = [ this.DefaultIconsStrip, this.DefaultIconSize, iconPathOrStripInfoArrayOrIndex ] ; + + var oButton = new FCKToolbarButtonUI( name, label, tooltip, iconPathOrStripInfoArrayOrIndex, style, state ) ; + oButton._FCKToolbar = this ; + oButton.OnClick = FCKToolbar_OnItemClick ; + + return this.AddItem( oButton ) ; +} + +function FCKToolbar_OnItemClick( item ) +{ + var oToolbar = item._FCKToolbar ; + + if ( oToolbar.OnItemClick ) + oToolbar.OnItemClick( oToolbar, item ) ; +} + +FCKToolbar.prototype.AddSeparator = function() +{ + this.AddItem( new FCKToolbarSeparator() ) ; +} + +FCKToolbar.prototype.Create = function( parentElement ) +{ + var oDoc = FCKTools.GetElementDocument( parentElement ) ; + + var e = oDoc.createElement( 'table' ) ; + e.className = 'TB_Toolbar' ; + e.style.styleFloat = e.style.cssFloat = ( FCKLang.Dir == 'ltr' ? 'left' : 'right' ) ; + e.dir = FCKLang.Dir ; + e.cellPadding = 0 ; + e.cellSpacing = 0 ; + + var targetRow = e.insertRow(-1) ; + + // Insert the start cell. + var eCell ; + + if ( !this.HideStart ) + { + eCell = targetRow.insertCell(-1) ; + eCell.appendChild( oDoc.createElement( 'div' ) ).className = 'TB_Start' ; + } + + for ( var i = 0 ; i < this.Items.length ; i++ ) + { + this.Items[i].Create( targetRow.insertCell(-1) ) ; + } + + // Insert the ending cell. + if ( !this.HideEnd ) + { + eCell = targetRow.insertCell(-1) ; + eCell.appendChild( oDoc.createElement( 'div' ) ).className = 'TB_End' ; + } + + parentElement.appendChild( e ) ; +} + +var FCKToolbarSeparator = function() +{} + +FCKToolbarSeparator.prototype.Create = function( parentElement ) +{ + FCKTools.AppendElement( parentElement, 'div' ).className = 'TB_Separator' ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarbreak_gecko.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarbreak_gecko.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarbreak_gecko.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,36 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKToolbarBreak Class: breaks the toolbars. + * It makes it possible to force the toolbar to break to a new line. + * This is the Gecko specific implementation. + */ + +var FCKToolbarBreak = function() +{} + +FCKToolbarBreak.prototype.Create = function( targetElement ) +{ + var oBreakDiv = targetElement.ownerDocument.createElement( 'div' ) ; + + oBreakDiv.style.clear = oBreakDiv.style.cssFloat = FCKLang.Dir == 'rtl' ? 'right' : 'left' ; + + targetElement.appendChild( oBreakDiv ) ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarbreak_ie.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarbreak_ie.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarbreak_ie.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,38 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKToolbarBreak Class: breaks the toolbars. + * It makes it possible to force the toolbar to break to a new line. + * This is the IE specific implementation. + */ + +var FCKToolbarBreak = function() +{} + +FCKToolbarBreak.prototype.Create = function( targetElement ) +{ + var oBreakDiv = FCKTools.GetElementDocument( targetElement ).createElement( 'div' ) ; + + oBreakDiv.className = 'TB_Break' ; + + oBreakDiv.style.clear = FCKLang.Dir == 'rtl' ? 'left' : 'right' ; + + targetElement.appendChild( oBreakDiv ) ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarbutton.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarbutton.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarbutton.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,81 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKToolbarButton Class: represents a button in the toolbar. + */ + +var FCKToolbarButton = function( commandName, label, tooltip, style, sourceView, contextSensitive, icon ) +{ + this.CommandName = commandName ; + this.Label = label ; + this.Tooltip = tooltip ; + this.Style = style ; + this.SourceView = sourceView ? true : false ; + this.ContextSensitive = contextSensitive ? true : false ; + + if ( icon == null ) + this.IconPath = FCKConfig.SkinPath + 'toolbar/' + commandName.toLowerCase() + '.gif' ; + else if ( typeof( icon ) == 'number' ) + this.IconPath = [ FCKConfig.SkinPath + 'fck_strip.gif', 16, icon ] ; + else + this.IconPath = icon ; +} + +FCKToolbarButton.prototype.Create = function( targetElement ) +{ + this._UIButton = new FCKToolbarButtonUI( this.CommandName, this.Label, this.Tooltip, this.IconPath, this.Style ) ; + this._UIButton.OnClick = this.Click ; + this._UIButton._ToolbarButton = this ; + this._UIButton.Create( targetElement ) ; +} + +FCKToolbarButton.prototype.RefreshState = function() +{ + var uiButton = this._UIButton ; + + if ( !uiButton ) + return ; + + // Gets the actual state. + var eState = FCK.ToolbarSet.CurrentInstance.Commands.GetCommand( this.CommandName ).GetState() ; + + // If there are no state changes than do nothing and return. + if ( eState == uiButton.State ) return ; + + // Sets the actual state. + uiButton.ChangeState( eState ) ; +} + +FCKToolbarButton.prototype.Click = function() +{ + var oToolbarButton = this._ToolbarButton || this ; + FCK.ToolbarSet.CurrentInstance.Commands.GetCommand( oToolbarButton.CommandName ).Execute() ; +} + +FCKToolbarButton.prototype.Enable = function() +{ + this.RefreshState() ; +} + +FCKToolbarButton.prototype.Disable = function() +{ + // Sets the actual state. + this._UIButton.ChangeState( FCK_TRISTATE_DISABLED ) ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarbuttonui.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarbuttonui.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarbuttonui.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,198 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKToolbarButtonUI Class: interface representation of a toolbar button. + */ + +var FCKToolbarButtonUI = function( name, label, tooltip, iconPathOrStripInfoArray, style, state ) +{ + this.Name = name ; + this.Label = label || name ; + this.Tooltip = tooltip || this.Label ; + this.Style = style || FCK_TOOLBARITEM_ONLYICON ; + this.State = state || FCK_TRISTATE_OFF ; + + this.Icon = new FCKIcon( iconPathOrStripInfoArray ) ; + + if ( FCK.IECleanup ) + FCK.IECleanup.AddItem( this, FCKToolbarButtonUI_Cleanup ) ; +} + + +FCKToolbarButtonUI.prototype._CreatePaddingElement = function( document ) +{ + var oImg = document.createElement( 'IMG' ) ; + oImg.className = 'TB_Button_Padding' ; + oImg.src = FCK_SPACER_PATH ; + return oImg ; +} + +FCKToolbarButtonUI.prototype.Create = function( parentElement ) +{ + var oDoc = FCKTools.GetElementDocument( parentElement ) ; + + // Create the Main Element. + var oMainElement = this.MainElement = oDoc.createElement( 'DIV' ) ; + oMainElement.title = this.Tooltip ; + + // The following will prevent the button from catching the focus. + if ( FCKBrowserInfo.IsGecko ) + oMainElement.onmousedown = FCKTools.CancelEvent ; + + FCKTools.AddEventListenerEx( oMainElement, 'mouseover', FCKToolbarButtonUI_OnMouseOver, this ) ; + FCKTools.AddEventListenerEx( oMainElement, 'mouseout', FCKToolbarButtonUI_OnMouseOut, this ) ; + FCKTools.AddEventListenerEx( oMainElement, 'click', FCKToolbarButtonUI_OnClick, this ) ; + + this.ChangeState( this.State, true ) ; + + if ( this.Style == FCK_TOOLBARITEM_ONLYICON && !this.ShowArrow ) + { + // <td><div class="TB_Button_On" title="Smiley">{Image}</div></td> + + oMainElement.appendChild( this.Icon.CreateIconElement( oDoc ) ) ; + } + else + { + // <td><div class="TB_Button_On" title="Smiley"><table cellpadding="0" cellspacing="0"><tr><td>{Image}</td><td nowrap>Toolbar Button</td><td><img class="TB_Button_Padding"></td></tr></table></div></td> + // <td><div class="TB_Button_On" title="Smiley"><table cellpadding="0" cellspacing="0"><tr><td><img class="TB_Button_Padding"></td><td nowrap>Toolbar Button</td><td><img class="TB_Button_Padding"></td></tr></table></div></td> + + var oTable = oMainElement.appendChild( oDoc.createElement( 'TABLE' ) ) ; + oTable.cellPadding = 0 ; + oTable.cellSpacing = 0 ; + + var oRow = oTable.insertRow(-1) ; + + // The Image cell (icon or padding). + var oCell = oRow.insertCell(-1) ; + + if ( this.Style == FCK_TOOLBARITEM_ONLYICON || this.Style == FCK_TOOLBARITEM_ICONTEXT ) + oCell.appendChild( this.Icon.CreateIconElement( oDoc ) ) ; + else + oCell.appendChild( this._CreatePaddingElement( oDoc ) ) ; + + if ( this.Style == FCK_TOOLBARITEM_ONLYTEXT || this.Style == FCK_TOOLBARITEM_ICONTEXT ) + { + // The Text cell. + oCell = oRow.insertCell(-1) ; + oCell.className = 'TB_Button_Text' ; + oCell.noWrap = true ; + oCell.appendChild( oDoc.createTextNode( this.Label ) ) ; + } + + if ( this.ShowArrow ) + { + if ( this.Style != FCK_TOOLBARITEM_ONLYICON ) + { + // A padding cell. + oRow.insertCell(-1).appendChild( this._CreatePaddingElement( oDoc ) ) ; + } + + oCell = oRow.insertCell(-1) ; + var eImg = oCell.appendChild( oDoc.createElement( 'IMG' ) ) ; + eImg.src = FCKConfig.SkinPath + 'images/toolbar.buttonarrow.gif' ; + eImg.width = 5 ; + eImg.height = 3 ; + } + + // The last padding cell. + oCell = oRow.insertCell(-1) ; + oCell.appendChild( this._CreatePaddingElement( oDoc ) ) ; + } + + parentElement.appendChild( oMainElement ) ; +} + +FCKToolbarButtonUI.prototype.ChangeState = function( newState, force ) +{ + if ( !force && this.State == newState ) + return ; + + var e = this.MainElement ; + + // In IE it can happen when the page is reloaded that MainElement is null, so exit here + if ( !e ) + return ; + + switch ( parseInt( newState, 10 ) ) + { + case FCK_TRISTATE_OFF : + e.className = 'TB_Button_Off' ; + break ; + + case FCK_TRISTATE_ON : + e.className = 'TB_Button_On' ; + break ; + + case FCK_TRISTATE_DISABLED : + e.className = 'TB_Button_Disabled' ; + break ; + } + + this.State = newState ; +} + +function FCKToolbarButtonUI_OnMouseOver( ev, button ) +{ + if ( button.State == FCK_TRISTATE_OFF ) + this.className = 'TB_Button_Off_Over' ; + else if ( button.State == FCK_TRISTATE_ON ) + this.className = 'TB_Button_On_Over' ; +} + +function FCKToolbarButtonUI_OnMouseOut( ev, button ) +{ + if ( button.State == FCK_TRISTATE_OFF ) + this.className = 'TB_Button_Off' ; + else if ( button.State == FCK_TRISTATE_ON ) + this.className = 'TB_Button_On' ; +} + +function FCKToolbarButtonUI_OnClick( ev, button ) +{ + if ( button.OnClick && button.State != FCK_TRISTATE_DISABLED ) + button.OnClick( button ) ; +} + +function FCKToolbarButtonUI_Cleanup() +{ + // This one should not cause memory leak, but just for safety, let's clean + // it up. + this.MainElement = null ; +} + +/* + Sample outputs: + + This is the base structure. The variation is the image that is marked as {Image}: + <td><div class="TB_Button_On" title="Smiley">{Image}</div></td> + <td><div class="TB_Button_On" title="Smiley"><table cellpadding="0" cellspacing="0"><tr><td>{Image}</td><td nowrap>Toolbar Button</td><td><img class="TB_Button_Padding"></td></tr></table></div></td> + <td><div class="TB_Button_On" title="Smiley"><table cellpadding="0" cellspacing="0"><tr><td><img class="TB_Button_Padding"></td><td nowrap>Toolbar Button</td><td><img class="TB_Button_Padding"></td></tr></table></div></td> + + These are samples of possible {Image} values: + + Strip - IE version: + <div class="TB_Button_Image"><img src="strip.gif" style="top:-16px"></div> + + Strip : Firefox, Safari and Opera version + <img class="TB_Button_Image" style="background-position: 0px -16px;background-image: url(strip.gif);"> + + No-Strip : Browser independent: + <img class="TB_Button_Image" src="smiley.gif"> +*/ Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarfontformatcombo.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarfontformatcombo.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarfontformatcombo.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,139 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKToolbarPanelButton Class: Handles the Fonts combo selector. + */ + +var FCKToolbarFontFormatCombo = function( tooltip, style ) +{ + if ( tooltip === false ) + return ; + + this.CommandName = 'FontFormat' ; + this.Label = this.GetLabel() ; + this.Tooltip = tooltip ? tooltip : this.Label ; + this.Style = style ? style : FCK_TOOLBARITEM_ICONTEXT ; + + this.NormalLabel = 'Normal' ; + + this.PanelWidth = 190 ; + + this.DefaultLabel = FCKConfig.DefaultFontFormatLabel || '' ; +} + +// Inherit from FCKToolbarSpecialCombo. +FCKToolbarFontFormatCombo.prototype = new FCKToolbarStyleCombo( false ) ; + +FCKToolbarFontFormatCombo.prototype.GetLabel = function() +{ + return FCKLang.FontFormat ; +} + +FCKToolbarFontFormatCombo.prototype.GetStyles = function() +{ + var styles = {} ; + + // Get the format names from the language file. + var aNames = FCKLang['FontFormats'].split(';') ; + var oNames = { + p : aNames[0], + pre : aNames[1], + address : aNames[2], + h1 : aNames[3], + h2 : aNames[4], + h3 : aNames[5], + h4 : aNames[6], + h5 : aNames[7], + h6 : aNames[8], + div : aNames[9] || ( aNames[0] + ' (DIV)') + } ; + + // Get the available formats from the configuration file. + var elements = FCKConfig.FontFormats.split(';') ; + + for ( var i = 0 ; i < elements.length ; i++ ) + { + var elementName = elements[ i ] ; + var style = FCKStyles.GetStyle( '_FCK_' + elementName ) ; + if ( style ) + { + style.Label = oNames[ elementName ] ; + styles[ '_FCK_' + elementName ] = style ; + } + else + alert( "The FCKConfig.CoreStyles['" + elementName + "'] setting was not found. Please check the fckconfig.js file" ) ; + } + + return styles ; +} + +FCKToolbarFontFormatCombo.prototype.RefreshActiveItems = function( targetSpecialCombo ) +{ + var startElement = FCK.ToolbarSet.CurrentInstance.Selection.GetBoundaryParentElement( true ) ; + + if ( startElement ) + { + var path = new FCKElementPath( startElement ) ; + var blockElement = path.Block ; + + if ( blockElement ) + { + for ( var i in targetSpecialCombo.Items ) + { + var item = targetSpecialCombo.Items[i] ; + var style = item.Style ; + + if ( style.CheckElementRemovable( blockElement ) ) + { + targetSpecialCombo.SetLabel( style.Label ) ; + return ; + } + } + } + } + + targetSpecialCombo.SetLabel( this.DefaultLabel ) ; +} + +FCKToolbarFontFormatCombo.prototype.StyleCombo_OnBeforeClick = function( targetSpecialCombo ) +{ + // Clear the current selection. + targetSpecialCombo.DeselectAll() ; + + var startElement = FCK.ToolbarSet.CurrentInstance.Selection.GetBoundaryParentElement( true ) ; + + if ( startElement ) + { + var path = new FCKElementPath( startElement ) ; + var blockElement = path.Block ; + + for ( var i in targetSpecialCombo.Items ) + { + var item = targetSpecialCombo.Items[i] ; + var style = item.Style ; + + if ( style.CheckElementRemovable( blockElement ) ) + { + targetSpecialCombo.SelectItem( item ) ; + return ; + } + } + } +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarfontscombo.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarfontscombo.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarfontscombo.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,98 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKToolbarPanelButton Class: Handles the Fonts combo selector. + */ + +var FCKToolbarFontsCombo = function( tooltip, style ) +{ + this.CommandName = 'FontName' ; + this.Label = this.GetLabel() ; + this.Tooltip = tooltip ? tooltip : this.Label ; + this.Style = style ? style : FCK_TOOLBARITEM_ICONTEXT ; + + this.DefaultLabel = FCKConfig.DefaultFontLabel || '' ; +} + +// Inherit from FCKToolbarSpecialCombo. +FCKToolbarFontsCombo.prototype = new FCKToolbarFontFormatCombo( false ) ; + +FCKToolbarFontsCombo.prototype.GetLabel = function() +{ + return FCKLang.Font ; +} + +FCKToolbarFontsCombo.prototype.GetStyles = function() +{ + var baseStyle = FCKStyles.GetStyle( '_FCK_FontFace' ) ; + + if ( !baseStyle ) + { + alert( "The FCKConfig.CoreStyles['Size'] setting was not found. Please check the fckconfig.js file" ) ; + return {} ; + } + + var styles = {} ; + + var fonts = FCKConfig.FontNames.split(';') ; + + for ( var i = 0 ; i < fonts.length ; i++ ) + { + var fontParts = fonts[i].split('/') ; + var font = fontParts[0] ; + var caption = fontParts[1] || font ; + + var style = FCKTools.CloneObject( baseStyle ) ; + + style.SetVariable( 'Font', font ) ; + style.Label = caption ; + + styles[ caption ] = style ; + } + + return styles ; +} + +FCKToolbarFontsCombo.prototype.RefreshActiveItems = FCKToolbarStyleCombo.prototype.RefreshActiveItems ; + +FCKToolbarFontsCombo.prototype.StyleCombo_OnBeforeClick = function( targetSpecialCombo ) +{ + // Clear the current selection. + targetSpecialCombo.DeselectAll() ; + + var startElement = FCKSelection.GetBoundaryParentElement( true ) ; + + if ( startElement ) + { + var path = new FCKElementPath( startElement ) ; + + for ( var i in targetSpecialCombo.Items ) + { + var item = targetSpecialCombo.Items[i] ; + var style = item.Style ; + + if ( style.CheckActive( path ) ) + { + targetSpecialCombo.SelectItem( item ) ; + return ; + } + } + } +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarfontsizecombo.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarfontsizecombo.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarfontsizecombo.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,76 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKToolbarPanelButton Class: Handles the Fonts combo selector. + */ + +var FCKToolbarFontSizeCombo = function( tooltip, style ) +{ + this.CommandName = 'FontSize' ; + this.Label = this.GetLabel() ; + this.Tooltip = tooltip ? tooltip : this.Label ; + this.Style = style ? style : FCK_TOOLBARITEM_ICONTEXT ; + + this.DefaultLabel = FCKConfig.DefaultFontSizeLabel || '' ; + + this.FieldWidth = 70 ; +} + +// Inherit from FCKToolbarSpecialCombo. +FCKToolbarFontSizeCombo.prototype = new FCKToolbarFontFormatCombo( false ) ; + +FCKToolbarFontSizeCombo.prototype.GetLabel = function() +{ + return FCKLang.FontSize ; +} + +FCKToolbarFontSizeCombo.prototype.GetStyles = function() +{ + var baseStyle = FCKStyles.GetStyle( '_FCK_Size' ) ; + + if ( !baseStyle ) + { + alert( "The FCKConfig.CoreStyles['FontFace'] setting was not found. Please check the fckconfig.js file" ) ; + return {} ; + } + + var styles = {} ; + + var fonts = FCKConfig.FontSizes.split(';') ; + + for ( var i = 0 ; i < fonts.length ; i++ ) + { + var fontParts = fonts[i].split('/') ; + var font = fontParts[0] ; + var caption = fontParts[1] || font ; + + var style = FCKTools.CloneObject( baseStyle ) ; + style.SetVariable( 'Size', font ) ; + style.Label = caption ; + + styles[ caption ] = style ; + } + + return styles ; +} + +FCKToolbarFontSizeCombo.prototype.RefreshActiveItems = FCKToolbarStyleCombo.prototype.RefreshActiveItems ; + +FCKToolbarFontSizeCombo.prototype.StyleCombo_OnBeforeClick = FCKToolbarFontsCombo.prototype.StyleCombo_OnBeforeClick ; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarpanelbutton.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarpanelbutton.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarpanelbutton.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,103 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKToolbarPanelButton Class: represents a special button in the toolbar + * that shows a panel when pressed. + */ + +var FCKToolbarPanelButton = function( commandName, label, tooltip, style, icon ) +{ + this.CommandName = commandName ; + + var oIcon ; + + if ( icon == null ) + oIcon = FCKConfig.SkinPath + 'toolbar/' + commandName.toLowerCase() + '.gif' ; + else if ( typeof( icon ) == 'number' ) + oIcon = [ FCKConfig.SkinPath + 'fck_strip.gif', 16, icon ] ; + + var oUIButton = this._UIButton = new FCKToolbarButtonUI( commandName, label, tooltip, oIcon, style ) ; + oUIButton._FCKToolbarPanelButton = this ; + oUIButton.ShowArrow = true ; + oUIButton.OnClick = FCKToolbarPanelButton_OnButtonClick ; +} + +FCKToolbarPanelButton.prototype.TypeName = 'FCKToolbarPanelButton' ; + +FCKToolbarPanelButton.prototype.Create = function( parentElement ) +{ + parentElement.className += 'Menu' ; + + this._UIButton.Create( parentElement ) ; + + var oPanel = FCK.ToolbarSet.CurrentInstance.Commands.GetCommand( this.CommandName )._Panel ; + this.RegisterPanel( oPanel ) ; +} + +FCKToolbarPanelButton.prototype.RegisterPanel = function( oPanel ) +{ + if ( oPanel._FCKToolbarPanelButton ) + return ; + + oPanel._FCKToolbarPanelButton = this ; + + var eLineDiv = oPanel.Document.body.appendChild( oPanel.Document.createElement( 'div' ) ) ; + eLineDiv.style.position = 'absolute' ; + eLineDiv.style.top = '0px' ; + + var eLine = oPanel._FCKToolbarPanelButtonLineDiv = eLineDiv.appendChild( oPanel.Document.createElement( 'IMG' ) ) ; + eLine.className = 'TB_ConnectionLine' ; + eLine.style.position = 'absolute' ; +// eLine.style.backgroundColor = 'Red' ; + eLine.src = FCK_SPACER_PATH ; + + oPanel.OnHide = FCKToolbarPanelButton_OnPanelHide ; +} + +/* + Events +*/ + +function FCKToolbarPanelButton_OnButtonClick( toolbarButton ) +{ + var oButton = this._FCKToolbarPanelButton ; + var e = oButton._UIButton.MainElement ; + + oButton._UIButton.ChangeState( FCK_TRISTATE_ON ) ; + + // oButton.LineImg.style.width = ( e.offsetWidth - 2 ) + 'px' ; + + var oCommand = FCK.ToolbarSet.CurrentInstance.Commands.GetCommand( oButton.CommandName ) ; + var oPanel = oCommand._Panel ; + oPanel._FCKToolbarPanelButtonLineDiv.style.width = ( e.offsetWidth - 2 ) + 'px' ; + oCommand.Execute( 0, e.offsetHeight - 1, e ) ; // -1 to be over the border +} + +function FCKToolbarPanelButton_OnPanelHide() +{ + var oMenuButton = this._FCKToolbarPanelButton ; + oMenuButton._UIButton.ChangeState( FCK_TRISTATE_OFF ) ; +} + +// The Panel Button works like a normal button so the refresh state functions +// defined for the normal button can be reused here. +FCKToolbarPanelButton.prototype.RefreshState = FCKToolbarButton.prototype.RefreshState ; +FCKToolbarPanelButton.prototype.Enable = FCKToolbarButton.prototype.Enable ; +FCKToolbarPanelButton.prototype.Disable = FCKToolbarButton.prototype.Disable ; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarspecialcombo.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarspecialcombo.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarspecialcombo.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,146 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKToolbarSpecialCombo Class: This is a "abstract" base class to be used + * by the special combo toolbar elements like font name, font size, paragraph format, etc... + * + * The following properties and methods must be implemented when inheriting from + * this class: + * - Property: CommandName [ The command name to be executed ] + * - Method: GetLabel() [ Returns the label ] + * - CreateItems( targetSpecialCombo ) [ Add all items in the special combo ] + */ + +var FCKToolbarSpecialCombo = function() +{ + this.SourceView = false ; + this.ContextSensitive = true ; + this.FieldWidth = null ; + this.PanelWidth = null ; + this.PanelMaxHeight = null ; + //this._LastValue = null ; +} + + +FCKToolbarSpecialCombo.prototype.DefaultLabel = '' ; + +function FCKToolbarSpecialCombo_OnSelect( itemId, item ) +{ + FCK.ToolbarSet.CurrentInstance.Commands.GetCommand( this.CommandName ).Execute( itemId, item ) ; +} + +FCKToolbarSpecialCombo.prototype.Create = function( targetElement ) +{ + this._Combo = new FCKSpecialCombo( this.GetLabel(), this.FieldWidth, this.PanelWidth, this.PanelMaxHeight, FCKBrowserInfo.IsIE ? window : FCKTools.GetElementWindow( targetElement ).parent ) ; + + /* + this._Combo.FieldWidth = this.FieldWidth != null ? this.FieldWidth : 100 ; + this._Combo.PanelWidth = this.PanelWidth != null ? this.PanelWidth : 150 ; + this._Combo.PanelMaxHeight = this.PanelMaxHeight != null ? this.PanelMaxHeight : 150 ; + */ + + //this._Combo.Command.Name = this.Command.Name; +// this._Combo.Label = this.Label ; + this._Combo.Tooltip = this.Tooltip ; + this._Combo.Style = this.Style ; + + this.CreateItems( this._Combo ) ; + + this._Combo.Create( targetElement ) ; + + this._Combo.CommandName = this.CommandName ; + + this._Combo.OnSelect = FCKToolbarSpecialCombo_OnSelect ; +} + +function FCKToolbarSpecialCombo_RefreshActiveItems( combo, value ) +{ + combo.DeselectAll() ; + combo.SelectItem( value ) ; + combo.SetLabelById( value ) ; +} + +FCKToolbarSpecialCombo.prototype.RefreshState = function() +{ + // Gets the actual state. + var eState ; + +// if ( FCK.EditMode == FCK_EDITMODE_SOURCE && ! this.SourceView ) +// eState = FCK_TRISTATE_DISABLED ; +// else +// { + var sValue = FCK.ToolbarSet.CurrentInstance.Commands.GetCommand( this.CommandName ).GetState() ; + +// FCKDebug.Output( 'RefreshState of Special Combo "' + this.TypeOf + '" - State: ' + sValue ) ; + + if ( sValue != FCK_TRISTATE_DISABLED ) + { + eState = FCK_TRISTATE_ON ; + + if ( this.RefreshActiveItems ) + this.RefreshActiveItems( this._Combo, sValue ) ; + else + { + if ( this._LastValue !== sValue) + { + this._LastValue = sValue ; + + if ( !sValue || sValue.length == 0 ) + { + this._Combo.DeselectAll() ; + this._Combo.SetLabel( this.DefaultLabel ) ; + } + else + FCKToolbarSpecialCombo_RefreshActiveItems( this._Combo, sValue ) ; + } + } + } + else + eState = FCK_TRISTATE_DISABLED ; +// } + + // If there are no state changes then do nothing and return. + if ( eState == this.State ) return ; + + if ( eState == FCK_TRISTATE_DISABLED ) + { + this._Combo.DeselectAll() ; + this._Combo.SetLabel( '' ) ; + } + + // Sets the actual state. + this.State = eState ; + + // Updates the graphical state. + this._Combo.SetEnabled( eState != FCK_TRISTATE_DISABLED ) ; +} + +FCKToolbarSpecialCombo.prototype.Enable = function() +{ + this.RefreshState() ; +} + +FCKToolbarSpecialCombo.prototype.Disable = function() +{ + this.State = FCK_TRISTATE_DISABLED ; + this._Combo.DeselectAll() ; + this._Combo.SetLabel( '' ) ; + this._Combo.SetEnabled( false ) ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarstylecombo.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarstylecombo.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fcktoolbarstylecombo.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,200 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKToolbarPanelButton Class: Handles the Fonts combo selector. + */ + +var FCKToolbarStyleCombo = function( tooltip, style ) +{ + if ( tooltip === false ) + return ; + + this.CommandName = 'Style' ; + this.Label = this.GetLabel() ; + this.Tooltip = tooltip ? tooltip : this.Label ; + this.Style = style ? style : FCK_TOOLBARITEM_ICONTEXT ; + + this.DefaultLabel = FCKConfig.DefaultStyleLabel || '' ; +} + +// Inherit from FCKToolbarSpecialCombo. +FCKToolbarStyleCombo.prototype = new FCKToolbarSpecialCombo ; + +FCKToolbarStyleCombo.prototype.GetLabel = function() +{ + return FCKLang.Style ; +} + +FCKToolbarStyleCombo.prototype.GetStyles = function() +{ + var styles = {} ; + var allStyles = FCK.ToolbarSet.CurrentInstance.Styles.GetStyles() ; + + for ( var styleName in allStyles ) + { + var style = allStyles[ styleName ] ; + if ( !style.IsCore ) + styles[ styleName ] = style ; + } + return styles ; +} + +FCKToolbarStyleCombo.prototype.CreateItems = function( targetSpecialCombo ) +{ + var targetDoc = targetSpecialCombo._Panel.Document ; + + // Add the Editor Area CSS to the panel so the style classes are previewed correctly. + FCKTools.AppendStyleSheet( targetDoc, FCKConfig.ToolbarComboPreviewCSS ) ; + FCKTools.AppendStyleString( targetDoc, FCKConfig.EditorAreaStyles ) ; + targetDoc.body.className += ' ForceBaseFont' ; + + // Add ID and Class to the body. + FCKConfig.ApplyBodyAttributes( targetDoc.body ) ; + + // Get the styles list. + var styles = this.GetStyles() ; + + for ( var styleName in styles ) + { + var style = styles[ styleName ] ; + + // Object type styles have no preview. + var caption = style.GetType() == FCK_STYLE_OBJECT ? + styleName : + FCKToolbarStyleCombo_BuildPreview( style, style.Label || styleName ) ; + + var item = targetSpecialCombo.AddItem( styleName, caption ) ; + + item.Style = style ; + } + + // We must prepare the list before showing it. + targetSpecialCombo.OnBeforeClick = this.StyleCombo_OnBeforeClick ; +} + +FCKToolbarStyleCombo.prototype.RefreshActiveItems = function( targetSpecialCombo ) +{ + var startElement = FCK.ToolbarSet.CurrentInstance.Selection.GetBoundaryParentElement( true ) ; + + if ( startElement ) + { + var path = new FCKElementPath( startElement ) ; + var elements = path.Elements ; + + for ( var e = 0 ; e < elements.length ; e++ ) + { + for ( var i in targetSpecialCombo.Items ) + { + var item = targetSpecialCombo.Items[i] ; + var style = item.Style ; + + if ( style.CheckElementRemovable( elements[ e ], true ) ) + { + targetSpecialCombo.SetLabel( style.Label || style.Name ) ; + return ; + } + } + } + } + + targetSpecialCombo.SetLabel( this.DefaultLabel ) ; +} + +FCKToolbarStyleCombo.prototype.StyleCombo_OnBeforeClick = function( targetSpecialCombo ) +{ + // Two things are done here: + // - In a control selection, get the element name, so we'll display styles + // for that element only. + // - Select the styles that are active for the current selection. + + // Clear the current selection. + targetSpecialCombo.DeselectAll() ; + + var startElement ; + var path ; + var tagName ; + + var selection = FCK.ToolbarSet.CurrentInstance.Selection ; + + if ( selection.GetType() == 'Control' ) + { + startElement = selection.GetSelectedElement() ; + tagName = startElement.nodeName.toLowerCase() ; + } + else + { + startElement = selection.GetBoundaryParentElement( true ) ; + path = new FCKElementPath( startElement ) ; + } + + for ( var i in targetSpecialCombo.Items ) + { + var item = targetSpecialCombo.Items[i] ; + var style = item.Style ; + + if ( ( tagName && style.Element == tagName ) || ( !tagName && style.GetType() != FCK_STYLE_OBJECT ) ) + { + item.style.display = '' ; + + if ( ( path && style.CheckActive( path ) ) || ( !path && style.CheckElementRemovable( startElement, true ) ) ) + targetSpecialCombo.SelectItem( style.Name ) ; + } + else + item.style.display = 'none' ; + } +} + +function FCKToolbarStyleCombo_BuildPreview( style, caption ) +{ + var styleType = style.GetType() ; + var html = [] ; + + if ( styleType == FCK_STYLE_BLOCK ) + html.push( '<div class="BaseFont">' ) ; + + var elementName = style.Element ; + + // Avoid <bdo> in the preview. + if ( elementName == 'bdo' ) + elementName = 'span' ; + + html = [ '<', elementName ] ; + + // Assign all defined attributes. + var attribs = style._StyleDesc.Attributes ; + if ( attribs ) + { + for ( var att in attribs ) + { + html.push( ' ', att, '="', style.GetFinalAttributeValue( att ), '"' ) ; + } + } + + // Assign the style attribute. + if ( style._GetStyleText().length > 0 ) + html.push( ' style="', style.GetFinalStyleValue(), '"' ) ; + + html.push( '>', caption, '</', elementName, '>' ) ; + + if ( styleType == FCK_STYLE_BLOCK ) + html.push( '</div>' ) ; + + return html.join( '' ) ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckw3crange.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckw3crange.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckw3crange.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,451 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * This class partially implements the W3C DOM Range for browser that don't + * support the standards (like IE): + * http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html + */ + +var FCKW3CRange = function( parentDocument ) +{ + this._Document = parentDocument ; + + this.startContainer = null ; + this.startOffset = null ; + this.endContainer = null ; + this.endOffset = null ; + this.collapsed = true ; +} + +FCKW3CRange.CreateRange = function( parentDocument ) +{ + // We could opt to use the Range implementation of the browsers. The problem + // is that every browser have different bugs on their implementations, + // mostly related to different interpretations of the W3C specifications. + // So, for now, let's use our implementation and pray for browsers fixings + // soon. Otherwise will go crazy on trying to find out workarounds. + /* + // Get the browser implementation of the range, if available. + if ( parentDocument.createRange ) + { + var range = parentDocument.createRange() ; + if ( typeof( range.startContainer ) != 'undefined' ) + return range ; + } + */ + return new FCKW3CRange( parentDocument ) ; +} + +FCKW3CRange.CreateFromRange = function( parentDocument, sourceRange ) +{ + var range = FCKW3CRange.CreateRange( parentDocument ) ; + range.setStart( sourceRange.startContainer, sourceRange.startOffset ) ; + range.setEnd( sourceRange.endContainer, sourceRange.endOffset ) ; + return range ; +} + +FCKW3CRange.prototype = +{ + + _UpdateCollapsed : function() + { + this.collapsed = ( this.startContainer == this.endContainer && this.startOffset == this.endOffset ) ; + }, + + // W3C requires a check for the new position. If it is after the end + // boundary, the range should be collapsed to the new start. It seams we + // will not need this check for our use of this class so we can ignore it for now. + setStart : function( refNode, offset ) + { + this.startContainer = refNode ; + this.startOffset = offset ; + + if ( !this.endContainer ) + { + this.endContainer = refNode ; + this.endOffset = offset ; + } + + this._UpdateCollapsed() ; + }, + + // W3C requires a check for the new position. If it is before the start + // boundary, the range should be collapsed to the new end. It seams we + // will not need this check for our use of this class so we can ignore it for now. + setEnd : function( refNode, offset ) + { + this.endContainer = refNode ; + this.endOffset = offset ; + + if ( !this.startContainer ) + { + this.startContainer = refNode ; + this.startOffset = offset ; + } + + this._UpdateCollapsed() ; + }, + + setStartAfter : function( refNode ) + { + this.setStart( refNode.parentNode, FCKDomTools.GetIndexOf( refNode ) + 1 ) ; + }, + + setStartBefore : function( refNode ) + { + this.setStart( refNode.parentNode, FCKDomTools.GetIndexOf( refNode ) ) ; + }, + + setEndAfter : function( refNode ) + { + this.setEnd( refNode.parentNode, FCKDomTools.GetIndexOf( refNode ) + 1 ) ; + }, + + setEndBefore : function( refNode ) + { + this.setEnd( refNode.parentNode, FCKDomTools.GetIndexOf( refNode ) ) ; + }, + + collapse : function( toStart ) + { + if ( toStart ) + { + this.endContainer = this.startContainer ; + this.endOffset = this.startOffset ; + } + else + { + this.startContainer = this.endContainer ; + this.startOffset = this.endOffset ; + } + + this.collapsed = true ; + }, + + selectNodeContents : function( refNode ) + { + this.setStart( refNode, 0 ) ; + this.setEnd( refNode, refNode.nodeType == 3 ? refNode.data.length : refNode.childNodes.length ) ; + }, + + insertNode : function( newNode ) + { + var startContainer = this.startContainer ; + var startOffset = this.startOffset ; + + // If we are in a text node. + if ( startContainer.nodeType == 3 ) + { + startContainer.splitText( startOffset ) ; + + // Check if it is necessary to update the end boundary. + if ( startContainer == this.endContainer ) + this.setEnd( startContainer.nextSibling, this.endOffset - this.startOffset ) ; + + // Insert the new node it after the text node. + FCKDomTools.InsertAfterNode( startContainer, newNode ) ; + + return ; + } + else + { + // Simply insert the new node before the current start node. + startContainer.insertBefore( newNode, startContainer.childNodes[ startOffset ] || null ) ; + + // Check if it is necessary to update the end boundary. + if ( startContainer == this.endContainer ) + { + this.endOffset++ ; + this.collapsed = false ; + } + } + }, + + deleteContents : function() + { + if ( this.collapsed ) + return ; + + this._ExecContentsAction( 0 ) ; + }, + + extractContents : function() + { + var docFrag = new FCKDocumentFragment( this._Document ) ; + + if ( !this.collapsed ) + this._ExecContentsAction( 1, docFrag ) ; + + return docFrag ; + }, + + // The selection may be lost when cloning (due to the splitText() call). + cloneContents : function() + { + var docFrag = new FCKDocumentFragment( this._Document ) ; + + if ( !this.collapsed ) + this._ExecContentsAction( 2, docFrag ) ; + + return docFrag ; + }, + + _ExecContentsAction : function( action, docFrag ) + { + var startNode = this.startContainer ; + var endNode = this.endContainer ; + + var startOffset = this.startOffset ; + var endOffset = this.endOffset ; + + var removeStartNode = false ; + var removeEndNode = false ; + + // Check the start and end nodes and make the necessary removals or changes. + + // Start from the end, otherwise DOM mutations (splitText) made in the + // start boundary may interfere on the results here. + + // For text containers, we must simply split the node and point to the + // second part. The removal will be handled by the rest of the code . + if ( endNode.nodeType == 3 ) + endNode = endNode.splitText( endOffset ) ; + else + { + // If the end container has children and the offset is pointing + // to a child, then we should start from it. + if ( endNode.childNodes.length > 0 ) + { + // If the offset points after the last node. + if ( endOffset > endNode.childNodes.length - 1 ) + { + // Let's create a temporary node and mark it for removal. + endNode = FCKDomTools.InsertAfterNode( endNode.lastChild, this._Document.createTextNode('') ) ; + removeEndNode = true ; + } + else + endNode = endNode.childNodes[ endOffset ] ; + } + } + + // For text containers, we must simply split the node. The removal will + // be handled by the rest of the code . + if ( startNode.nodeType == 3 ) + { + startNode.splitText( startOffset ) ; + + // In cases the end node is the same as the start node, the above + // splitting will also split the end, so me must move the end to + // the second part of the split. + if ( startNode == endNode ) + endNode = startNode.nextSibling ; + } + else + { + // If the start container has children and the offset is pointing + // to a child, then we should start from its previous sibling. + + // If the offset points to the first node, we don't have a + // sibling, so let's use the first one, but mark it for removal. + if ( startOffset == 0 ) + { + // Let's create a temporary node and mark it for removal. + startNode = startNode.insertBefore( this._Document.createTextNode(''), startNode.firstChild ) ; + removeStartNode = true ; + } + else if ( startOffset > startNode.childNodes.length - 1 ) + { + // Let's create a temporary node and mark it for removal. + startNode = startNode.appendChild( this._Document.createTextNode('') ) ; + removeStartNode = true ; + } + else + startNode = startNode.childNodes[ startOffset ].previousSibling ; + } + + // Get the parent nodes tree for the start and end boundaries. + var startParents = FCKDomTools.GetParents( startNode ) ; + var endParents = FCKDomTools.GetParents( endNode ) ; + + // Compare them, to find the top most siblings. + var i, topStart, topEnd ; + + for ( i = 0 ; i < startParents.length ; i++ ) + { + topStart = startParents[i] ; + topEnd = endParents[i] ; + + // The compared nodes will match until we find the top most + // siblings (different nodes that have the same parent). + // "i" will hold the index in the parents array for the top + // most element. + if ( topStart != topEnd ) + break ; + } + + var clone, levelStartNode, levelClone, currentNode, currentSibling ; + + if ( docFrag ) + clone = docFrag.RootNode ; + + // Remove all successive sibling nodes for every node in the + // startParents tree. + for ( var j = i ; j < startParents.length ; j++ ) + { + levelStartNode = startParents[j] ; + + // For Extract and Clone, we must clone this level. + if ( clone && levelStartNode != startNode ) // action = 0 = Delete + levelClone = clone.appendChild( levelStartNode.cloneNode( levelStartNode == startNode ) ) ; + + currentNode = levelStartNode.nextSibling ; + + while( currentNode ) + { + // Stop processing when the current node matches a node in the + // endParents tree or if it is the endNode. + if ( currentNode == endParents[j] || currentNode == endNode ) + break ; + + // Cache the next sibling. + currentSibling = currentNode.nextSibling ; + + // If cloning, just clone it. + if ( action == 2 ) // 2 = Clone + clone.appendChild( currentNode.cloneNode( true ) ) ; + else + { + // Both Delete and Extract will remove the node. + currentNode.parentNode.removeChild( currentNode ) ; + + // When Extracting, move the removed node to the docFrag. + if ( action == 1 ) // 1 = Extract + clone.appendChild( currentNode ) ; + } + + currentNode = currentSibling ; + } + + if ( clone ) + clone = levelClone ; + } + + if ( docFrag ) + clone = docFrag.RootNode ; + + // Remove all previous sibling nodes for every node in the + // endParents tree. + for ( var k = i ; k < endParents.length ; k++ ) + { + levelStartNode = endParents[k] ; + + // For Extract and Clone, we must clone this level. + if ( action > 0 && levelStartNode != endNode ) // action = 0 = Delete + levelClone = clone.appendChild( levelStartNode.cloneNode( levelStartNode == endNode ) ) ; + + // The processing of siblings may have already been done by the parent. + if ( !startParents[k] || levelStartNode.parentNode != startParents[k].parentNode ) + { + currentNode = levelStartNode.previousSibling ; + + while( currentNode ) + { + // Stop processing when the current node matches a node in the + // startParents tree or if it is the startNode. + if ( currentNode == startParents[k] || currentNode == startNode ) + break ; + + // Cache the next sibling. + currentSibling = currentNode.previousSibling ; + + // If cloning, just clone it. + if ( action == 2 ) // 2 = Clone + clone.insertBefore( currentNode.cloneNode( true ), clone.firstChild ) ; + else + { + // Both Delete and Extract will remove the node. + currentNode.parentNode.removeChild( currentNode ) ; + + // When Extracting, mode the removed node to the docFrag. + if ( action == 1 ) // 1 = Extract + clone.insertBefore( currentNode, clone.firstChild ) ; + } + + currentNode = currentSibling ; + } + } + + if ( clone ) + clone = levelClone ; + } + + if ( action == 2 ) // 2 = Clone. + { + // No changes in the DOM should be done, so fix the split text (if any). + + var startTextNode = this.startContainer ; + if ( startTextNode.nodeType == 3 ) + { + startTextNode.data += startTextNode.nextSibling.data ; + startTextNode.parentNode.removeChild( startTextNode.nextSibling ) ; + } + + var endTextNode = this.endContainer ; + if ( endTextNode.nodeType == 3 && endTextNode.nextSibling ) + { + endTextNode.data += endTextNode.nextSibling.data ; + endTextNode.parentNode.removeChild( endTextNode.nextSibling ) ; + } + } + else + { + // Collapse the range. + + // If a node has been partially selected, collapse the range between + // topStart and topEnd. Otherwise, simply collapse it to the start. (W3C specs). + if ( topStart && topEnd && ( startNode.parentNode != topStart.parentNode || endNode.parentNode != topEnd.parentNode ) ) + { + var endIndex = FCKDomTools.GetIndexOf( topEnd ) ; + + // If the start node is to be removed, we must correct the + // index to reflect the removal. + if ( removeStartNode && topEnd.parentNode == startNode.parentNode ) + endIndex-- ; + + this.setStart( topEnd.parentNode, endIndex ) ; + } + + // Collapse it to the start. + this.collapse( true ) ; + } + + // Cleanup any marked node. + if( removeStartNode ) + startNode.parentNode.removeChild( startNode ) ; + + if( removeEndNode && endNode.parentNode ) + endNode.parentNode.removeChild( endNode ) ; + }, + + cloneRange : function() + { + return FCKW3CRange.CreateFromRange( this._Document, this ) ; + } +} ; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckxml.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckxml.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckxml.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,108 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKXml Class: class to load and manipulate XML files. + * (IE specific implementation) + */ + +var FCKXml = function() +{ + this.Error = false ; +} + +FCKXml.GetAttribute = function( node, attName, defaultValue ) +{ + var attNode = node.attributes.getNamedItem( attName ) ; + return attNode ? attNode.value : defaultValue ; +} + +/** + * Transforms a XML element node in a JavaScript object. Attributes defined for + * the element will be available as properties, as long as child element + * nodes, but the later will generate arrays with property names prefixed with "$". + * + * For example, the following XML element: + * + * <SomeNode name="Test" key="2"> + * <MyChild id="10"> + * <OtherLevel name="Level 3" /> + * </MyChild> + * <MyChild id="25" /> + * <AnotherChild price="499" /> + * </SomeNode> + * + * ... results in the following object: + * + * { + * name : "Test", + * key : "2", + * $MyChild : + * [ + * { + * id : "10", + * $OtherLevel : + * { + * name : "Level 3" + * } + * }, + * { + * id : "25" + * } + * ], + * $AnotherChild : + * [ + * { + * price : "499" + * } + * ] + * } + */ +FCKXml.TransformToObject = function( element ) +{ + if ( !element ) + return null ; + + var obj = {} ; + + var attributes = element.attributes ; + for ( var i = 0 ; i < attributes.length ; i++ ) + { + var att = attributes[i] ; + obj[ att.name ] = att.value ; + } + + var childNodes = element.childNodes ; + for ( i = 0 ; i < childNodes.length ; i++ ) + { + var child = childNodes[i] ; + + if ( child.nodeType == 1 ) + { + var childName = '$' + child.nodeName ; + var childList = obj[ childName ] ; + if ( !childList ) + childList = obj[ childName ] = [] ; + + childList.push( this.TransformToObject( child ) ) ; + } + } + + return obj ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckxml_gecko.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckxml_gecko.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckxml_gecko.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,102 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKXml Class: class to load and manipulate XML files. + */ + +FCKXml.prototype = +{ + LoadUrl : function( urlToCall ) + { + this.Error = false ; + + var oXml ; + var oXmlHttp = FCKTools.CreateXmlObject( 'XmlHttp' ) ; + oXmlHttp.open( 'GET', urlToCall, false ) ; + oXmlHttp.send( null ) ; + + if ( oXmlHttp.status == 200 || oXmlHttp.status == 304 ) + oXml = oXmlHttp.responseXML ; + else if ( oXmlHttp.status == 0 && oXmlHttp.readyState == 4 ) + oXml = oXmlHttp.responseXML ; + else + oXml = null ; + + if ( oXml ) + { + // Try to access something on it. + try + { + var test = oXml.firstChild ; + } + catch (e) + { + // If document.domain has been changed (#123), we'll have a security + // error at this point. The workaround here is parsing the responseText: + // http://alexander.kirk.at/2006/07/27/firefox-15-xmlhttprequest-reqresponsexml... + oXml = (new DOMParser()).parseFromString( oXmlHttp.responseText, 'text/xml' ) ; + } + } + + if ( !oXml || !oXml.firstChild ) + { + this.Error = true ; + if ( window.confirm( 'Error loading "' + urlToCall + '" (HTTP Status: ' + oXmlHttp.status + ').\r\nDo you want to see the server response dump?' ) ) + alert( oXmlHttp.responseText ) ; + } + + this.DOMDocument = oXml ; + }, + + SelectNodes : function( xpath, contextNode ) + { + if ( this.Error ) + return new Array() ; + + var aNodeArray = new Array(); + + var xPathResult = this.DOMDocument.evaluate( xpath, contextNode ? contextNode : this.DOMDocument, + this.DOMDocument.createNSResolver(this.DOMDocument.documentElement), XPathResult.ORDERED_NODE_ITERATOR_TYPE, null) ; + if ( xPathResult ) + { + var oNode = xPathResult.iterateNext() ; + while( oNode ) + { + aNodeArray[aNodeArray.length] = oNode ; + oNode = xPathResult.iterateNext(); + } + } + return aNodeArray ; + }, + + SelectSingleNode : function( xpath, contextNode ) + { + if ( this.Error ) + return null ; + + var xPathResult = this.DOMDocument.evaluate( xpath, contextNode ? contextNode : this.DOMDocument, + this.DOMDocument.createNSResolver(this.DOMDocument.documentElement), 9, null); + + if ( xPathResult && xPathResult.singleNodeValue ) + return xPathResult.singleNodeValue ; + else + return null ; + } +} ; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckxml_ie.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckxml_ie.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/classes/fckxml_ie.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,88 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKXml Class: class to load and manipulate XML files. + * (IE specific implementation) + */ + +FCKXml.prototype = +{ + LoadUrl : function( urlToCall ) + { + this.Error = false ; + + var oXmlHttp = FCKTools.CreateXmlObject( 'XmlHttp' ) ; + + if ( !oXmlHttp ) + { + this.Error = true ; + return ; + } + + oXmlHttp.open( "GET", urlToCall, false ) ; + + oXmlHttp.send( null ) ; + + if ( oXmlHttp.status == 200 || oXmlHttp.status == 304 ) + this.DOMDocument = oXmlHttp.responseXML ; + else if ( oXmlHttp.status == 0 && oXmlHttp.readyState == 4 ) + { + this.DOMDocument = FCKTools.CreateXmlObject( 'DOMDocument' ) ; + this.DOMDocument.async = false ; + this.DOMDocument.resolveExternals = false ; + this.DOMDocument.loadXML( oXmlHttp.responseText ) ; + } + else + { + this.DOMDocument = null ; + } + + if ( this.DOMDocument == null || this.DOMDocument.firstChild == null ) + { + this.Error = true ; + if (window.confirm( 'Error loading "' + urlToCall + '"\r\nDo you want to see more info?' ) ) + alert( 'URL requested: "' + urlToCall + '"\r\n' + + 'Server response:\r\nStatus: ' + oXmlHttp.status + '\r\n' + + 'Response text:\r\n' + oXmlHttp.responseText ) ; + } + }, + + SelectNodes : function( xpath, contextNode ) + { + if ( this.Error ) + return new Array() ; + + if ( contextNode ) + return contextNode.selectNodes( xpath ) ; + else + return this.DOMDocument.selectNodes( xpath ) ; + }, + + SelectSingleNode : function( xpath, contextNode ) + { + if ( this.Error ) + return null ; + + if ( contextNode ) + return contextNode.selectSingleNode( xpath ) ; + else + return this.DOMDocument.selectSingleNode( xpath ) ; + } +} ; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fck_othercommands.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fck_othercommands.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fck_othercommands.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,518 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Definition of other commands that are not available internaly in the + * browser (see FCKNamedCommand). + */ + +// ### General Dialog Box Commands. +var FCKDialogCommand = function( name, title, url, width, height, getStateFunction, getStateParam, customValue ) +{ + this.Name = name ; + this.Title = title ; + this.Url = url ; + this.Width = width ; + this.Height = height ; + this.CustomValue = customValue ; + + this.GetStateFunction = getStateFunction ; + this.GetStateParam = getStateParam ; + + this.Resizable = false ; +} + +FCKDialogCommand.prototype.Execute = function() +{ + FCKDialog.OpenDialog( 'FCKDialog_' + this.Name , this.Title, this.Url, this.Width, this.Height, this.CustomValue, null, this.Resizable ) ; +} + +FCKDialogCommand.prototype.GetState = function() +{ + if ( this.GetStateFunction ) + return this.GetStateFunction( this.GetStateParam ) ; + else + return FCK.EditMode == FCK_EDITMODE_WYSIWYG ? FCK_TRISTATE_OFF : FCK_TRISTATE_DISABLED ; +} + +// Generic Undefined command (usually used when a command is under development). +var FCKUndefinedCommand = function() +{ + this.Name = 'Undefined' ; +} + +FCKUndefinedCommand.prototype.Execute = function() +{ + alert( FCKLang.NotImplemented ) ; +} + +FCKUndefinedCommand.prototype.GetState = function() +{ + return FCK_TRISTATE_OFF ; +} + + +// ### FormatBlock +var FCKFormatBlockCommand = function() +{} + +FCKFormatBlockCommand.prototype = +{ + Name : 'FormatBlock', + + Execute : FCKStyleCommand.prototype.Execute, + + GetState : function() + { + return FCK.EditorDocument ? FCK_TRISTATE_OFF : FCK_TRISTATE_DISABLED ; + } +}; + +// ### FontName + +var FCKFontNameCommand = function() +{} + +FCKFontNameCommand.prototype = +{ + Name : 'FontName', + Execute : FCKStyleCommand.prototype.Execute, + GetState : FCKFormatBlockCommand.prototype.GetState +}; + +// ### FontSize +var FCKFontSizeCommand = function() +{} + +FCKFontSizeCommand.prototype = +{ + Name : 'FontSize', + Execute : FCKStyleCommand.prototype.Execute, + GetState : FCKFormatBlockCommand.prototype.GetState +}; + +// ### Preview +var FCKPreviewCommand = function() +{ + this.Name = 'Preview' ; +} + +FCKPreviewCommand.prototype.Execute = function() +{ + FCK.Preview() ; +} + +FCKPreviewCommand.prototype.GetState = function() +{ + return FCK_TRISTATE_OFF ; +} + +// ### Save +var FCKSaveCommand = function() +{ + this.Name = 'Save' ; +} + +FCKSaveCommand.prototype.Execute = function() +{ + // Get the linked field form. + var oForm = FCK.GetParentForm() ; + + if ( typeof( oForm.onsubmit ) == 'function' ) + { + var bRet = oForm.onsubmit() ; + if ( bRet != null && bRet === false ) + return ; + } + + // Submit the form. + // If there's a button named "submit" then the form.submit() function is masked and + // can't be called in Mozilla, so we call the click() method of that button. + if ( typeof( oForm.submit ) == 'function' ) + oForm.submit() ; + else + oForm.submit.click() ; +} + +FCKSaveCommand.prototype.GetState = function() +{ + return FCK_TRISTATE_OFF ; +} + +// ### NewPage +var FCKNewPageCommand = function() +{ + this.Name = 'NewPage' ; +} + +FCKNewPageCommand.prototype.Execute = function() +{ + FCKUndo.SaveUndoStep() ; + FCK.SetData( '' ) ; + FCKUndo.Typing = true ; + FCK.Focus() ; +} + +FCKNewPageCommand.prototype.GetState = function() +{ + return FCK_TRISTATE_OFF ; +} + +// ### Source button +var FCKSourceCommand = function() +{ + this.Name = 'Source' ; +} + +FCKSourceCommand.prototype.Execute = function() +{ + if ( FCKConfig.SourcePopup ) // Until v2.2, it was mandatory for FCKBrowserInfo.IsGecko. + { + var iWidth = FCKConfig.ScreenWidth * 0.65 ; + var iHeight = FCKConfig.ScreenHeight * 0.65 ; + FCKDialog.OpenDialog( 'FCKDialog_Source', FCKLang.Source, 'dialog/fck_source.html', iWidth, iHeight, null, null, true ) ; + } + else + FCK.SwitchEditMode() ; +} + +FCKSourceCommand.prototype.GetState = function() +{ + return ( FCK.EditMode == FCK_EDITMODE_WYSIWYG ? FCK_TRISTATE_OFF : FCK_TRISTATE_ON ) ; +} + +// ### Undo +var FCKUndoCommand = function() +{ + this.Name = 'Undo' ; +} + +FCKUndoCommand.prototype.Execute = function() +{ + FCKUndo.Undo() ; +} + +FCKUndoCommand.prototype.GetState = function() +{ + if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG ) + return FCK_TRISTATE_DISABLED ; + return ( FCKUndo.CheckUndoState() ? FCK_TRISTATE_OFF : FCK_TRISTATE_DISABLED ) ; +} + +// ### Redo +var FCKRedoCommand = function() +{ + this.Name = 'Redo' ; +} + +FCKRedoCommand.prototype.Execute = function() +{ + FCKUndo.Redo() ; +} + +FCKRedoCommand.prototype.GetState = function() +{ + if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG ) + return FCK_TRISTATE_DISABLED ; + return ( FCKUndo.CheckRedoState() ? FCK_TRISTATE_OFF : FCK_TRISTATE_DISABLED ) ; +} + +// ### Page Break +var FCKPageBreakCommand = function() +{ + this.Name = 'PageBreak' ; +} + +FCKPageBreakCommand.prototype.Execute = function() +{ + // Take an undo snapshot before changing the document + FCKUndo.SaveUndoStep() ; + +// var e = FCK.EditorDocument.createElement( 'CENTER' ) ; +// e.style.pageBreakAfter = 'always' ; + + // Tidy was removing the empty CENTER tags, so the following solution has + // been found. It also validates correctly as XHTML 1.0 Strict. + var e = FCK.EditorDocument.createElement( 'DIV' ) ; + e.style.pageBreakAfter = 'always' ; + e.innerHTML = '<span style="DISPLAY:none"> </span>' ; + + var oFakeImage = FCKDocumentProcessor_CreateFakeImage( 'FCK__PageBreak', e ) ; + var oRange = new FCKDomRange( FCK.EditorWindow ) ; + oRange.MoveToSelection() ; + var oSplitInfo = oRange.SplitBlock() ; + oRange.InsertNode( oFakeImage ) ; + + FCK.Events.FireEvent( 'OnSelectionChange' ) ; +} + +FCKPageBreakCommand.prototype.GetState = function() +{ + if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG ) + return FCK_TRISTATE_DISABLED ; + return 0 ; // FCK_TRISTATE_OFF +} + +// FCKUnlinkCommand - by Johnny Egeland (johnny@coretrek.com) +var FCKUnlinkCommand = function() +{ + this.Name = 'Unlink' ; +} + +FCKUnlinkCommand.prototype.Execute = function() +{ + // Take an undo snapshot before changing the document + FCKUndo.SaveUndoStep() ; + + if ( FCKBrowserInfo.IsGeckoLike ) + { + var oLink = FCK.Selection.MoveToAncestorNode( 'A' ) ; + // The unlink command can generate a span in Firefox, so let's do it our way. See #430 + if ( oLink ) + FCKTools.RemoveOuterTags( oLink ) ; + + return ; + } + + FCK.ExecuteNamedCommand( this.Name ) ; +} + +FCKUnlinkCommand.prototype.GetState = function() +{ + if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG ) + return FCK_TRISTATE_DISABLED ; + var state = FCK.GetNamedCommandState( this.Name ) ; + + // Check that it isn't an anchor + if ( state == FCK_TRISTATE_OFF && FCK.EditMode == FCK_EDITMODE_WYSIWYG ) + { + var oLink = FCKSelection.MoveToAncestorNode( 'A' ) ; + var bIsAnchor = ( oLink && oLink.name.length > 0 && oLink.href.length == 0 ) ; + if ( bIsAnchor ) + state = FCK_TRISTATE_DISABLED ; + } + + return state ; +} + +// FCKSelectAllCommand +var FCKSelectAllCommand = function() +{ + this.Name = 'SelectAll' ; +} + +FCKSelectAllCommand.prototype.Execute = function() +{ + if ( FCK.EditMode == FCK_EDITMODE_WYSIWYG ) + { + FCK.ExecuteNamedCommand( 'SelectAll' ) ; + } + else + { + // Select the contents of the textarea + var textarea = FCK.EditingArea.Textarea ; + if ( FCKBrowserInfo.IsIE ) + { + textarea.createTextRange().execCommand( 'SelectAll' ) ; + } + else + { + textarea.selectionStart = 0 ; + textarea.selectionEnd = textarea.value.length ; + } + textarea.focus() ; + } +} + +FCKSelectAllCommand.prototype.GetState = function() +{ + if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG ) + return FCK_TRISTATE_DISABLED ; + return FCK_TRISTATE_OFF ; +} + +// FCKPasteCommand +var FCKPasteCommand = function() +{ + this.Name = 'Paste' ; +} + +FCKPasteCommand.prototype = +{ + Execute : function() + { + if ( FCKBrowserInfo.IsIE ) + FCK.Paste() ; + else + FCK.ExecuteNamedCommand( 'Paste' ) ; + }, + + GetState : function() + { + if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG ) + return FCK_TRISTATE_DISABLED ; + return FCK.GetNamedCommandState( 'Paste' ) ; + } +} ; + +// FCKRuleCommand +var FCKRuleCommand = function() +{ + this.Name = 'Rule' ; +} + +FCKRuleCommand.prototype = +{ + Execute : function() + { + FCKUndo.SaveUndoStep() ; + FCK.InsertElement( 'hr' ) ; + }, + + GetState : function() + { + if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG ) + return FCK_TRISTATE_DISABLED ; + return FCK.GetNamedCommandState( 'InsertHorizontalRule' ) ; + } +} ; + +// FCKCutCopyCommand +var FCKCutCopyCommand = function( isCut ) +{ + this.Name = isCut ? 'Cut' : 'Copy' ; +} + +FCKCutCopyCommand.prototype = +{ + Execute : function() + { + var enabled = false ; + + if ( FCKBrowserInfo.IsIE ) + { + // The following seems to be the only reliable way to detect that + // cut/copy is enabled in IE. It will fire the oncut/oncopy event + // only if the security settings enabled the command to execute. + + var onEvent = function() + { + enabled = true ; + } ; + + var eventName = 'on' + this.Name.toLowerCase() ; + + FCK.EditorDocument.body.attachEvent( eventName, onEvent ) ; + FCK.ExecuteNamedCommand( this.Name ) ; + FCK.EditorDocument.body.detachEvent( eventName, onEvent ) ; + } + else + { + try + { + // Other browsers throw an error if the command is disabled. + FCK.ExecuteNamedCommand( this.Name ) ; + enabled = true ; + } + catch(e){} + } + + if ( !enabled ) + alert( FCKLang[ 'PasteError' + this.Name ] ) ; + }, + + GetState : function() + { + // Strangely, the Cut command happens to have the correct states for + // both Copy and Cut in all browsers. + return FCK.EditMode != FCK_EDITMODE_WYSIWYG ? + FCK_TRISTATE_DISABLED : + FCK.GetNamedCommandState( 'Cut' ) ; + } +}; + +var FCKAnchorDeleteCommand = function() +{ + this.Name = 'AnchorDelete' ; +} + +FCKAnchorDeleteCommand.prototype = +{ + Execute : function() + { + if (FCK.Selection.GetType() == 'Control') + { + FCK.Selection.Delete(); + } + else + { + var oFakeImage = FCK.Selection.GetSelectedElement() ; + if ( oFakeImage ) + { + if ( oFakeImage.tagName == 'IMG' && oFakeImage.getAttribute('_fckanchor') ) + oAnchor = FCK.GetRealElement( oFakeImage ) ; + else + oFakeImage = null ; + } + + //Search for a real anchor + if ( !oFakeImage ) + { + oAnchor = FCK.Selection.MoveToAncestorNode( 'A' ) ; + if ( oAnchor ) + FCK.Selection.SelectNode( oAnchor ) ; + } + + // If it's also a link, then just remove the name and exit + if ( oAnchor.href.length != 0 ) + { + oAnchor.removeAttribute( 'name' ) ; + // Remove temporary class for IE + if ( FCKBrowserInfo.IsIE ) + oAnchor.className = oAnchor.className.replace( FCKRegexLib.FCK_Class, '' ) ; + return ; + } + + // We need to remove the anchor + // If we got a fake image, then just remove it and we're done + if ( oFakeImage ) + { + oFakeImage.parentNode.removeChild( oFakeImage ) ; + return ; + } + // Empty anchor, so just remove it + if ( oAnchor.innerHTML.length == 0 ) + { + oAnchor.parentNode.removeChild( oAnchor ) ; + return ; + } + // Anchor with content, leave the content + FCKTools.RemoveOuterTags( oAnchor ) ; + } + if ( FCKBrowserInfo.IsGecko ) + FCK.Selection.Collapse( true ) ; + }, + + GetState : function() + { + if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG ) + return FCK_TRISTATE_DISABLED ; + return FCK.GetNamedCommandState( 'Unlink') ; + } +}; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckblockquotecommand.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckblockquotecommand.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckblockquotecommand.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,250 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKBlockQuoteCommand Class: adds or removes blockquote tags. + */ + +var FCKBlockQuoteCommand = function() +{ +} + +FCKBlockQuoteCommand.prototype = +{ + Execute : function() + { + FCKUndo.SaveUndoStep() ; + + var state = this.GetState() ; + + var range = new FCKDomRange( FCK.EditorWindow ) ; + range.MoveToSelection() ; + + var bookmark = range.CreateBookmark() ; + + // Kludge for #1592: if the bookmark nodes are in the beginning of + // blockquote, then move them to the nearest block element in the + // blockquote. + if ( FCKBrowserInfo.IsIE ) + { + var bStart = range.GetBookmarkNode( bookmark, true ) ; + var bEnd = range.GetBookmarkNode( bookmark, false ) ; + + var cursor ; + + if ( bStart + && bStart.parentNode.nodeName.IEquals( 'blockquote' ) + && !bStart.previousSibling ) + { + cursor = bStart ; + while ( ( cursor = cursor.nextSibling ) ) + { + if ( FCKListsLib.BlockElements[ cursor.nodeName.toLowerCase() ] ) + FCKDomTools.MoveNode( bStart, cursor, true ) ; + } + } + + if ( bEnd + && bEnd.parentNode.nodeName.IEquals( 'blockquote' ) + && !bEnd.previousSibling ) + { + cursor = bEnd ; + while ( ( cursor = cursor.nextSibling ) ) + { + if ( FCKListsLib.BlockElements[ cursor.nodeName.toLowerCase() ] ) + { + if ( cursor.firstChild == bStart ) + FCKDomTools.InsertAfterNode( bStart, bEnd ) ; + else + FCKDomTools.MoveNode( bEnd, cursor, true ) ; + } + } + } + } + + var iterator = new FCKDomRangeIterator( range ) ; + var block ; + + if ( state == FCK_TRISTATE_OFF ) + { + iterator.EnforceRealBlocks = true ; + var paragraphs = [] ; + while ( ( block = iterator.GetNextParagraph() ) ) + paragraphs.push( block ) ; + + // If no paragraphs, create one from the current selection position. + if ( paragraphs.length < 1 ) + { + para = range.Window.document.createElement( FCKConfig.EnterMode.IEquals( 'p' ) ? 'p' : 'div' ) ; + range.InsertNode( para ) ; + para.appendChild( range.Window.document.createTextNode( '\ufeff' ) ) ; + range.MoveToBookmark( bookmark ) ; + range.MoveToNodeContents( para ) ; + range.Collapse( true ) ; + bookmark = range.CreateBookmark() ; + paragraphs.push( para ) ; + } + + // Make sure all paragraphs have the same parent. + var commonParent = paragraphs[0].parentNode ; + var tmp = [] ; + for ( var i = 0 ; i < paragraphs.length ; i++ ) + { + block = paragraphs[i] ; + commonParent = FCKDomTools.GetCommonParents( block.parentNode, commonParent ).pop() ; + } + var lastBlock = null ; + while ( paragraphs.length > 0 ) + { + block = paragraphs.shift() ; + while ( block.parentNode != commonParent ) + block = block.parentNode ; + if ( block != lastBlock ) + tmp.push( block ) ; + lastBlock = block ; + } + + // If any of the selected blocks is a blockquote, remove it to prevent nested blockquotes. + while ( tmp.length > 0 ) + { + block = tmp.shift() ; + if ( block.nodeName.IEquals( 'blockquote' ) ) + { + var docFrag = FCKTools.GetElementDocument( block ).createDocumentFragment() ; + while ( block.firstChild ) + { + docFrag.appendChild( block.removeChild( block.firstChild ) ) ; + paragraphs.push( docFrag.lastChild ) ; + } + block.parentNode.replaceChild( docFrag, block ) ; + } + else + paragraphs.push( block ) ; + } + + // Now we have all the blocks to be included in a new blockquote node. + var bqBlock = range.Window.document.createElement( 'blockquote' ) ; + commonParent.insertBefore( bqBlock, paragraphs[0] ) ; + while ( paragraphs.length > 0 ) + { + block = paragraphs.shift() ; + bqBlock.appendChild( block ) ; + } + } + else if ( state == FCK_TRISTATE_ON ) + { + var moveOutNodes = [] ; + while ( ( block = iterator.GetNextParagraph() ) ) + { + var bqParent = null ; + var bqChild = null ; + while ( block.parentNode ) + { + if ( block.parentNode.nodeName.IEquals( 'blockquote' ) ) + { + bqParent = block.parentNode ; + bqChild = block ; + break ; + } + block = block.parentNode ; + } + + if ( bqParent && bqChild ) + moveOutNodes.push( bqChild ) ; + } + + var movedNodes = [] ; + while ( moveOutNodes.length > 0 ) + { + var node = moveOutNodes.shift() ; + var bqBlock = node.parentNode ; + + // If the node is located at the beginning or the end, just take it out without splitting. + // Otherwise, split the blockquote node and move the paragraph in between the two blockquote nodes. + if ( node == node.parentNode.firstChild ) + { + bqBlock.parentNode.insertBefore( bqBlock.removeChild( node ), bqBlock ) ; + if ( ! bqBlock.firstChild ) + bqBlock.parentNode.removeChild( bqBlock ) ; + } + else if ( node == node.parentNode.lastChild ) + { + bqBlock.parentNode.insertBefore( bqBlock.removeChild( node ), bqBlock.nextSibling ) ; + if ( ! bqBlock.firstChild ) + bqBlock.parentNode.removeChild( bqBlock ) ; + } + else + FCKDomTools.BreakParent( node, node.parentNode, range ) ; + + movedNodes.push( node ) ; + } + + if ( FCKConfig.EnterMode.IEquals( 'br' ) ) + { + while ( movedNodes.length ) + { + var node = movedNodes.shift() ; + var firstTime = true ; + if ( node.nodeName.IEquals( 'div' ) ) + { + var docFrag = FCKTools.GetElementDocument( node ).createDocumentFragment() ; + var needBeginBr = firstTime && node.previousSibling && + !FCKListsLib.BlockBoundaries[node.previousSibling.nodeName.toLowerCase()] ; + if ( firstTime && needBeginBr ) + docFrag.appendChild( FCKTools.GetElementDocument( node ).createElement( 'br' ) ) ; + var needEndBr = node.nextSibling && + !FCKListsLib.BlockBoundaries[node.nextSibling.nodeName.toLowerCase()] ; + while ( node.firstChild ) + docFrag.appendChild( node.removeChild( node.firstChild ) ) ; + if ( needEndBr ) + docFrag.appendChild( FCKTools.GetElementDocument( node ).createElement( 'br' ) ) ; + node.parentNode.replaceChild( docFrag, node ) ; + firstTime = false ; + } + } + } + } + range.MoveToBookmark( bookmark ) ; + range.Select() ; + + FCK.Focus() ; + FCK.Events.FireEvent( 'OnSelectionChange' ) ; + }, + + GetState : function() + { + // Disabled if not WYSIWYG. + if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG || ! FCK.EditorWindow ) + return FCK_TRISTATE_DISABLED ; + + var path = new FCKElementPath( FCKSelection.GetBoundaryParentElement( true ) ) ; + var firstBlock = path.Block || path.BlockLimit ; + + if ( !firstBlock || firstBlock.nodeName.toLowerCase() == 'body' ) + return FCK_TRISTATE_OFF ; + + // See if the first block has a blockquote parent. + for ( var i = 0 ; i < path.Elements.length ; i++ ) + { + if ( path.Elements[i].nodeName.IEquals( 'blockquote' ) ) + return FCK_TRISTATE_ON ; + } + return FCK_TRISTATE_OFF ; + } +} ; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckcorestylecommand.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckcorestylecommand.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckcorestylecommand.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,61 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKCoreStyleCommand Class: controls the execution of a core style. Core + * styles are usually represented as buttons in the toolbar., like Bold and + * Italic. + */ + + var FCKCoreStyleCommand = function( coreStyleName ) + { + this.Name = 'CoreStyle' ; + this.StyleName = '_FCK_' + coreStyleName ; + this.IsActive = false ; + + FCKStyles.AttachStyleStateChange( this.StyleName, this._OnStyleStateChange, this ) ; + } + + FCKCoreStyleCommand.prototype = + { + Execute : function() + { + FCKUndo.SaveUndoStep() ; + + if ( this.IsActive ) + FCKStyles.RemoveStyle( this.StyleName ) ; + else + FCKStyles.ApplyStyle( this.StyleName ) ; + + FCK.Focus() ; + FCK.Events.FireEvent( 'OnSelectionChange' ) ; + }, + + GetState : function() + { + if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG ) + return FCK_TRISTATE_DISABLED ; + return this.IsActive ? FCK_TRISTATE_ON : FCK_TRISTATE_OFF ; + }, + + _OnStyleStateChange : function( styleName, isActive ) + { + this.IsActive = isActive ; + } + }; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckfitwindow.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckfitwindow.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckfitwindow.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,180 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Stretch the editor to full window size and back. + */ + +var FCKFitWindow = function() +{ + this.Name = 'FitWindow' ; +} + +FCKFitWindow.prototype.Execute = function() +{ + var eEditorFrame = window.frameElement ; + var eEditorFrameStyle = eEditorFrame.style ; + + var eMainWindow = parent ; + var eDocEl = eMainWindow.document.documentElement ; + var eBody = eMainWindow.document.body ; + var eBodyStyle = eBody.style ; + var eParent ; + + // No original style properties known? Go fullscreen. + if ( !this.IsMaximized ) + { + // Registering an event handler when the window gets resized. + if( FCKBrowserInfo.IsIE ) + eMainWindow.attachEvent( 'onresize', FCKFitWindow_Resize ) ; + else + eMainWindow.addEventListener( 'resize', FCKFitWindow_Resize, true ) ; + + // Save the scrollbars position. + this._ScrollPos = FCKTools.GetScrollPosition( eMainWindow ) ; + + // Save and reset the styles for the entire node tree. They could interfere in the result. + eParent = eEditorFrame ; + // The extra () is to avoid a warning with strict error checking. This is ok. + while( (eParent = eParent.parentNode) ) + { + if ( eParent.nodeType == 1 ) + { + eParent._fckSavedStyles = FCKTools.SaveStyles( eParent ) ; + eParent.style.zIndex = FCKConfig.FloatingPanelsZIndex - 1 ; + } + } + + // Hide IE scrollbars (in strict mode). + if ( FCKBrowserInfo.IsIE ) + { + this.documentElementOverflow = eDocEl.style.overflow ; + eDocEl.style.overflow = 'hidden' ; + eBodyStyle.overflow = 'hidden' ; + } + else + { + // Hide the scroolbars in Firefox. + eBodyStyle.overflow = 'hidden' ; + eBodyStyle.width = '0px' ; + eBodyStyle.height = '0px' ; + } + + // Save the IFRAME styles. + this._EditorFrameStyles = FCKTools.SaveStyles( eEditorFrame ) ; + + // Resize. + var oViewPaneSize = FCKTools.GetViewPaneSize( eMainWindow ) ; + + eEditorFrameStyle.position = "absolute"; + eEditorFrameStyle.zIndex = FCKConfig.FloatingPanelsZIndex - 1; + eEditorFrameStyle.left = "0px"; + eEditorFrameStyle.top = "0px"; + eEditorFrameStyle.width = oViewPaneSize.Width + "px"; + eEditorFrameStyle.height = oViewPaneSize.Height + "px"; + + // Giving the frame some (huge) borders on his right and bottom + // side to hide the background that would otherwise show when the + // editor is in fullsize mode and the window is increased in size + // not for IE, because IE immediately adapts the editor on resize, + // without showing any of the background oddly in firefox, the + // editor seems not to fill the whole frame, so just setting the + // background of it to white to cover the page laying behind it anyway. + if ( !FCKBrowserInfo.IsIE ) + { + eEditorFrameStyle.borderRight = eEditorFrameStyle.borderBottom = "9999px solid white" ; + eEditorFrameStyle.backgroundColor = "white"; + } + + // Scroll to top left. + eMainWindow.scrollTo(0, 0); + + // Is the editor still not on the top left? Let's find out and fix that as well. (Bug #174) + var editorPos = FCKTools.GetWindowPosition( eMainWindow, eEditorFrame ) ; + if ( editorPos.x != 0 ) + eEditorFrameStyle.left = ( -1 * editorPos.x ) + "px" ; + if ( editorPos.y != 0 ) + eEditorFrameStyle.top = ( -1 * editorPos.y ) + "px" ; + + this.IsMaximized = true ; + } + else // Resize to original size. + { + // Remove the event handler of window resizing. + if( FCKBrowserInfo.IsIE ) + eMainWindow.detachEvent( "onresize", FCKFitWindow_Resize ) ; + else + eMainWindow.removeEventListener( "resize", FCKFitWindow_Resize, true ) ; + + // Restore the CSS position for the entire node tree. + eParent = eEditorFrame ; + // The extra () is to avoid a warning with strict error checking. This is ok. + while( (eParent = eParent.parentNode) ) + { + if ( eParent._fckSavedStyles ) + { + FCKTools.RestoreStyles( eParent, eParent._fckSavedStyles ) ; + eParent._fckSavedStyles = null ; + } + } + + // Restore IE scrollbars + if ( FCKBrowserInfo.IsIE ) + eDocEl.style.overflow = this.documentElementOverflow ; + + // Restore original size + FCKTools.RestoreStyles( eEditorFrame, this._EditorFrameStyles ) ; + + // Restore the window scroll position. + eMainWindow.scrollTo( this._ScrollPos.X, this._ScrollPos.Y ) ; + + this.IsMaximized = false ; + } + + FCKToolbarItems.GetItem('FitWindow').RefreshState() ; + + // It seams that Firefox restarts the editing area when making this changes. + // On FF 1.0.x, the area is not anymore editable. On FF 1.5+, the special + //configuration, like DisableFFTableHandles and DisableObjectResizing get + //lost, so we must reset it. Also, the cursor position and selection are + //also lost, even if you comment the following line (MakeEditable). + // if ( FCKBrowserInfo.IsGecko10 ) // Initially I thought it was a FF 1.0 only problem. + if ( FCK.EditMode == FCK_EDITMODE_WYSIWYG ) + FCK.EditingArea.MakeEditable() ; + + FCK.Focus() ; +} + +FCKFitWindow.prototype.GetState = function() +{ + if ( FCKConfig.ToolbarLocation != 'In' ) + return FCK_TRISTATE_DISABLED ; + else + return ( this.IsMaximized ? FCK_TRISTATE_ON : FCK_TRISTATE_OFF ); +} + +function FCKFitWindow_Resize() +{ + var oViewPaneSize = FCKTools.GetViewPaneSize( parent ) ; + + var eEditorFrameStyle = window.frameElement.style ; + + eEditorFrameStyle.width = oViewPaneSize.Width + 'px' ; + eEditorFrameStyle.height = oViewPaneSize.Height + 'px' ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckindentcommands.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckindentcommands.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckindentcommands.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,282 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKIndentCommand Class: controls block indentation. + */ + +var FCKIndentCommand = function( name, offset ) +{ + this.Name = name ; + this.Offset = offset ; + this.IndentCSSProperty = FCKConfig.ContentLangDirection.IEquals( 'ltr' ) ? 'marginLeft' : 'marginRight' ; +} + +FCKIndentCommand._InitIndentModeParameters = function() +{ + if ( FCKConfig.IndentClasses && FCKConfig.IndentClasses.length > 0 ) + { + this._UseIndentClasses = true ; + this._IndentClassMap = {} ; + for ( var i = 0 ; i < FCKConfig.IndentClasses.length ;i++ ) + this._IndentClassMap[FCKConfig.IndentClasses[i]] = i + 1 ; + this._ClassNameRegex = new RegExp( '(?:^|\\s+)(' + FCKConfig.IndentClasses.join( '|' ) + ')(?=$|\\s)' ) ; + } + else + this._UseIndentClasses = false ; +} + + +FCKIndentCommand.prototype = +{ + Execute : function() + { + // Save an undo snapshot before doing anything. + FCKUndo.SaveUndoStep() ; + + var range = new FCKDomRange( FCK.EditorWindow ) ; + range.MoveToSelection() ; + var bookmark = range.CreateBookmark() ; + + // Two cases to handle here: either we're in a list, or not. + // If we're in a list, then the indent/outdent operations would be done on the list nodes. + // Otherwise, apply the operation on the nearest block nodes. + var nearestListBlock = FCKDomTools.GetCommonParentNode( range.StartNode || range.StartContainer , + range.EndNode || range.EndContainer, + ['ul', 'ol'] ) ; + if ( nearestListBlock ) + this._IndentList( range, nearestListBlock ) ; + else + this._IndentBlock( range ) ; + + range.MoveToBookmark( bookmark ) ; + range.Select() ; + + FCK.Focus() ; + FCK.Events.FireEvent( 'OnSelectionChange' ) ; + }, + + GetState : function() + { + // Disabled if not WYSIWYG. + if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG || ! FCK.EditorWindow ) + return FCK_TRISTATE_DISABLED ; + + // Initialize parameters if not already initialzed. + if ( FCKIndentCommand._UseIndentClasses == undefined ) + FCKIndentCommand._InitIndentModeParameters() ; + + // If we're not in a list, and the starting block's indentation is zero, and the current + // command is the outdent command, then we should return FCK_TRISTATE_DISABLED. + var startContainer = FCKSelection.GetBoundaryParentElement( true ) ; + var endContainer = FCKSelection.GetBoundaryParentElement( false ) ; + var listNode = FCKDomTools.GetCommonParentNode( startContainer, endContainer, ['ul','ol'] ) ; + + if ( listNode ) + { + if ( this.Name.IEquals( 'outdent' ) ) + return FCK_TRISTATE_OFF ; + var firstItem = FCKTools.GetElementAscensor( startContainer, 'li' ) ; + if ( !firstItem || !firstItem.previousSibling ) + return FCK_TRISTATE_DISABLED ; + return FCK_TRISTATE_OFF ; + } + if ( ! FCKIndentCommand._UseIndentClasses && this.Name.IEquals( 'indent' ) ) + return FCK_TRISTATE_OFF; + + var path = new FCKElementPath( startContainer ) ; + var firstBlock = path.Block || path.BlockLimit ; + if ( !firstBlock ) + return FCK_TRISTATE_DISABLED ; + + if ( FCKIndentCommand._UseIndentClasses ) + { + var indentClass = firstBlock.className.match( FCKIndentCommand._ClassNameRegex ) ; + var indentStep = 0 ; + if ( indentClass != null ) + { + indentClass = indentClass[1] ; + indentStep = FCKIndentCommand._IndentClassMap[indentClass] ; + } + if ( ( this.Name == 'outdent' && indentStep == 0 ) || + ( this.Name == 'indent' && indentStep == FCKConfig.IndentClasses.length ) ) + return FCK_TRISTATE_DISABLED ; + return FCK_TRISTATE_OFF ; + } + else + { + var indent = parseInt( firstBlock.style[this.IndentCSSProperty], 10 ) ; + if ( isNaN( indent ) ) + indent = 0 ; + if ( indent <= 0 ) + return FCK_TRISTATE_DISABLED ; + return FCK_TRISTATE_OFF ; + } + }, + + _IndentBlock : function( range ) + { + var iterator = new FCKDomRangeIterator( range ) ; + iterator.EnforceRealBlocks = true ; + + range.Expand( 'block_contents' ) ; + var commonParents = FCKDomTools.GetCommonParents( range.StartContainer, range.EndContainer ) ; + var nearestParent = commonParents[commonParents.length - 1] ; + var block ; + + while ( ( block = iterator.GetNextParagraph() ) ) + { + // We don't want to indent subtrees recursively, so only perform the indent operation + // if the block itself is the nearestParent, or the block's parent is the nearestParent. + if ( ! ( block == nearestParent || block.parentNode == nearestParent ) ) + continue ; + + if ( FCKIndentCommand._UseIndentClasses ) + { + // Transform current class name to indent step index. + var indentClass = block.className.match( FCKIndentCommand._ClassNameRegex ) ; + var indentStep = 0 ; + if ( indentClass != null ) + { + indentClass = indentClass[1] ; + indentStep = FCKIndentCommand._IndentClassMap[indentClass] ; + } + + // Operate on indent step index, transform indent step index back to class name. + if ( this.Name.IEquals( 'outdent' ) ) + indentStep-- ; + else if ( this.Name.IEquals( 'indent' ) ) + indentStep++ ; + indentStep = Math.min( indentStep, FCKConfig.IndentClasses.length ) ; + indentStep = Math.max( indentStep, 0 ) ; + var className = block.className.replace( FCKIndentCommand._ClassNameRegex, '' ) ; + if ( indentStep < 1 ) + block.className = className ; + else + block.className = ( className.length > 0 ? className + ' ' : '' ) + + FCKConfig.IndentClasses[indentStep - 1] ; + } + else + { + // Offset distance is assumed to be in pixels for now. + var currentOffset = parseInt( block.style[this.IndentCSSProperty], 10 ) ; + if ( isNaN( currentOffset ) ) + currentOffset = 0 ; + currentOffset += this.Offset ; + currentOffset = Math.max( currentOffset, 0 ) ; + currentOffset = Math.ceil( currentOffset / this.Offset ) * this.Offset ; + block.style[this.IndentCSSProperty] = currentOffset ? currentOffset + FCKConfig.IndentUnit : '' ; + if ( block.getAttribute( 'style' ) == '' ) + block.removeAttribute( 'style' ) ; + } + } + }, + + _IndentList : function( range, listNode ) + { + // Our starting and ending points of the range might be inside some blocks under a list item... + // So before playing with the iterator, we need to expand the block to include the list items. + var startContainer = range.StartContainer ; + var endContainer = range.EndContainer ; + while ( startContainer && startContainer.parentNode != listNode ) + startContainer = startContainer.parentNode ; + while ( endContainer && endContainer.parentNode != listNode ) + endContainer = endContainer.parentNode ; + + if ( ! startContainer || ! endContainer ) + return ; + + // Now we can iterate over the individual items on the same tree depth. + var block = startContainer ; + var itemsToMove = [] ; + var stopFlag = false ; + while ( stopFlag == false ) + { + if ( block == endContainer ) + stopFlag = true ; + itemsToMove.push( block ) ; + block = block.nextSibling ; + } + if ( itemsToMove.length < 1 ) + return ; + + // Do indent or outdent operations on the array model of the list, not the list's DOM tree itself. + // The array model demands that it knows as much as possible about the surrounding lists, we need + // to feed it the further ancestor node that is still a list. + var listParents = FCKDomTools.GetParents( listNode ) ; + for ( var i = 0 ; i < listParents.length ; i++ ) + { + if ( listParents[i].nodeName.IEquals( ['ul', 'ol'] ) ) + { + listNode = listParents[i] ; + break ; + } + } + var indentOffset = this.Name.IEquals( 'indent' ) ? 1 : -1 ; + var startItem = itemsToMove[0] ; + var lastItem = itemsToMove[ itemsToMove.length - 1 ] ; + var markerObj = {} ; + + // Convert the list DOM tree into a one dimensional array. + var listArray = FCKDomTools.ListToArray( listNode, markerObj ) ; + + // Apply indenting or outdenting on the array. + var baseIndent = listArray[lastItem._FCK_ListArray_Index].indent ; + for ( var i = startItem._FCK_ListArray_Index ; i <= lastItem._FCK_ListArray_Index ; i++ ) + listArray[i].indent += indentOffset ; + for ( var i = lastItem._FCK_ListArray_Index + 1 ; i < listArray.length && listArray[i].indent > baseIndent ; i++ ) + listArray[i].indent += indentOffset ; + + /* For debug use only + var PrintArray = function( listArray, doc ) + { + var s = [] ; + for ( var i = 0 ; i < listArray.length ; i++ ) + { + for ( var j in listArray[i] ) + { + if ( j != 'contents' ) + s.push( j + ":" + listArray[i][j] + "; " ) ; + else + { + var docFrag = doc.createDocumentFragment() ; + var tmpNode = doc.createElement( 'span' ) ; + for ( var k = 0 ; k < listArray[i][j].length ; k++ ) + docFrag.appendChild( listArray[i][j][k].cloneNode( true ) ) ; + tmpNode.appendChild( docFrag ) ; + s.push( j + ":" + tmpNode.innerHTML + "; ") ; + } + } + s.push( '\n' ) ; + } + alert( s.join('') ) ; + } + PrintArray( listArray, FCK.EditorDocument ) ; + */ + + // Convert the array back to a DOM forest (yes we might have a few subtrees now). + // And replace the old list with the new forest. + var newList = FCKDomTools.ArrayToList( listArray ) ; + if ( newList ) + listNode.parentNode.replaceChild( newList.listNode, listNode ) ; + + // Clean up the markers. + FCKDomTools.ClearAllMarkers( markerObj ) ; + } +} ; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckjustifycommands.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckjustifycommands.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckjustifycommands.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,173 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKJustifyCommand Class: controls block justification. + */ + +var FCKJustifyCommand = function( alignValue ) +{ + this.AlignValue = alignValue ; + + // Detect whether this is the instance for the default alignment. + var contentDir = FCKConfig.ContentLangDirection.toLowerCase() ; + this.IsDefaultAlign = ( alignValue == 'left' && contentDir == 'ltr' ) || + ( alignValue == 'right' && contentDir == 'rtl' ) ; + + // Get the class name to be used by this instance. + var cssClassName = this._CssClassName = ( function() + { + var classes = FCKConfig.JustifyClasses ; + if ( classes ) + { + switch ( alignValue ) + { + case 'left' : + return classes[0] || null ; + case 'center' : + return classes[1] || null ; + case 'right' : + return classes[2] || null ; + case 'justify' : + return classes[3] || null ; + } + } + return null ; + } )() ; + + if ( cssClassName && cssClassName.length > 0 ) + this._CssClassRegex = new RegExp( '(?:^|\\s+)' + cssClassName + '(?=$|\\s)' ) ; +} + +FCKJustifyCommand._GetClassNameRegex = function() +{ + var regex = FCKJustifyCommand._ClassRegex ; + if ( regex != undefined ) + return regex ; + + var names = [] ; + + var classes = FCKConfig.JustifyClasses ; + if ( classes ) + { + for ( var i = 0 ; i < 4 ; i++ ) + { + var className = classes[i] ; + if ( className && className.length > 0 ) + names.push( className ) ; + } + } + + if ( names.length > 0 ) + regex = new RegExp( '(?:^|\\s+)(?:' + names.join( '|' ) + ')(?=$|\\s)' ) ; + else + regex = null ; + + return FCKJustifyCommand._ClassRegex = regex ; +} + +FCKJustifyCommand.prototype = +{ + Execute : function() + { + // Save an undo snapshot before doing anything. + FCKUndo.SaveUndoStep() ; + + var range = new FCKDomRange( FCK.EditorWindow ) ; + range.MoveToSelection() ; + + var currentState = this.GetState() ; + if ( currentState == FCK_TRISTATE_DISABLED ) + return ; + + // Store a bookmark of the selection since the paragraph iterator might + // change the DOM tree and break selections. + var bookmark = range.CreateBookmark() ; + + var cssClassName = this._CssClassName ; + + // Apply alignment setting for each paragraph. + var iterator = new FCKDomRangeIterator( range ) ; + var block ; + while ( ( block = iterator.GetNextParagraph() ) ) + { + block.removeAttribute( 'align' ) ; + + if ( cssClassName ) + { + // Remove the any of the alignment classes from the className. + var className = block.className.replace( FCKJustifyCommand._GetClassNameRegex(), '' ) ; + + // Append the desired class name. + if ( currentState == FCK_TRISTATE_OFF ) + { + if ( className.length > 0 ) + className += ' ' ; + block.className = className + cssClassName ; + } + else if ( className.length == 0 ) + FCKDomTools.RemoveAttribute( block, 'class' ) ; + } + else + { + var style = block.style ; + if ( currentState == FCK_TRISTATE_OFF ) + style.textAlign = this.AlignValue ; + else + { + style.textAlign = '' ; + if ( style.cssText.length == 0 ) + block.removeAttribute( 'style' ) ; + } + } + } + + // Restore previous selection. + range.MoveToBookmark( bookmark ) ; + range.Select() ; + + FCK.Focus() ; + FCK.Events.FireEvent( 'OnSelectionChange' ) ; + }, + + GetState : function() + { + // Disabled if not WYSIWYG. + if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG || ! FCK.EditorWindow ) + return FCK_TRISTATE_DISABLED ; + + // Retrieve the first selected block. + var path = new FCKElementPath( FCKSelection.GetBoundaryParentElement( true ) ) ; + var firstBlock = path.Block || path.BlockLimit ; + + if ( !firstBlock || firstBlock.nodeName.toLowerCase() == 'body' ) + return FCK_TRISTATE_OFF ; + + // Check if the desired style is already applied to the block. + var currentAlign ; + if ( FCKBrowserInfo.IsIE ) + currentAlign = firstBlock.currentStyle.textAlign ; + else + currentAlign = FCK.EditorWindow.getComputedStyle( firstBlock, '' ).getPropertyValue( 'text-align' ); + currentAlign = currentAlign.replace( /(-moz-|-webkit-|start|auto)/i, '' ); + if ( ( !currentAlign && this.IsDefaultAlign ) || currentAlign == this.AlignValue ) + return FCK_TRISTATE_ON ; + return FCK_TRISTATE_OFF ; + } +} ; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fcklistcommands.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fcklistcommands.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fcklistcommands.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,382 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Implementation for the "Insert/Remove Ordered/Unordered List" commands. + */ + +var FCKListCommand = function( name, tagName ) +{ + this.Name = name ; + this.TagName = tagName ; +} + +FCKListCommand.prototype = +{ + GetState : function() + { + // Disabled if not WYSIWYG. + if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG || ! FCK.EditorWindow ) + return FCK_TRISTATE_DISABLED ; + + // We'll use the style system's convention to determine list state here... + // If the starting block is a descendant of an <ol> or <ul> node, then we're in a list. + var startContainer = FCKSelection.GetBoundaryParentElement( true ) ; + var listNode = startContainer ; + while ( listNode ) + { + if ( listNode.nodeName.IEquals( [ 'ul', 'ol' ] ) ) + break ; + listNode = listNode.parentNode ; + } + if ( listNode && listNode.nodeName.IEquals( this.TagName ) ) + return FCK_TRISTATE_ON ; + else + return FCK_TRISTATE_OFF ; + }, + + Execute : function() + { + FCKUndo.SaveUndoStep() ; + + var doc = FCK.EditorDocument ; + var range = new FCKDomRange( FCK.EditorWindow ) ; + range.MoveToSelection() ; + var state = this.GetState() ; + + // Midas lists rule #1 says we can create a list even in an empty document. + // But FCKDomRangeIterator wouldn't run if the document is really empty. + // So create a paragraph if the document is empty and we're going to create a list. + if ( state == FCK_TRISTATE_OFF ) + { + FCKDomTools.TrimNode( doc.body ) ; + if ( ! doc.body.firstChild ) + { + var paragraph = doc.createElement( 'p' ) ; + doc.body.appendChild( paragraph ) ; + range.MoveToNodeContents( paragraph ) ; + } + } + + var bookmark = range.CreateBookmark() ; + + // Group the blocks up because there are many cases where multiple lists have to be created, + // or multiple lists have to be cancelled. + var listGroups = [] ; + var markerObj = {} ; + var iterator = new FCKDomRangeIterator( range ) ; + var block ; + + iterator.ForceBrBreak = ( state == FCK_TRISTATE_OFF ) ; + var nextRangeExists = true ; + var rangeQueue = null ; + while ( nextRangeExists ) + { + while ( ( block = iterator.GetNextParagraph() ) ) + { + var path = new FCKElementPath( block ) ; + var listNode = null ; + var processedFlag = false ; + var blockLimit = path.BlockLimit ; + + // First, try to group by a list ancestor. + for ( var i = path.Elements.length - 1 ; i >= 0 ; i-- ) + { + var el = path.Elements[i] ; + if ( el.nodeName.IEquals( ['ol', 'ul'] ) ) + { + // If we've encountered a list inside a block limit + // The last group object of the block limit element should + // no longer be valid. Since paragraphs after the list + // should belong to a different group of paragraphs before + // the list. (Bug #1309) + if ( blockLimit._FCK_ListGroupObject ) + blockLimit._FCK_ListGroupObject = null ; + + var groupObj = el._FCK_ListGroupObject ; + if ( groupObj ) + groupObj.contents.push( block ) ; + else + { + groupObj = { 'root' : el, 'contents' : [ block ] } ; + listGroups.push( groupObj ) ; + FCKDomTools.SetElementMarker( markerObj, el, '_FCK_ListGroupObject', groupObj ) ; + } + processedFlag = true ; + break ; + } + } + + if ( processedFlag ) + continue ; + + // No list ancestor? Group by block limit. + var root = blockLimit ; + if ( root._FCK_ListGroupObject ) + root._FCK_ListGroupObject.contents.push( block ) ; + else + { + var groupObj = { 'root' : root, 'contents' : [ block ] } ; + FCKDomTools.SetElementMarker( markerObj, root, '_FCK_ListGroupObject', groupObj ) ; + listGroups.push( groupObj ) ; + } + } + + if ( FCKBrowserInfo.IsIE ) + nextRangeExists = false ; + else + { + if ( rangeQueue == null ) + { + rangeQueue = [] ; + var selectionObject = FCKSelection.GetSelection() ; + if ( selectionObject && listGroups.length == 0 ) + rangeQueue.push( selectionObject.getRangeAt( 0 ) ) ; + for ( var i = 1 ; selectionObject && i < selectionObject.rangeCount ; i++ ) + rangeQueue.push( selectionObject.getRangeAt( i ) ) ; + } + if ( rangeQueue.length < 1 ) + nextRangeExists = false ; + else + { + var internalRange = FCKW3CRange.CreateFromRange( doc, rangeQueue.shift() ) ; + range._Range = internalRange ; + range._UpdateElementInfo() ; + if ( range.StartNode.nodeName.IEquals( 'td' ) ) + range.SetStart( range.StartNode, 1 ) ; + if ( range.EndNode.nodeName.IEquals( 'td' ) ) + range.SetEnd( range.EndNode, 2 ) ; + iterator = new FCKDomRangeIterator( range ) ; + iterator.ForceBrBreak = ( state == FCK_TRISTATE_OFF ) ; + } + } + } + + // Now we have two kinds of list groups, groups rooted at a list, and groups rooted at a block limit element. + // We either have to build lists or remove lists, for removing a list does not makes sense when we are looking + // at the group that's not rooted at lists. So we have three cases to handle. + var listsCreated = [] ; + while ( listGroups.length > 0 ) + { + var groupObj = listGroups.shift() ; + if ( state == FCK_TRISTATE_OFF ) + { + if ( groupObj.root.nodeName.IEquals( ['ul', 'ol'] ) ) + this._ChangeListType( groupObj, markerObj, listsCreated ) ; + else + this._CreateList( groupObj, listsCreated ) ; + } + else if ( state == FCK_TRISTATE_ON && groupObj.root.nodeName.IEquals( ['ul', 'ol'] ) ) + this._RemoveList( groupObj, markerObj ) ; + } + + // For all new lists created, merge adjacent, same type lists. + for ( var i = 0 ; i < listsCreated.length ; i++ ) + { + var listNode = listsCreated[i] ; + var stopFlag = false ; + var currentNode = listNode ; + while ( ! stopFlag ) + { + currentNode = currentNode.nextSibling ; + if ( currentNode && currentNode.nodeType == 3 && currentNode.nodeValue.search( /^[\n\r\t ]*$/ ) == 0 ) + continue ; + stopFlag = true ; + } + + if ( currentNode && currentNode.nodeName.IEquals( this.TagName ) ) + { + currentNode.parentNode.removeChild( currentNode ) ; + while ( currentNode.firstChild ) + listNode.appendChild( currentNode.removeChild( currentNode.firstChild ) ) ; + } + + stopFlag = false ; + currentNode = listNode ; + while ( ! stopFlag ) + { + currentNode = currentNode.previousSibling ; + if ( currentNode && currentNode.nodeType == 3 && currentNode.nodeValue.search( /^[\n\r\t ]*$/ ) == 0 ) + continue ; + stopFlag = true ; + } + if ( currentNode && currentNode.nodeName.IEquals( this.TagName ) ) + { + currentNode.parentNode.removeChild( currentNode ) ; + while ( currentNode.lastChild ) + listNode.insertBefore( currentNode.removeChild( currentNode.lastChild ), + listNode.firstChild ) ; + } + } + + // Clean up, restore selection and update toolbar button states. + FCKDomTools.ClearAllMarkers( markerObj ) ; + range.MoveToBookmark( bookmark ) ; + range.Select() ; + + FCK.Focus() ; + FCK.Events.FireEvent( 'OnSelectionChange' ) ; + }, + + _ChangeListType : function( groupObj, markerObj, listsCreated ) + { + // This case is easy... + // 1. Convert the whole list into a one-dimensional array. + // 2. Change the list type by modifying the array. + // 3. Recreate the whole list by converting the array to a list. + // 4. Replace the original list with the recreated list. + var listArray = FCKDomTools.ListToArray( groupObj.root, markerObj ) ; + var selectedListItems = [] ; + for ( var i = 0 ; i < groupObj.contents.length ; i++ ) + { + var itemNode = groupObj.contents[i] ; + itemNode = FCKTools.GetElementAscensor( itemNode, 'li' ) ; + if ( ! itemNode || itemNode._FCK_ListItem_Processed ) + continue ; + selectedListItems.push( itemNode ) ; + FCKDomTools.SetElementMarker( markerObj, itemNode, '_FCK_ListItem_Processed', true ) ; + } + var fakeParent = FCKTools.GetElementDocument( groupObj.root ).createElement( this.TagName ) ; + for ( var i = 0 ; i < selectedListItems.length ; i++ ) + { + var listIndex = selectedListItems[i]._FCK_ListArray_Index ; + listArray[listIndex].parent = fakeParent ; + } + var newList = FCKDomTools.ArrayToList( listArray, markerObj ) ; + for ( var i = 0 ; i < newList.listNode.childNodes.length ; i++ ) + { + if ( newList.listNode.childNodes[i].nodeName.IEquals( this.TagName ) ) + listsCreated.push( newList.listNode.childNodes[i] ) ; + } + groupObj.root.parentNode.replaceChild( newList.listNode, groupObj.root ) ; + }, + + _CreateList : function( groupObj, listsCreated ) + { + var contents = groupObj.contents ; + var doc = FCKTools.GetElementDocument( groupObj.root ) ; + var listContents = [] ; + + // It is possible to have the contents returned by DomRangeIterator to be the same as the root. + // e.g. when we're running into table cells. + // In such a case, enclose the childNodes of contents[0] into a <div>. + if ( contents.length == 1 && contents[0] == groupObj.root ) + { + var divBlock = doc.createElement( 'div' ); + while ( contents[0].firstChild ) + divBlock.appendChild( contents[0].removeChild( contents[0].firstChild ) ) ; + contents[0].appendChild( divBlock ) ; + contents[0] = divBlock ; + } + + // Calculate the common parent node of all content blocks. + var commonParent = groupObj.contents[0].parentNode ; + for ( var i = 0 ; i < contents.length ; i++ ) + commonParent = FCKDomTools.GetCommonParents( commonParent, contents[i].parentNode ).pop() ; + + // We want to insert things that are in the same tree level only, so calculate the contents again + // by expanding the selected blocks to the same tree level. + for ( var i = 0 ; i < contents.length ; i++ ) + { + var contentNode = contents[i] ; + while ( contentNode.parentNode ) + { + if ( contentNode.parentNode == commonParent ) + { + listContents.push( contentNode ) ; + break ; + } + contentNode = contentNode.parentNode ; + } + } + + if ( listContents.length < 1 ) + return ; + + // Insert the list to the DOM tree. + var insertAnchor = listContents[listContents.length - 1].nextSibling ; + var listNode = doc.createElement( this.TagName ) ; + listsCreated.push( listNode ) ; + while ( listContents.length ) + { + var contentBlock = listContents.shift() ; + var docFrag = doc.createDocumentFragment() ; + while ( contentBlock.firstChild ) + docFrag.appendChild( contentBlock.removeChild( contentBlock.firstChild ) ) ; + contentBlock.parentNode.removeChild( contentBlock ) ; + var listItem = doc.createElement( 'li' ) ; + listItem.appendChild( docFrag ) ; + listNode.appendChild( listItem ) ; + } + commonParent.insertBefore( listNode, insertAnchor ) ; + }, + + _RemoveList : function( groupObj, markerObj ) + { + // This is very much like the change list type operation. + // Except that we're changing the selected items' indent to -1 in the list array. + var listArray = FCKDomTools.ListToArray( groupObj.root, markerObj ) ; + var selectedListItems = [] ; + for ( var i = 0 ; i < groupObj.contents.length ; i++ ) + { + var itemNode = groupObj.contents[i] ; + itemNode = FCKTools.GetElementAscensor( itemNode, 'li' ) ; + if ( ! itemNode || itemNode._FCK_ListItem_Processed ) + continue ; + selectedListItems.push( itemNode ) ; + FCKDomTools.SetElementMarker( markerObj, itemNode, '_FCK_ListItem_Processed', true ) ; + } + + var lastListIndex = null ; + for ( var i = 0 ; i < selectedListItems.length ; i++ ) + { + var listIndex = selectedListItems[i]._FCK_ListArray_Index ; + listArray[listIndex].indent = -1 ; + lastListIndex = listIndex ; + } + + // After cutting parts of the list out with indent=-1, we still have to maintain the array list + // model's nextItem.indent <= currentItem.indent + 1 invariant. Otherwise the array model of the + // list cannot be converted back to a real DOM list. + for ( var i = lastListIndex + 1; i < listArray.length ; i++ ) + { + if ( listArray[i].indent > listArray[i-1].indent + 1 ) + { + var indentOffset = listArray[i-1].indent + 1 - listArray[i].indent ; + var oldIndent = listArray[i].indent ; + while ( listArray[i] && listArray[i].indent >= oldIndent) + { + listArray[i].indent += indentOffset ; + i++ ; + } + i-- ; + } + } + + var newList = FCKDomTools.ArrayToList( listArray, markerObj ) ; + // If groupObj.root is the last element in its parent, or its nextSibling is a <br>, then we should + // not add a <br> after the final item. So, check for the cases and trim the <br>. + if ( groupObj.root.nextSibling == null || groupObj.root.nextSibling.nodeName.IEquals( 'br' ) ) + { + if ( newList.listNode.lastChild.nodeName.IEquals( 'br' ) ) + newList.listNode.removeChild( newList.listNode.lastChild ) ; + } + groupObj.root.parentNode.replaceChild( newList.listNode, groupObj.root ) ; + } +}; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fcknamedcommand.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fcknamedcommand.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fcknamedcommand.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,39 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKNamedCommand Class: represents an internal browser command. + */ + +var FCKNamedCommand = function( commandName ) +{ + this.Name = commandName ; +} + +FCKNamedCommand.prototype.Execute = function() +{ + FCK.ExecuteNamedCommand( this.Name ) ; +} + +FCKNamedCommand.prototype.GetState = function() +{ + if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG ) + return FCK_TRISTATE_DISABLED ; + return FCK.GetNamedCommandState( this.Name ) ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckpasteplaintextcommand.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckpasteplaintextcommand.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckpasteplaintextcommand.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,40 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKPastePlainTextCommand Class: represents the + * "Paste as Plain Text" command. + */ + +var FCKPastePlainTextCommand = function() +{ + this.Name = 'PasteText' ; +} + +FCKPastePlainTextCommand.prototype.Execute = function() +{ + FCK.PasteAsPlainText() ; +} + +FCKPastePlainTextCommand.prototype.GetState = function() +{ + if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG ) + return FCK_TRISTATE_DISABLED ; + return FCK.GetNamedCommandState( 'Paste' ) ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckpastewordcommand.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckpastewordcommand.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckpastewordcommand.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,40 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKPasteWordCommand Class: represents the "Paste from Word" command. + */ + +var FCKPasteWordCommand = function() +{ + this.Name = 'PasteWord' ; +} + +FCKPasteWordCommand.prototype.Execute = function() +{ + FCK.PasteFromWord() ; +} + +FCKPasteWordCommand.prototype.GetState = function() +{ + if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG || FCKConfig.ForcePasteAsPlainText ) + return FCK_TRISTATE_DISABLED ; + else + return FCK.GetNamedCommandState( 'Paste' ) ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckremoveformatcommand.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckremoveformatcommand.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckremoveformatcommand.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,45 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKRemoveFormatCommand Class: controls the execution of a core style. Core + * styles are usually represented as buttons in the toolbar., like Bold and + * Italic. + */ + + var FCKRemoveFormatCommand = function() + { + this.Name = 'RemoveFormat' ; + } + + FCKRemoveFormatCommand.prototype = + { + Execute : function() + { + FCKStyles.RemoveAll() ; + + FCK.Focus() ; + FCK.Events.FireEvent( 'OnSelectionChange' ) ; + }, + + GetState : function() + { + return FCK.EditorWindow ? FCK_TRISTATE_OFF : FCK_TRISTATE_DISABLED ; + } + }; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckshowblocks.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckshowblocks.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckshowblocks.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,74 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKShowBlockCommand Class: the "Show Blocks" command. + */ + +var FCKShowBlockCommand = function( name, defaultState ) +{ + this.Name = name ; + if ( defaultState != undefined ) + this._SavedState = defaultState ; + else + this._SavedState = null ; +} + +FCKShowBlockCommand.prototype.Execute = function() +{ + var state = this.GetState() ; + + if ( state == FCK_TRISTATE_DISABLED ) + return ; + + var body = FCK.EditorDocument.body ; + + if ( state == FCK_TRISTATE_ON ) + body.className = body.className.replace( /(^| )FCK__ShowBlocks/g, '' ) ; + else + body.className += ' FCK__ShowBlocks' ; + + FCK.Events.FireEvent( 'OnSelectionChange' ) ; +} + +FCKShowBlockCommand.prototype.GetState = function() +{ + if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG ) + return FCK_TRISTATE_DISABLED ; + + // On some cases FCK.EditorDocument.body is not yet available + if ( !FCK.EditorDocument ) + return FCK_TRISTATE_OFF ; + + if ( /FCK__ShowBlocks(?:\s|$)/.test( FCK.EditorDocument.body.className ) ) + return FCK_TRISTATE_ON ; + + return FCK_TRISTATE_OFF ; +} + +FCKShowBlockCommand.prototype.SaveState = function() +{ + this._SavedState = this.GetState() ; +} + +FCKShowBlockCommand.prototype.RestoreState = function() +{ + if ( this._SavedState != null && this.GetState() != this._SavedState ) + this.Execute() ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckspellcheckcommand_gecko.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckspellcheckcommand_gecko.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckspellcheckcommand_gecko.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,41 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKStyleCommand Class: represents the "Spell Check" command. + * (Gecko specific implementation) + */ + +var FCKSpellCheckCommand = function() +{ + this.Name = 'SpellCheck' ; + this.IsEnabled = ( FCKConfig.SpellChecker == 'SpellerPages' ) ; +} + +FCKSpellCheckCommand.prototype.Execute = function() +{ + FCKDialog.OpenDialog( 'FCKDialog_SpellCheck', 'Spell Check', 'dialog/fck_spellerpages.html', 440, 480 ) ; +} + +FCKSpellCheckCommand.prototype.GetState = function() +{ + if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG ) + return FCK_TRISTATE_DISABLED ; + return this.IsEnabled ? FCK_TRISTATE_OFF : FCK_TRISTATE_DISABLED ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckspellcheckcommand_ie.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckspellcheckcommand_ie.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckspellcheckcommand_ie.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,69 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKStyleCommand Class: represents the "Spell Check" command. + * (IE specific implementation) + */ + +var FCKSpellCheckCommand = function() +{ + this.Name = 'SpellCheck' ; + this.IsEnabled = ( FCKConfig.SpellChecker == 'ieSpell' || FCKConfig.SpellChecker == 'SpellerPages' ) ; +} + +FCKSpellCheckCommand.prototype.Execute = function() +{ + switch ( FCKConfig.SpellChecker ) + { + case 'ieSpell' : + this._RunIeSpell() ; + break ; + + case 'SpellerPages' : + FCKDialog.OpenDialog( 'FCKDialog_SpellCheck', 'Spell Check', 'dialog/fck_spellerpages.html', 440, 480 ) ; + break ; + } +} + +FCKSpellCheckCommand.prototype._RunIeSpell = function() +{ + try + { + var oIeSpell = new ActiveXObject( "ieSpell.ieSpellExtension" ) ; + oIeSpell.CheckAllLinkedDocuments( FCK.EditorDocument ) ; + } + catch( e ) + { + if( e.number == -2146827859 ) + { + if ( confirm( FCKLang.IeSpellDownload ) ) + window.open( FCKConfig.IeSpellDownloadUrl , 'IeSpellDownload' ) ; + } + else + alert( 'Error Loading ieSpell: ' + e.message + ' (' + e.number + ')' ) ; + } +} + +FCKSpellCheckCommand.prototype.GetState = function() +{ + if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG ) + return FCK_TRISTATE_DISABLED ; + return this.IsEnabled ? FCK_TRISTATE_OFF : FCK_TRISTATE_DISABLED ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckstylecommand.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckstylecommand.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fckstylecommand.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,60 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKStyleCommand Class: represents the "Style" command. + */ + +var FCKStyleCommand = function() +{} + +FCKStyleCommand.prototype = +{ + Name : 'Style', + + Execute : function( styleName, styleComboItem ) + { + FCKUndo.SaveUndoStep() ; + + if ( styleComboItem.Selected ) + FCK.Styles.RemoveStyle( styleComboItem.Style ) ; + else + FCK.Styles.ApplyStyle( styleComboItem.Style ) ; + + FCKUndo.SaveUndoStep() ; + + FCK.Focus() ; + FCK.Events.FireEvent( 'OnSelectionChange' ) ; + }, + + GetState : function() + { + if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG || !FCK.EditorDocument ) + return FCK_TRISTATE_DISABLED ; + + if ( FCKSelection.GetType() == 'Control' ) + { + var el = FCKSelection.GetSelectedElement() ; + if ( !el || !FCKStyles.CheckHasObjectStyle( el.nodeName.toLowerCase() ) ) + return FCK_TRISTATE_DISABLED ; + } + + return FCK_TRISTATE_OFF ; + } +}; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fcktablecommand.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fcktablecommand.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fcktablecommand.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,106 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKPastePlainTextCommand Class: represents the + * "Paste as Plain Text" command. + */ + +var FCKTableCommand = function( command ) +{ + this.Name = command ; +} + +FCKTableCommand.prototype.Execute = function() +{ + FCKUndo.SaveUndoStep() ; + + if ( ! FCKBrowserInfo.IsGecko ) + { + switch ( this.Name ) + { + case 'TableMergeRight' : + return FCKTableHandler.MergeRight() ; + case 'TableMergeDown' : + return FCKTableHandler.MergeDown() ; + } + } + + switch ( this.Name ) + { + case 'TableInsertRowAfter' : + return FCKTableHandler.InsertRow( false ) ; + case 'TableInsertRowBefore' : + return FCKTableHandler.InsertRow( true ) ; + case 'TableDeleteRows' : + return FCKTableHandler.DeleteRows() ; + case 'TableInsertColumnAfter' : + return FCKTableHandler.InsertColumn( false ) ; + case 'TableInsertColumnBefore' : + return FCKTableHandler.InsertColumn( true ) ; + case 'TableDeleteColumns' : + return FCKTableHandler.DeleteColumns() ; + case 'TableInsertCellAfter' : + return FCKTableHandler.InsertCell( null, false ) ; + case 'TableInsertCellBefore' : + return FCKTableHandler.InsertCell( null, true ) ; + case 'TableDeleteCells' : + return FCKTableHandler.DeleteCells() ; + case 'TableMergeCells' : + return FCKTableHandler.MergeCells() ; + case 'TableHorizontalSplitCell' : + return FCKTableHandler.HorizontalSplitCell() ; + case 'TableVerticalSplitCell' : + return FCKTableHandler.VerticalSplitCell() ; + case 'TableDelete' : + return FCKTableHandler.DeleteTable() ; + default : + return alert( FCKLang.UnknownCommand.replace( /%1/g, this.Name ) ) ; + } +} + +FCKTableCommand.prototype.GetState = function() +{ + if ( FCK.EditorDocument != null && FCKSelection.HasAncestorNode( 'TABLE' ) ) + { + switch ( this.Name ) + { + case 'TableHorizontalSplitCell' : + case 'TableVerticalSplitCell' : + if ( FCKTableHandler.GetSelectedCells().length == 1 ) + return FCK_TRISTATE_OFF ; + else + return FCK_TRISTATE_DISABLED ; + case 'TableMergeCells' : + if ( FCKTableHandler.CheckIsSelectionRectangular() + && FCKTableHandler.GetSelectedCells().length > 1 ) + return FCK_TRISTATE_OFF ; + else + return FCK_TRISTATE_DISABLED ; + case 'TableMergeRight' : + return FCKTableHandler.GetMergeRightTarget() ? FCK_TRISTATE_OFF : FCK_TRISTATE_DISABLED ; + case 'TableMergeDown' : + return FCKTableHandler.GetMergeDownTarget() ? FCK_TRISTATE_OFF : FCK_TRISTATE_DISABLED ; + default : + return FCK_TRISTATE_OFF ; + } + } + else + return FCK_TRISTATE_DISABLED; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fcktextcolorcommand.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fcktextcolorcommand.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/commandclasses/fcktextcolorcommand.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,201 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * FCKTextColorCommand Class: represents the text color comand. It shows the + * color selection panel. + */ + +// FCKTextColorCommand Constructor +// type: can be 'ForeColor' or 'BackColor'. +var FCKTextColorCommand = function( type ) +{ + this.Name = type == 'ForeColor' ? 'TextColor' : 'BGColor' ; + this.Type = type ; + + var oWindow ; + + if ( FCKBrowserInfo.IsIE ) + oWindow = window ; + else if ( FCK.ToolbarSet._IFrame ) + oWindow = FCKTools.GetElementWindow( FCK.ToolbarSet._IFrame ) ; + else + oWindow = window.parent ; + + this._Panel = new FCKPanel( oWindow ) ; + this._Panel.AppendStyleSheet( FCKConfig.SkinEditorCSS ) ; + this._Panel.MainNode.className = 'FCK_Panel' ; + this._CreatePanelBody( this._Panel.Document, this._Panel.MainNode ) ; + FCK.ToolbarSet.ToolbarItems.GetItem( this.Name ).RegisterPanel( this._Panel ) ; + + FCKTools.DisableSelection( this._Panel.Document.body ) ; +} + +FCKTextColorCommand.prototype.Execute = function( panelX, panelY, relElement ) +{ + // Show the Color Panel at the desired position. + this._Panel.Show( panelX, panelY, relElement ) ; +} + +FCKTextColorCommand.prototype.SetColor = function( color ) +{ + FCKUndo.SaveUndoStep() ; + + var style = FCKStyles.GetStyle( '_FCK_' + + ( this.Type == 'ForeColor' ? 'Color' : 'BackColor' ) ) ; + + if ( !color || color.length == 0 ) + FCK.Styles.RemoveStyle( style ) ; + else + { + style.SetVariable( 'Color', color ) ; + FCKStyles.ApplyStyle( style ) ; + } + + FCKUndo.SaveUndoStep() ; + + FCK.Focus() ; + FCK.Events.FireEvent( 'OnSelectionChange' ) ; +} + +FCKTextColorCommand.prototype.GetState = function() +{ + if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG ) + return FCK_TRISTATE_DISABLED ; + return FCK_TRISTATE_OFF ; +} + +function FCKTextColorCommand_OnMouseOver() +{ + this.className = 'ColorSelected' ; +} + +function FCKTextColorCommand_OnMouseOut() +{ + this.className = 'ColorDeselected' ; +} + +function FCKTextColorCommand_OnClick( ev, command, color ) +{ + this.className = 'ColorDeselected' ; + command.SetColor( color ) ; + command._Panel.Hide() ; +} + +function FCKTextColorCommand_AutoOnClick( ev, command ) +{ + this.className = 'ColorDeselected' ; + command.SetColor( '' ) ; + command._Panel.Hide() ; +} + +function FCKTextColorCommand_MoreOnClick( ev, command ) +{ + this.className = 'ColorDeselected' ; + command._Panel.Hide() ; + FCKDialog.OpenDialog( 'FCKDialog_Color', FCKLang.DlgColorTitle, 'dialog/fck_colorselector.html', 410, 320, + FCKTools.Bind( command, command.SetColor ) ) ; +} + +FCKTextColorCommand.prototype._CreatePanelBody = function( targetDocument, targetDiv ) +{ + function CreateSelectionDiv() + { + var oDiv = targetDocument.createElement( "DIV" ) ; + oDiv.className = 'ColorDeselected' ; + FCKTools.AddEventListenerEx( oDiv, 'mouseover', FCKTextColorCommand_OnMouseOver ) ; + FCKTools.AddEventListenerEx( oDiv, 'mouseout', FCKTextColorCommand_OnMouseOut ) ; + + return oDiv ; + } + + // Create the Table that will hold all colors. + var oTable = targetDiv.appendChild( targetDocument.createElement( "TABLE" ) ) ; + oTable.className = 'ForceBaseFont' ; // Firefox 1.5 Bug. + oTable.style.tableLayout = 'fixed' ; + oTable.cellPadding = 0 ; + oTable.cellSpacing = 0 ; + oTable.border = 0 ; + oTable.width = 150 ; + + var oCell = oTable.insertRow(-1).insertCell(-1) ; + oCell.colSpan = 8 ; + + // Create the Button for the "Automatic" color selection. + var oDiv = oCell.appendChild( CreateSelectionDiv() ) ; + oDiv.innerHTML = + '<table cellspacing="0" cellpadding="0" width="100%" border="0">\ + <tr>\ + <td><div class="ColorBoxBorder"><div class="ColorBox" style="background-color: #000000"></div></div></td>\ + <td nowrap width="100%" align="center">' + FCKLang.ColorAutomatic + '</td>\ + </tr>\ + </table>' ; + + FCKTools.AddEventListenerEx( oDiv, 'click', FCKTextColorCommand_AutoOnClick, this ) ; + + // Dirty hack for Opera, Safari and Firefox 3. + if ( !FCKBrowserInfo.IsIE ) + oDiv.style.width = '96%' ; + + // Create an array of colors based on the configuration file. + var aColors = FCKConfig.FontColors.toString().split(',') ; + + // Create the colors table based on the array. + var iCounter = 0 ; + while ( iCounter < aColors.length ) + { + var oRow = oTable.insertRow(-1) ; + + for ( var i = 0 ; i < 8 ; i++, iCounter++ ) + { + // The div will be created even if no more colors are available. + // Extra divs will be hidden later in the code. (#1597) + if ( iCounter < aColors.length ) + { + var colorParts = aColors[iCounter].split('/') ; + var colorValue = '#' + colorParts[0] ; + var colorName = colorParts[1] || colorValue ; + } + + oDiv = oRow.insertCell(-1).appendChild( CreateSelectionDiv() ) ; + oDiv.innerHTML = '<div class="ColorBoxBorder"><div class="ColorBox" style="background-color: ' + colorValue + '"></div></div>' ; + + if ( iCounter >= aColors.length ) + oDiv.style.visibility = 'hidden' ; + else + FCKTools.AddEventListenerEx( oDiv, 'click', FCKTextColorCommand_OnClick, [ this, colorName ] ) ; + } + } + + // Create the Row and the Cell for the "More Colors..." button. + if ( FCKConfig.EnableMoreFontColors ) + { + oCell = oTable.insertRow(-1).insertCell(-1) ; + oCell.colSpan = 8 ; + + oDiv = oCell.appendChild( CreateSelectionDiv() ) ; + oDiv.innerHTML = '<table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td nowrap align="center">' + FCKLang.ColorMoreColors + '</td></tr></table>' ; + + FCKTools.AddEventListenerEx( oDiv, 'click', FCKTextColorCommand_MoreOnClick, this ) ; + } + + // Dirty hack for Opera, Safari and Firefox 3. + if ( !FCKBrowserInfo.IsIE ) + oDiv.style.width = '96%' ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fck.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fck.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fck.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,1175 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Creation and initialization of the "FCK" object. This is the main object + * that represents an editor instance. + */ + +// FCK represents the active editor instance. +var FCK = +{ + Name : FCKURLParams[ 'InstanceName' ], + Status : FCK_STATUS_NOTLOADED, + EditMode : FCK_EDITMODE_WYSIWYG, + Toolbar : null, + HasFocus : false, + DataProcessor : new FCKDataProcessor(), + + GetInstanceObject : (function() + { + var w = window ; + return function( name ) + { + return w[name] ; + } + })(), + + AttachToOnSelectionChange : function( functionPointer ) + { + this.Events.AttachEvent( 'OnSelectionChange', functionPointer ) ; + }, + + GetLinkedFieldValue : function() + { + return this.LinkedField.value ; + }, + + GetParentForm : function() + { + return this.LinkedField.form ; + } , + + // # START : IsDirty implementation + + StartupValue : '', + + IsDirty : function() + { + if ( this.EditMode == FCK_EDITMODE_SOURCE ) + return ( this.StartupValue != this.EditingArea.Textarea.value ) ; + else + { + // It can happen switching between design and source mode in Gecko + if ( ! this.EditorDocument ) + return false ; + + return ( this.StartupValue != this.EditorDocument.body.innerHTML ) ; + } + }, + + ResetIsDirty : function() + { + if ( this.EditMode == FCK_EDITMODE_SOURCE ) + this.StartupValue = this.EditingArea.Textarea.value ; + else if ( this.EditorDocument.body ) + this.StartupValue = this.EditorDocument.body.innerHTML ; + }, + + // # END : IsDirty implementation + + StartEditor : function() + { + this.TempBaseTag = FCKConfig.BaseHref.length > 0 ? '<base href="' + FCKConfig.BaseHref + '" _fcktemp="true"></base>' : '' ; + + // Setup the keystroke handler. + var oKeystrokeHandler = FCK.KeystrokeHandler = new FCKKeystrokeHandler() ; + oKeystrokeHandler.OnKeystroke = _FCK_KeystrokeHandler_OnKeystroke ; + + // Set the config keystrokes. + oKeystrokeHandler.SetKeystrokes( FCKConfig.Keystrokes ) ; + + // In IE7, if the editor tries to access the clipboard by code, a dialog is + // shown to the user asking if the application is allowed to access or not. + // Due to the IE implementation of it, the KeystrokeHandler will not work + //well in this case, so we must leave the pasting keys to have their default behavior. + if ( FCKBrowserInfo.IsIE7 ) + { + if ( ( CTRL + 86 /*V*/ ) in oKeystrokeHandler.Keystrokes ) + oKeystrokeHandler.SetKeystrokes( [ CTRL + 86, true ] ) ; + + if ( ( SHIFT + 45 /*INS*/ ) in oKeystrokeHandler.Keystrokes ) + oKeystrokeHandler.SetKeystrokes( [ SHIFT + 45, true ] ) ; + } + + // Retain default behavior for Ctrl-Backspace. (Bug #362) + oKeystrokeHandler.SetKeystrokes( [ CTRL + 8, true ] ) ; + + this.EditingArea = new FCKEditingArea( document.getElementById( 'xEditingArea' ) ) ; + this.EditingArea.FFSpellChecker = FCKConfig.FirefoxSpellChecker ; + + // Set the editor's startup contents. + this.SetData( this.GetLinkedFieldValue(), true ) ; + + // Tab key handling for source mode. + FCKTools.AddEventListener( document, "keydown", this._TabKeyHandler ) ; + + // Add selection change listeners. They must be attached only once. + this.AttachToOnSelectionChange( _FCK_PaddingNodeListener ) ; + if ( FCKBrowserInfo.IsGecko ) + this.AttachToOnSelectionChange( this._ExecCheckEmptyBlock ) ; + + }, + + Focus : function() + { + FCK.EditingArea.Focus() ; + }, + + SetStatus : function( newStatus ) + { + this.Status = newStatus ; + + if ( newStatus == FCK_STATUS_ACTIVE ) + { + FCKFocusManager.AddWindow( window, true ) ; + + if ( FCKBrowserInfo.IsIE ) + FCKFocusManager.AddWindow( window.frameElement, true ) ; + + // Force the focus in the editor. + if ( FCKConfig.StartupFocus ) + FCK.Focus() ; + } + + this.Events.FireEvent( 'OnStatusChange', newStatus ) ; + + }, + + // Fixes the body by moving all inline and text nodes to appropriate block + // elements. + FixBody : function() + { + var sBlockTag = FCKConfig.EnterMode ; + + // In 'br' mode, no fix must be done. + if ( sBlockTag != 'p' && sBlockTag != 'div' ) + return ; + + var oDocument = this.EditorDocument ; + + if ( !oDocument ) + return ; + + var oBody = oDocument.body ; + + if ( !oBody ) + return ; + + FCKDomTools.TrimNode( oBody ) ; + + var oNode = oBody.firstChild ; + var oNewBlock ; + + while ( oNode ) + { + var bMoveNode = false ; + + switch ( oNode.nodeType ) + { + // Element Node. + case 1 : + var nodeName = oNode.nodeName.toLowerCase() ; + if ( !FCKListsLib.BlockElements[ nodeName ] && + nodeName != 'li' && + !oNode.getAttribute('_fckfakelement') && + oNode.getAttribute('_moz_dirty') == null ) + bMoveNode = true ; + break ; + + // Text Node. + case 3 : + // Ignore space only or empty text. + if ( oNewBlock || oNode.nodeValue.Trim().length > 0 ) + bMoveNode = true ; + } + + if ( bMoveNode ) + { + var oParent = oNode.parentNode ; + + if ( !oNewBlock ) + oNewBlock = oParent.insertBefore( oDocument.createElement( sBlockTag ), oNode ) ; + + oNewBlock.appendChild( oParent.removeChild( oNode ) ) ; + + oNode = oNewBlock.nextSibling ; + } + else + { + if ( oNewBlock ) + { + FCKDomTools.TrimNode( oNewBlock ) ; + oNewBlock = null ; + } + oNode = oNode.nextSibling ; + } + } + + if ( oNewBlock ) + FCKDomTools.TrimNode( oNewBlock ) ; + }, + + GetData : function( format ) + { + // We assume that if the user is in source editing, the editor value must + // represent the exact contents of the source, as the user wanted it to be. + if ( FCK.EditMode == FCK_EDITMODE_SOURCE ) + return FCK.EditingArea.Textarea.value ; + + this.FixBody() ; + + var oDoc = FCK.EditorDocument ; + if ( !oDoc ) + return null ; + + var isFullPage = FCKConfig.FullPage ; + + // Call the Data Processor to generate the output data. + var data = FCK.DataProcessor.ConvertToDataFormat( + isFullPage ? oDoc.documentElement : oDoc.body, + !isFullPage, + FCKConfig.IgnoreEmptyParagraphValue, + format ) ; + + // Restore protected attributes. + data = FCK.ProtectEventsRestore( data ) ; + + if ( FCKBrowserInfo.IsIE ) + data = data.replace( FCKRegexLib.ToReplace, '$1' ) ; + + if ( isFullPage ) + { + if ( FCK.DocTypeDeclaration && FCK.DocTypeDeclaration.length > 0 ) + data = FCK.DocTypeDeclaration + '\n' + data ; + + if ( FCK.XmlDeclaration && FCK.XmlDeclaration.length > 0 ) + data = FCK.XmlDeclaration + '\n' + data ; + } + + return FCKConfig.ProtectedSource.Revert( data ) ; + }, + + UpdateLinkedField : function() + { + var value = FCK.GetXHTML( FCKConfig.FormatOutput ) ; + + if ( FCKConfig.HtmlEncodeOutput ) + value = FCKTools.HTMLEncode( value ) ; + + FCK.LinkedField.value = value ; + FCK.Events.FireEvent( 'OnAfterLinkedFieldUpdate' ) ; + }, + + RegisteredDoubleClickHandlers : new Object(), + + OnDoubleClick : function( element ) + { + var oCalls = FCK.RegisteredDoubleClickHandlers[ element.tagName.toUpperCase() ] ; + + if ( oCalls ) + { + for ( var i = 0 ; i < oCalls.length ; i++ ) + oCalls[ i ]( element ) ; + } + + // Generic handler for any element + oCalls = FCK.RegisteredDoubleClickHandlers[ '*' ] ; + + if ( oCalls ) + { + for ( var i = 0 ; i < oCalls.length ; i++ ) + oCalls[ i ]( element ) ; + } + + }, + + // Register objects that can handle double click operations. + RegisterDoubleClickHandler : function( handlerFunction, tag ) + { + var nodeName = tag || '*' ; + nodeName = nodeName.toUpperCase() ; + + var aTargets ; + + if ( !( aTargets = FCK.RegisteredDoubleClickHandlers[ nodeName ] ) ) + FCK.RegisteredDoubleClickHandlers[ nodeName ] = [ handlerFunction ] ; + else + { + // Check that the event handler isn't already registered with the same listener + // It doesn't detect function pointers belonging to an object (at least in Gecko) + if ( aTargets.IndexOf( handlerFunction ) == -1 ) + aTargets.push( handlerFunction ) ; + } + + }, + + OnAfterSetHTML : function() + { + FCKDocumentProcessor.Process( FCK.EditorDocument ) ; + FCKUndo.SaveUndoStep() ; + + FCK.Events.FireEvent( 'OnSelectionChange' ) ; + FCK.Events.FireEvent( 'OnAfterSetHTML' ) ; + }, + + // Saves URLs on links and images on special attributes, so they don't change when + // moving around. + ProtectUrls : function( html ) + { + // <A> href + html = html.replace( FCKRegexLib.ProtectUrlsA , '$& _fcksavedurl=$1' ) ; + + // <IMG> src + html = html.replace( FCKRegexLib.ProtectUrlsImg , '$& _fcksavedurl=$1' ) ; + + // <AREA> href + html = html.replace( FCKRegexLib.ProtectUrlsArea , '$& _fcksavedurl=$1' ) ; + + return html ; + }, + + // Saves event attributes (like onclick) so they don't get executed while + // editing. + ProtectEvents : function( html ) + { + return html.replace( FCKRegexLib.TagsWithEvent, _FCK_ProtectEvents_ReplaceTags ) ; + }, + + ProtectEventsRestore : function( html ) + { + return html.replace( FCKRegexLib.ProtectedEvents, _FCK_ProtectEvents_RestoreEvents ) ; + }, + + ProtectTags : function( html ) + { + var sTags = FCKConfig.ProtectedTags ; + + // IE doesn't support <abbr> and it breaks it. Let's protect it. + if ( FCKBrowserInfo.IsIE ) + sTags += sTags.length > 0 ? '|ABBR|XML|EMBED|OBJECT' : 'ABBR|XML|EMBED|OBJECT' ; + + var oRegex ; + if ( sTags.length > 0 ) + { + oRegex = new RegExp( '<(' + sTags + ')(?!\w|:)', 'gi' ) ; + html = html.replace( oRegex, '<FCK:$1' ) ; + + oRegex = new RegExp( '<\/(' + sTags + ')>', 'gi' ) ; + html = html.replace( oRegex, '<\/FCK:$1>' ) ; + } + + // Protect some empty elements. We must do it separately because the + // original tag may not contain the closing slash, like <hr>: + // - <meta> tags get executed, so if you have a redirect meta, the + // content will move to the target page. + // - <hr> may destroy the document structure if not well + // positioned. The trick is protect it here and restore them in + // the FCKDocumentProcessor. + sTags = 'META' ; + if ( FCKBrowserInfo.IsIE ) + sTags += '|HR' ; + + oRegex = new RegExp( '<((' + sTags + ')(?=\\s|>|/)[\\s\\S]*?)/?>', 'gi' ) ; + html = html.replace( oRegex, '<FCK:$1 />' ) ; + + return html ; + }, + + SetData : function( data, resetIsDirty ) + { + this.EditingArea.Mode = FCK.EditMode ; + + // If there was an onSelectionChange listener in IE we must remove it to avoid crashes #1498 + if ( FCKBrowserInfo.IsIE && FCK.EditorDocument ) + { + FCK.EditorDocument.detachEvent("onselectionchange", Doc_OnSelectionChange ) ; + } + + if ( FCK.EditMode == FCK_EDITMODE_WYSIWYG ) + { + // Save the resetIsDirty for later use (async) + this._ForceResetIsDirty = ( resetIsDirty === true ) ; + + // Protect parts of the code that must remain untouched (and invisible) + // during editing. + data = FCKConfig.ProtectedSource.Protect( data ) ; + + // Call the Data Processor to transform the data. + data = FCK.DataProcessor.ConvertToHtml( data ) ; + + // Fix for invalid self-closing tags (see #152). + data = data.replace( FCKRegexLib.InvalidSelfCloseTags, '$1></$2>' ) ; + + // Protect event attributes (they could get fired in the editing area). + data = FCK.ProtectEvents( data ) ; + + // Protect some things from the browser itself. + data = FCK.ProtectUrls( data ) ; + data = FCK.ProtectTags( data ) ; + + // Insert the base tag (FCKConfig.BaseHref), if not exists in the source. + // The base must be the first tag in the HEAD, to get relative + // links on styles, for example. + if ( FCK.TempBaseTag.length > 0 && !FCKRegexLib.HasBaseTag.test( data ) ) + data = data.replace( FCKRegexLib.HeadOpener, '$&' + FCK.TempBaseTag ) ; + + // Build the HTML for the additional things we need on <head>. + var sHeadExtra = '' ; + + if ( !FCKConfig.FullPage ) + sHeadExtra += _FCK_GetEditorAreaStyleTags() ; + + if ( FCKBrowserInfo.IsIE ) + sHeadExtra += FCK._GetBehaviorsStyle() ; + else if ( FCKConfig.ShowBorders ) + sHeadExtra += FCKTools.GetStyleHtml( FCK_ShowTableBordersCSS, true ) ; + + sHeadExtra += FCKTools.GetStyleHtml( FCK_InternalCSS, true ) ; + + // Attention: do not change it before testing it well (sample07)! + // This is tricky... if the head ends with <meta ... content type>, + // Firefox will break. But, it works if we place our extra stuff as + // the last elements in the HEAD. + data = data.replace( FCKRegexLib.HeadCloser, sHeadExtra + '$&' ) ; + + // Load the HTML in the editing area. + this.EditingArea.OnLoad = _FCK_EditingArea_OnLoad ; + this.EditingArea.Start( data ) ; + } + else + { + // Remove the references to the following elements, as the editing area + // IFRAME will be removed. + FCK.EditorWindow = null ; + FCK.EditorDocument = null ; + FCKDomTools.PaddingNode = null ; + + this.EditingArea.OnLoad = null ; + this.EditingArea.Start( data ) ; + + // Enables the context menu in the textarea. + this.EditingArea.Textarea._FCKShowContextMenu = true ; + + // Removes the enter key handler. + FCK.EnterKeyHandler = null ; + + if ( resetIsDirty ) + this.ResetIsDirty() ; + + // Listen for keystroke events. + FCK.KeystrokeHandler.AttachToElement( this.EditingArea.Textarea ) ; + + this.EditingArea.Textarea.focus() ; + + FCK.Events.FireEvent( 'OnAfterSetHTML' ) ; + } + + if ( FCKBrowserInfo.IsGecko ) + window.onresize() ; + }, + + // This collection is used by the browser specific implementations to tell + // which named commands must be handled separately. + RedirectNamedCommands : new Object(), + + ExecuteNamedCommand : function( commandName, commandParameter, noRedirect, noSaveUndo ) + { + if ( !noSaveUndo ) + FCKUndo.SaveUndoStep() ; + + if ( !noRedirect && FCK.RedirectNamedCommands[ commandName ] != null ) + FCK.ExecuteRedirectedNamedCommand( commandName, commandParameter ) ; + else + { + FCK.Focus() ; + FCK.EditorDocument.execCommand( commandName, false, commandParameter ) ; + FCK.Events.FireEvent( 'OnSelectionChange' ) ; + } + + if ( !noSaveUndo ) + FCKUndo.SaveUndoStep() ; + }, + + GetNamedCommandState : function( commandName ) + { + try + { + + // Bug #50 : Safari never returns positive state for the Paste command, override that. + if ( FCKBrowserInfo.IsSafari && FCK.EditorWindow && commandName.IEquals( 'Paste' ) ) + return FCK_TRISTATE_OFF ; + + if ( !FCK.EditorDocument.queryCommandEnabled( commandName ) ) + return FCK_TRISTATE_DISABLED ; + else + { + return FCK.EditorDocument.queryCommandState( commandName ) ? FCK_TRISTATE_ON : FCK_TRISTATE_OFF ; + } + } + catch ( e ) + { + return FCK_TRISTATE_OFF ; + } + }, + + GetNamedCommandValue : function( commandName ) + { + var sValue = '' ; + var eState = FCK.GetNamedCommandState( commandName ) ; + + if ( eState == FCK_TRISTATE_DISABLED ) + return null ; + + try + { + sValue = this.EditorDocument.queryCommandValue( commandName ) ; + } + catch(e) {} + + return sValue ? sValue : '' ; + }, + + Paste : function( _callListenersOnly ) + { + // First call 'OnPaste' listeners. + if ( FCK.Status != FCK_STATUS_COMPLETE || !FCK.Events.FireEvent( 'OnPaste' ) ) + return false ; + + // Then call the default implementation. + return _callListenersOnly || FCK._ExecPaste() ; + }, + + PasteFromWord : function() + { + FCKDialog.OpenDialog( 'FCKDialog_Paste', FCKLang.PasteFromWord, 'dialog/fck_paste.html', 400, 330, 'Word' ) ; + }, + + Preview : function() + { + var sHTML ; + + if ( FCKConfig.FullPage ) + { + if ( FCK.TempBaseTag.length > 0 ) + sHTML = FCK.TempBaseTag + FCK.GetXHTML() ; + else + sHTML = FCK.GetXHTML() ; + } + else + { + sHTML = + FCKConfig.DocType + + '<html dir="' + FCKConfig.ContentLangDirection + '">' + + '<head>' + + FCK.TempBaseTag + + '<title>' + FCKLang.Preview + '</title>' + + _FCK_GetEditorAreaStyleTags() + + '</head><body' + FCKConfig.GetBodyAttributes() + '>' + + FCK.GetXHTML() + + '</body></html>' ; + } + + var iWidth = FCKConfig.ScreenWidth * 0.8 ; + var iHeight = FCKConfig.ScreenHeight * 0.7 ; + var iLeft = ( FCKConfig.ScreenWidth - iWidth ) / 2 ; + + var sOpenUrl = '' ; + if ( FCK_IS_CUSTOM_DOMAIN && FCKBrowserInfo.IsIE) + { + window._FCKHtmlToLoad = sHTML ; + sOpenUrl = 'javascript:void( (function(){' + + 'document.open() ;' + + 'document.domain="' + document.domain + '" ;' + + 'document.write( window.opener._FCKHtmlToLoad );' + + 'document.close() ;' + + 'window.opener._FCKHtmlToLoad = null ;' + + '})() )' ; + } + + var oWindow = window.open( sOpenUrl, null, 'toolbar=yes,location=no,status=yes,menubar=yes,scrollbars=yes,resizable=yes,width=' + iWidth + ',height=' + iHeight + ',left=' + iLeft ) ; + + if ( !FCK_IS_CUSTOM_DOMAIN || !FCKBrowserInfo.IsIE) + { + oWindow.document.write( sHTML ); + oWindow.document.close(); + } + + }, + + SwitchEditMode : function( noUndo ) + { + var bIsWysiwyg = ( FCK.EditMode == FCK_EDITMODE_WYSIWYG ) ; + + // Save the current IsDirty state, so we may restore it after the switch. + var bIsDirty = FCK.IsDirty() ; + + var sHtml ; + + // Update the HTML in the view output to show. + if ( bIsWysiwyg ) + { + FCKCommands.GetCommand( 'ShowBlocks' ).SaveState() ; + if ( !noUndo && FCKBrowserInfo.IsIE ) + FCKUndo.SaveUndoStep() ; + + sHtml = FCK.GetXHTML( FCKConfig.FormatSource ) ; + + if ( sHtml == null ) + return false ; + } + else + sHtml = this.EditingArea.Textarea.value ; + + FCK.EditMode = bIsWysiwyg ? FCK_EDITMODE_SOURCE : FCK_EDITMODE_WYSIWYG ; + + FCK.SetData( sHtml, !bIsDirty ) ; + + // Set the Focus. + FCK.Focus() ; + + // Update the toolbar (Running it directly causes IE to fail). + FCKTools.RunFunction( FCK.ToolbarSet.RefreshModeState, FCK.ToolbarSet ) ; + + return true ; + }, + + InsertElement : function( element ) + { + // The parameter may be a string (element name), so transform it in an element. + if ( typeof element == 'string' ) + element = this.EditorDocument.createElement( element ) ; + + var elementName = element.nodeName.toLowerCase() ; + + FCKSelection.Restore() ; + + // Create a range for the selection. V3 will have a new selection + // object that may internally supply this feature. + var range = new FCKDomRange( this.EditorWindow ) ; + + if ( FCKListsLib.BlockElements[ elementName ] != null ) + { + range.SplitBlock() ; + range.InsertNode( element ) ; + + var next = FCKDomTools.GetNextSourceElement( element, false, null, [ 'hr','br','param','img','area','input' ], true ) ; + + // Be sure that we have something after the new element, so we can move the cursor there. + if ( !next && FCKConfig.EnterMode != 'br') + { + next = this.EditorDocument.body.appendChild( this.EditorDocument.createElement( FCKConfig.EnterMode ) ) ; + + if ( FCKBrowserInfo.IsGeckoLike ) + FCKTools.AppendBogusBr( next ) ; + } + + if ( FCKListsLib.EmptyElements[ elementName ] == null ) + range.MoveToElementEditStart( element ) ; + else if ( next ) + range.MoveToElementEditStart( next ) ; + else + range.MoveToPosition( element, 4 ) ; + + if ( FCKBrowserInfo.IsGecko ) + { + if ( next ) + next.scrollIntoView( false ) ; + element.scrollIntoView( false ) ; + } + } + else + { + // Delete the current selection and insert the node. + range.MoveToSelection() ; + range.DeleteContents() ; + range.InsertNode( element ) ; + + // Move the selection right after the new element. + // DISCUSSION: Should we select the element instead? + range.SetStart( element, 4 ) ; + range.SetEnd( element, 4 ) ; + } + + range.Select() ; + range.Release() ; + + // REMOVE IT: The focus should not really be set here. It is up to the + // calling code to reset the focus if needed. + this.Focus() ; + + return element ; + }, + + _InsertBlockElement : function( blockElement ) + { + }, + + _IsFunctionKey : function( keyCode ) + { + // keys that are captured but do not change editor contents + if ( keyCode >= 16 && keyCode <= 20 ) + // shift, ctrl, alt, pause, capslock + return true ; + if ( keyCode == 27 || ( keyCode >= 33 && keyCode <= 40 ) ) + // esc, page up, page down, end, home, left, up, right, down + return true ; + if ( keyCode == 45 ) + // insert, no effect on FCKeditor, yet + return true ; + return false ; + }, + + _KeyDownListener : function( evt ) + { + if (! evt) + evt = FCK.EditorWindow.event ; + if ( FCK.EditorWindow ) + { + if ( !FCK._IsFunctionKey(evt.keyCode) // do not capture function key presses, like arrow keys or shift/alt/ctrl + && !(evt.ctrlKey || evt.metaKey) // do not capture Ctrl hotkeys, as they have their snapshot capture logic + && !(evt.keyCode == 46) ) // do not capture Del, it has its own capture logic in fckenterkey.js + FCK._KeyDownUndo() ; + } + return true ; + }, + + _KeyDownUndo : function() + { + if ( !FCKUndo.Typing ) + { + FCKUndo.SaveUndoStep() ; + FCKUndo.Typing = true ; + FCK.Events.FireEvent( "OnSelectionChange" ) ; + } + + FCKUndo.TypesCount++ ; + FCKUndo.Changed = 1 ; + + if ( FCKUndo.TypesCount > FCKUndo.MaxTypes ) + { + FCKUndo.TypesCount = 0 ; + FCKUndo.SaveUndoStep() ; + } + }, + + _TabKeyHandler : function( evt ) + { + if ( ! evt ) + evt = window.event ; + + var keystrokeValue = evt.keyCode ; + + // Pressing <Tab> in source mode should produce a tab space in the text area, not + // changing the focus to something else. + if ( keystrokeValue == 9 && FCK.EditMode != FCK_EDITMODE_WYSIWYG ) + { + if ( FCKBrowserInfo.IsIE ) + { + var range = document.selection.createRange() ; + if ( range.parentElement() != FCK.EditingArea.Textarea ) + return true ; + range.text = '\t' ; + range.select() ; + } + else + { + var a = [] ; + var el = FCK.EditingArea.Textarea ; + var selStart = el.selectionStart ; + var selEnd = el.selectionEnd ; + a.push( el.value.substr(0, selStart ) ) ; + a.push( '\t' ) ; + a.push( el.value.substr( selEnd ) ) ; + el.value = a.join( '' ) ; + el.setSelectionRange( selStart + 1, selStart + 1 ) ; + } + + if ( evt.preventDefault ) + return evt.preventDefault() ; + + return evt.returnValue = false ; + } + + return true ; + } +} ; + +FCK.Events = new FCKEvents( FCK ) ; + +// DEPRECATED in favor or "GetData". +FCK.GetHTML = FCK.GetXHTML = FCK.GetData ; + +// DEPRECATED in favor of "SetData". +FCK.SetHTML = FCK.SetData ; + +// InsertElementAndGetIt and CreateElement are Deprecated : returns the same value as InsertElement. +FCK.InsertElementAndGetIt = FCK.CreateElement = FCK.InsertElement ; + +// Replace all events attributes (like onclick). +function _FCK_ProtectEvents_ReplaceTags( tagMatch ) +{ + return tagMatch.replace( FCKRegexLib.EventAttributes, _FCK_ProtectEvents_ReplaceEvents ) ; +} + +// Replace an event attribute with its respective __fckprotectedatt attribute. +// The original event markup will be encoded and saved as the value of the new +// attribute. +function _FCK_ProtectEvents_ReplaceEvents( eventMatch, attName ) +{ + return ' ' + attName + '_fckprotectedatt="' + encodeURIComponent( eventMatch ) + '"' ; +} + +function _FCK_ProtectEvents_RestoreEvents( match, encodedOriginal ) +{ + return decodeURIComponent( encodedOriginal ) ; +} + +function _FCK_MouseEventsListener( evt ) +{ + if ( ! evt ) + evt = window.event ; + if ( evt.type == 'mousedown' ) + FCK.MouseDownFlag = true ; + else if ( evt.type == 'mouseup' ) + FCK.MouseDownFlag = false ; + else if ( evt.type == 'mousemove' ) + FCK.Events.FireEvent( 'OnMouseMove', evt ) ; +} + +function _FCK_PaddingNodeListener() +{ + if ( FCKConfig.EnterMode.IEquals( 'br' ) ) + return ; + FCKDomTools.EnforcePaddingNode( FCK.EditorDocument, FCKConfig.EnterMode ) ; + + if ( ! FCKBrowserInfo.IsIE && FCKDomTools.PaddingNode ) + { + // Prevent the caret from going between the body and the padding node in Firefox. + // i.e. <body>|<p></p></body> + var sel = FCKSelection.GetSelection() ; + if ( sel && sel.rangeCount == 1 ) + { + var range = sel.getRangeAt( 0 ) ; + if ( range.collapsed && range.startContainer == FCK.EditorDocument.body && range.startOffset == 0 ) + { + range.selectNodeContents( FCKDomTools.PaddingNode ) ; + range.collapse( true ) ; + sel.removeAllRanges() ; + sel.addRange( range ) ; + } + } + } + else if ( FCKDomTools.PaddingNode ) + { + // Prevent the caret from going into an empty body but not into the padding node in IE. + // i.e. <body><p></p>|</body> + var parentElement = FCKSelection.GetParentElement() ; + var paddingNode = FCKDomTools.PaddingNode ; + if ( parentElement && parentElement.nodeName.IEquals( 'body' ) ) + { + if ( FCK.EditorDocument.body.childNodes.length == 1 + && FCK.EditorDocument.body.firstChild == paddingNode ) + { + var range = FCK.EditorDocument.body.createTextRange() ; + var clearContents = false ; + if ( !paddingNode.childNodes.firstChild ) + { + paddingNode.appendChild( FCKTools.GetElementDocument( paddingNode ).createTextNode( '\ufeff' ) ) ; + clearContents = true ; + } + range.moveToElementText( paddingNode ) ; + range.select() ; + if ( clearContents ) + range.pasteHTML( '' ) ; + } + } + } +} + +function _FCK_EditingArea_OnLoad() +{ + // Get the editor's window and document (DOM) + FCK.EditorWindow = FCK.EditingArea.Window ; + FCK.EditorDocument = FCK.EditingArea.Document ; + + FCK.InitializeBehaviors() ; + + // Listen for mousedown and mouseup events for tracking drag and drops. + FCK.MouseDownFlag = false ; + FCKTools.AddEventListener( FCK.EditorDocument, 'mousemove', _FCK_MouseEventsListener ) ; + FCKTools.AddEventListener( FCK.EditorDocument, 'mousedown', _FCK_MouseEventsListener ) ; + FCKTools.AddEventListener( FCK.EditorDocument, 'mouseup', _FCK_MouseEventsListener ) ; + + // Most of the CTRL key combos do not work under Safari for onkeydown and onkeypress (See #1119) + // But we can use the keyup event to override some of these... + if ( FCKBrowserInfo.IsSafari ) + { + var undoFunc = function( evt ) + { + if ( ! ( evt.ctrlKey || evt.metaKey ) ) + return ; + if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG ) + return ; + switch ( evt.keyCode ) + { + case 89: + FCKUndo.Redo() ; + break ; + case 90: + FCKUndo.Undo() ; + break ; + } + } + + FCKTools.AddEventListener( FCK.EditorDocument, 'keyup', undoFunc ) ; + } + + // Create the enter key handler + FCK.EnterKeyHandler = new FCKEnterKey( FCK.EditorWindow, FCKConfig.EnterMode, FCKConfig.ShiftEnterMode, FCKConfig.TabSpaces ) ; + + // Listen for keystroke events. + FCK.KeystrokeHandler.AttachToElement( FCK.EditorDocument ) ; + + if ( FCK._ForceResetIsDirty ) + FCK.ResetIsDirty() ; + + // This is a tricky thing for IE. In some cases, even if the cursor is + // blinking in the editing, the keystroke handler doesn't catch keyboard + // events. We must activate the editing area to make it work. (#142). + if ( FCKBrowserInfo.IsIE && FCK.HasFocus ) + FCK.EditorDocument.body.setActive() ; + + FCK.OnAfterSetHTML() ; + + // Restore show blocks status. + FCKCommands.GetCommand( 'ShowBlocks' ).RestoreState() ; + + // Check if it is not a startup call, otherwise complete the startup. + if ( FCK.Status != FCK_STATUS_NOTLOADED ) + return ; + + FCK.SetStatus( FCK_STATUS_ACTIVE ) ; +} + +function _FCK_GetEditorAreaStyleTags() +{ + return FCKTools.GetStyleHtml( FCKConfig.EditorAreaCSS ) + + FCKTools.GetStyleHtml( FCKConfig.EditorAreaStyles ) ; +} + +function _FCK_KeystrokeHandler_OnKeystroke( keystroke, keystrokeValue ) +{ + if ( FCK.Status != FCK_STATUS_COMPLETE ) + return false ; + + if ( FCK.EditMode == FCK_EDITMODE_WYSIWYG ) + { + switch ( keystrokeValue ) + { + case 'Paste' : + return !FCK.Paste() ; + + case 'Cut' : + FCKUndo.SaveUndoStep() ; + return false ; + } + } + else + { + // In source mode, some actions must have their default behavior. + if ( keystrokeValue.Equals( 'Paste', 'Undo', 'Redo', 'SelectAll', 'Cut' ) ) + return false ; + } + + // The return value indicates if the default behavior of the keystroke must + // be cancelled. Let's do that only if the Execute() call explicitly returns "false". + var oCommand = FCK.Commands.GetCommand( keystrokeValue ) ; + + // If the command is disabled then ignore the keystroke + if ( oCommand.GetState() == FCK_TRISTATE_DISABLED ) + return false ; + + return ( oCommand.Execute.apply( oCommand, FCKTools.ArgumentsToArray( arguments, 2 ) ) !== false ) ; +} + +// Set the FCK.LinkedField reference to the field that will be used to post the +// editor data. +(function() +{ + // There is a bug on IE... getElementById returns any META tag that has the + // name set to the ID you are looking for. So the best way in to get the array + // by names and look for the correct one. + // As ASP.Net generates a ID that is different from the Name, we must also + // look for the field based on the ID (the first one is the ID). + + var oDocument = window.parent.document ; + + // Try to get the field using the ID. + var eLinkedField = oDocument.getElementById( FCK.Name ) ; + + var i = 0; + while ( eLinkedField || i == 0 ) + { + if ( eLinkedField && eLinkedField.tagName.toLowerCase().Equals( 'input', 'textarea' ) ) + { + FCK.LinkedField = eLinkedField ; + break ; + } + + eLinkedField = oDocument.getElementsByName( FCK.Name )[i++] ; + } +})() ; + +var FCKTempBin = +{ + Elements : new Array(), + + AddElement : function( element ) + { + var iIndex = this.Elements.length ; + this.Elements[ iIndex ] = element ; + return iIndex ; + }, + + RemoveElement : function( index ) + { + var e = this.Elements[ index ] ; + this.Elements[ index ] = null ; + return e ; + }, + + Reset : function() + { + var i = 0 ; + while ( i < this.Elements.length ) + this.Elements[ i++ ] = null ; + this.Elements.length = 0 ; + } +} ; + + + +// # Focus Manager: Manages the focus in the editor. +var FCKFocusManager = FCK.FocusManager = +{ + IsLocked : false, + + AddWindow : function( win, sendToEditingArea ) + { + var oTarget ; + + if ( FCKBrowserInfo.IsIE ) + oTarget = win.nodeType == 1 ? win : win.frameElement ? win.frameElement : win.document ; + else if ( FCKBrowserInfo.IsSafari ) + oTarget = win ; + else + oTarget = win.document ; + + FCKTools.AddEventListener( oTarget, 'blur', FCKFocusManager_Win_OnBlur ) ; + FCKTools.AddEventListener( oTarget, 'focus', sendToEditingArea ? FCKFocusManager_Win_OnFocus_Area : FCKFocusManager_Win_OnFocus ) ; + }, + + RemoveWindow : function( win ) + { + if ( FCKBrowserInfo.IsIE ) + oTarget = win.nodeType == 1 ? win : win.frameElement ? win.frameElement : win.document ; + else + oTarget = win.document ; + + FCKTools.RemoveEventListener( oTarget, 'blur', FCKFocusManager_Win_OnBlur ) ; + FCKTools.RemoveEventListener( oTarget, 'focus', FCKFocusManager_Win_OnFocus_Area ) ; + FCKTools.RemoveEventListener( oTarget, 'focus', FCKFocusManager_Win_OnFocus ) ; + }, + + Lock : function() + { + this.IsLocked = true ; + }, + + Unlock : function() + { + if ( this._HasPendingBlur ) + FCKFocusManager._Timer = window.setTimeout( FCKFocusManager_FireOnBlur, 100 ) ; + + this.IsLocked = false ; + }, + + _ResetTimer : function() + { + this._HasPendingBlur = false ; + + if ( this._Timer ) + { + window.clearTimeout( this._Timer ) ; + delete this._Timer ; + } + } +} ; + +function FCKFocusManager_Win_OnBlur() +{ + if ( typeof(FCK) != 'undefined' && FCK.HasFocus ) + { + FCKFocusManager._ResetTimer() ; + FCKFocusManager._Timer = window.setTimeout( FCKFocusManager_FireOnBlur, 100 ) ; + } +} + +function FCKFocusManager_FireOnBlur() +{ + if ( FCKFocusManager.IsLocked ) + FCKFocusManager._HasPendingBlur = true ; + else + { + FCK.HasFocus = false ; + FCK.Events.FireEvent( "OnBlur" ) ; + } +} + +function FCKFocusManager_Win_OnFocus_Area() +{ + // Check if we are already focusing the editor (to avoid loops). + if ( FCKFocusManager._IsFocusing ) + return ; + + FCKFocusManager._IsFocusing = true ; + + FCK.Focus() ; + FCKFocusManager_Win_OnFocus() ; + + // The above FCK.Focus() call may trigger other focus related functions. + // So, to avoid a loop, we delay the focusing mark removal, so it get + // executed after all othre functions have been run. + FCKTools.RunFunction( function() + { + delete FCKFocusManager._IsFocusing ; + } ) ; +} + +function FCKFocusManager_Win_OnFocus() +{ + FCKFocusManager._ResetTimer() ; + + if ( !FCK.HasFocus && !FCKFocusManager.IsLocked ) + { + FCK.HasFocus = true ; + FCK.Events.FireEvent( "OnFocus" ) ; + } +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fck_contextmenu.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fck_contextmenu.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fck_contextmenu.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,325 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Defines the FCK.ContextMenu object that is responsible for all + * Context Menu operations in the editing area. + */ + +FCK.ContextMenu = new Object() ; +FCK.ContextMenu.Listeners = new Array() ; + +FCK.ContextMenu.RegisterListener = function( listener ) +{ + if ( listener ) + this.Listeners.push( listener ) ; +} + +function FCK_ContextMenu_Init() +{ + var oInnerContextMenu = FCK.ContextMenu._InnerContextMenu = new FCKContextMenu( FCKBrowserInfo.IsIE ? window : window.parent, FCKLang.Dir ) ; + oInnerContextMenu.CtrlDisable = FCKConfig.BrowserContextMenuOnCtrl ; + oInnerContextMenu.OnBeforeOpen = FCK_ContextMenu_OnBeforeOpen ; + oInnerContextMenu.OnItemClick = FCK_ContextMenu_OnItemClick ; + + // Get the registering function. + var oMenu = FCK.ContextMenu ; + + // Register all configured context menu listeners. + for ( var i = 0 ; i < FCKConfig.ContextMenu.length ; i++ ) + oMenu.RegisterListener( FCK_ContextMenu_GetListener( FCKConfig.ContextMenu[i] ) ) ; +} + +function FCK_ContextMenu_GetListener( listenerName ) +{ + switch ( listenerName ) + { + case 'Generic' : + return { + AddItems : function( menu, tag, tagName ) + { + menu.AddItem( 'Cut' , FCKLang.Cut , 7, FCKCommands.GetCommand( 'Cut' ).GetState() == FCK_TRISTATE_DISABLED ) ; + menu.AddItem( 'Copy' , FCKLang.Copy , 8, FCKCommands.GetCommand( 'Copy' ).GetState() == FCK_TRISTATE_DISABLED ) ; + menu.AddItem( 'Paste' , FCKLang.Paste , 9, FCKCommands.GetCommand( 'Paste' ).GetState() == FCK_TRISTATE_DISABLED ) ; + }} ; + + case 'Table' : + return { + AddItems : function( menu, tag, tagName ) + { + var bIsTable = ( tagName == 'TABLE' ) ; + var bIsCell = ( !bIsTable && FCKSelection.HasAncestorNode( 'TABLE' ) ) ; + + if ( bIsCell ) + { + menu.AddSeparator() ; + var oItem = menu.AddItem( 'Cell' , FCKLang.CellCM ) ; + oItem.AddItem( 'TableInsertCellBefore' , FCKLang.InsertCellBefore, 69 ) ; + oItem.AddItem( 'TableInsertCellAfter' , FCKLang.InsertCellAfter, 58 ) ; + oItem.AddItem( 'TableDeleteCells' , FCKLang.DeleteCells, 59 ) ; + if ( FCKBrowserInfo.IsGecko ) + oItem.AddItem( 'TableMergeCells' , FCKLang.MergeCells, 60, + FCKCommands.GetCommand( 'TableMergeCells' ).GetState() == FCK_TRISTATE_DISABLED ) ; + else + { + oItem.AddItem( 'TableMergeRight' , FCKLang.MergeRight, 60, + FCKCommands.GetCommand( 'TableMergeRight' ).GetState() == FCK_TRISTATE_DISABLED ) ; + oItem.AddItem( 'TableMergeDown' , FCKLang.MergeDown, 60, + FCKCommands.GetCommand( 'TableMergeDown' ).GetState() == FCK_TRISTATE_DISABLED ) ; + } + oItem.AddItem( 'TableHorizontalSplitCell' , FCKLang.HorizontalSplitCell, 61, + FCKCommands.GetCommand( 'TableHorizontalSplitCell' ).GetState() == FCK_TRISTATE_DISABLED ) ; + oItem.AddItem( 'TableVerticalSplitCell' , FCKLang.VerticalSplitCell, 61, + FCKCommands.GetCommand( 'TableVerticalSplitCell' ).GetState() == FCK_TRISTATE_DISABLED ) ; + oItem.AddSeparator() ; + oItem.AddItem( 'TableCellProp' , FCKLang.CellProperties, 57, + FCKCommands.GetCommand( 'TableCellProp' ).GetState() == FCK_TRISTATE_DISABLED ) ; + + menu.AddSeparator() ; + oItem = menu.AddItem( 'Row' , FCKLang.RowCM ) ; + oItem.AddItem( 'TableInsertRowBefore' , FCKLang.InsertRowBefore, 70 ) ; + oItem.AddItem( 'TableInsertRowAfter' , FCKLang.InsertRowAfter, 62 ) ; + oItem.AddItem( 'TableDeleteRows' , FCKLang.DeleteRows, 63 ) ; + + menu.AddSeparator() ; + oItem = menu.AddItem( 'Column' , FCKLang.ColumnCM ) ; + oItem.AddItem( 'TableInsertColumnBefore', FCKLang.InsertColumnBefore, 71 ) ; + oItem.AddItem( 'TableInsertColumnAfter' , FCKLang.InsertColumnAfter, 64 ) ; + oItem.AddItem( 'TableDeleteColumns' , FCKLang.DeleteColumns, 65 ) ; + } + + if ( bIsTable || bIsCell ) + { + menu.AddSeparator() ; + menu.AddItem( 'TableDelete' , FCKLang.TableDelete ) ; + menu.AddItem( 'TableProp' , FCKLang.TableProperties, 39 ) ; + } + }} ; + + case 'Link' : + return { + AddItems : function( menu, tag, tagName ) + { + var bInsideLink = ( tagName == 'A' || FCKSelection.HasAncestorNode( 'A' ) ) ; + + if ( bInsideLink || FCK.GetNamedCommandState( 'Unlink' ) != FCK_TRISTATE_DISABLED ) + { + // Go up to the anchor to test its properties + var oLink = FCKSelection.MoveToAncestorNode( 'A' ) ; + var bIsAnchor = ( oLink && oLink.name.length > 0 && oLink.href.length == 0 ) ; + // If it isn't a link then don't add the Link context menu + if ( bIsAnchor ) + return ; + + menu.AddSeparator() ; + if ( bInsideLink ) + menu.AddItem( 'Link', FCKLang.EditLink , 34 ) ; + menu.AddItem( 'Unlink' , FCKLang.RemoveLink , 35 ) ; + } + }} ; + + case 'Image' : + return { + AddItems : function( menu, tag, tagName ) + { + if ( tagName == 'IMG' && !tag.getAttribute( '_fckfakelement' ) ) + { + menu.AddSeparator() ; + menu.AddItem( 'Image', FCKLang.ImageProperties, 37 ) ; + } + }} ; + + case 'Anchor' : + return { + AddItems : function( menu, tag, tagName ) + { + // Go up to the anchor to test its properties + var oLink = FCKSelection.MoveToAncestorNode( 'A' ) ; + var bIsAnchor = ( oLink && oLink.name.length > 0 ) ; + + if ( bIsAnchor || ( tagName == 'IMG' && tag.getAttribute( '_fckanchor' ) ) ) + { + menu.AddSeparator() ; + menu.AddItem( 'Anchor', FCKLang.AnchorProp, 36 ) ; + menu.AddItem( 'AnchorDelete', FCKLang.AnchorDelete ) ; + } + }} ; + + case 'Flash' : + return { + AddItems : function( menu, tag, tagName ) + { + if ( tagName == 'IMG' && tag.getAttribute( '_fckflash' ) ) + { + menu.AddSeparator() ; + menu.AddItem( 'Flash', FCKLang.FlashProperties, 38 ) ; + } + }} ; + + case 'Form' : + return { + AddItems : function( menu, tag, tagName ) + { + if ( FCKSelection.HasAncestorNode('FORM') ) + { + menu.AddSeparator() ; + menu.AddItem( 'Form', FCKLang.FormProp, 48 ) ; + } + }} ; + + case 'Checkbox' : + return { + AddItems : function( menu, tag, tagName ) + { + if ( tagName == 'INPUT' && tag.type == 'checkbox' ) + { + menu.AddSeparator() ; + menu.AddItem( 'Checkbox', FCKLang.CheckboxProp, 49 ) ; + } + }} ; + + case 'Radio' : + return { + AddItems : function( menu, tag, tagName ) + { + if ( tagName == 'INPUT' && tag.type == 'radio' ) + { + menu.AddSeparator() ; + menu.AddItem( 'Radio', FCKLang.RadioButtonProp, 50 ) ; + } + }} ; + + case 'TextField' : + return { + AddItems : function( menu, tag, tagName ) + { + if ( tagName == 'INPUT' && ( tag.type == 'text' || tag.type == 'password' ) ) + { + menu.AddSeparator() ; + menu.AddItem( 'TextField', FCKLang.TextFieldProp, 51 ) ; + } + }} ; + + case 'HiddenField' : + return { + AddItems : function( menu, tag, tagName ) + { + if ( tagName == 'IMG' && tag.getAttribute( '_fckinputhidden' ) ) + { + menu.AddSeparator() ; + menu.AddItem( 'HiddenField', FCKLang.HiddenFieldProp, 56 ) ; + } + }} ; + + case 'ImageButton' : + return { + AddItems : function( menu, tag, tagName ) + { + if ( tagName == 'INPUT' && tag.type == 'image' ) + { + menu.AddSeparator() ; + menu.AddItem( 'ImageButton', FCKLang.ImageButtonProp, 55 ) ; + } + }} ; + + case 'Button' : + return { + AddItems : function( menu, tag, tagName ) + { + if ( tagName == 'INPUT' && ( tag.type == 'button' || tag.type == 'submit' || tag.type == 'reset' ) ) + { + menu.AddSeparator() ; + menu.AddItem( 'Button', FCKLang.ButtonProp, 54 ) ; + } + }} ; + + case 'Select' : + return { + AddItems : function( menu, tag, tagName ) + { + if ( tagName == 'SELECT' ) + { + menu.AddSeparator() ; + menu.AddItem( 'Select', FCKLang.SelectionFieldProp, 53 ) ; + } + }} ; + + case 'Textarea' : + return { + AddItems : function( menu, tag, tagName ) + { + if ( tagName == 'TEXTAREA' ) + { + menu.AddSeparator() ; + menu.AddItem( 'Textarea', FCKLang.TextareaProp, 52 ) ; + } + }} ; + + case 'BulletedList' : + return { + AddItems : function( menu, tag, tagName ) + { + if ( FCKSelection.HasAncestorNode('UL') ) + { + menu.AddSeparator() ; + menu.AddItem( 'BulletedList', FCKLang.BulletedListProp, 27 ) ; + } + }} ; + + case 'NumberedList' : + return { + AddItems : function( menu, tag, tagName ) + { + if ( FCKSelection.HasAncestorNode('OL') ) + { + menu.AddSeparator() ; + menu.AddItem( 'NumberedList', FCKLang.NumberedListProp, 26 ) ; + } + }} ; + } + return null ; +} + +function FCK_ContextMenu_OnBeforeOpen() +{ + // Update the UI. + FCK.Events.FireEvent( 'OnSelectionChange' ) ; + + // Get the actual selected tag (if any). + var oTag, sTagName ; + + // The extra () is to avoid a warning with strict error checking. This is ok. + if ( (oTag = FCKSelection.GetSelectedElement()) ) + sTagName = oTag.tagName ; + + // Cleanup the current menu items. + var oMenu = FCK.ContextMenu._InnerContextMenu ; + oMenu.RemoveAllItems() ; + + // Loop through the listeners. + var aListeners = FCK.ContextMenu.Listeners ; + for ( var i = 0 ; i < aListeners.length ; i++ ) + aListeners[i].AddItems( oMenu, oTag, sTagName ) ; +} + +function FCK_ContextMenu_OnItemClick( item ) +{ + FCK.Focus() ; + FCKCommands.GetCommand( item.Name ).Execute( item.CustomData ) ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fck_gecko.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fck_gecko.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fck_gecko.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,456 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Creation and initialization of the "FCK" object. This is the main + * object that represents an editor instance. + * (Gecko specific implementations) + */ + +FCK.Description = "FCKeditor for Gecko Browsers" ; + +FCK.InitializeBehaviors = function() +{ + // When calling "SetData", the editing area IFRAME gets a fixed height. So we must recalculate it. + if ( window.onresize ) // Not for Safari/Opera. + window.onresize() ; + + FCKFocusManager.AddWindow( this.EditorWindow ) ; + + this.ExecOnSelectionChange = function() + { + FCK.Events.FireEvent( "OnSelectionChange" ) ; + } + + this._ExecDrop = function( evt ) + { + if ( FCK.MouseDownFlag ) + { + FCK.MouseDownFlag = false ; + return ; + } + + if ( FCKConfig.ForcePasteAsPlainText ) + { + if ( evt.dataTransfer ) + { + var text = evt.dataTransfer.getData( 'Text' ) ; + text = FCKTools.HTMLEncode( text ) ; + text = FCKTools.ProcessLineBreaks( window, FCKConfig, text ) ; + FCK.InsertHtml( text ) ; + } + else if ( FCKConfig.ShowDropDialog ) + FCK.PasteAsPlainText() ; + + evt.preventDefault() ; + evt.stopPropagation() ; + } + } + + this._ExecCheckCaret = function( evt ) + { + if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG ) + return ; + + if ( evt.type == 'keypress' ) + { + var keyCode = evt.keyCode ; + // ignore if positioning key is not pressed. + // left or up arrow keys need to be processed as well, since <a> links can be expanded in Gecko's editor + // when the caret moved left or up from another block element below. + if ( keyCode < 33 || keyCode > 40 ) + return ; + } + + var blockEmptyStop = function( node ) + { + if ( node.nodeType != 1 ) + return false ; + var tag = node.tagName.toLowerCase() ; + return ( FCKListsLib.BlockElements[tag] || FCKListsLib.EmptyElements[tag] ) ; + } + + var moveCursor = function() + { + var selection = FCKSelection.GetSelection() ; + var range = selection.getRangeAt(0) ; + if ( ! range || ! range.collapsed ) + return ; + + var node = range.endContainer ; + + // only perform the patched behavior if we're at the end of a text node. + if ( node.nodeType != 3 ) + return ; + + if ( node.nodeValue.length != range.endOffset ) + return ; + + // only perform the patched behavior if we're in an <a> tag, or the End key is pressed. + var parentTag = node.parentNode.tagName.toLowerCase() ; + if ( ! ( parentTag == 'a' || String(node.parentNode.contentEditable) == 'false' || + ( ! ( FCKListsLib.BlockElements[parentTag] || FCKListsLib.NonEmptyBlockElements[parentTag] ) + && keyCode == 35 ) ) ) + return ; + + // our caret has moved to just after the last character of a text node under an unknown tag, how to proceed? + // first, see if there are other text nodes by DFS walking from this text node. + // - if the DFS has scanned all nodes under my parent, then go the next step. + // - if there is a text node after me but still under my parent, then do nothing and return. + var nextTextNode = FCKTools.GetNextTextNode( node, node.parentNode, blockEmptyStop ) ; + if ( nextTextNode ) + return ; + + // we're pretty sure we need to move the caret forcefully from here. + range = FCK.EditorDocument.createRange() ; + + nextTextNode = FCKTools.GetNextTextNode( node, node.parentNode.parentNode, blockEmptyStop ) ; + if ( nextTextNode ) + { + // Opera thinks the dummy empty text node we append beyond the end of <a> nodes occupies a caret + // position. So if the user presses the left key and we reset the caret position here, the user + // wouldn't be able to go back. + if ( FCKBrowserInfo.IsOpera && keyCode == 37 ) + return ; + + // now we want to get out of our current parent node, adopt the next parent, and move the caret to + // the appropriate text node under our new parent. + // our new parent might be our current parent's siblings if we are lucky. + range.setStart( nextTextNode, 0 ) ; + range.setEnd( nextTextNode, 0 ) ; + } + else + { + // no suitable next siblings under our grandparent! what to do next? + while ( node.parentNode + && node.parentNode != FCK.EditorDocument.body + && node.parentNode != FCK.EditorDocument.documentElement + && node == node.parentNode.lastChild + && ( ! FCKListsLib.BlockElements[node.parentNode.tagName.toLowerCase()] + && ! FCKListsLib.NonEmptyBlockElements[node.parentNode.tagName.toLowerCase()] ) ) + node = node.parentNode ; + + + if ( FCKListsLib.BlockElements[ parentTag ] + || FCKListsLib.EmptyElements[ parentTag ] + || node == FCK.EditorDocument.body ) + { + // if our parent is a block node, move to the end of our parent. + range.setStart( node, node.childNodes.length ) ; + range.setEnd( node, node.childNodes.length ) ; + } + else + { + // things are a little bit more interesting if our parent is not a block node + // due to the weired ways how Gecko's caret acts... + var stopNode = node.nextSibling ; + + // find out the next block/empty element at our grandparent, we'll + // move the caret just before it. + while ( stopNode ) + { + if ( stopNode.nodeType != 1 ) + { + stopNode = stopNode.nextSibling ; + continue ; + } + + var stopTag = stopNode.tagName.toLowerCase() ; + if ( FCKListsLib.BlockElements[stopTag] || FCKListsLib.EmptyElements[stopTag] + || FCKListsLib.NonEmptyBlockElements[stopTag] ) + break ; + stopNode = stopNode.nextSibling ; + } + + // note that the dummy marker below is NEEDED, otherwise the caret's behavior will + // be broken in Gecko. + var marker = FCK.EditorDocument.createTextNode( '' ) ; + if ( stopNode ) + node.parentNode.insertBefore( marker, stopNode ) ; + else + node.parentNode.appendChild( marker ) ; + range.setStart( marker, 0 ) ; + range.setEnd( marker, 0 ) ; + } + } + + selection.removeAllRanges() ; + selection.addRange( range ) ; + FCK.Events.FireEvent( "OnSelectionChange" ) ; + } + + setTimeout( moveCursor, 1 ) ; + } + + this.ExecOnSelectionChangeTimer = function() + { + if ( FCK.LastOnChangeTimer ) + window.clearTimeout( FCK.LastOnChangeTimer ) ; + + FCK.LastOnChangeTimer = window.setTimeout( FCK.ExecOnSelectionChange, 100 ) ; + } + + this.EditorDocument.addEventListener( 'mouseup', this.ExecOnSelectionChange, false ) ; + + // On Gecko, firing the "OnSelectionChange" event on every key press started to be too much + // slow. So, a timer has been implemented to solve performance issues when typing to quickly. + this.EditorDocument.addEventListener( 'keyup', this.ExecOnSelectionChangeTimer, false ) ; + + this._DblClickListener = function( e ) + { + FCK.OnDoubleClick( e.target ) ; + e.stopPropagation() ; + } + this.EditorDocument.addEventListener( 'dblclick', this._DblClickListener, true ) ; + + // Record changes for the undo system when there are key down events. + this.EditorDocument.addEventListener( 'keydown', this._KeyDownListener, false ) ; + + // Hooks for data object drops + if ( FCKBrowserInfo.IsGecko ) + { + this.EditorWindow.addEventListener( 'dragdrop', this._ExecDrop, true ) ; + } + else if ( FCKBrowserInfo.IsSafari ) + { + var cancelHandler = function( evt ){ if ( ! FCK.MouseDownFlag ) evt.returnValue = false ; } + this.EditorDocument.addEventListener( 'dragenter', cancelHandler, true ) ; + this.EditorDocument.addEventListener( 'dragover', cancelHandler, true ) ; + this.EditorDocument.addEventListener( 'drop', this._ExecDrop, true ) ; + this.EditorDocument.addEventListener( 'mousedown', + function( ev ) + { + var element = ev.srcElement ; + + if ( element.nodeName.IEquals( 'IMG', 'HR', 'INPUT', 'TEXTAREA', 'SELECT' ) ) + { + FCKSelection.SelectNode( element ) ; + } + }, true ) ; + + this.EditorDocument.addEventListener( 'mouseup', + function( ev ) + { + if ( ev.srcElement.nodeName.IEquals( 'INPUT', 'TEXTAREA', 'SELECT' ) ) + ev.preventDefault() + }, true ) ; + + this.EditorDocument.addEventListener( 'click', + function( ev ) + { + if ( ev.srcElement.nodeName.IEquals( 'INPUT', 'TEXTAREA', 'SELECT' ) ) + ev.preventDefault() + }, true ) ; + } + + // Kludge for buggy Gecko caret positioning logic (Bug #393 and #1056) + if ( FCKBrowserInfo.IsGecko || FCKBrowserInfo.IsOpera ) + { + this.EditorDocument.addEventListener( 'keypress', this._ExecCheckCaret, false ) ; + this.EditorDocument.addEventListener( 'click', this._ExecCheckCaret, false ) ; + } + + // Reset the context menu. + FCK.ContextMenu._InnerContextMenu.SetMouseClickWindow( FCK.EditorWindow ) ; + FCK.ContextMenu._InnerContextMenu.AttachToElement( FCK.EditorDocument ) ; +} + +FCK.MakeEditable = function() +{ + this.EditingArea.MakeEditable() ; +} + +// Disable the context menu in the editor (outside the editing area). +function Document_OnContextMenu( e ) +{ + if ( !e.target._FCKShowContextMenu ) + e.preventDefault() ; +} +document.oncontextmenu = Document_OnContextMenu ; + +// GetNamedCommandState overload for Gecko. +FCK._BaseGetNamedCommandState = FCK.GetNamedCommandState ; +FCK.GetNamedCommandState = function( commandName ) +{ + switch ( commandName ) + { + case 'Unlink' : + return FCKSelection.HasAncestorNode('A') ? FCK_TRISTATE_OFF : FCK_TRISTATE_DISABLED ; + default : + return FCK._BaseGetNamedCommandState( commandName ) ; + } +} + +// Named commands to be handled by this browsers specific implementation. +FCK.RedirectNamedCommands = +{ + Print : true, + Paste : true +} ; + +// ExecuteNamedCommand overload for Gecko. +FCK.ExecuteRedirectedNamedCommand = function( commandName, commandParameter ) +{ + switch ( commandName ) + { + case 'Print' : + FCK.EditorWindow.print() ; + break ; + case 'Paste' : + try + { + // Force the paste dialog for Safari (#50). + if ( FCKBrowserInfo.IsSafari ) + throw '' ; + + if ( FCK.Paste() ) + FCK.ExecuteNamedCommand( 'Paste', null, true ) ; + } + catch (e) { FCKDialog.OpenDialog( 'FCKDialog_Paste', FCKLang.Paste, 'dialog/fck_paste.html', 400, 330, 'Security' ) ; } + break ; + default : + FCK.ExecuteNamedCommand( commandName, commandParameter ) ; + } +} + +FCK._ExecPaste = function() +{ + // Save a snapshot for undo before actually paste the text + FCKUndo.SaveUndoStep() ; + + if ( FCKConfig.ForcePasteAsPlainText ) + { + FCK.PasteAsPlainText() ; + return false ; + } + + /* For now, the AutoDetectPasteFromWord feature is IE only. */ + return true ; +} + +//** +// FCK.InsertHtml: Inserts HTML at the current cursor location. Deletes the +// selected content if any. +FCK.InsertHtml = function( html ) +{ + html = FCKConfig.ProtectedSource.Protect( html ) ; + html = FCK.ProtectEvents( html ) ; + html = FCK.ProtectUrls( html ) ; + html = FCK.ProtectTags( html ) ; + + // Save an undo snapshot first. + FCKUndo.SaveUndoStep() ; + + // Insert the HTML code. + this.EditorDocument.execCommand( 'inserthtml', false, html ) ; + this.Focus() ; + + FCKDocumentProcessor.Process( FCK.EditorDocument ) ; + + // For some strange reason the SaveUndoStep() call doesn't activate the undo button at the first InsertHtml() call. + this.Events.FireEvent( "OnSelectionChange" ) ; +} + +FCK.PasteAsPlainText = function() +{ + // TODO: Implement the "Paste as Plain Text" code. + + // If the function is called immediately Firefox 2 does automatically paste the contents as soon as the new dialog is created + // so we run it in a Timeout and the paste event can be cancelled + FCKTools.RunFunction( FCKDialog.OpenDialog, FCKDialog, ['FCKDialog_Paste', FCKLang.PasteAsText, 'dialog/fck_paste.html', 400, 330, 'PlainText'] ) ; + +/* + var sText = FCKTools.HTMLEncode( clipboardData.getData("Text") ) ; + sText = sText.replace( /\n/g, '<BR>' ) ; + this.InsertHtml( sText ) ; +*/ +} +/* +FCK.PasteFromWord = function() +{ + // TODO: Implement the "Paste as Plain Text" code. + + FCKDialog.OpenDialog( 'FCKDialog_Paste', FCKLang.PasteFromWord, 'dialog/fck_paste.html', 400, 330, 'Word' ) ; + +// FCK.CleanAndPaste( FCK.GetClipboardHTML() ) ; +} +*/ +FCK.GetClipboardHTML = function() +{ + return '' ; +} + +FCK.CreateLink = function( url, noUndo ) +{ + // Creates the array that will be returned. It contains one or more created links (see #220). + var aCreatedLinks = new Array() ; + + FCK.ExecuteNamedCommand( 'Unlink', null, false, !!noUndo ) ; + + if ( url.length > 0 ) + { + // Generate a temporary name for the link. + var sTempUrl = 'javascript:void(0);/*' + ( new Date().getTime() ) + '*/' ; + + // Use the internal "CreateLink" command to create the link. + FCK.ExecuteNamedCommand( 'CreateLink', sTempUrl, false, !!noUndo ) ; + + // Retrieve the just created links using XPath. + var oLinksInteractor = this.EditorDocument.evaluate("//a[@href='" + sTempUrl + "']", this.EditorDocument.body, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null) ; + + // Add all links to the returning array. + for ( var i = 0 ; i < oLinksInteractor.snapshotLength ; i++ ) + { + var oLink = oLinksInteractor.snapshotItem( i ) ; + oLink.href = url ; + + // It may happen that the browser (aka Safari) decides to use the + // URL as the link content to not leave it empty. In this case, + // let's reset it. + if ( sTempUrl == oLink.innerHTML ) + oLink.innerHTML = '' ; + + aCreatedLinks.push( oLink ) ; + } + } + + return aCreatedLinks ; +} + +FCK._FillEmptyBlock = function( emptyBlockNode ) +{ + if ( ! emptyBlockNode || emptyBlockNode.nodeType != 1 ) + return ; + var nodeTag = emptyBlockNode.tagName.toLowerCase() ; + if ( nodeTag != 'p' && nodeTag != 'div' ) + return ; + if ( emptyBlockNode.firstChild ) + return ; + FCKTools.AppendBogusBr( emptyBlockNode ) ; +} + +FCK._ExecCheckEmptyBlock = function() +{ + FCK._FillEmptyBlock( FCK.EditorDocument.body.firstChild ) ; + var sel = FCKSelection.GetSelection() ; + if ( !sel || sel.rangeCount < 1 ) + return ; + var range = sel.getRangeAt( 0 ); + FCK._FillEmptyBlock( range.startContainer ) ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fck_ie.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fck_ie.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fck_ie.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,453 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Creation and initialization of the "FCK" object. This is the main + * object that represents an editor instance. + * (IE specific implementations) + */ + +FCK.Description = "FCKeditor for Internet Explorer 5.5+" ; + +FCK._GetBehaviorsStyle = function() +{ + if ( !FCK._BehaviorsStyle ) + { + var sBasePath = FCKConfig.FullBasePath ; + var sTableBehavior = '' ; + var sStyle ; + + // The behaviors should be pointed using the FullBasePath to avoid security + // errors when using a different BaseHref. + sStyle = '<style type="text/css" _fcktemp="true">' ; + + if ( FCKConfig.ShowBorders ) + sTableBehavior = 'url(' + sBasePath + 'css/behaviors/showtableborders.htc)' ; + + // Disable resize handlers. + sStyle += 'INPUT,TEXTAREA,SELECT,.FCK__Anchor,.FCK__PageBreak,.FCK__InputHidden' ; + + if ( FCKConfig.DisableObjectResizing ) + { + sStyle += ',IMG' ; + sTableBehavior += ' url(' + sBasePath + 'css/behaviors/disablehandles.htc)' ; + } + + sStyle += ' { behavior: url(' + sBasePath + 'css/behaviors/disablehandles.htc) ; }' ; + + if ( sTableBehavior.length > 0 ) + sStyle += 'TABLE { behavior: ' + sTableBehavior + ' ; }' ; + + sStyle += '</style>' ; + FCK._BehaviorsStyle = sStyle ; + } + + return FCK._BehaviorsStyle ; +} + +function Doc_OnMouseUp() +{ + if ( FCK.EditorWindow.event.srcElement.tagName == 'HTML' ) + { + FCK.Focus() ; + FCK.EditorWindow.event.cancelBubble = true ; + FCK.EditorWindow.event.returnValue = false ; + } +} + +function Doc_OnPaste() +{ + var body = FCK.EditorDocument.body ; + + body.detachEvent( 'onpaste', Doc_OnPaste ) ; + + var ret = FCK.Paste( !FCKConfig.ForcePasteAsPlainText && !FCKConfig.AutoDetectPasteFromWord ) ; + + body.attachEvent( 'onpaste', Doc_OnPaste ) ; + + return ret ; +} + +function Doc_OnDblClick() +{ + FCK.OnDoubleClick( FCK.EditorWindow.event.srcElement ) ; + FCK.EditorWindow.event.cancelBubble = true ; +} + +function Doc_OnSelectionChange() +{ + // Don't fire the event if no document is loaded. + if ( !FCK.IsSelectionChangeLocked && FCK.EditorDocument ) + FCK.Events.FireEvent( "OnSelectionChange" ) ; +} + +function Doc_OnDrop() +{ + if ( FCK.MouseDownFlag ) + { + FCK.MouseDownFlag = false ; + return ; + } + + if ( FCKConfig.ForcePasteAsPlainText ) + { + var evt = FCK.EditorWindow.event ; + + if ( FCK._CheckIsPastingEnabled() || FCKConfig.ShowDropDialog ) + FCK.PasteAsPlainText( evt.dataTransfer.getData( 'Text' ) ) ; + + evt.returnValue = false ; + evt.cancelBubble = true ; + } +} + +FCK.InitializeBehaviors = function( dontReturn ) +{ + // Set the focus to the editable area when clicking in the document area. + // TODO: The cursor must be positioned at the end. + this.EditorDocument.attachEvent( 'onmouseup', Doc_OnMouseUp ) ; + + // Intercept pasting operations + this.EditorDocument.body.attachEvent( 'onpaste', Doc_OnPaste ) ; + + // Intercept drop operations + this.EditorDocument.body.attachEvent( 'ondrop', Doc_OnDrop ) ; + + // Reset the context menu. + FCK.ContextMenu._InnerContextMenu.AttachToElement( FCK.EditorDocument.body ) ; + + this.EditorDocument.attachEvent("onkeydown", FCK._KeyDownListener ) ; + + this.EditorDocument.attachEvent("ondblclick", Doc_OnDblClick ) ; + + // Catch cursor selection changes. + this.EditorDocument.attachEvent("onselectionchange", Doc_OnSelectionChange ) ; + + FCKTools.AddEventListener( FCK.EditorDocument, 'mousedown', Doc_OnMouseDown ) ; +} + +FCK.InsertHtml = function( html ) +{ + html = FCKConfig.ProtectedSource.Protect( html ) ; + html = FCK.ProtectEvents( html ) ; + html = FCK.ProtectUrls( html ) ; + html = FCK.ProtectTags( html ) ; + +// FCK.Focus() ; + FCK.EditorWindow.focus() ; + + FCKUndo.SaveUndoStep() ; + + // Gets the actual selection. + var oSel = FCKSelection.GetSelection() ; + + // Deletes the actual selection contents. + if ( oSel.type.toLowerCase() == 'control' ) + oSel.clear() ; + + // Using the following trick, any comment in the beginning of the HTML will + // be preserved. + html = '<span id="__fakeFCKRemove__" style="display:none;">fakeFCKRemove</span>' + html ; + + // Insert the HTML. + oSel.createRange().pasteHTML( html ) ; + + // Remove the fake node + FCK.EditorDocument.getElementById('__fakeFCKRemove__').removeNode( true ) ; + + FCKDocumentProcessor.Process( FCK.EditorDocument ) ; + + // For some strange reason the SaveUndoStep() call doesn't activate the undo button at the first InsertHtml() call. + this.Events.FireEvent( "OnSelectionChange" ) ; +} + +FCK.SetInnerHtml = function( html ) // IE Only +{ + var oDoc = FCK.EditorDocument ; + // Using the following trick, any comment in the beginning of the HTML will + // be preserved. + oDoc.body.innerHTML = '<div id="__fakeFCKRemove__"> </div>' + html ; + oDoc.getElementById('__fakeFCKRemove__').removeNode( true ) ; +} + +function FCK_PreloadImages() +{ + var oPreloader = new FCKImagePreloader() ; + + // Add the configured images. + oPreloader.AddImages( FCKConfig.PreloadImages ) ; + + // Add the skin icons strip. + oPreloader.AddImages( FCKConfig.SkinPath + 'fck_strip.gif' ) ; + + oPreloader.OnComplete = LoadToolbarSetup ; + oPreloader.Start() ; +} + +// Disable the context menu in the editor (outside the editing area). +function Document_OnContextMenu() +{ + return ( event.srcElement._FCKShowContextMenu == true ) ; +} +document.oncontextmenu = Document_OnContextMenu ; + +function FCK_Cleanup() +{ + this.LinkedField = null ; + this.EditorWindow = null ; + this.EditorDocument = null ; +} + +FCK._ExecPaste = function() +{ + // As we call ExecuteNamedCommand('Paste'), it would enter in a loop. So, let's use a semaphore. + if ( FCK._PasteIsRunning ) + return true ; + + if ( FCKConfig.ForcePasteAsPlainText ) + { + FCK.PasteAsPlainText() ; + return false ; + } + + var sHTML = FCK._CheckIsPastingEnabled( true ) ; + + if ( sHTML === false ) + FCKTools.RunFunction( FCKDialog.OpenDialog, FCKDialog, ['FCKDialog_Paste', FCKLang.Paste, 'dialog/fck_paste.html', 400, 330, 'Security'] ) ; + else + { + if ( FCKConfig.AutoDetectPasteFromWord && sHTML.length > 0 ) + { + var re = /<\w[^>]*(( class="?MsoNormal"?)|(="mso-))/gi ; + if ( re.test( sHTML ) ) + { + if ( confirm( FCKLang.PasteWordConfirm ) ) + { + FCK.PasteFromWord() ; + return false ; + } + } + } + + // Instead of inserting the retrieved HTML, let's leave the OS work for us, + // by calling FCK.ExecuteNamedCommand( 'Paste' ). It could give better results. + + // Enable the semaphore to avoid a loop. + FCK._PasteIsRunning = true ; + + FCK.ExecuteNamedCommand( 'Paste' ) ; + + // Removes the semaphore. + delete FCK._PasteIsRunning ; + } + + // Let's always make a custom implementation (return false), otherwise + // the new Keyboard Handler may conflict with this code, and the CTRL+V code + // could result in a simple "V" being pasted. + return false ; +} + +FCK.PasteAsPlainText = function( forceText ) +{ + if ( !FCK._CheckIsPastingEnabled() ) + { + FCKDialog.OpenDialog( 'FCKDialog_Paste', FCKLang.PasteAsText, 'dialog/fck_paste.html', 400, 330, 'PlainText' ) ; + return ; + } + + // Get the data available in the clipboard in text format. + var sText = null ; + if ( ! forceText ) + sText = clipboardData.getData("Text") ; + else + sText = forceText ; + + if ( sText && sText.length > 0 ) + { + // Replace the carriage returns with <BR> + sText = FCKTools.HTMLEncode( sText ) ; + sText = FCKTools.ProcessLineBreaks( window, FCKConfig, sText ) ; + + var closeTagIndex = sText.search( '</p>' ) ; + var startTagIndex = sText.search( '<p>' ) ; + + if ( ( closeTagIndex != -1 && startTagIndex != -1 && closeTagIndex < startTagIndex ) + || ( closeTagIndex != -1 && startTagIndex == -1 ) ) + { + var prefix = sText.substr( 0, closeTagIndex ) ; + sText = sText.substr( closeTagIndex + 4 ) ; + this.InsertHtml( prefix ) ; + } + + // Insert the resulting data in the editor. + FCKUndo.SaveLocked = true ; + this.InsertHtml( sText ) ; + FCKUndo.SaveLocked = false ; + } +} + +FCK._CheckIsPastingEnabled = function( returnContents ) +{ + // The following seams to be the only reliable way to check is script + // pasting operations are enabled in the security settings of IE6 and IE7. + // It adds a little bit of overhead to the check, but so far that's the + // only way, mainly because of IE7. + + FCK._PasteIsEnabled = false ; + + document.body.attachEvent( 'onpaste', FCK_CheckPasting_Listener ) ; + + // The execCommand in GetClipboardHTML will fire the "onpaste", only if the + // security settings are enabled. + var oReturn = FCK.GetClipboardHTML() ; + + document.body.detachEvent( 'onpaste', FCK_CheckPasting_Listener ) ; + + if ( FCK._PasteIsEnabled ) + { + if ( !returnContents ) + oReturn = true ; + } + else + oReturn = false ; + + delete FCK._PasteIsEnabled ; + + return oReturn ; +} + +function FCK_CheckPasting_Listener() +{ + FCK._PasteIsEnabled = true ; +} + +FCK.GetClipboardHTML = function() +{ + var oDiv = document.getElementById( '___FCKHiddenDiv' ) ; + + if ( !oDiv ) + { + oDiv = document.createElement( 'DIV' ) ; + oDiv.id = '___FCKHiddenDiv' ; + + var oDivStyle = oDiv.style ; + oDivStyle.position = 'absolute' ; + oDivStyle.visibility = oDivStyle.overflow = 'hidden' ; + oDivStyle.width = oDivStyle.height = 1 ; + + document.body.appendChild( oDiv ) ; + } + + oDiv.innerHTML = '' ; + + var oTextRange = document.body.createTextRange() ; + oTextRange.moveToElementText( oDiv ) ; + oTextRange.execCommand( 'Paste' ) ; + + var sData = oDiv.innerHTML ; + oDiv.innerHTML = '' ; + + return sData ; +} + +FCK.CreateLink = function( url, noUndo ) +{ + // Creates the array that will be returned. It contains one or more created links (see #220). + var aCreatedLinks = new Array() ; + + // Remove any existing link in the selection. + FCK.ExecuteNamedCommand( 'Unlink', null, false, !!noUndo ) ; + + if ( url.length > 0 ) + { + // If there are several images, and you try to link each one, all the images get inside the link: + // <img><img> -> <a><img></a><img> -> <a><img><img></a> due to the call to 'CreateLink' (bug in IE) + if (FCKSelection.GetType() == 'Control') + { + // Create a link + var oLink = this.EditorDocument.createElement( 'A' ) ; + oLink.href = url ; + + // Get the selected object + var oControl = FCKSelection.GetSelectedElement() ; + // Put the link just before the object + oControl.parentNode.insertBefore(oLink, oControl) ; + // Move the object inside the link + oControl.parentNode.removeChild( oControl ) ; + oLink.appendChild( oControl ) ; + + return [ oLink ] ; + } + + // Generate a temporary name for the link. + var sTempUrl = 'javascript:void(0);/*' + ( new Date().getTime() ) + '*/' ; + + // Use the internal "CreateLink" command to create the link. + FCK.ExecuteNamedCommand( 'CreateLink', sTempUrl, false, !!noUndo ) ; + + // Look for the just create link. + var oLinks = this.EditorDocument.links ; + + for ( i = 0 ; i < oLinks.length ; i++ ) + { + var oLink = oLinks[i] ; + + // Check it this a newly created link. + // getAttribute must be used. oLink.url may cause problems with IE7 (#555). + if ( oLink.getAttribute( 'href', 2 ) == sTempUrl ) + { + var sInnerHtml = oLink.innerHTML ; // Save the innerHTML (IE changes it if it is like an URL). + oLink.href = url ; + oLink.innerHTML = sInnerHtml ; // Restore the innerHTML. + + // If the last child is a <br> move it outside the link or it + // will be too easy to select this link again #388. + var oLastChild = oLink.lastChild ; + if ( oLastChild && oLastChild.nodeName == 'BR' ) + { + // Move the BR after the link. + FCKDomTools.InsertAfterNode( oLink, oLink.removeChild( oLastChild ) ) ; + } + + aCreatedLinks.push( oLink ) ; + } + } + } + + return aCreatedLinks ; +} + +function _FCK_RemoveDisabledAtt() +{ + this.removeAttribute( 'disabled' ) ; +} + +function Doc_OnMouseDown( evt ) +{ + var e = evt.srcElement ; + + // Radio buttons and checkboxes should not be allowed to be triggered in IE + // in editable mode. Otherwise the whole browser window may be locked by + // the buttons. (#1782) + if ( e.nodeName.IEquals( 'input' ) && e.type.IEquals( ['radio', 'checkbox'] ) && !e.disabled ) + { + e.disabled = true ; + FCKTools.SetTimeout( _FCK_RemoveDisabledAtt, 1, e ) ; + } +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckbrowserinfo.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckbrowserinfo.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckbrowserinfo.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,61 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Contains browser detection information. + */ + +var s = navigator.userAgent.toLowerCase() ; + +var FCKBrowserInfo = +{ + IsIE : /*@cc_on!@*/false, + IsIE7 : /*@cc_on!@*/false && ( parseInt( s.match( /msie (\d+)/ )[1], 10 ) >= 7 ), + IsIE6 : /*@cc_on!@*/false && ( parseInt( s.match( /msie (\d+)/ )[1], 10 ) >= 6 ), + IsGecko : s.Contains('gecko/'), + IsSafari : s.Contains(' applewebkit/'), // Read "IsWebKit" + IsOpera : !!window.opera, + IsAIR : s.Contains(' adobeair/'), + IsMac : s.Contains('macintosh') +} ; + +// Completes the browser info with further Gecko information. +(function( browserInfo ) +{ + browserInfo.IsGeckoLike = ( browserInfo.IsGecko || browserInfo.IsSafari || browserInfo.IsOpera ) ; + + if ( browserInfo.IsGecko ) + { + var geckoVersion = s.match( /gecko\/(\d+)/ )[1] ; + + // Actually "10" refers to Gecko versions before Firefox 1.5, when + // Gecko 1.8 (build 20051111) has been released. + + // Some browser (like Mozilla 1.7.13) may have a Gecko build greater + // than 20051111, so we must also check for the revision number not to + // be 1.7 (we are assuming that rv < 1.7 will not have build > 20051111). + + // TODO: Future versions may consider the rv number only, but it is + // still to check that all Gecko based browser present the rv number. + browserInfo.IsGecko10 = ( ( geckoVersion < 20051111 ) || ( /rv:1\.7/.test(s) ) ) ; + browserInfo.IsGecko19 = /rv:1\.9/.test(s) ; + } + else + browserInfo.IsGecko10 = false ; +})(FCKBrowserInfo) ; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckcodeformatter.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckcodeformatter.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckcodeformatter.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,100 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Format the HTML. + */ + +var FCKCodeFormatter = new Object() ; + +FCKCodeFormatter.Init = function() +{ + var oRegex = this.Regex = new Object() ; + + // Regex for line breaks. + oRegex.BlocksOpener = /\<(P|DIV|H1|H2|H3|H4|H5|H6|ADDRESS|PRE|OL|UL|LI|TITLE|META|LINK|BASE|SCRIPT|LINK|TD|TH|AREA|OPTION)[^\>]*\>/gi ; + oRegex.BlocksCloser = /\<\/(P|DIV|H1|H2|H3|H4|H5|H6|ADDRESS|PRE|OL|UL|LI|TITLE|META|LINK|BASE|SCRIPT|LINK|TD|TH|AREA|OPTION)[^\>]*\>/gi ; + + oRegex.NewLineTags = /\<(BR|HR)[^\>]*\>/gi ; + + oRegex.MainTags = /\<\/?(HTML|HEAD|BODY|FORM|TABLE|TBODY|THEAD|TR)[^\>]*\>/gi ; + + oRegex.LineSplitter = /\s*\n+\s*/g ; + + // Regex for indentation. + oRegex.IncreaseIndent = /^\<(HTML|HEAD|BODY|FORM|TABLE|TBODY|THEAD|TR|UL|OL)[ \/\>]/i ; + oRegex.DecreaseIndent = /^\<\/(HTML|HEAD|BODY|FORM|TABLE|TBODY|THEAD|TR|UL|OL)[ \>]/i ; + oRegex.FormatIndentatorRemove = new RegExp( '^' + FCKConfig.FormatIndentator ) ; + + oRegex.ProtectedTags = /(<PRE[^>]*>)([\s\S]*?)(<\/PRE>)/gi ; +} + +FCKCodeFormatter._ProtectData = function( outer, opener, data, closer ) +{ + return opener + '___FCKpd___' + FCKCodeFormatter.ProtectedData.AddItem( data ) + closer ; +} + +FCKCodeFormatter.Format = function( html ) +{ + if ( !this.Regex ) + this.Init() ; + + // Protected content that remain untouched during the + // process go in the following array. + FCKCodeFormatter.ProtectedData = new Array() ; + + var sFormatted = html.replace( this.Regex.ProtectedTags, FCKCodeFormatter._ProtectData ) ; + + // Line breaks. + sFormatted = sFormatted.replace( this.Regex.BlocksOpener, '\n$&' ) ; + sFormatted = sFormatted.replace( this.Regex.BlocksCloser, '$&\n' ) ; + sFormatted = sFormatted.replace( this.Regex.NewLineTags, '$&\n' ) ; + sFormatted = sFormatted.replace( this.Regex.MainTags, '\n$&\n' ) ; + + // Indentation. + var sIndentation = '' ; + + var asLines = sFormatted.split( this.Regex.LineSplitter ) ; + sFormatted = '' ; + + for ( var i = 0 ; i < asLines.length ; i++ ) + { + var sLine = asLines[i] ; + + if ( sLine.length == 0 ) + continue ; + + if ( this.Regex.DecreaseIndent.test( sLine ) ) + sIndentation = sIndentation.replace( this.Regex.FormatIndentatorRemove, '' ) ; + + sFormatted += sIndentation + sLine + '\n' ; + + if ( this.Regex.IncreaseIndent.test( sLine ) ) + sIndentation += FCKConfig.FormatIndentator ; + } + + // Now we put back the protected data. + for ( var j = 0 ; j < FCKCodeFormatter.ProtectedData.length ; j++ ) + { + var oRegex = new RegExp( '___FCKpd___' + j ) ; + sFormatted = sFormatted.replace( oRegex, FCKCodeFormatter.ProtectedData[j].replace( /\$/g, '$$$$' ) ) ; + } + + return sFormatted.Trim() ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckcommands.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckcommands.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckcommands.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,167 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Define all commands available in the editor. + */ + +var FCKCommands = FCK.Commands = new Object() ; +FCKCommands.LoadedCommands = new Object() ; + +FCKCommands.RegisterCommand = function( commandName, command ) +{ + this.LoadedCommands[ commandName ] = command ; +} + +FCKCommands.GetCommand = function( commandName ) +{ + var oCommand = FCKCommands.LoadedCommands[ commandName ] ; + + if ( oCommand ) + return oCommand ; + + switch ( commandName ) + { + case 'Bold' : + case 'Italic' : + case 'Underline' : + case 'StrikeThrough': + case 'Subscript' : + case 'Superscript' : oCommand = new FCKCoreStyleCommand( commandName ) ; break ; + + case 'RemoveFormat' : oCommand = new FCKRemoveFormatCommand() ; break ; + + case 'DocProps' : oCommand = new FCKDialogCommand( 'DocProps' , FCKLang.DocProps , 'dialog/fck_docprops.html' , 400, 380, FCKCommands.GetFullPageState ) ; break ; + case 'Templates' : oCommand = new FCKDialogCommand( 'Templates' , FCKLang.DlgTemplatesTitle , 'dialog/fck_template.html' , 380, 450 ) ; break ; + case 'Link' : oCommand = new FCKDialogCommand( 'Link' , FCKLang.DlgLnkWindowTitle , 'dialog/fck_link.html' , 400, 300 ) ; break ; + case 'Unlink' : oCommand = new FCKUnlinkCommand() ; break ; + case 'Anchor' : oCommand = new FCKDialogCommand( 'Anchor' , FCKLang.DlgAnchorTitle , 'dialog/fck_anchor.html' , 370, 160 ) ; break ; + case 'AnchorDelete' : oCommand = new FCKAnchorDeleteCommand() ; break ; + case 'BulletedList' : oCommand = new FCKDialogCommand( 'BulletedList', FCKLang.BulletedListProp , 'dialog/fck_listprop.html?UL' , 370, 160 ) ; break ; + case 'NumberedList' : oCommand = new FCKDialogCommand( 'NumberedList', FCKLang.NumberedListProp , 'dialog/fck_listprop.html?OL' , 370, 160 ) ; break ; + case 'About' : oCommand = new FCKDialogCommand( 'About' , FCKLang.About , 'dialog/fck_about.html' , 420, 330, function(){ return FCK_TRISTATE_OFF ; } ) ; break ; + case 'Find' : oCommand = new FCKDialogCommand( 'Find' , FCKLang.DlgFindAndReplaceTitle, 'dialog/fck_replace.html' , 340, 230, null, null, 'Find' ) ; break ; + case 'Replace' : oCommand = new FCKDialogCommand( 'Replace' , FCKLang.DlgFindAndReplaceTitle, 'dialog/fck_replace.html' , 340, 230, null, null, 'Replace' ) ; break ; + + case 'Image' : oCommand = new FCKDialogCommand( 'Image' , FCKLang.DlgImgTitle , 'dialog/fck_image.html' , 450, 390 ) ; break ; + case 'Flash' : oCommand = new FCKDialogCommand( 'Flash' , FCKLang.DlgFlashTitle , 'dialog/fck_flash.html' , 450, 390 ) ; break ; + case 'SpecialChar' : oCommand = new FCKDialogCommand( 'SpecialChar', FCKLang.DlgSpecialCharTitle , 'dialog/fck_specialchar.html' , 400, 290 ) ; break ; + case 'Smiley' : oCommand = new FCKDialogCommand( 'Smiley' , FCKLang.DlgSmileyTitle , 'dialog/fck_smiley.html' , FCKConfig.SmileyWindowWidth, FCKConfig.SmileyWindowHeight ) ; break ; + case 'Table' : oCommand = new FCKDialogCommand( 'Table' , FCKLang.DlgTableTitle , 'dialog/fck_table.html' , 480, 250 ) ; break ; + case 'TableProp' : oCommand = new FCKDialogCommand( 'Table' , FCKLang.DlgTableTitle , 'dialog/fck_table.html?Parent', 480, 250 ) ; break ; + case 'TableCellProp': oCommand = new FCKDialogCommand( 'TableCell' , FCKLang.DlgCellTitle , 'dialog/fck_tablecell.html' , 550, 240 ) ; break ; + + case 'Style' : oCommand = new FCKStyleCommand() ; break ; + + case 'FontName' : oCommand = new FCKFontNameCommand() ; break ; + case 'FontSize' : oCommand = new FCKFontSizeCommand() ; break ; + case 'FontFormat' : oCommand = new FCKFormatBlockCommand() ; break ; + + case 'Source' : oCommand = new FCKSourceCommand() ; break ; + case 'Preview' : oCommand = new FCKPreviewCommand() ; break ; + case 'Save' : oCommand = new FCKSaveCommand() ; break ; + case 'NewPage' : oCommand = new FCKNewPageCommand() ; break ; + case 'PageBreak' : oCommand = new FCKPageBreakCommand() ; break ; + case 'Rule' : oCommand = new FCKRuleCommand() ; break ; + + case 'TextColor' : oCommand = new FCKTextColorCommand('ForeColor') ; break ; + case 'BGColor' : oCommand = new FCKTextColorCommand('BackColor') ; break ; + + case 'Paste' : oCommand = new FCKPasteCommand() ; break ; + case 'PasteText' : oCommand = new FCKPastePlainTextCommand() ; break ; + case 'PasteWord' : oCommand = new FCKPasteWordCommand() ; break ; + + case 'JustifyLeft' : oCommand = new FCKJustifyCommand( 'left' ) ; break ; + case 'JustifyCenter' : oCommand = new FCKJustifyCommand( 'center' ) ; break ; + case 'JustifyRight' : oCommand = new FCKJustifyCommand( 'right' ) ; break ; + case 'JustifyFull' : oCommand = new FCKJustifyCommand( 'justify' ) ; break ; + case 'Indent' : oCommand = new FCKIndentCommand( 'indent', FCKConfig.IndentLength ) ; break ; + case 'Outdent' : oCommand = new FCKIndentCommand( 'outdent', FCKConfig.IndentLength * -1 ) ; break ; + case 'Blockquote' : oCommand = new FCKBlockQuoteCommand() ; break ; + + case 'TableInsertRowAfter' : oCommand = new FCKTableCommand('TableInsertRowAfter') ; break ; + case 'TableInsertRowBefore' : oCommand = new FCKTableCommand('TableInsertRowBefore') ; break ; + case 'TableDeleteRows' : oCommand = new FCKTableCommand('TableDeleteRows') ; break ; + case 'TableInsertColumnAfter' : oCommand = new FCKTableCommand('TableInsertColumnAfter') ; break ; + case 'TableInsertColumnBefore' : oCommand = new FCKTableCommand('TableInsertColumnBefore') ; break ; + case 'TableDeleteColumns' : oCommand = new FCKTableCommand('TableDeleteColumns') ; break ; + case 'TableInsertCellAfter' : oCommand = new FCKTableCommand('TableInsertCellAfter') ; break ; + case 'TableInsertCellBefore' : oCommand = new FCKTableCommand('TableInsertCellBefore') ; break ; + case 'TableDeleteCells' : oCommand = new FCKTableCommand('TableDeleteCells') ; break ; + case 'TableMergeCells' : oCommand = new FCKTableCommand('TableMergeCells') ; break ; + case 'TableMergeRight' : oCommand = new FCKTableCommand('TableMergeRight') ; break ; + case 'TableMergeDown' : oCommand = new FCKTableCommand('TableMergeDown') ; break ; + case 'TableHorizontalSplitCell' : oCommand = new FCKTableCommand('TableHorizontalSplitCell') ; break ; + case 'TableVerticalSplitCell' : oCommand = new FCKTableCommand('TableVerticalSplitCell') ; break ; + case 'TableDelete' : oCommand = new FCKTableCommand('TableDelete') ; break ; + + case 'Form' : oCommand = new FCKDialogCommand( 'Form' , FCKLang.Form , 'dialog/fck_form.html' , 380, 210 ) ; break ; + case 'Checkbox' : oCommand = new FCKDialogCommand( 'Checkbox' , FCKLang.Checkbox , 'dialog/fck_checkbox.html' , 380, 200 ) ; break ; + case 'Radio' : oCommand = new FCKDialogCommand( 'Radio' , FCKLang.RadioButton , 'dialog/fck_radiobutton.html' , 380, 200 ) ; break ; + case 'TextField' : oCommand = new FCKDialogCommand( 'TextField' , FCKLang.TextField , 'dialog/fck_textfield.html' , 380, 210 ) ; break ; + case 'Textarea' : oCommand = new FCKDialogCommand( 'Textarea' , FCKLang.Textarea , 'dialog/fck_textarea.html' , 380, 210 ) ; break ; + case 'HiddenField' : oCommand = new FCKDialogCommand( 'HiddenField', FCKLang.HiddenField , 'dialog/fck_hiddenfield.html' , 380, 190 ) ; break ; + case 'Button' : oCommand = new FCKDialogCommand( 'Button' , FCKLang.Button , 'dialog/fck_button.html' , 380, 210 ) ; break ; + case 'Select' : oCommand = new FCKDialogCommand( 'Select' , FCKLang.SelectionField, 'dialog/fck_select.html' , 400, 340 ) ; break ; + case 'ImageButton' : oCommand = new FCKDialogCommand( 'ImageButton', FCKLang.ImageButton , 'dialog/fck_image.html?ImageButton', 450, 390 ) ; break ; + + case 'SpellCheck' : oCommand = new FCKSpellCheckCommand() ; break ; + case 'FitWindow' : oCommand = new FCKFitWindow() ; break ; + + case 'Undo' : oCommand = new FCKUndoCommand() ; break ; + case 'Redo' : oCommand = new FCKRedoCommand() ; break ; + case 'Copy' : oCommand = new FCKCutCopyCommand( false ) ; break ; + case 'Cut' : oCommand = new FCKCutCopyCommand( true ) ; break ; + + case 'SelectAll' : oCommand = new FCKSelectAllCommand() ; break ; + case 'InsertOrderedList' : oCommand = new FCKListCommand( 'insertorderedlist', 'ol' ) ; break ; + case 'InsertUnorderedList' : oCommand = new FCKListCommand( 'insertunorderedlist', 'ul' ) ; break ; + case 'ShowBlocks' : oCommand = new FCKShowBlockCommand( 'ShowBlocks', FCKConfig.StartupShowBlocks ? FCK_TRISTATE_ON : FCK_TRISTATE_OFF ) ; break ; + + // Generic Undefined command (usually used when a command is under development). + case 'Undefined' : oCommand = new FCKUndefinedCommand() ; break ; + + // By default we assume that it is a named command. + default: + if ( FCKRegexLib.NamedCommands.test( commandName ) ) + oCommand = new FCKNamedCommand( commandName ) ; + else + { + alert( FCKLang.UnknownCommand.replace( /%1/g, commandName ) ) ; + return null ; + } + } + + FCKCommands.LoadedCommands[ commandName ] = oCommand ; + + return oCommand ; +} + +// Gets the state of the "Document Properties" button. It must be enabled only +// when "Full Page" editing is available. +FCKCommands.GetFullPageState = function() +{ + return FCKConfig.FullPage ? FCK_TRISTATE_OFF : FCK_TRISTATE_DISABLED ; +} + + +FCKCommands.GetBooleanState = function( isDisabled ) +{ + return isDisabled ? FCK_TRISTATE_DISABLED : FCK_TRISTATE_OFF ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckconfig.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckconfig.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckconfig.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,238 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Creates and initializes the FCKConfig object. + */ + +var FCKConfig = FCK.Config = new Object() ; + +/* + For the next major version (probably 3.0) we should move all this stuff to + another dedicated object and leave FCKConfig as a holder object for settings only). +*/ + +// Editor Base Path +if ( document.location.protocol == 'file:' ) +{ + FCKConfig.BasePath = decodeURIComponent( document.location.pathname.substr(1) ) ; + FCKConfig.BasePath = FCKConfig.BasePath.replace( /\\/gi, '/' ) ; + + // The way to address local files is different according to the OS. + // In Windows it is file:// but in MacOs it is file:/// so let's get it automatically + var sFullProtocol = document.location.href.match( /^(file\:\/{2,3})/ )[1] ; + // #945 Opera does strange things with files loaded from the disk, and it fails in Mac to load xml files + if ( FCKBrowserInfo.IsOpera ) + sFullProtocol += 'localhost/' ; + + FCKConfig.BasePath = sFullProtocol + FCKConfig.BasePath.substring( 0, FCKConfig.BasePath.lastIndexOf( '/' ) + 1) ; + FCKConfig.FullBasePath = FCKConfig.BasePath ; +} +else +{ + FCKConfig.BasePath = document.location.pathname.substring( 0, document.location.pathname.lastIndexOf( '/' ) + 1) ; + FCKConfig.FullBasePath = document.location.protocol + '//' + document.location.host + FCKConfig.BasePath ; +} + +FCKConfig.EditorPath = FCKConfig.BasePath.replace( /editor\/$/, '' ) ; + +// There is a bug in Gecko. If the editor is hidden on startup, an error is +// thrown when trying to get the screen dimensions. +try +{ + FCKConfig.ScreenWidth = screen.width ; + FCKConfig.ScreenHeight = screen.height ; +} +catch (e) +{ + FCKConfig.ScreenWidth = 800 ; + FCKConfig.ScreenHeight = 600 ; +} + +// Override the actual configuration values with the values passed throw the +// hidden field "<InstanceName>___Config". +FCKConfig.ProcessHiddenField = function() +{ + this.PageConfig = new Object() ; + + // Get the hidden field. + var oConfigField = window.parent.document.getElementById( FCK.Name + '___Config' ) ; + + // Do nothing if the config field was not defined. + if ( ! oConfigField ) return ; + + var aCouples = oConfigField.value.split('&') ; + + for ( var i = 0 ; i < aCouples.length ; i++ ) + { + if ( aCouples[i].length == 0 ) + continue ; + + var aConfig = aCouples[i].split( '=' ) ; + var sKey = decodeURIComponent( aConfig[0] ) ; + var sVal = decodeURIComponent( aConfig[1] ) ; + + if ( sKey == 'CustomConfigurationsPath' ) // The Custom Config File path must be loaded immediately. + FCKConfig[ sKey ] = sVal ; + + else if ( sVal.toLowerCase() == "true" ) // If it is a boolean TRUE. + this.PageConfig[ sKey ] = true ; + + else if ( sVal.toLowerCase() == "false" ) // If it is a boolean FALSE. + this.PageConfig[ sKey ] = false ; + + else if ( sVal.length > 0 && !isNaN( sVal ) ) // If it is a number. + this.PageConfig[ sKey ] = parseInt( sVal, 10 ) ; + + else // In any other case it is a string. + this.PageConfig[ sKey ] = sVal ; + } +} + +function FCKConfig_LoadPageConfig() +{ + var oPageConfig = FCKConfig.PageConfig ; + for ( var sKey in oPageConfig ) + FCKConfig[ sKey ] = oPageConfig[ sKey ] ; +} + +function FCKConfig_PreProcess() +{ + var oConfig = FCKConfig ; + + // Force debug mode if fckdebug=true in the QueryString (main page). + if ( oConfig.AllowQueryStringDebug ) + { + try + { + if ( (/fckdebug=true/i).test( window.top.location.search ) ) + oConfig.Debug = true ; + } + catch (e) { /* Ignore it. Much probably we are inside a FRAME where the "top" is in another domain (security error). */ } + } + + // Certifies that the "PluginsPath" configuration ends with a slash. + if ( !oConfig.PluginsPath.EndsWith('/') ) + oConfig.PluginsPath += '/' ; + + // If no ToolbarComboPreviewCSS, point it to EditorAreaCSS. + var sComboPreviewCSS = oConfig.ToolbarComboPreviewCSS ; + if ( !sComboPreviewCSS || sComboPreviewCSS.length == 0 ) + oConfig.ToolbarComboPreviewCSS = oConfig.EditorAreaCSS ; + + // Turn the attributes that will be removed in the RemoveFormat from a string to an array + oConfig.RemoveAttributesArray = (oConfig.RemoveAttributes || '').split( ',' ); + + if ( !FCKConfig.SkinEditorCSS || FCKConfig.SkinEditorCSS.length == 0 ) + FCKConfig.SkinEditorCSS = FCKConfig.SkinPath + 'fck_editor.css' ; + + if ( !FCKConfig.SkinDialogCSS || FCKConfig.SkinDialogCSS.length == 0 ) + FCKConfig.SkinDialogCSS = FCKConfig.SkinPath + 'fck_dialog.css' ; +} + +// Define toolbar sets collection. +FCKConfig.ToolbarSets = new Object() ; + +// Defines the plugins collection. +FCKConfig.Plugins = new Object() ; +FCKConfig.Plugins.Items = new Array() ; + +FCKConfig.Plugins.Add = function( name, langs, path ) +{ + FCKConfig.Plugins.Items.AddItem( [name, langs, path] ) ; +} + +// FCKConfig.ProtectedSource: object that holds a collection of Regular +// Expressions that defined parts of the raw HTML that must remain untouched +// like custom tags, scripts, server side code, etc... +FCKConfig.ProtectedSource = new Object() ; + +// Generates a string used to identify and locate the Protected Tags comments. +FCKConfig.ProtectedSource._CodeTag = (new Date()).valueOf() ; + +// Initialize the regex array with the default ones. +FCKConfig.ProtectedSource.RegexEntries = [ + // First of any other protection, we must protect all comments to avoid + // loosing them (of course, IE related). + /<!--[\s\S]*?-->/g , + + // Script tags will also be forced to be protected, otherwise IE will execute them. + /<script[\s\S]*?<\/script>/gi, + + // <noscript> tags (get lost in IE and messed up in FF). + /<noscript[\s\S]*?<\/noscript>/gi +] ; + +FCKConfig.ProtectedSource.Add = function( regexPattern ) +{ + this.RegexEntries.AddItem( regexPattern ) ; +} + +FCKConfig.ProtectedSource.Protect = function( html ) +{ + var codeTag = this._CodeTag ; + function _Replace( protectedSource ) + { + var index = FCKTempBin.AddElement( protectedSource ) ; + return '<!--{' + codeTag + index + '}-->' ; + } + + for ( var i = 0 ; i < this.RegexEntries.length ; i++ ) + { + html = html.replace( this.RegexEntries[i], _Replace ) ; + } + + return html ; +} + +FCKConfig.ProtectedSource.Revert = function( html, clearBin ) +{ + function _Replace( m, opener, index ) + { + var protectedValue = clearBin ? FCKTempBin.RemoveElement( index ) : FCKTempBin.Elements[ index ] ; + // There could be protected source inside another one. + return FCKConfig.ProtectedSource.Revert( protectedValue, clearBin ) ; + } + + var regex = new RegExp( "(<|<)!--\\{" + this._CodeTag + "(\\d+)\\}--(>|>)", "g" ) ; + return html.replace( regex, _Replace ) ; +} + +// Returns a string with the attributes that must be appended to the body +FCKConfig.GetBodyAttributes = function() +{ + var bodyAttributes = '' ; + // Add id and class to the body. + if ( this.BodyId && this.BodyId.length > 0 ) + bodyAttributes += ' id="' + this.BodyId + '"' ; + if ( this.BodyClass && this.BodyClass.length > 0 ) + bodyAttributes += ' class="' + this.BodyClass + '"' ; + + return bodyAttributes ; +} + +// Sets the body attributes directly on the node +FCKConfig.ApplyBodyAttributes = function( oBody ) +{ + // Add ID and Class to the body + if ( this.BodyId && this.BodyId.length > 0 ) + oBody.id = FCKConfig.BodyId ; + if ( this.BodyClass && this.BodyClass.length > 0 ) + oBody.className += ' ' + FCKConfig.BodyClass ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckdebug.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckdebug.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckdebug.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,56 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Debug window control and operations. + */ + +var FCKDebug = new Object() ; + +FCKDebug._GetWindow = function() +{ + if ( !this.DebugWindow || this.DebugWindow.closed ) + this.DebugWindow = window.open( FCKConfig.BasePath + 'fckdebug.html', 'FCKeditorDebug', 'menubar=no,scrollbars=yes,resizable=yes,location=no,toolbar=no,width=600,height=500', true ) ; + + return this.DebugWindow ; +} + +FCKDebug.Output = function( message, color, noParse ) +{ + if ( ! FCKConfig.Debug ) + return ; + + try + { + this._GetWindow().Output( message, color ) ; + } + catch ( e ) {} // Ignore errors +} + +FCKDebug.OutputObject = function( anyObject, color ) +{ + if ( ! FCKConfig.Debug ) + return ; + + try + { + this._GetWindow().OutputObject( anyObject, color ) ; + } + catch ( e ) {} // Ignore errors +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckdialog.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckdialog.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckdialog.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,234 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Dialog windows operations. + */ + +var FCKDialog = ( function() +{ + var topDialog ; + var baseZIndex ; + var cover ; + + // The document that holds the dialog. + var topWindow = window.parent ; + + while ( topWindow.parent && topWindow.parent != topWindow ) + { + try + { + if ( topWindow.parent.document.domain != document.domain ) + break ; + if ( topWindow.parent.document.getElementsByTagName( 'frameset' ).length > 0 ) + break ; + } + catch ( e ) + { + break ; + } + topWindow = topWindow.parent ; + } + + var topDocument = topWindow.document ; + + var getZIndex = function() + { + if ( !baseZIndex ) + baseZIndex = FCKConfig.FloatingPanelsZIndex + 999 ; + return ++baseZIndex ; + } + + // TODO : This logic is not actually working when reducing the window, only + // when enlarging it. + var resizeHandler = function() + { + if ( !cover ) + return ; + + var relElement = FCKTools.IsStrictMode( topDocument ) ? topDocument.documentElement : topDocument.body ; + + FCKDomTools.SetElementStyles( cover, + { + 'width' : Math.max( relElement.scrollWidth, + relElement.clientWidth, + topDocument.scrollWidth || 0 ) - 1 + 'px', + 'height' : Math.max( relElement.scrollHeight, + relElement.clientHeight, + topDocument.scrollHeight || 0 ) - 1 + 'px' + } ) ; + } + + var resetStyles = function( element ) + { + element.style.cssText = 'margin:0;' + + 'padding:0;' + + 'border:0;' + + 'background-color:transparent;' + + 'background-image:none;' ; + } + + return { + /** + * Opens a dialog window using the standard dialog template. + */ + OpenDialog : function( dialogName, dialogTitle, dialogPage, width, height, customValue, parentWindow, resizable ) + { + if ( !topDialog ) + this.DisplayMainCover() ; + + // Setup the dialog info to be passed to the dialog. + var dialogInfo = + { + Title : dialogTitle, + Page : dialogPage, + Editor : window, + CustomValue : customValue, // Optional + TopWindow : topWindow + } + + FCK.ToolbarSet.CurrentInstance.Selection.Save() ; + + // Calculate the dialog position, centering it on the screen. + var viewSize = FCKTools.GetViewPaneSize( topWindow ) ; + var scrollPosition = FCKTools.GetScrollPosition( topWindow ) ; + var iTop = Math.max( scrollPosition.Y + ( viewSize.Height - height - 20 ) / 2, 0 ) ; + var iLeft = Math.max( scrollPosition.X + ( viewSize.Width - width - 20 ) / 2, 0 ) ; + + // Setup the IFRAME that will hold the dialog. + var dialog = topDocument.createElement( 'iframe' ) ; + resetStyles( dialog ) ; + dialog.src = FCKConfig.BasePath + 'fckdialog.html' ; + + // Dummy URL for testing whether the code in fckdialog.js alone leaks memory. + // dialog.src = 'about:blank'; + + dialog.frameBorder = 0 ; + dialog.allowTransparency = true ; + FCKDomTools.SetElementStyles( dialog, + { + 'position' : 'absolute', + 'top' : iTop + 'px', + 'left' : iLeft + 'px', + 'width' : width + 'px', + 'height' : height + 'px', + 'zIndex' : getZIndex() + } ) ; + + // Save the dialog info to be used by the dialog page once loaded. + dialog._DialogArguments = dialogInfo ; + + // Append the IFRAME to the target document. + topDocument.body.appendChild( dialog ) ; + + // Keep record of the dialog's parent/child relationships. + dialog._ParentDialog = topDialog ; + topDialog = dialog ; + }, + + /** + * (For internal use) + * Called when the top dialog is closed. + */ + OnDialogClose : function( dialogWindow ) + { + var dialog = dialogWindow.frameElement ; + FCKDomTools.RemoveNode( dialog ) ; + + if ( dialog._ParentDialog ) // Nested Dialog. + { + topDialog = dialog._ParentDialog ; + dialog._ParentDialog.contentWindow.SetEnabled( true ) ; + } + else // First Dialog. + { + // Set the Focus in the browser, so the "OnBlur" event is not + // fired. In IE, there is no need to do that because the dialog + // already moved the selection to the editing area before + // closing (EnsureSelection). Also, the Focus() call here + // causes memory leak on IE7 (weird). + if ( !FCKBrowserInfo.IsIE ) + FCK.Focus() ; + + this.HideMainCover() ; + // Bug #1918: Assigning topDialog = null directly causes IE6 to crash. + setTimeout( function(){ topDialog = null ; }, 0 ) ; + + // Release the previously saved selection. + FCK.ToolbarSet.CurrentInstance.Selection.Release() ; + } + }, + + DisplayMainCover : function() + { + // Setup the DIV that will be used to cover. + cover = topDocument.createElement( 'div' ) ; + resetStyles( cover ) ; + FCKDomTools.SetElementStyles( cover, + { + 'position' : 'absolute', + 'zIndex' : getZIndex(), + 'top' : '0px', + 'left' : '0px', + 'backgroundColor' : FCKConfig.BackgroundBlockerColor + } ) ; + FCKDomTools.SetOpacity( cover, FCKConfig.BackgroundBlockerOpacity ) ; + + // For IE6-, we need to fill the cover with a transparent IFRAME, + // to properly block <select> fields. + if ( FCKBrowserInfo.IsIE && !FCKBrowserInfo.IsIE7 ) + { + var iframe = topDocument.createElement( 'iframe' ) ; + resetStyles( iframe ) ; + iframe.hideFocus = true ; + iframe.frameBorder = 0 ; + iframe.src = FCKTools.GetVoidUrl() ; + FCKDomTools.SetElementStyles( iframe, + { + 'width' : '100%', + 'height' : '100%', + 'position' : 'absolute', + 'left' : '0px', + 'top' : '0px', + 'filter' : 'progid:DXImageTransform.Microsoft.Alpha(opacity=0)' + } ) ; + cover.appendChild( iframe ) ; + } + + // We need to manually adjust the cover size on resize. + FCKTools.AddEventListener( topWindow, 'resize', resizeHandler ) ; + resizeHandler() ; + + topDocument.body.appendChild( cover ) ; + + FCKFocusManager.Lock() ; + }, + + HideMainCover : function() + { + FCKDomTools.RemoveNode( cover ) ; + FCKFocusManager.Unlock() ; + }, + + GetCover : function() + { + return cover ; + } + } ; +} )() ; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckdocumentprocessor.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckdocumentprocessor.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckdocumentprocessor.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,249 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Advanced document processors. + */ + +var FCKDocumentProcessor = new Object() ; +FCKDocumentProcessor._Items = new Array() ; + +FCKDocumentProcessor.AppendNew = function() +{ + var oNewItem = new Object() ; + this._Items.AddItem( oNewItem ) ; + return oNewItem ; +} + +FCKDocumentProcessor.Process = function( document ) +{ + var bIsDirty = FCK.IsDirty() ; + var oProcessor, i = 0 ; + while( ( oProcessor = this._Items[i++] ) ) + oProcessor.ProcessDocument( document ) ; + if ( !bIsDirty ) + FCK.ResetIsDirty() ; +} + +var FCKDocumentProcessor_CreateFakeImage = function( fakeClass, realElement ) +{ + var oImg = FCKTools.GetElementDocument( realElement ).createElement( 'IMG' ) ; + oImg.className = fakeClass ; + oImg.src = FCKConfig.FullBasePath + 'images/spacer.gif' ; + oImg.setAttribute( '_fckfakelement', 'true', 0 ) ; + oImg.setAttribute( '_fckrealelement', FCKTempBin.AddElement( realElement ), 0 ) ; + return oImg ; +} + +// Link Anchors +if ( FCKBrowserInfo.IsIE || FCKBrowserInfo.IsOpera ) +{ + var FCKAnchorsProcessor = FCKDocumentProcessor.AppendNew() ; + FCKAnchorsProcessor.ProcessDocument = function( document ) + { + var aLinks = document.getElementsByTagName( 'A' ) ; + + var oLink ; + var i = aLinks.length - 1 ; + while ( i >= 0 && ( oLink = aLinks[i--] ) ) + { + // If it is anchor. Doesn't matter if it's also a link (even better: we show that it's both a link and an anchor) + if ( oLink.name.length > 0 ) + { + //if the anchor has some content then we just add a temporary class + if ( oLink.innerHTML !== '' ) + { + if ( FCKBrowserInfo.IsIE ) + oLink.className += ' FCK__AnchorC' ; + } + else + { + var oImg = FCKDocumentProcessor_CreateFakeImage( 'FCK__Anchor', oLink.cloneNode(true) ) ; + oImg.setAttribute( '_fckanchor', 'true', 0 ) ; + + oLink.parentNode.insertBefore( oImg, oLink ) ; + oLink.parentNode.removeChild( oLink ) ; + } + } + } + } +} + +// Page Breaks +var FCKPageBreaksProcessor = FCKDocumentProcessor.AppendNew() ; +FCKPageBreaksProcessor.ProcessDocument = function( document ) +{ + var aDIVs = document.getElementsByTagName( 'DIV' ) ; + + var eDIV ; + var i = aDIVs.length - 1 ; + while ( i >= 0 && ( eDIV = aDIVs[i--] ) ) + { + if ( eDIV.style.pageBreakAfter == 'always' && eDIV.childNodes.length == 1 && eDIV.childNodes[0].style && eDIV.childNodes[0].style.display == 'none' ) + { + var oFakeImage = FCKDocumentProcessor_CreateFakeImage( 'FCK__PageBreak', eDIV.cloneNode(true) ) ; + + eDIV.parentNode.insertBefore( oFakeImage, eDIV ) ; + eDIV.parentNode.removeChild( eDIV ) ; + } + } +/* + var aCenters = document.getElementsByTagName( 'CENTER' ) ; + + var oCenter ; + var i = aCenters.length - 1 ; + while ( i >= 0 && ( oCenter = aCenters[i--] ) ) + { + if ( oCenter.style.pageBreakAfter == 'always' && oCenter.innerHTML.Trim().length == 0 ) + { + var oFakeImage = FCKDocumentProcessor_CreateFakeImage( 'FCK__PageBreak', oCenter.cloneNode(true) ) ; + + oCenter.parentNode.insertBefore( oFakeImage, oCenter ) ; + oCenter.parentNode.removeChild( oCenter ) ; + } + } +*/ +} + +// EMBED and OBJECT tags. +FCKEmbedAndObjectProcessor = (function() +{ + var customProcessors = [] ; + + var processElement = function( el ) + { + var clone = el.cloneNode( true ) ; + var replaceElement ; + var fakeImg = replaceElement = FCKDocumentProcessor_CreateFakeImage( 'FCK__UnknownObject', clone ) ; + FCKEmbedAndObjectProcessor.RefreshView( fakeImg, el ) ; + + for ( var i = 0 ; i < customProcessors.length ; i++ ) + replaceElement = customProcessors[i]( el, replaceElement ) || replaceElement ; + + if ( replaceElement != fakeImg ) + FCKTempBin.RemoveElement( fakeImg.getAttribute( '_fckrealelement' ) ) ; + + el.parentNode.replaceChild( replaceElement, el ) ; + } + + return FCKTools.Merge( FCKDocumentProcessor.AppendNew(), + { + ProcessDocument : function( doc ) + { + // Firefox 3 would sometimes throw an unknown exception while accessing EMBEDs and OBJECTs + // without the setTimeout(). + FCKTools.RunFunction( function() + { + // Process OBJECTs first, since EMBEDs can sometimes go inside OBJECTS (e.g. Flash). + var aObjects = doc.getElementsByTagName( 'object' ); + for ( var i = aObjects.length - 1 ; i >= 0 ; i-- ) + processElement( aObjects[i] ) ; + + // Now process any EMBEDs left. + var aEmbeds = doc.getElementsByTagName( 'embed' ) ; + for ( var i = aEmbeds.length - 1 ; i >= 0 ; i-- ) + processElement( aEmbeds[i] ) ; + } ) ; + }, + + RefreshView : function( placeHolder, original ) + { + if ( original.getAttribute( 'width' ) > 0 ) + placeHolder.style.width = FCKTools.ConvertHtmlSizeToStyle( original.getAttribute( 'width' ) ) ; + + if ( original.getAttribute( 'height' ) > 0 ) + placeHolder.style.height = FCKTools.ConvertHtmlSizeToStyle( original.getAttribute( 'height' ) ) ; + }, + + AddCustomHandler : function( func ) + { + customProcessors.push( func ) ; + } + } ) ; +} )() ; + +FCK.GetRealElement = function( fakeElement ) +{ + var e = FCKTempBin.Elements[ fakeElement.getAttribute('_fckrealelement') ] ; + + if ( fakeElement.getAttribute('_fckflash') ) + { + if ( fakeElement.style.width.length > 0 ) + e.width = FCKTools.ConvertStyleSizeToHtml( fakeElement.style.width ) ; + + if ( fakeElement.style.height.length > 0 ) + e.height = FCKTools.ConvertStyleSizeToHtml( fakeElement.style.height ) ; + } + + return e ; +} + +// HR Processor. +// This is a IE only (tricky) thing. We protect all HR tags before loading them +// (see FCK.ProtectTags). Here we put the HRs back. +if ( FCKBrowserInfo.IsIE ) +{ + FCKDocumentProcessor.AppendNew().ProcessDocument = function( document ) + { + var aHRs = document.getElementsByTagName( 'HR' ) ; + + var eHR ; + var i = aHRs.length - 1 ; + while ( i >= 0 && ( eHR = aHRs[i--] ) ) + { + // Create the replacement HR. + var newHR = document.createElement( 'hr' ) ; + newHR.mergeAttributes( eHR, true ) ; + + // We must insert the new one after it. insertBefore will not work in all cases. + FCKDomTools.InsertAfterNode( eHR, newHR ) ; + + eHR.parentNode.removeChild( eHR ) ; + } + } +} + +// INPUT:hidden Processor. +FCKDocumentProcessor.AppendNew().ProcessDocument = function( document ) +{ + var aInputs = document.getElementsByTagName( 'INPUT' ) ; + + var oInput ; + var i = aInputs.length - 1 ; + while ( i >= 0 && ( oInput = aInputs[i--] ) ) + { + if ( oInput.type == 'hidden' ) + { + var oImg = FCKDocumentProcessor_CreateFakeImage( 'FCK__InputHidden', oInput.cloneNode(true) ) ; + oImg.setAttribute( '_fckinputhidden', 'true', 0 ) ; + + oInput.parentNode.insertBefore( oImg, oInput ) ; + oInput.parentNode.removeChild( oInput ) ; + } + } +} + +// Flash handler. +FCKEmbedAndObjectProcessor.AddCustomHandler( function( el, fakeImg ) + { + if ( ! ( el.nodeName.IEquals( 'embed' ) && ( el.type == 'application/x-shockwave-flash' || /\.swf($|#|\?)/i.test( el.src ) ) ) ) + return ; + fakeImg.className = 'FCK__Flash' ; + fakeImg.setAttribute( '_fckflash', 'true', 0 ); + } ) ; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckdomtools.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckdomtools.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckdomtools.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,1024 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Utility functions to work with the DOM. + */ + +var FCKDomTools = +{ + /** + * Move all child nodes from one node to another. + */ + MoveChildren : function( source, target, toTargetStart ) + { + if ( source == target ) + return ; + + var eChild ; + + if ( toTargetStart ) + { + while ( (eChild = source.lastChild) ) + target.insertBefore( source.removeChild( eChild ), target.firstChild ) ; + } + else + { + while ( (eChild = source.firstChild) ) + target.appendChild( source.removeChild( eChild ) ) ; + } + }, + + MoveNode : function( source, target, toTargetStart ) + { + if ( toTargetStart ) + target.insertBefore( FCKDomTools.RemoveNode( source ), target.firstChild ) ; + else + target.appendChild( FCKDomTools.RemoveNode( source ) ) ; + }, + + // Remove blank spaces from the beginning and the end of the contents of a node. + TrimNode : function( node ) + { + this.LTrimNode( node ) ; + this.RTrimNode( node ) ; + }, + + LTrimNode : function( node ) + { + var eChildNode ; + + while ( (eChildNode = node.firstChild) ) + { + if ( eChildNode.nodeType == 3 ) + { + var sTrimmed = eChildNode.nodeValue.LTrim() ; + var iOriginalLength = eChildNode.nodeValue.length ; + + if ( sTrimmed.length == 0 ) + { + node.removeChild( eChildNode ) ; + continue ; + } + else if ( sTrimmed.length < iOriginalLength ) + { + eChildNode.splitText( iOriginalLength - sTrimmed.length ) ; + node.removeChild( node.firstChild ) ; + } + } + break ; + } + }, + + RTrimNode : function( node ) + { + var eChildNode ; + + while ( (eChildNode = node.lastChild) ) + { + if ( eChildNode.nodeType == 3 ) + { + var sTrimmed = eChildNode.nodeValue.RTrim() ; + var iOriginalLength = eChildNode.nodeValue.length ; + + if ( sTrimmed.length == 0 ) + { + // If the trimmed text node is empty, just remove it. + + // Use "eChildNode.parentNode" instead of "node" to avoid IE bug (#81). + eChildNode.parentNode.removeChild( eChildNode ) ; + continue ; + } + else if ( sTrimmed.length < iOriginalLength ) + { + // If the trimmed text length is less than the original + // length, strip all spaces from the end by splitting + // the text and removing the resulting useless node. + + eChildNode.splitText( sTrimmed.length ) ; + // Use "node.lastChild.parentNode" instead of "node" to avoid IE bug (#81). + node.lastChild.parentNode.removeChild( node.lastChild ) ; + } + } + break ; + } + + if ( !FCKBrowserInfo.IsIE && !FCKBrowserInfo.IsOpera ) + { + eChildNode = node.lastChild ; + + if ( eChildNode && eChildNode.nodeType == 1 && eChildNode.nodeName.toLowerCase() == 'br' ) + { + // Use "eChildNode.parentNode" instead of "node" to avoid IE bug (#324). + eChildNode.parentNode.removeChild( eChildNode ) ; + } + } + }, + + RemoveNode : function( node, excludeChildren ) + { + if ( excludeChildren ) + { + // Move all children before the node. + var eChild ; + while ( (eChild = node.firstChild) ) + node.parentNode.insertBefore( node.removeChild( eChild ), node ) ; + } + + return node.parentNode.removeChild( node ) ; + }, + + GetFirstChild : function( node, childNames ) + { + // If childNames is a string, transform it in a Array. + if ( typeof ( childNames ) == 'string' ) + childNames = [ childNames ] ; + + var eChild = node.firstChild ; + while( eChild ) + { + if ( eChild.nodeType == 1 && eChild.tagName.Equals.apply( eChild.tagName, childNames ) ) + return eChild ; + + eChild = eChild.nextSibling ; + } + + return null ; + }, + + GetLastChild : function( node, childNames ) + { + // If childNames is a string, transform it in a Array. + if ( typeof ( childNames ) == 'string' ) + childNames = [ childNames ] ; + + var eChild = node.lastChild ; + while( eChild ) + { + if ( eChild.nodeType == 1 && ( !childNames || eChild.tagName.Equals( childNames ) ) ) + return eChild ; + + eChild = eChild.previousSibling ; + } + + return null ; + }, + + /* + * Gets the previous element (nodeType=1) in the source order. Returns + * "null" If no element is found. + * @param {Object} currentNode The node to start searching from. + * @param {Boolean} ignoreSpaceTextOnly Sets how text nodes will be + * handled. If set to "true", only white spaces text nodes + * will be ignored, while non white space text nodes will stop + * the search, returning null. If "false" or omitted, all + * text nodes are ignored. + * @param {string[]} stopSearchElements An array of element names that + * will cause the search to stop when found, returning null. + * May be omitted (or null). + * @param {string[]} ignoreElements An array of element names that + * must be ignored during the search. + */ + GetPreviousSourceElement : function( currentNode, ignoreSpaceTextOnly, stopSearchElements, ignoreElements ) + { + if ( !currentNode ) + return null ; + + if ( stopSearchElements && currentNode.nodeType == 1 && currentNode.nodeName.IEquals( stopSearchElements ) ) + return null ; + + if ( currentNode.previousSibling ) + currentNode = currentNode.previousSibling ; + else + return this.GetPreviousSourceElement( currentNode.parentNode, ignoreSpaceTextOnly, stopSearchElements, ignoreElements ) ; + + while ( currentNode ) + { + if ( currentNode.nodeType == 1 ) + { + if ( stopSearchElements && currentNode.nodeName.IEquals( stopSearchElements ) ) + break ; + + if ( !ignoreElements || !currentNode.nodeName.IEquals( ignoreElements ) ) + return currentNode ; + } + else if ( ignoreSpaceTextOnly && currentNode.nodeType == 3 && currentNode.nodeValue.RTrim().length > 0 ) + break ; + + if ( currentNode.lastChild ) + currentNode = currentNode.lastChild ; + else + return this.GetPreviousSourceElement( currentNode, ignoreSpaceTextOnly, stopSearchElements, ignoreElements ) ; + } + + return null ; + }, + + /* + * Gets the next element (nodeType=1) in the source order. Returns + * "null" If no element is found. + * @param {Object} currentNode The node to start searching from. + * @param {Boolean} ignoreSpaceTextOnly Sets how text nodes will be + * handled. If set to "true", only white spaces text nodes + * will be ignored, while non white space text nodes will stop + * the search, returning null. If "false" or omitted, all + * text nodes are ignored. + * @param {string[]} stopSearchElements An array of element names that + * will cause the search to stop when found, returning null. + * May be omitted (or null). + * @param {string[]} ignoreElements An array of element names that + * must be ignored during the search. + */ + GetNextSourceElement : function( currentNode, ignoreSpaceTextOnly, stopSearchElements, ignoreElements, startFromSibling ) + { + while( ( currentNode = this.GetNextSourceNode( currentNode, startFromSibling ) ) ) // Only one "=". + { + if ( currentNode.nodeType == 1 ) + { + if ( stopSearchElements && currentNode.nodeName.IEquals( stopSearchElements ) ) + break ; + + if ( ignoreElements && currentNode.nodeName.IEquals( ignoreElements ) ) + return this.GetNextSourceElement( currentNode, ignoreSpaceTextOnly, stopSearchElements, ignoreElements ) ; + + return currentNode ; + } + else if ( ignoreSpaceTextOnly && currentNode.nodeType == 3 && currentNode.nodeValue.RTrim().length > 0 ) + break ; + } + + return null ; + }, + + /* + * Get the next DOM node available in source order. + */ + GetNextSourceNode : function( currentNode, startFromSibling, nodeType, stopSearchNode ) + { + if ( !currentNode ) + return null ; + + var node ; + + if ( !startFromSibling && currentNode.firstChild ) + node = currentNode.firstChild ; + else + { + if ( stopSearchNode && currentNode == stopSearchNode ) + return null ; + + node = currentNode.nextSibling ; + + if ( !node && ( !stopSearchNode || stopSearchNode != currentNode.parentNode ) ) + return this.GetNextSourceNode( currentNode.parentNode, true, nodeType, stopSearchNode ) ; + } + + if ( nodeType && node && node.nodeType != nodeType ) + return this.GetNextSourceNode( node, false, nodeType, stopSearchNode ) ; + + return node ; + }, + + /* + * Get the next DOM node available in source order. + */ + GetPreviousSourceNode : function( currentNode, startFromSibling, nodeType, stopSearchNode ) + { + if ( !currentNode ) + return null ; + + var node ; + + if ( !startFromSibling && currentNode.lastChild ) + node = currentNode.lastChild ; + else + { + if ( stopSearchNode && currentNode == stopSearchNode ) + return null ; + + node = currentNode.previousSibling ; + + if ( !node && ( !stopSearchNode || stopSearchNode != currentNode.parentNode ) ) + return this.GetPreviousSourceNode( currentNode.parentNode, true, nodeType, stopSearchNode ) ; + } + + if ( nodeType && node && node.nodeType != nodeType ) + return this.GetPreviousSourceNode( node, false, nodeType, stopSearchNode ) ; + + return node ; + }, + + // Inserts a element after a existing one. + InsertAfterNode : function( existingNode, newNode ) + { + return existingNode.parentNode.insertBefore( newNode, existingNode.nextSibling ) ; + }, + + GetParents : function( node ) + { + var parents = new Array() ; + + while ( node ) + { + parents.unshift( node ) ; + node = node.parentNode ; + } + + return parents ; + }, + + GetCommonParents : function( node1, node2 ) + { + var p1 = this.GetParents( node1 ) ; + var p2 = this.GetParents( node2 ) ; + var retval = [] ; + for ( var i = 0 ; i < p1.length ; i++ ) + { + if ( p1[i] == p2[i] ) + retval.push( p1[i] ) ; + } + return retval ; + }, + + GetCommonParentNode : function( node1, node2, tagList ) + { + var tagMap = {} ; + if ( ! tagList.pop ) + tagList = [ tagList ] ; + while ( tagList.length > 0 ) + tagMap[tagList.pop().toLowerCase()] = 1 ; + + var commonParents = this.GetCommonParents( node1, node2 ) ; + var currentParent = null ; + while ( ( currentParent = commonParents.pop() ) ) + { + if ( tagMap[currentParent.nodeName.toLowerCase()] ) + return currentParent ; + } + return null ; + }, + + GetIndexOf : function( node ) + { + var currentNode = node.parentNode ? node.parentNode.firstChild : null ; + var currentIndex = -1 ; + + while ( currentNode ) + { + currentIndex++ ; + + if ( currentNode == node ) + return currentIndex ; + + currentNode = currentNode.nextSibling ; + } + + return -1 ; + }, + + PaddingNode : null, + + EnforcePaddingNode : function( doc, tagName ) + { + // In IE it can happen when the page is reloaded that doc or doc.body is null, so exit here + try + { + if ( !doc || !doc.body ) + return ; + } + catch (e) + { + return ; + } + + this.CheckAndRemovePaddingNode( doc, tagName, true ) ; + try + { + if ( doc.body.lastChild && ( doc.body.lastChild.nodeType != 1 + || doc.body.lastChild.tagName.toLowerCase() == tagName.toLowerCase() ) ) + return ; + } + catch (e) + { + return ; + } + + var node = doc.createElement( tagName ) ; + if ( FCKBrowserInfo.IsGecko && FCKListsLib.NonEmptyBlockElements[ tagName ] ) + FCKTools.AppendBogusBr( node ) ; + this.PaddingNode = node ; + if ( doc.body.childNodes.length == 1 + && doc.body.firstChild.nodeType == 1 + && doc.body.firstChild.tagName.toLowerCase() == 'br' + && ( doc.body.firstChild.getAttribute( '_moz_dirty' ) != null + || doc.body.firstChild.getAttribute( 'type' ) == '_moz' ) ) + doc.body.replaceChild( node, doc.body.firstChild ) ; + else + doc.body.appendChild( node ) ; + }, + + CheckAndRemovePaddingNode : function( doc, tagName, dontRemove ) + { + var paddingNode = this.PaddingNode ; + if ( ! paddingNode ) + return ; + + // If the padding node is changed, remove its status as a padding node. + try + { + if ( paddingNode.parentNode != doc.body + || paddingNode.tagName.toLowerCase() != tagName + || ( paddingNode.childNodes.length > 1 ) + || ( paddingNode.firstChild && paddingNode.firstChild.nodeValue != '\xa0' + && String(paddingNode.firstChild.tagName).toLowerCase() != 'br' ) ) + { + this.PaddingNode = null ; + return ; + } + } + catch (e) + { + this.PaddingNode = null ; + return ; + } + + // Now we're sure the padding node exists, and it is unchanged, and it + // isn't the only node in doc.body, remove it. + if ( !dontRemove ) + { + if ( paddingNode.parentNode.childNodes.length > 1 ) + paddingNode.parentNode.removeChild( paddingNode ) ; + this.PaddingNode = null ; + } + }, + + HasAttribute : function( element, attributeName ) + { + if ( element.hasAttribute ) + return element.hasAttribute( attributeName ) ; + else + { + var att = element.attributes[ attributeName ] ; + return ( att != undefined && att.specified ) ; + } + }, + + /** + * Checks if an element has "specified" attributes. + */ + HasAttributes : function( element ) + { + var attributes = element.attributes ; + + for ( var i = 0 ; i < attributes.length ; i++ ) + { + if ( FCKBrowserInfo.IsIE && attributes[i].nodeName == 'class' ) + { + // IE has a strange bug. If calling removeAttribute('className'), + // the attributes collection will still contain the "class" + // attribute, which will be marked as "specified", even if the + // outerHTML of the element is not displaying the class attribute. + // Note : I was not able to reproduce it outside the editor, + // but I've faced it while working on the TC of #1391. + if ( element.className.length > 0 ) + return true ; + } + else if ( attributes[i].specified ) + return true ; + } + + return false ; + }, + + /** + * Remove an attribute from an element. + */ + RemoveAttribute : function( element, attributeName ) + { + if ( FCKBrowserInfo.IsIE && attributeName.toLowerCase() == 'class' ) + attributeName = 'className' ; + + return element.removeAttribute( attributeName, 0 ) ; + }, + + /** + * Removes an array of attributes from an element + */ + RemoveAttributes : function (element, aAttributes ) + { + for ( var i = 0 ; i < aAttributes.length ; i++ ) + this.RemoveAttribute( element, aAttributes[i] ); + }, + + GetAttributeValue : function( element, att ) + { + var attName = att ; + + if ( typeof att == 'string' ) + att = element.attributes[ att ] ; + else + attName = att.nodeName ; + + if ( att && att.specified ) + { + // IE returns "null" for the nodeValue of a "style" attribute. + if ( attName == 'style' ) + return element.style.cssText ; + // There are two cases when the nodeValue must be used: + // - for the "class" attribute (all browsers). + // - for events attributes (IE only). + else if ( attName == 'class' || attName.indexOf('on') == 0 ) + return att.nodeValue ; + else + { + // Use getAttribute to get its value exactly as it is + // defined. + return element.getAttribute( attName, 2 ) ; + } + } + return null ; + }, + + /** + * Checks whether one element contains the other. + */ + Contains : function( mainElement, otherElement ) + { + // IE supports contains, but only for element nodes. + if ( mainElement.contains && otherElement.nodeType == 1 ) + return mainElement.contains( otherElement ) ; + + while ( ( otherElement = otherElement.parentNode ) ) // Only one "=" + { + if ( otherElement == mainElement ) + return true ; + } + return false ; + }, + + /** + * Breaks a parent element in the position of one of its contained elements. + * For example, in the following case: + * <b>This <i>is some<span /> sample</i> test text</b> + * If element = <span />, we have these results: + * <b>This <i>is some</i><span /><i> sample</i> test text</b> (If parent = <i>) + * <b>This <i>is some</i></b><span /><b><i> sample</i> test text</b> (If parent = <b>) + */ + BreakParent : function( element, parent, reusableRange ) + { + var range = reusableRange || new FCKDomRange( FCKTools.GetElementWindow( element ) ) ; + + // We'll be extracting part of this element, so let's use our + // range to get the correct piece. + range.SetStart( element, 4 ) ; + range.SetEnd( parent, 4 ) ; + + // Extract it. + var docFrag = range.ExtractContents() ; + + // Move the element outside the broken element. + range.InsertNode( element.parentNode.removeChild( element ) ) ; + + // Re-insert the extracted piece after the element. + docFrag.InsertAfterNode( element ) ; + + range.Release( !!reusableRange ) ; + }, + + /** + * Retrieves a uniquely identifiable tree address of a DOM tree node. + * The tree address returns is an array of integers, with each integer + * indicating a child index from a DOM tree node, starting from + * document.documentElement. + * + * For example, assuming <body> is the second child from <html> (<head> + * being the first), and we'd like to address the third child under the + * fourth child of body, the tree address returned would be: + * [1, 3, 2] + * + * The tree address cannot be used for finding back the DOM tree node once + * the DOM tree structure has been modified. + */ + GetNodeAddress : function( node, normalized ) + { + var retval = [] ; + while ( node && node != FCKTools.GetElementDocument( node ).documentElement ) + { + var parentNode = node.parentNode ; + var currentIndex = -1 ; + for( var i = 0 ; i < parentNode.childNodes.length ; i++ ) + { + var candidate = parentNode.childNodes[i] ; + if ( normalized === true && + candidate.nodeType == 3 && + candidate.previousSibling && + candidate.previousSibling.nodeType == 3 ) + continue; + currentIndex++ ; + if ( parentNode.childNodes[i] == node ) + break ; + } + retval.unshift( currentIndex ) ; + node = node.parentNode ; + } + return retval ; + }, + + /** + * The reverse transformation of FCKDomTools.GetNodeAddress(). This + * function returns the DOM node pointed to by its index address. + */ + GetNodeFromAddress : function( doc, addr, normalized ) + { + var cursor = doc.documentElement ; + for ( var i = 0 ; i < addr.length ; i++ ) + { + var target = addr[i] ; + if ( ! normalized ) + { + cursor = cursor.childNodes[target] ; + continue ; + } + + var currentIndex = -1 ; + for (var j = 0 ; j < cursor.childNodes.length ; j++ ) + { + var candidate = cursor.childNodes[j] ; + if ( normalized === true && + candidate.nodeType == 3 && + candidate.previousSibling && + candidate.previousSibling.nodeType == 3 ) + continue ; + currentIndex++ ; + if ( currentIndex == target ) + { + cursor = candidate ; + break ; + } + } + } + return cursor ; + }, + + CloneElement : function( element ) + { + element = element.cloneNode( false ) ; + + // The "id" attribute should never be cloned to avoid duplication. + element.removeAttribute( 'id', false ) ; + + return element ; + }, + + ClearElementJSProperty : function( element, attrName ) + { + if ( FCKBrowserInfo.IsIE ) + element.removeAttribute( attrName ) ; + else + delete element[attrName] ; + }, + + SetElementMarker : function ( markerObj, element, attrName, value) + { + var id = String( parseInt( Math.random() * 0xfffffff, 10 ) ) ; + element._FCKMarkerId = id ; + element[attrName] = value ; + if ( ! markerObj[id] ) + markerObj[id] = { 'element' : element, 'markers' : {} } ; + markerObj[id]['markers'][attrName] = value ; + }, + + ClearElementMarkers : function( markerObj, element, clearMarkerObj ) + { + var id = element._FCKMarkerId ; + if ( ! id ) + return ; + this.ClearElementJSProperty( element, '_FCKMarkerId' ) ; + for ( var j in markerObj[id]['markers'] ) + this.ClearElementJSProperty( element, j ) ; + if ( clearMarkerObj ) + delete markerObj[id] ; + }, + + ClearAllMarkers : function( markerObj ) + { + for ( var i in markerObj ) + this.ClearElementMarkers( markerObj, markerObj[i]['element'], true ) ; + }, + + /** + * Convert a DOM list tree into a data structure that is easier to + * manipulate. This operation should be non-intrusive in the sense that it + * does not change the DOM tree, with the exception that it may add some + * markers to the list item nodes when markerObj is specified. + */ + ListToArray : function( listNode, markerObj, baseArray, baseIndentLevel, grandparentNode ) + { + if ( ! listNode.nodeName.IEquals( ['ul', 'ol'] ) ) + return [] ; + + if ( ! baseIndentLevel ) + baseIndentLevel = 0 ; + if ( ! baseArray ) + baseArray = [] ; + // Iterate over all list items to get their contents and look for inner lists. + for ( var i = 0 ; i < listNode.childNodes.length ; i++ ) + { + var listItem = listNode.childNodes[i] ; + if ( ! listItem.nodeName.IEquals( 'li' ) ) + continue ; + var itemObj = { 'parent' : listNode, 'indent' : baseIndentLevel, 'contents' : [] } ; + if ( ! grandparentNode ) + { + itemObj.grandparent = listNode.parentNode ; + if ( itemObj.grandparent && itemObj.grandparent.nodeName.IEquals( 'li' ) ) + itemObj.grandparent = itemObj.grandparent.parentNode ; + } + else + itemObj.grandparent = grandparentNode ; + if ( markerObj ) + this.SetElementMarker( markerObj, listItem, '_FCK_ListArray_Index', baseArray.length ) ; + baseArray.push( itemObj ) ; + for ( var j = 0 ; j < listItem.childNodes.length ; j++ ) + { + var child = listItem.childNodes[j] ; + if ( child.nodeName.IEquals( ['ul', 'ol'] ) ) + // Note the recursion here, it pushes inner list items with + // +1 indentation in the correct order. + this.ListToArray( child, markerObj, baseArray, baseIndentLevel + 1, itemObj.grandparent ) ; + else + itemObj.contents.push( child ) ; + } + } + return baseArray ; + }, + + // Convert our internal representation of a list back to a DOM forest. + ArrayToList : function( listArray, markerObj, baseIndex ) + { + if ( baseIndex == undefined ) + baseIndex = 0 ; + if ( ! listArray || listArray.length < baseIndex + 1 ) + return null ; + var doc = FCKTools.GetElementDocument( listArray[baseIndex].parent ) ; + var retval = doc.createDocumentFragment() ; + var rootNode = null ; + var currentIndex = baseIndex ; + var indentLevel = Math.max( listArray[baseIndex].indent, 0 ) ; + var currentListItem = null ; + while ( true ) + { + var item = listArray[currentIndex] ; + if ( item.indent == indentLevel ) + { + if ( ! rootNode || listArray[currentIndex].parent.nodeName != rootNode.nodeName ) + { + rootNode = listArray[currentIndex].parent.cloneNode( false ) ; + retval.appendChild( rootNode ) ; + } + currentListItem = doc.createElement( 'li' ) ; + rootNode.appendChild( currentListItem ) ; + for ( var i = 0 ; i < item.contents.length ; i++ ) + currentListItem.appendChild( item.contents[i].cloneNode( true ) ) ; + currentIndex++ ; + } + else if ( item.indent == Math.max( indentLevel, 0 ) + 1 ) + { + var listData = this.ArrayToList( listArray, null, currentIndex ) ; + currentListItem.appendChild( listData.listNode ) ; + currentIndex = listData.nextIndex ; + } + else if ( item.indent == -1 && baseIndex == 0 && item.grandparent ) + { + var currentListItem ; + if ( item.grandparent.nodeName.IEquals( ['ul', 'ol'] ) ) + currentListItem = doc.createElement( 'li' ) ; + else + { + if ( FCKConfig.EnterMode.IEquals( ['div', 'p'] ) && ! item.grandparent.nodeName.IEquals( 'td' ) ) + currentListItem = doc.createElement( FCKConfig.EnterMode ) ; + else + currentListItem = doc.createDocumentFragment() ; + } + for ( var i = 0 ; i < item.contents.length ; i++ ) + currentListItem.appendChild( item.contents[i].cloneNode( true ) ) ; + if ( currentListItem.nodeType == 11 ) + { + if ( currentListItem.lastChild && + currentListItem.lastChild.getAttribute && + currentListItem.lastChild.getAttribute( 'type' ) == '_moz' ) + currentListItem.removeChild( currentListItem.lastChild ); + currentListItem.appendChild( doc.createElement( 'br' ) ) ; + } + if ( currentListItem.nodeName.IEquals( FCKConfig.EnterMode ) && currentListItem.firstChild ) + { + this.TrimNode( currentListItem ) ; + if ( FCKListsLib.BlockBoundaries[currentListItem.firstChild.nodeName.toLowerCase()] ) + { + var tmp = doc.createDocumentFragment() ; + while ( currentListItem.firstChild ) + tmp.appendChild( currentListItem.removeChild( currentListItem.firstChild ) ) ; + currentListItem = tmp ; + } + } + if ( FCKBrowserInfo.IsGeckoLike && currentListItem.nodeName.IEquals( ['div', 'p'] ) ) + FCKTools.AppendBogusBr( currentListItem ) ; + retval.appendChild( currentListItem ) ; + rootNode = null ; + currentIndex++ ; + } + else + return null ; + + if ( listArray.length <= currentIndex || Math.max( listArray[currentIndex].indent, 0 ) < indentLevel ) + { + break ; + } + } + + // Clear marker attributes for the new list tree made of cloned nodes, if any. + if ( markerObj ) + { + var currentNode = retval.firstChild ; + while ( currentNode ) + { + if ( currentNode.nodeType == 1 ) + this.ClearElementMarkers( markerObj, currentNode ) ; + currentNode = this.GetNextSourceNode( currentNode ) ; + } + } + + return { 'listNode' : retval, 'nextIndex' : currentIndex } ; + }, + + /** + * Get the next sibling node for a node. If "includeEmpties" is false, + * only element or non empty text nodes are returned. + */ + GetNextSibling : function( node, includeEmpties ) + { + node = node.nextSibling ; + + while ( node && !includeEmpties && node.nodeType != 1 && ( node.nodeType != 3 || node.nodeValue.length == 0 ) ) + node = node.nextSibling ; + + return node ; + }, + + /** + * Get the previous sibling node for a node. If "includeEmpties" is false, + * only element or non empty text nodes are returned. + */ + GetPreviousSibling : function( node, includeEmpties ) + { + node = node.previousSibling ; + + while ( node && !includeEmpties && node.nodeType != 1 && ( node.nodeType != 3 || node.nodeValue.length == 0 ) ) + node = node.previousSibling ; + + return node ; + }, + + /** + * Checks if an element has no "useful" content inside of it + * node tree. No "useful" content means empty text node or a signle empty + * inline node. + * elementCheckCallback may point to a function that returns a boolean + * indicating that a child element must be considered in the element check. + */ + CheckIsEmptyElement : function( element, elementCheckCallback ) + { + var child = element.firstChild ; + var elementChild ; + + while ( child ) + { + if ( child.nodeType == 1 ) + { + if ( elementChild || !FCKListsLib.InlineNonEmptyElements[ child.nodeName.toLowerCase() ] ) + return false ; + + if ( !elementCheckCallback || elementCheckCallback( child ) === true ) + elementChild = child ; + } + else if ( child.nodeType == 3 && child.nodeValue.length > 0 ) + return false ; + + child = child.nextSibling ; + } + + return elementChild ? this.CheckIsEmptyElement( elementChild, elementCheckCallback ) : true ; + }, + + SetElementStyles : function( element, styleDict ) + { + var style = element.style ; + for ( var styleName in styleDict ) + style[ styleName ] = styleDict[ styleName ] ; + }, + + SetOpacity : function( element, opacity ) + { + if ( FCKBrowserInfo.IsIE ) + { + opacity = Math.round( opacity * 100 ) ; + element.style.filter = ( opacity > 100 ? '' : 'progid:DXImageTransform.Microsoft.Alpha(opacity=' + opacity + ')' ) ; + } + else + element.style.opacity = opacity ; + }, + + GetCurrentElementStyle : function( element, propertyName ) + { + if ( FCKBrowserInfo.IsIE ) + return element.currentStyle[ propertyName ] ; + else + return element.ownerDocument.defaultView.getComputedStyle( element, '' ).getPropertyValue( propertyName ) ; + }, + + GetPositionedAncestor : function( element ) + { + var currentElement = element ; + + while ( currentElement != FCKTools.GetElementDocument( currentElement ).documentElement ) + { + if ( this.GetCurrentElementStyle( currentElement, 'position' ) != 'static' ) + return currentElement ; + + if ( currentElement == FCKTools.GetElementDocument( currentElement ).documentElement + && currentWindow != w ) + currentElement = currentWindow.frameElement ; + else + currentElement = currentElement.parentNode ; + } + + return null ; + }, + + /** + * Current implementation for ScrollIntoView (due to #1462). We don't have + * a complete implementation here, just the things that fit our needs. + */ + ScrollIntoView : function( element, alignTop ) + { + // Get the element window. + var window = FCKTools.GetElementWindow( element ) ; + var windowHeight = FCKTools.GetViewPaneSize( window ).Height ; + + // Starts the offset that will be scrolled with the negative value of + // the visible window height. + var offset = windowHeight * -1 ; + + // Appends the height it we are about to align the bottoms. + if ( alignTop === false ) + { + offset += element.offsetHeight ; + + // Consider the margin in the scroll, which is ok for our current + // needs, but needs investigation if we will be using this function + // in other places. + offset += parseInt( this.GetCurrentElementStyle( element, 'marginBottom' ) || 0, 10 ) ; + } + + // Appends the offsets for the entire element hierarchy. + offset += element.offsetTop ; + while ( ( element = element.offsetParent ) ) + offset += element.offsetTop || 0 ; + + // Scroll the window to the desired position, if not already visible. + var currentScroll = FCKTools.GetScrollPosition( window ).Y ; + if ( offset > 0 && offset > currentScroll ) + window.scrollTo( 0, offset ) ; + }, + + /** + * Check if the element can be edited inside the browser. + */ + CheckIsEditable : function( element ) + { + // Get the element name. + var nodeName = element.nodeName.toLowerCase() ; + + // Get the element DTD (defaults to span for unknown elements). + var childDTD = FCK.DTD[ nodeName ] || FCK.DTD.span ; + + // In the DTD # == text node. + return ( childDTD['#'] && !FCKListsLib.NonEditableElements[ nodeName ] ) ; + } +} ; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcklanguagemanager.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcklanguagemanager.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcklanguagemanager.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,163 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Defines the FCKLanguageManager object that is used for language + * operations. + */ + +var FCKLanguageManager = FCK.Language = +{ + AvailableLanguages : + { + af : 'Afrikaans', + ar : 'Arabic', + bg : 'Bulgarian', + bn : 'Bengali/Bangla', + bs : 'Bosnian', + ca : 'Catalan', + cs : 'Czech', + da : 'Danish', + de : 'German', + el : 'Greek', + en : 'English', + 'en-au' : 'English (Australia)', + 'en-ca' : 'English (Canadian)', + 'en-uk' : 'English (United Kingdom)', + eo : 'Esperanto', + es : 'Spanish', + et : 'Estonian', + eu : 'Basque', + fa : 'Persian', + fi : 'Finnish', + fo : 'Faroese', + fr : 'French', + 'fr-ca' : 'French (Canada)', + gl : 'Galician', + he : 'Hebrew', + hi : 'Hindi', + hr : 'Croatian', + hu : 'Hungarian', + it : 'Italian', + ja : 'Japanese', + km : 'Khmer', + ko : 'Korean', + lt : 'Lithuanian', + lv : 'Latvian', + mn : 'Mongolian', + ms : 'Malay', + nb : 'Norwegian Bokmal', + nl : 'Dutch', + no : 'Norwegian', + pl : 'Polish', + pt : 'Portuguese (Portugal)', + 'pt-br' : 'Portuguese (Brazil)', + ro : 'Romanian', + ru : 'Russian', + sk : 'Slovak', + sl : 'Slovenian', + sr : 'Serbian (Cyrillic)', + 'sr-latn' : 'Serbian (Latin)', + sv : 'Swedish', + th : 'Thai', + tr : 'Turkish', + uk : 'Ukrainian', + vi : 'Vietnamese', + zh : 'Chinese Traditional', + 'zh-cn' : 'Chinese Simplified' + }, + + GetActiveLanguage : function() + { + if ( FCKConfig.AutoDetectLanguage ) + { + var sUserLang ; + + // IE accepts "navigator.userLanguage" while Gecko "navigator.language". + if ( navigator.userLanguage ) + sUserLang = navigator.userLanguage.toLowerCase() ; + else if ( navigator.language ) + sUserLang = navigator.language.toLowerCase() ; + else + { + // Firefox 1.0 PR has a bug: it doens't support the "language" property. + return FCKConfig.DefaultLanguage ; + } + + // Some language codes are set in 5 characters, + // like "pt-br" for Brazilian Portuguese. + if ( sUserLang.length >= 5 ) + { + sUserLang = sUserLang.substr(0,5) ; + if ( this.AvailableLanguages[sUserLang] ) return sUserLang ; + } + + // If the user's browser is set to, for example, "pt-br" but only the + // "pt" language file is available then get that file. + if ( sUserLang.length >= 2 ) + { + sUserLang = sUserLang.substr(0,2) ; + if ( this.AvailableLanguages[sUserLang] ) return sUserLang ; + } + } + + return this.DefaultLanguage ; + }, + + TranslateElements : function( targetDocument, tag, propertyToSet, encode ) + { + var e = targetDocument.getElementsByTagName(tag) ; + var sKey, s ; + for ( var i = 0 ; i < e.length ; i++ ) + { + // The extra () is to avoid a warning with strict error checking. This is ok. + if ( (sKey = e[i].getAttribute( 'fckLang' )) ) + { + // The extra () is to avoid a warning with strict error checking. This is ok. + if ( (s = FCKLang[ sKey ]) ) + { + if ( encode ) + s = FCKTools.HTMLEncode( s ) ; + e[i][ propertyToSet ] = s ; + } + } + } + }, + + TranslatePage : function( targetDocument ) + { + this.TranslateElements( targetDocument, 'INPUT', 'value' ) ; + this.TranslateElements( targetDocument, 'SPAN', 'innerHTML' ) ; + this.TranslateElements( targetDocument, 'LABEL', 'innerHTML' ) ; + this.TranslateElements( targetDocument, 'OPTION', 'innerHTML', true ) ; + this.TranslateElements( targetDocument, 'LEGEND', 'innerHTML' ) ; + }, + + Initialize : function() + { + if ( this.AvailableLanguages[ FCKConfig.DefaultLanguage ] ) + this.DefaultLanguage = FCKConfig.DefaultLanguage ; + else + this.DefaultLanguage = 'en' ; + + this.ActiveLanguage = new Object() ; + this.ActiveLanguage.Code = this.GetActiveLanguage() ; + this.ActiveLanguage.Name = this.AvailableLanguages[ this.ActiveLanguage.Code ] ; + } +} ; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcklisthandler.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcklisthandler.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcklisthandler.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,152 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Tool object to manage HTML lists items (UL, OL and LI). + */ + +var FCKListHandler = +{ + OutdentListItem : function( listItem ) + { + var eParent = listItem.parentNode ; + + // It may happen that a LI is not in a UL or OL (Orphan). + if ( eParent.tagName.toUpperCase().Equals( 'UL','OL' ) ) + { + var oDocument = FCKTools.GetElementDocument( listItem ) ; + var oDogFrag = new FCKDocumentFragment( oDocument ) ; + + // All children and successive siblings will be moved to a a DocFrag. + var eNextSiblings = oDogFrag.RootNode ; + var eHasLiSibling = false ; + + // If we have nested lists inside it, let's move it to the list of siblings. + var eChildList = FCKDomTools.GetFirstChild( listItem, ['UL','OL'] ) ; + if ( eChildList ) + { + eHasLiSibling = true ; + + var eChild ; + // The extra () is to avoid a warning with strict error checking. This is ok. + while ( (eChild = eChildList.firstChild) ) + eNextSiblings.appendChild( eChildList.removeChild( eChild ) ) ; + + FCKDomTools.RemoveNode( eChildList ) ; + } + + // Move all successive siblings. + var eSibling ; + var eHasSuccessiveLiSibling = false ; + // The extra () is to avoid a warning with strict error checking. This is ok. + while ( (eSibling = listItem.nextSibling) ) + { + if ( !eHasLiSibling && eSibling.nodeType == 1 && eSibling.nodeName.toUpperCase() == 'LI' ) + eHasSuccessiveLiSibling = eHasLiSibling = true ; + + eNextSiblings.appendChild( eSibling.parentNode.removeChild( eSibling ) ) ; + + // If a sibling is a incorrectly nested UL or OL, consider only its children. + if ( !eHasSuccessiveLiSibling && eSibling.nodeType == 1 && eSibling.nodeName.toUpperCase().Equals( 'UL','OL' ) ) + FCKDomTools.RemoveNode( eSibling, true ) ; + } + + // If we are in a list chain. + var sParentParentTag = eParent.parentNode.tagName.toUpperCase() ; + var bWellNested = ( sParentParentTag == 'LI' ) ; + if ( bWellNested || sParentParentTag.Equals( 'UL','OL' ) ) + { + if ( eHasLiSibling ) + { + var eChildList = eParent.cloneNode( false ) ; + oDogFrag.AppendTo( eChildList ) ; + listItem.appendChild( eChildList ) ; + } + else if ( bWellNested ) + oDogFrag.InsertAfterNode( eParent.parentNode ) ; + else + oDogFrag.InsertAfterNode( eParent ) ; + + // Move the LI after its parent.parentNode (the upper LI in the hierarchy). + if ( bWellNested ) + FCKDomTools.InsertAfterNode( eParent.parentNode, eParent.removeChild( listItem ) ) ; + else + FCKDomTools.InsertAfterNode( eParent, eParent.removeChild( listItem ) ) ; + } + else + { + if ( eHasLiSibling ) + { + var eNextList = eParent.cloneNode( false ) ; + oDogFrag.AppendTo( eNextList ) ; + FCKDomTools.InsertAfterNode( eParent, eNextList ) ; + } + + var eBlock = oDocument.createElement( FCKConfig.EnterMode == 'p' ? 'p' : 'div' ) ; + FCKDomTools.MoveChildren( eParent.removeChild( listItem ), eBlock ) ; + FCKDomTools.InsertAfterNode( eParent, eBlock ) ; + + if ( FCKConfig.EnterMode == 'br' ) + { + // We need the bogus to make it work properly. In Gecko, we + // need it before the new block, on IE, after it. + if ( FCKBrowserInfo.IsGecko ) + eBlock.parentNode.insertBefore( FCKTools.CreateBogusBR( oDocument ), eBlock ) ; + else + FCKDomTools.InsertAfterNode( eBlock, FCKTools.CreateBogusBR( oDocument ) ) ; + + FCKDomTools.RemoveNode( eBlock, true ) ; + } + } + + if ( this.CheckEmptyList( eParent ) ) + FCKDomTools.RemoveNode( eParent, true ) ; + } + }, + + CheckEmptyList : function( listElement ) + { + return ( FCKDomTools.GetFirstChild( listElement, 'LI' ) == null ) ; + }, + + // Check if the list has contents (excluding nested lists). + CheckListHasContents : function( listElement ) + { + var eChildNode = listElement.firstChild ; + + while ( eChildNode ) + { + switch ( eChildNode.nodeType ) + { + case 1 : + if ( !eChildNode.nodeName.IEquals( 'UL','LI' ) ) + return true ; + break ; + + case 3 : + if ( eChildNode.nodeValue.Trim().length > 0 ) + return true ; + } + + eChildNode = eChildNode.nextSibling ; + } + + return false ; + } +} ; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcklistslib.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcklistslib.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcklistslib.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,63 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Library of keys collections. + * + * Test have shown that check for the existence of a key in an object is the + * most efficient list entry check (10x faster that regex). Example: + * if ( FCKListsLib.<ListName>[key] != null ) + */ + +var FCKListsLib = +{ + // We are not handling <ins> and <del> as block elements, for now. + BlockElements : { address:1,blockquote:1,center:1,div:1,dl:1,fieldset:1,form:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,hr:1,marquee:1,noscript:1,ol:1,p:1,pre:1,script:1,table:1,ul:1 }, + + // Block elements that may be filled with if empty. + NonEmptyBlockElements : { p:1,div:1,form:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,address:1,pre:1,ol:1,ul:1,li:1,td:1,th:1 }, + + // Inline elements which MUST have child nodes. + InlineChildReqElements : { abbr:1,acronym:1,b:1,bdo:1,big:1,cite:1,code:1,del:1,dfn:1,em:1,font:1,i:1,ins:1,label:1,kbd:1,q:1,samp:1,small:1,span:1,strike:1,strong:1,sub:1,sup:1,tt:1,u:1,'var':1 }, + + // Inline elements which are not marked as empty "Empty" in the XHTML DTD. + InlineNonEmptyElements : { a:1,abbr:1,acronym:1,b:1,bdo:1,big:1,cite:1,code:1,del:1,dfn:1,em:1,font:1,i:1,ins:1,label:1,kbd:1,q:1,samp:1,small:1,span:1,strike:1,strong:1,sub:1,sup:1,tt:1,u:1,'var':1 }, + + // Elements marked as empty "Empty" in the XHTML DTD. + EmptyElements : { base:1,col:1,meta:1,link:1,hr:1,br:1,param:1,img:1,area:1,input:1 }, + + // Elements that may be considered the "Block boundary" in an element path. + PathBlockElements : { address:1,blockquote:1,dl:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,p:1,pre:1,li:1,dt:1,de:1 }, + + // Elements that may be considered the "Block limit" in an element path. + PathBlockLimitElements : { body:1,div:1,td:1,th:1,caption:1,form:1 }, + + // Block elements for the Styles System. + StyleBlockElements : { address:1,div:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,p:1,pre:1 }, + + // Object elements for the Styles System. + StyleObjectElements : { img:1,hr:1,li:1,table:1,tr:1,td:1,embed:1,object:1,ol:1,ul:1 }, + + // Elements that accept text nodes, but are not possible to edit in the browser. + NonEditableElements : { button:1,option:1,script:1,iframe:1,textarea:1,object:1,embed:1,map:1,applet:1 }, + + // Elements used to separate block contents. + BlockBoundaries : { p:1,div:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,hr:1,address:1,pre:1,ol:1,ul:1,li:1,dt:1,de:1,table:1,thead:1,tbody:1,tfoot:1,tr:1,th:1,td:1,caption:1,col:1,colgroup:1,blockquote:1,body:1 }, + ListBoundaries : { p:1,div:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,hr:1,address:1,pre:1,ol:1,ul:1,li:1,dt:1,de:1,table:1,thead:1,tbody:1,tfoot:1,tr:1,th:1,td:1,caption:1,col:1,colgroup:1,blockquote:1,body:1,br:1 } +} ; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckplugins.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckplugins.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckplugins.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,46 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Defines the FCKPlugins object that is responsible for loading the Plugins. + */ + +var FCKPlugins = FCK.Plugins = new Object() ; +FCKPlugins.ItemsCount = 0 ; +FCKPlugins.Items = new Object() ; + +FCKPlugins.Load = function() +{ + var oItems = FCKPlugins.Items ; + + // build the plugins collection. + for ( var i = 0 ; i < FCKConfig.Plugins.Items.length ; i++ ) + { + var oItem = FCKConfig.Plugins.Items[i] ; + var oPlugin = oItems[ oItem[0] ] = new FCKPlugin( oItem[0], oItem[1], oItem[2] ) ; + FCKPlugins.ItemsCount++ ; + } + + // Load all items in the plugins collection. + for ( var s in oItems ) + oItems[s].Load() ; + + // This is a self destroyable function (must be called once). + FCKPlugins.Load = null ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckregexlib.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckregexlib.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckregexlib.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,99 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * These are some Regular Expressions used by the editor. + */ + +var FCKRegexLib = +{ +// This is the Regular expression used by the SetData method for the "'" entity. +AposEntity : /'/gi , + +// Used by the Styles combo to identify styles that can't be applied to text. +ObjectElements : /^(?:IMG|TABLE|TR|TD|TH|INPUT|SELECT|TEXTAREA|HR|OBJECT|A|UL|OL|LI)$/i , + +// List all named commands (commands that can be interpreted by the browser "execCommand" method. +NamedCommands : /^(?:Cut|Copy|Paste|Print|SelectAll|RemoveFormat|Unlink|Undo|Redo|Bold|Italic|Underline|StrikeThrough|Subscript|Superscript|JustifyLeft|JustifyCenter|JustifyRight|JustifyFull|Outdent|Indent|InsertOrderedList|InsertUnorderedList|InsertHorizontalRule)$/i , + +BeforeBody : /(^[\s\S]*\<body[^\>]*\>)/i, +AfterBody : /(\<\/body\>[\s\S]*$)/i, + +// Temporary text used to solve some browser specific limitations. +ToReplace : /___fcktoreplace:([\w]+)/ig , + +// Get the META http-equiv attribute from the tag. +MetaHttpEquiv : /http-equiv\s*=\s*["']?([^"' ]+)/i , + +HasBaseTag : /<base /i , +HasBodyTag : /<body[\s|>]/i , + +HtmlOpener : /<html\s?[^>]*>/i , +HeadOpener : /<head\s?[^>]*>/i , +HeadCloser : /<\/head\s*>/i , + +// Temporary classes (Tables without border, Anchors with content) used in IE +FCK_Class : /\s*FCK__[^ ]*(?=\s+|$)/ , + +// Validate element names (it must be in lowercase). +ElementName : /(^[a-z_:][\w.\-:]*\w$)|(^[a-z_]$)/ , + +// Used in conjunction with the FCKConfig.ForceSimpleAmpersand configuration option. +ForceSimpleAmpersand : /___FCKAmp___/g , + +// Get the closing parts of the tags with no closing tags, like <br/>... gets the "/>" part. +SpaceNoClose : /\/>/g , + +// Empty elements may be <p></p> or even a simple opening <p> (see #211). +EmptyParagraph : /^<(p|div|address|h\d|center)(?=[ >])[^>]*>\s*(<\/\1>)?$/ , + +EmptyOutParagraph : /^<(p|div|address|h\d|center)(?=[ >])[^>]*>(?:\s*| )(<\/\1>)?$/ , + +TagBody : /></ , + +GeckoEntitiesMarker : /#\?-\:/g , + +// We look for the "src" and href attribute with the " or ' or without one of +// them. We have to do all in one, otherwise we will have problems with URLs +// like "thumbnail.php?src=someimage.jpg" (SF-BUG 1554141). +ProtectUrlsImg : /<img(?=\s).*?\ssrc=((?:(?:\s*)("|').*?\2)|(?:[^"'][^ >]+))/gi , +ProtectUrlsA : /<a(?=\s).*?\shref=((?:(?:\s*)("|').*?\2)|(?:[^"'][^ >]+))/gi , +ProtectUrlsArea : /<area(?=\s).*?\shref=((?:(?:\s*)("|').*?\2)|(?:[^"'][^ >]+))/gi , + +Html4DocType : /HTML 4\.0 Transitional/i , +DocTypeTag : /<!DOCTYPE[^>]*>/i , + +// These regex are used to save the original event attributes in the HTML. +TagsWithEvent : /<[^\>]+ on\w+[\s\r\n]*=[\s\r\n]*?('|")[\s\S]+?\>/g , +EventAttributes : /\s(on\w+)[\s\r\n]*=[\s\r\n]*?('|")([\s\S]*?)\2/g, +ProtectedEvents : /\s\w+_fckprotectedatt="([^"]+)"/g, + +StyleProperties : /\S+\s*:/g, + +// [a-zA-Z0-9:]+ seams to be more efficient than [\w:]+ +InvalidSelfCloseTags : /(<(?!base|meta|link|hr|br|param|img|area|input)([a-zA-Z0-9:]+)[^>]*)\/>/gi, + +// All variables defined in a style attribute or style definition. The variable +// name is returned with $2. +StyleVariableAttName : /#\(\s*("|')(.+?)\1[^\)]*\s*\)/g, + +RegExp : /^\/(.*)\/([gim]*)$/, + +HtmlTag : /<[^\s<>](?:"[^"]*"|'[^']*'|[^<])*>/ +} ; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckselection.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckselection.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckselection.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,42 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Active selection functions. + */ + +var FCKSelection = FCK.Selection = +{ + GetParentBlock : function() + { + var retval = this.GetParentElement() ; + while ( retval ) + { + if ( FCKListsLib.BlockBoundaries[retval.nodeName.toLowerCase()] ) + break ; + retval = retval.parentNode ; + } + return retval ; + }, + + ApplyStyle : function( styleDefinition ) + { + FCKStyles.ApplyStyle( new FCKStyle( styleDefinition ) ) ; + } +} ; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckselection_gecko.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckselection_gecko.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckselection_gecko.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,220 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Active selection functions. (Gecko specific implementation) + */ + +// Get the selection type (like document.select.type in IE). +FCKSelection.GetType = function() +{ + // By default set the type to "Text". + var type = 'Text' ; + + // Check if the actual selection is a Control (IMG, TABLE, HR, etc...). + + var sel ; + try { sel = this.GetSelection() ; } catch (e) {} + + if ( sel && sel.rangeCount == 1 ) + { + var range = sel.getRangeAt(0) ; + if ( range.startContainer == range.endContainer + && ( range.endOffset - range.startOffset ) == 1 + && range.startContainer.nodeType == 1 + && FCKListsLib.StyleObjectElements[ range.startContainer.childNodes[ range.startOffset ].nodeName.toLowerCase() ] ) + { + type = 'Control' ; + } + } + + return type ; +} + +// Retrieves the selected element (if any), just in the case that a single +// element (object like and image or a table) is selected. +FCKSelection.GetSelectedElement = function() +{ + var selection = !!FCK.EditorWindow && this.GetSelection() ; + if ( !selection || selection.rangeCount < 1 ) + return null ; + + var range = selection.getRangeAt( 0 ) ; + if ( range.startContainer != range.endContainer || range.startContainer.nodeType != 1 || range.startOffset != range.endOffset - 1 ) + return null ; + + var node = range.startContainer.childNodes[ range.startOffset ] ; + if ( node.nodeType != 1 ) + return null ; + + return node ; +} + +FCKSelection.GetParentElement = function() +{ + if ( this.GetType() == 'Control' ) + return FCKSelection.GetSelectedElement().parentNode ; + else + { + var oSel = this.GetSelection() ; + if ( oSel ) + { + // make the common case fast - for collapsed/nearly collapsed selections just return anchor.parent. + if ( oSel.anchorNode && oSel.anchorNode == oSel.focusNode ) + return oSel.anchorNode.parentNode ; + + // looks like we're having a large selection here. To make the behavior same as IE's TextRange.parentElement(), + // we need to find the nearest ancestor node which encapsulates both the beginning and the end of the selection. + // TODO: A simpler logic can be found. + var anchorPath = new FCKElementPath( oSel.anchorNode ) ; + var focusPath = new FCKElementPath( oSel.focusNode ) ; + var deepPath = null ; + var shallowPath = null ; + if ( anchorPath.Elements.length > focusPath.Elements.length ) + { + deepPath = anchorPath.Elements ; + shallowPath = focusPath.Elements ; + } + else + { + deepPath = focusPath.Elements ; + shallowPath = anchorPath.Elements ; + } + + var deepPathBase = deepPath.length - shallowPath.length ; + for( var i = 0 ; i < shallowPath.length ; i++) + { + if ( deepPath[deepPathBase + i] == shallowPath[i]) + return shallowPath[i]; + } + return null ; + } + } + return null ; +} + +FCKSelection.GetBoundaryParentElement = function( startBoundary ) +{ + if ( ! FCK.EditorWindow ) + return null ; + if ( this.GetType() == 'Control' ) + return FCKSelection.GetSelectedElement().parentNode ; + else + { + var oSel = this.GetSelection() ; + if ( oSel && oSel.rangeCount > 0 ) + { + var range = oSel.getRangeAt( startBoundary ? 0 : ( oSel.rangeCount - 1 ) ) ; + + var element = startBoundary ? range.startContainer : range.endContainer ; + + return ( element.nodeType == 1 ? element : element.parentNode ) ; + } + } + return null ; +} + +FCKSelection.SelectNode = function( element ) +{ + var oRange = FCK.EditorDocument.createRange() ; + oRange.selectNode( element ) ; + + var oSel = this.GetSelection() ; + oSel.removeAllRanges() ; + oSel.addRange( oRange ) ; +} + +FCKSelection.Collapse = function( toStart ) +{ + var oSel = this.GetSelection() ; + + if ( toStart == null || toStart === true ) + oSel.collapseToStart() ; + else + oSel.collapseToEnd() ; +} + +// The "nodeTagName" parameter must be Upper Case. +FCKSelection.HasAncestorNode = function( nodeTagName ) +{ + var oContainer = this.GetSelectedElement() ; + if ( ! oContainer && FCK.EditorWindow ) + { + try { oContainer = this.GetSelection().getRangeAt(0).startContainer ; } + catch(e){} + } + + while ( oContainer ) + { + if ( oContainer.nodeType == 1 && oContainer.tagName == nodeTagName ) return true ; + oContainer = oContainer.parentNode ; + } + + return false ; +} + +// The "nodeTagName" parameter must be Upper Case. +FCKSelection.MoveToAncestorNode = function( nodeTagName ) +{ + var oNode ; + + var oContainer = this.GetSelectedElement() ; + if ( ! oContainer ) + oContainer = this.GetSelection().getRangeAt(0).startContainer ; + + while ( oContainer ) + { + if ( oContainer.nodeName == nodeTagName ) + return oContainer ; + + oContainer = oContainer.parentNode ; + } + return null ; +} + +FCKSelection.Delete = function() +{ + // Gets the actual selection. + var oSel = this.GetSelection() ; + + // Deletes the actual selection contents. + for ( var i = 0 ; i < oSel.rangeCount ; i++ ) + { + oSel.getRangeAt(i).deleteContents() ; + } + + return oSel ; +} + +/** + * Returns the native selection object. + */ +FCKSelection.GetSelection = function() +{ + return FCK.EditorWindow.getSelection() ; +} + +// The following are IE only features (we don't need then in other browsers +// currently). +FCKSelection.Save = function() +{} +FCKSelection.Restore = function() +{} +FCKSelection.Release = function() +{} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckselection_ie.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckselection_ie.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckselection_ie.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,275 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Active selection functions. (IE specific implementation) + */ + +// Get the selection type. +FCKSelection.GetType = function() +{ + // It is possible that we can still get a text range object even when type=='None' is returned by IE. + // So we'd better check the object returned by createRange() rather than by looking at the type. + try + { + var ieType = FCKSelection.GetSelection().type ; + if ( ieType == 'Control' || ieType == 'Text' ) + return ieType ; + + if ( this.GetSelection().createRange().parentElement ) + return 'Text' ; + } + catch(e) + { + // Nothing to do, it will return None properly. + } + + return 'None' ; +} ; + +// Retrieves the selected element (if any), just in the case that a single +// element (object like and image or a table) is selected. +FCKSelection.GetSelectedElement = function() +{ + if ( this.GetType() == 'Control' ) + { + var oRange = this.GetSelection().createRange() ; + + if ( oRange && oRange.item ) + return this.GetSelection().createRange().item(0) ; + } + return null ; +} ; + +FCKSelection.GetParentElement = function() +{ + switch ( this.GetType() ) + { + case 'Control' : + var el = FCKSelection.GetSelectedElement() ; + return el ? el.parentElement : null ; + + case 'None' : + return null ; + + default : + return this.GetSelection().createRange().parentElement() ; + } +} ; + +FCKSelection.GetBoundaryParentElement = function( startBoundary ) +{ + switch ( this.GetType() ) + { + case 'Control' : + var el = FCKSelection.GetSelectedElement() ; + return el ? el.parentElement : null ; + + case 'None' : + return null ; + + default : + var doc = FCK.EditorDocument ; + + var range = doc.selection.createRange() ; + range.collapse( startBoundary !== false ) ; + + var el = range.parentElement() ; + + // It may happen that range is comming from outside "doc", so we + // must check it (#1204). + return FCKTools.GetElementDocument( el ) == doc ? el : null ; + } +} ; + +FCKSelection.SelectNode = function( node ) +{ + FCK.Focus() ; + this.GetSelection().empty() ; + var oRange ; + try + { + // Try to select the node as a control. + oRange = FCK.EditorDocument.body.createControlRange() ; + oRange.addElement( node ) ; + } + catch(e) + { + // If failed, select it as a text range. + oRange = FCK.EditorDocument.body.createTextRange() ; + oRange.moveToElementText( node ) ; + } + + oRange.select() ; +} ; + +FCKSelection.Collapse = function( toStart ) +{ + FCK.Focus() ; + if ( this.GetType() == 'Text' ) + { + var oRange = this.GetSelection().createRange() ; + oRange.collapse( toStart == null || toStart === true ) ; + oRange.select() ; + } +} ; + +// The "nodeTagName" parameter must be Upper Case. +FCKSelection.HasAncestorNode = function( nodeTagName ) +{ + var oContainer ; + + if ( this.GetSelection().type == "Control" ) + { + oContainer = this.GetSelectedElement() ; + } + else + { + var oRange = this.GetSelection().createRange() ; + oContainer = oRange.parentElement() ; + } + + while ( oContainer ) + { + if ( oContainer.tagName == nodeTagName ) return true ; + oContainer = oContainer.parentNode ; + } + + return false ; +} ; + +// The "nodeTagName" parameter must be UPPER CASE. +FCKSelection.MoveToAncestorNode = function( nodeTagName ) +{ + var oNode, oRange ; + + if ( ! FCK.EditorDocument ) + return null ; + + if ( this.GetSelection().type == "Control" ) + { + oRange = this.GetSelection().createRange() ; + for ( i = 0 ; i < oRange.length ; i++ ) + { + if (oRange(i).parentNode) + { + oNode = oRange(i).parentNode ; + break ; + } + } + } + else + { + oRange = this.GetSelection().createRange() ; + oNode = oRange.parentElement() ; + } + + while ( oNode && oNode.nodeName != nodeTagName ) + oNode = oNode.parentNode ; + + return oNode ; +} ; + +FCKSelection.Delete = function() +{ + // Gets the actual selection. + var oSel = this.GetSelection() ; + + // Deletes the actual selection contents. + if ( oSel.type.toLowerCase() != "none" ) + { + oSel.clear() ; + } + + return oSel ; +} ; + +/** + * Returns the native selection object. + */ +FCKSelection.GetSelection = function() +{ + this.Restore() ; + return FCK.EditorDocument.selection ; +} + +FCKSelection.Save = function() +{ + // Ensures the editor has the selection focus. (#1801) + FCK.Focus() ; + + var editorDocument = FCK.EditorDocument ; + + if ( !editorDocument ) + return ; + + var selection = editorDocument.selection ; + var range ; + + if ( selection ) + { + range = selection.createRange() ; + + // Ensure that the range comes from the editor document. + if ( range ) + { + if ( range.parentElement && FCKTools.GetElementDocument( range.parentElement() ) != editorDocument ) + range = null ; + else if ( range.item && FCKTools.GetElementDocument( range.item(0) )!= editorDocument ) + range = null ; + } + } + + this.SelectionData = range ; +} + +FCKSelection._GetSelectionDocument = function( selection ) +{ + var range = selection.createRange() ; + if ( !range ) + return null; + else if ( range.item ) + return FCKTools.GetElementDocument( range.item( 0 ) ) ; + else + return FCKTools.GetElementDocument( range.parentElement() ) ; +} + +FCKSelection.Restore = function() +{ + if ( this.SelectionData ) + { + FCK.IsSelectionChangeLocked = true ; + + try + { + // Don't repeat the restore process if the editor document is already selected. + if ( this._GetSelectionDocument( FCK.EditorDocument.selection ) == FCK.EditorDocument ) + return ; + this.SelectionData.select() ; + } + catch ( e ) {} + + FCK.IsSelectionChangeLocked = false ; + } +} + +FCKSelection.Release = function() +{ + delete this.SelectionData ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckstyles.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckstyles.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckstyles.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,381 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Handles styles in a give document. + */ + +var FCKStyles = FCK.Styles = +{ + _Callbacks : {}, + _ObjectStyles : {}, + + ApplyStyle : function( style ) + { + if ( typeof style == 'string' ) + style = this.GetStyles()[ style ] ; + + if ( style ) + { + if ( style.GetType() == FCK_STYLE_OBJECT ) + style.ApplyToObject( FCKSelection.GetSelectedElement() ) ; + else + style.ApplyToSelection( FCK.EditorWindow ) ; + + FCK.Events.FireEvent( 'OnSelectionChange' ) ; + } + }, + + RemoveStyle : function( style ) + { + if ( typeof style == 'string' ) + style = this.GetStyles()[ style ] ; + + if ( style ) + { + style.RemoveFromSelection( FCK.EditorWindow ) ; + FCK.Events.FireEvent( 'OnSelectionChange' ) ; + } + }, + + /** + * Defines a callback function to be called when the current state of a + * specific style changes. + */ + AttachStyleStateChange : function( styleName, callback, callbackOwner ) + { + var callbacks = this._Callbacks[ styleName ] ; + + if ( !callbacks ) + callbacks = this._Callbacks[ styleName ] = [] ; + + callbacks.push( [ callback, callbackOwner ] ) ; + }, + + CheckSelectionChanges : function() + { + var startElement = FCKSelection.GetBoundaryParentElement( true ) ; + + if ( !startElement ) + return ; + + // Walks the start node parents path, checking all styles that are being listened. + var path = new FCKElementPath( startElement ) ; + var styles = this.GetStyles() ; + + for ( var styleName in styles ) + { + var callbacks = this._Callbacks[ styleName ] ; + + if ( callbacks ) + { + var style = styles[ styleName ] ; + var state = style.CheckActive( path ) ; + + if ( state != ( style._LastState || null ) ) + { + style._LastState = state ; + + for ( var i = 0 ; i < callbacks.length ; i++ ) + { + var callback = callbacks[i][0] ; + var callbackOwner = callbacks[i][1] ; + + callback.call( callbackOwner || window, styleName, state ) ; + } + } + } + } + }, + + CheckStyleInSelection : function( styleName ) + { + return false ; + }, + + _GetRemoveFormatTagsRegex : function () + { + var regex = new RegExp( '^(?:' + FCKConfig.RemoveFormatTags.replace( /,/g,'|' ) + ')$', 'i' ) ; + + return (this._GetRemoveFormatTagsRegex = function() + { + return regex ; + }) + && regex ; + }, + + /** + * Remove all styles from the current selection. + * TODO: + * - This is almost a duplication of FCKStyle.RemoveFromRange. We should + * try to merge things. + */ + RemoveAll : function() + { + var range = new FCKDomRange( FCK.EditorWindow ) ; + range.MoveToSelection() ; + + if ( range.CheckIsCollapsed() ) + return ; + + // Expand the range, if inside inline element boundaries. + range.Expand( 'inline_elements' ) ; + + // Get the bookmark nodes. + // Bookmark the range so we can re-select it after processing. + var bookmark = range.CreateBookmark( true ) ; + + // The style will be applied within the bookmark boundaries. + var startNode = range.GetBookmarkNode( bookmark, true ) ; + var endNode = range.GetBookmarkNode( bookmark, false ) ; + + range.Release( true ) ; + + var tagsRegex = this._GetRemoveFormatTagsRegex() ; + + // We need to check the selection boundaries (bookmark spans) to break + // the code in a way that we can properly remove partially selected nodes. + // For example, removing a <b> style from + // <b>This is [some text</b> to show <b>the] problem</b> + // ... where [ and ] represent the selection, must result: + // <b>This is </b>[some text to show the]<b> problem</b> + // The strategy is simple, we just break the partial nodes before the + // removal logic, having something that could be represented this way: + // <b>This is </b>[<b>some text</b> to show <b>the</b>]<b> problem</b> + + // Let's start checking the start boundary. + var path = new FCKElementPath( startNode ) ; + var pathElements = path.Elements ; + var pathElement ; + + for ( var i = 1 ; i < pathElements.length ; i++ ) + { + pathElement = pathElements[i] ; + + if ( pathElement == path.Block || pathElement == path.BlockLimit ) + break ; + + // If this element can be removed (even partially). + if ( tagsRegex.test( pathElement.nodeName ) ) + FCKDomTools.BreakParent( startNode, pathElement, range ) ; + } + + // Now the end boundary. + path = new FCKElementPath( endNode ) ; + pathElements = path.Elements ; + + for ( var i = 1 ; i < pathElements.length ; i++ ) + { + pathElement = pathElements[i] ; + + if ( pathElement == path.Block || pathElement == path.BlockLimit ) + break ; + + elementName = pathElement.nodeName.toLowerCase() ; + + // If this element can be removed (even partially). + if ( tagsRegex.test( pathElement.nodeName ) ) + FCKDomTools.BreakParent( endNode, pathElement, range ) ; + } + + // Navigate through all nodes between the bookmarks. + var currentNode = FCKDomTools.GetNextSourceNode( startNode, true, 1 ) ; + + while ( currentNode ) + { + // If we have reached the end of the selection, stop looping. + if ( currentNode == endNode ) + break ; + + // Cache the next node to be processed. Do it now, because + // currentNode may be removed. + var nextNode = FCKDomTools.GetNextSourceNode( currentNode, false, 1 ) ; + + // Remove elements nodes that match with this style rules. + if ( tagsRegex.test( currentNode.nodeName ) ) + FCKDomTools.RemoveNode( currentNode, true ) ; + else + FCKDomTools.RemoveAttributes( currentNode, FCKConfig.RemoveAttributesArray ); + + currentNode = nextNode ; + } + + range.SelectBookmark( bookmark ) ; + + FCK.Events.FireEvent( 'OnSelectionChange' ) ; + }, + + GetStyle : function( styleName ) + { + return this.GetStyles()[ styleName ] ; + }, + + GetStyles : function() + { + var styles = this._GetStyles ; + if ( !styles ) + { + styles = this._GetStyles = FCKTools.Merge( + this._LoadStylesCore(), + this._LoadStylesCustom(), + this._LoadStylesXml() ) ; + } + return styles ; + }, + + CheckHasObjectStyle : function( elementName ) + { + return !!this._ObjectStyles[ elementName ] ; + }, + + _LoadStylesCore : function() + { + var styles = {}; + var styleDefs = FCKConfig.CoreStyles ; + + for ( var styleName in styleDefs ) + { + // Core styles are prefixed with _FCK_. + var style = styles[ '_FCK_' + styleName ] = new FCKStyle( styleDefs[ styleName ] ) ; + style.IsCore = true ; + } + return styles ; + }, + + _LoadStylesCustom : function() + { + var styles = {}; + var styleDefs = FCKConfig.CustomStyles ; + + if ( styleDefs ) + { + for ( var styleName in styleDefs ) + { + var style = styles[ styleName ] = new FCKStyle( styleDefs[ styleName ] ) ; + style.Name = styleName ; + } + } + + return styles ; + }, + + _LoadStylesXml : function() + { + var styles = {}; + + var stylesXmlPath = FCKConfig.StylesXmlPath ; + + if ( !stylesXmlPath || stylesXmlPath.length == 0 ) + return styles ; + + // Load the XML file into a FCKXml object. + var xml = new FCKXml() ; + xml.LoadUrl( stylesXmlPath ) ; + + var stylesXmlObj = FCKXml.TransformToObject( xml.SelectSingleNode( 'Styles' ) ) ; + + // Get the "Style" nodes defined in the XML file. + var styleNodes = stylesXmlObj.$Style ; + + // Check that it did contain some valid nodes + if ( !styleNodes ) + return styles ; + + // Add each style to our "Styles" collection. + for ( var i = 0 ; i < styleNodes.length ; i++ ) + { + var styleNode = styleNodes[i] ; + + var element = ( styleNode.element || '' ).toLowerCase() ; + + if ( element.length == 0 ) + throw( 'The element name is required. Error loading "' + stylesXmlPath + '"' ) ; + + var styleDef = { + Element : element, + Attributes : {}, + Styles : {}, + Overrides : [] + } ; + + // Get the attributes defined for the style (if any). + var attNodes = styleNode.$Attribute || [] ; + + // Add the attributes to the style definition object. + for ( var j = 0 ; j < attNodes.length ; j++ ) + { + styleDef.Attributes[ attNodes[j].name ] = attNodes[j].value ; + } + + // Get the styles defined for the style (if any). + var cssStyleNodes = styleNode.$Style || [] ; + + // Add the attributes to the style definition object. + for ( j = 0 ; j < cssStyleNodes.length ; j++ ) + { + styleDef.Styles[ cssStyleNodes[j].name ] = cssStyleNodes[j].value ; + } + + // Load override definitions. + var cssStyleOverrideNodes = styleNode.$Override ; + if ( cssStyleOverrideNodes ) + { + for ( j = 0 ; j < cssStyleOverrideNodes.length ; j++ ) + { + var overrideNode = cssStyleOverrideNodes[j] ; + var overrideDef = + { + Element : overrideNode.element + } ; + + var overrideAttNode = overrideNode.$Attribute ; + if ( overrideAttNode ) + { + overrideDef.Attributes = {} ; + for ( var k = 0 ; k < overrideAttNode.length ; k++ ) + { + var overrideAttValue = overrideAttNode[k].value || null ; + if ( overrideAttValue ) + { + // Check if the override attribute value is a regular expression. + var regexMatch = overrideAttValue && FCKRegexLib.RegExp.exec( overrideAttValue ) ; + if ( regexMatch ) + overrideAttValue = new RegExp( regexMatch[1], regexMatch[2] || '' ) ; + } + overrideDef.Attributes[ overrideAttNode[k].name ] = overrideAttValue ; + } + } + + styleDef.Overrides.push( overrideDef ) ; + } + } + + var style = new FCKStyle( styleDef ) ; + style.Name = styleNode.name || element ; + + if ( style.GetType() == FCK_STYLE_OBJECT ) + this._ObjectStyles[ element ] = true ; + + // Add the style to the "Styles" collection using it's name as the key. + styles[ style.Name ] = style ; + } + + return styles ; + } +} ; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcktablehandler.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcktablehandler.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcktablehandler.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,858 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Manage table operations. + */ + +var FCKTableHandler = new Object() ; + +FCKTableHandler.InsertRow = function( insertBefore ) +{ + // Get the row where the selection is placed in. + var oRow = FCKSelection.MoveToAncestorNode( 'TR' ) ; + if ( !oRow ) return ; + + // Create a clone of the row. + var oNewRow = oRow.cloneNode( true ) ; + + // Insert the new row (copy) before of it. + oRow.parentNode.insertBefore( oNewRow, oRow ) ; + + // Clean one of the rows to produce the illusion of inserting an empty row before or after. + FCKTableHandler.ClearRow( insertBefore ? oNewRow : oRow ) ; +} + +FCKTableHandler.DeleteRows = function( row ) +{ + // If no row has been passed as a parameter, + // then get the row( s ) containing the cells where the selection is placed in. + // If user selected multiple rows ( by selecting multiple cells ), walk + // the selected cell list and delete the rows containing the selected cells + if ( ! row ) + { + var aCells = FCKTableHandler.GetSelectedCells() ; + var aRowsToDelete = new Array() ; + //queue up the rows -- it's possible ( and likely ) that we may get duplicates + for ( var i = 0; i < aCells.length; i++ ) + { + var oRow = FCKTools.GetElementAscensor( aCells[i],'TR' ) ; + aRowsToDelete[oRow.rowIndex] = oRow ; + } + for ( var i = aRowsToDelete.length; i >= 0; i-- ) + { + if ( aRowsToDelete[i] ) + FCKTableHandler.DeleteRows( aRowsToDelete[i] ); + } + return ; + } + + // Get the row's table. + var oTable = FCKTools.GetElementAscensor( row, 'TABLE' ) ; + + // If just one row is available then delete the entire table. + if ( oTable.rows.length == 1 ) + { + FCKTableHandler.DeleteTable( oTable ) ; + return ; + } + + // Delete the row. + row.parentNode.removeChild( row ) ; +} + +FCKTableHandler.DeleteTable = function( table ) +{ + // If no table has been passed as a parameter, + // then get the table where the selection is placed in. + if ( !table ) + { + table = FCKSelection.GetSelectedElement() ; + if ( !table || table.tagName != 'TABLE' ) + table = FCKSelection.MoveToAncestorNode( 'TABLE' ) ; + } + if ( !table ) return ; + + // Delete the table. + FCKSelection.SelectNode( table ) ; + FCKSelection.Collapse(); + + // if the table is wrapped with a singleton <p> ( or something similar ), remove + // the surrounding tag -- which likely won't show after deletion anyway + if ( table.parentNode.childNodes.length == 1 ) + table.parentNode.parentNode.removeChild( table.parentNode ); + else + table.parentNode.removeChild( table ) ; +} + +FCKTableHandler.InsertColumn = function( insertBefore ) +{ + // Get the cell where the selection is placed in. + var oCell = null ; + var nodes = this.GetSelectedCells() ; + + if ( nodes && nodes.length ) + oCell = nodes[ insertBefore ? 0 : ( nodes.length - 1 ) ] ; + + if ( ! oCell ) + return ; + + // Get the cell's table. + var oTable = FCKTools.GetElementAscensor( oCell, 'TABLE' ) ; + + var iIndex = oCell.cellIndex ; + + // Loop throw all rows available in the table. + for ( var i = 0 ; i < oTable.rows.length ; i++ ) + { + // Get the row. + var oRow = oTable.rows[i] ; + + // If the row doens't have enough cells, ignore it. + if ( oRow.cells.length < ( iIndex + 1 ) ) + continue ; + + oCell = oRow.cells[iIndex].cloneNode(false) ; + + if ( FCKBrowserInfo.IsGeckoLike ) + FCKTools.AppendBogusBr( oCell ) ; + + // Get back the currently selected cell. + var oBaseCell = oRow.cells[iIndex] ; + + if ( insertBefore ) + oRow.insertBefore( oCell, oBaseCell ) ; + else if ( oBaseCell.nextSibling ) + oRow.insertBefore( oCell, oBaseCell.nextSibling ) ; + else + oRow.appendChild( oCell ) ; + } +} + +FCKTableHandler.DeleteColumns = function( oCell ) +{ + // if user selected multiple cols ( by selecting multiple cells ), walk + // the selected cell list and delete the rows containing the selected cells + if ( !oCell ) + { + var aColsToDelete = FCKTableHandler.GetSelectedCells(); + for ( var i = aColsToDelete.length; i >= 0; i-- ) + { + if ( aColsToDelete[i] ) + FCKTableHandler.DeleteColumns( aColsToDelete[i] ); + } + return; + } + + if ( !oCell ) return ; + + // Get the cell's table. + var oTable = FCKTools.GetElementAscensor( oCell, 'TABLE' ) ; + + // Get the cell index. + var iIndex = oCell.cellIndex ; + + // Loop throw all rows (from down to up, because it's possible that some + // rows will be deleted). + for ( var i = oTable.rows.length - 1 ; i >= 0 ; i-- ) + { + // Get the row. + var oRow = oTable.rows[i] ; + + // If the cell to be removed is the first one and the row has just one cell. + if ( iIndex == 0 && oRow.cells.length == 1 ) + { + // Remove the entire row. + FCKTableHandler.DeleteRows( oRow ) ; + continue ; + } + + // If the cell to be removed exists the delete it. + if ( oRow.cells[iIndex] ) + oRow.removeChild( oRow.cells[iIndex] ) ; + } +} + +FCKTableHandler.InsertCell = function( cell, insertBefore ) +{ + // Get the cell where the selection is placed in. + var oCell = null ; + var nodes = this.GetSelectedCells() ; + if ( nodes && nodes.length ) + oCell = nodes[ insertBefore ? 0 : ( nodes.length - 1 ) ] ; + if ( ! oCell ) + return null ; + + // Create the new cell element to be added. + var oNewCell = FCK.EditorDocument.createElement( 'TD' ) ; + if ( FCKBrowserInfo.IsGeckoLike ) + FCKTools.AppendBogusBr( oNewCell ) ; + + if ( !insertBefore && oCell.cellIndex == oCell.parentNode.cells.length - 1 ) + oCell.parentNode.appendChild( oNewCell ) ; + else + oCell.parentNode.insertBefore( oNewCell, insertBefore ? oCell : oCell.nextSibling ) ; + + return oNewCell ; +} + +FCKTableHandler.DeleteCell = function( cell ) +{ + // If this is the last cell in the row. + if ( cell.parentNode.cells.length == 1 ) + { + // Delete the entire row. + FCKTableHandler.DeleteRows( FCKTools.GetElementAscensor( cell, 'TR' ) ) ; + return ; + } + + // Delete the cell from the row. + cell.parentNode.removeChild( cell ) ; +} + +FCKTableHandler.DeleteCells = function() +{ + var aCells = FCKTableHandler.GetSelectedCells() ; + + for ( var i = aCells.length - 1 ; i >= 0 ; i-- ) + { + FCKTableHandler.DeleteCell( aCells[i] ) ; + } +} + +FCKTableHandler._MarkCells = function( cells, label ) +{ + for ( var i = 0 ; i < cells.length ; i++ ) + cells[i][label] = true ; +} + +FCKTableHandler._UnmarkCells = function( cells, label ) +{ + for ( var i = 0 ; i < cells.length ; i++ ) + { + if ( FCKBrowserInfo.IsIE ) + cells[i].removeAttribute( label ) ; + else + delete cells[i][label] ; + } +} + +FCKTableHandler._ReplaceCellsByMarker = function( tableMap, marker, substitute ) +{ + for ( var i = 0 ; i < tableMap.length ; i++ ) + { + for ( var j = 0 ; j < tableMap[i].length ; j++ ) + { + if ( tableMap[i][j][marker] ) + tableMap[i][j] = substitute ; + } + } +} + +FCKTableHandler._GetMarkerGeometry = function( tableMap, rowIdx, colIdx, markerName ) +{ + var selectionWidth = 0 ; + var selectionHeight = 0 ; + var cellsLeft = 0 ; + var cellsUp = 0 ; + for ( var i = colIdx ; tableMap[rowIdx][i] && tableMap[rowIdx][i][markerName] ; i++ ) + selectionWidth++ ; + for ( var i = colIdx - 1 ; tableMap[rowIdx][i] && tableMap[rowIdx][i][markerName] ; i-- ) + { + selectionWidth++ ; + cellsLeft++ ; + } + for ( var i = rowIdx ; tableMap[i] && tableMap[i][colIdx] && tableMap[i][colIdx][markerName] ; i++ ) + selectionHeight++ ; + for ( var i = rowIdx - 1 ; tableMap[i] && tableMap[i][colIdx] && tableMap[i][colIdx][markerName] ; i-- ) + { + selectionHeight++ ; + cellsUp++ ; + } + return { 'width' : selectionWidth, 'height' : selectionHeight, 'x' : cellsLeft, 'y' : cellsUp } ; +} + +FCKTableHandler.CheckIsSelectionRectangular = function() +{ + // If every row and column in an area on a plane are of the same width and height, + // Then the area is a rectangle. + var cells = FCKTableHandler.GetSelectedCells() ; + if ( cells.length < 1 ) + return false ; + + this._MarkCells( cells, '_CellSelected' ) ; + + var tableMap = this._CreateTableMap( cells[0].parentNode.parentNode ) ; + var rowIdx = cells[0].parentNode.rowIndex ; + var colIdx = this._GetCellIndexSpan( tableMap, rowIdx, cells[0] ) ; + + var geometry = this._GetMarkerGeometry( tableMap, rowIdx, colIdx, '_CellSelected' ) ; + var baseColIdx = colIdx - geometry.x ; + var baseRowIdx = rowIdx - geometry.y ; + + if ( geometry.width >= geometry.height ) + { + for ( colIdx = baseColIdx ; colIdx < baseColIdx + geometry.width ; colIdx++ ) + { + rowIdx = baseRowIdx + ( colIdx - baseColIdx ) % geometry.height ; + if ( ! tableMap[rowIdx] || ! tableMap[rowIdx][colIdx] ) + { + this._UnmarkCells( cells, '_CellSelected' ) ; + return false ; + } + var g = this._GetMarkerGeometry( tableMap, rowIdx, colIdx, '_CellSelected' ) ; + if ( g.width != geometry.width || g.height != geometry.height ) + { + this._UnmarkCells( cells, '_CellSelected' ) ; + return false ; + } + } + } + else + { + for ( rowIdx = baseRowIdx ; rowIdx < baseRowIdx + geometry.height ; rowIdx++ ) + { + colIdx = baseColIdx + ( rowIdx - baseRowIdx ) % geometry.width ; + if ( ! tableMap[rowIdx] || ! tableMap[rowIdx][colIdx] ) + { + this._UnmarkCells( cells, '_CellSelected' ) ; + return false ; + } + var g = this._GetMarkerGeometry( tableMap, rowIdx, colIdx, '_CellSelected' ) ; + if ( g.width != geometry.width || g.height != geometry.height ) + { + this._UnmarkCells( cells, '_CellSelected' ) ; + return false ; + } + } + } + + this._UnmarkCells( cells, '_CellSelected' ) ; + return true ; +} + +FCKTableHandler.MergeCells = function() +{ + // Get all selected cells. + var cells = this.GetSelectedCells() ; + if ( cells.length < 2 ) + return ; + + // Assume the selected cells are already in a rectangular geometry. + // Because the checking is already done by FCKTableCommand. + var refCell = cells[0] ; + var tableMap = this._CreateTableMap( refCell.parentNode.parentNode ) ; + var rowIdx = refCell.parentNode.rowIndex ; + var colIdx = this._GetCellIndexSpan( tableMap, rowIdx, refCell ) ; + + this._MarkCells( cells, '_SelectedCells' ) ; + var selectionGeometry = this._GetMarkerGeometry( tableMap, rowIdx, colIdx, '_SelectedCells' ) ; + + var baseColIdx = colIdx - selectionGeometry.x ; + var baseRowIdx = rowIdx - selectionGeometry.y ; + var cellContents = FCKTools.GetElementDocument( refCell ).createDocumentFragment() ; + for ( var i = 0 ; i < selectionGeometry.height ; i++ ) + { + var rowChildNodesCount = 0 ; + for ( var j = 0 ; j < selectionGeometry.width ; j++ ) + { + var currentCell = tableMap[baseRowIdx + i][baseColIdx + j] ; + while ( currentCell.childNodes.length > 0 ) + { + var node = currentCell.removeChild( currentCell.firstChild ) ; + if ( node.nodeType != 1 + || ( node.getAttribute( 'type', 2 ) != '_moz' && node.getAttribute( '_moz_dirty' ) != null ) ) + { + cellContents.appendChild( node ) ; + rowChildNodesCount++ ; + } + } + } + if ( rowChildNodesCount > 0 ) + cellContents.appendChild( FCKTools.GetElementDocument( refCell ).createElement( 'br' ) ) ; + } + + this._ReplaceCellsByMarker( tableMap, '_SelectedCells', refCell ) ; + this._UnmarkCells( cells, '_SelectedCells' ) ; + this._InstallTableMap( tableMap, refCell.parentNode.parentNode ) ; + refCell.appendChild( cellContents ) ; + + if ( FCKBrowserInfo.IsGeckoLike && ( ! refCell.firstChild ) ) + FCKTools.AppendBogusBr( refCell ) ; + + this._MoveCaretToCell( refCell, false ) ; +} + +FCKTableHandler.MergeRight = function() +{ + var target = this.GetMergeRightTarget() ; + if ( target == null ) + return ; + var refCell = target.refCell ; + var tableMap = target.tableMap ; + var nextCell = target.nextCell ; + + var cellContents = FCK.EditorDocument.createDocumentFragment() ; + while ( nextCell && nextCell.childNodes && nextCell.childNodes.length > 0 ) + cellContents.appendChild( nextCell.removeChild( nextCell.firstChild ) ) ; + + nextCell.parentNode.removeChild( nextCell ) ; + refCell.appendChild( cellContents ) ; + this._MarkCells( [nextCell], '_Replace' ) ; + this._ReplaceCellsByMarker( tableMap, '_Replace', refCell ) ; + this._InstallTableMap( tableMap, refCell.parentNode.parentNode ) ; + + this._MoveCaretToCell( refCell, false ) ; +} + +FCKTableHandler.MergeDown = function() +{ + var target = this.GetMergeDownTarget() ; + if ( target == null ) + return ; + var refCell = target.refCell ; + var tableMap = target.tableMap ; + var nextCell = target.nextCell ; + + var cellContents = FCKTools.GetElementDocument( refCell ).createDocumentFragment() ; + while ( nextCell && nextCell.childNodes && nextCell.childNodes.length > 0 ) + cellContents.appendChild( nextCell.removeChild( nextCell.firstChild ) ) ; + if ( cellContents.firstChild ) + cellContents.insertBefore( FCKTools.GetElementDocument( nextCell ).createElement( 'br' ), cellContents.firstChild ) ; + refCell.appendChild( cellContents ) ; + this._MarkCells( [nextCell], '_Replace' ) ; + this._ReplaceCellsByMarker( tableMap, '_Replace', refCell ) ; + this._InstallTableMap( tableMap, refCell.parentNode.parentNode ) ; + + this._MoveCaretToCell( refCell, false ) ; +} + +FCKTableHandler.HorizontalSplitCell = function() +{ + var cells = FCKTableHandler.GetSelectedCells() ; + if ( cells.length != 1 ) + return ; + + var refCell = cells[0] ; + var tableMap = this._CreateTableMap( refCell.parentNode.parentNode ) ; + var rowIdx = refCell.parentNode.rowIndex ; + var colIdx = FCKTableHandler._GetCellIndexSpan( tableMap, rowIdx, refCell ) ; + var cellSpan = isNaN( refCell.colSpan ) ? 1 : refCell.colSpan ; + + if ( cellSpan > 1 ) + { + // Splittng a multi-column cell - original cell gets ceil(colSpan/2) columns, + // new cell gets floor(colSpan/2). + var newCellSpan = Math.ceil( cellSpan / 2 ) ; + var newCell = FCKTools.GetElementDocument( refCell ).createElement( 'td' ) ; + if ( FCKBrowserInfo.IsGeckoLike ) + FCKTools.AppendBogusBr( newCell ) ; + var startIdx = colIdx + newCellSpan ; + var endIdx = colIdx + cellSpan ; + var rowSpan = isNaN( refCell.rowSpan ) ? 1 : refCell.rowSpan ; + for ( var r = rowIdx ; r < rowIdx + rowSpan ; r++ ) + { + for ( var i = startIdx ; i < endIdx ; i++ ) + tableMap[r][i] = newCell ; + } + } + else + { + // Splitting a single-column cell - add a new cell, and expand + // cells crossing the same column. + var newTableMap = [] ; + for ( var i = 0 ; i < tableMap.length ; i++ ) + { + var newRow = tableMap[i].slice( 0, colIdx ) ; + if ( tableMap[i].length <= colIdx ) + { + newTableMap.push( newRow ) ; + continue ; + } + if ( tableMap[i][colIdx] == refCell ) + { + newRow.push( refCell ) ; + newRow.push( FCKTools.GetElementDocument( refCell ).createElement( 'td' ) ) ; + if ( FCKBrowserInfo.IsGeckoLike ) + FCKTools.AppendBogusBr( newRow[newRow.length - 1] ) ; + } + else + { + newRow.push( tableMap[i][colIdx] ) ; + newRow.push( tableMap[i][colIdx] ) ; + } + for ( var j = colIdx + 1 ; j < tableMap[i].length ; j++ ) + newRow.push( tableMap[i][j] ) ; + newTableMap.push( newRow ) ; + } + tableMap = newTableMap ; + } + + this._InstallTableMap( tableMap, refCell.parentNode.parentNode ) ; +} + +FCKTableHandler.VerticalSplitCell = function() +{ + var cells = FCKTableHandler.GetSelectedCells() ; + if ( cells.length != 1 ) + return ; + + var currentCell = cells[0] ; + var tableMap = this._CreateTableMap( currentCell.parentNode.parentNode ) ; + var cellIndex = FCKTableHandler._GetCellIndexSpan( tableMap, currentCell.parentNode.rowIndex, currentCell ) ; + var currentRowSpan = currentCell.rowSpan ; + var currentRowIndex = currentCell.parentNode.rowIndex ; + if ( isNaN( currentRowSpan ) ) + currentRowSpan = 1 ; + + if ( currentRowSpan > 1 ) + { + // 1. Set the current cell's rowSpan to 1. + currentCell.rowSpan = Math.ceil( currentRowSpan / 2 ) ; + + // 2. Find the appropriate place to insert a new cell at the next row. + var newCellRowIndex = currentRowIndex + Math.ceil( currentRowSpan / 2 ) ; + var insertMarker = null ; + for ( var i = cellIndex+1 ; i < tableMap[newCellRowIndex].length ; i++ ) + { + if ( tableMap[newCellRowIndex][i].parentNode.rowIndex == newCellRowIndex ) + { + insertMarker = tableMap[newCellRowIndex][i] ; + break ; + } + } + + // 3. Insert the new cell to the indicated place, with the appropriate rowSpan, next row. + var newCell = FCK.EditorDocument.createElement( 'td' ) ; + newCell.rowSpan = Math.floor( currentRowSpan / 2 ) ; + if ( FCKBrowserInfo.IsGeckoLike ) + FCKTools.AppendBogusBr( newCell ) ; + currentCell.parentNode.parentNode.rows[newCellRowIndex].insertBefore( newCell, insertMarker ) ; + } + else + { + // 1. Insert a new row. + var newCellRowIndex = currentRowIndex + 1 ; + var newRow = FCK.EditorDocument.createElement( 'tr' ) ; + currentCell.parentNode.parentNode.insertBefore( newRow, currentCell.parentNode.parentNode.rows[newCellRowIndex] ) ; + + // 2. +1 to rowSpan for all cells crossing currentCell's row. + for ( var i = 0 ; i < tableMap[currentRowIndex].length ; ) + { + var colSpan = tableMap[currentRowIndex][i].colSpan ; + if ( isNaN( colSpan ) || colSpan < 1 ) + colSpan = 1 ; + if ( i == cellIndex ) + { + i += colSpan ; + continue ; + } + var rowSpan = tableMap[currentRowIndex][i].rowSpan ; + if ( isNaN( rowSpan ) ) + rowSpan = 1 ; + tableMap[currentRowIndex][i].rowSpan = rowSpan + 1 ; + i += colSpan ; + } + + // 3. Insert a new cell to new row. + var newCell = FCK.EditorDocument.createElement( 'td' ) ; + if ( FCKBrowserInfo.IsGeckoLike ) + FCKTools.AppendBogusBr( newCell ) ; + newRow.appendChild( newCell ) ; + } +} + +// Get the cell index from a TableMap. +FCKTableHandler._GetCellIndexSpan = function( tableMap, rowIndex, cell ) +{ + if ( tableMap.length < rowIndex + 1 ) + return null ; + + var oRow = tableMap[ rowIndex ] ; + + for ( var c = 0 ; c < oRow.length ; c++ ) + { + if ( oRow[c] == cell ) + return c ; + } + + return null ; +} + +// Get the cell location from a TableMap. Returns an array with an [x,y] location +FCKTableHandler._GetCellLocation = function( tableMap, cell ) +{ + for ( var i = 0 ; i < tableMap.length; i++ ) + { + for ( var c = 0 ; c < tableMap[i].length ; c++ ) + { + if ( tableMap[i][c] == cell ) return [i,c]; + } + } + return null ; +} + +// Get the cells available in a column of a TableMap. +FCKTableHandler._GetColumnCells = function( tableMap, columnIndex ) +{ + var aCollCells = new Array() ; + + for ( var r = 0 ; r < tableMap.length ; r++ ) + { + var oCell = tableMap[r][columnIndex] ; + if ( oCell && ( aCollCells.length == 0 || aCollCells[ aCollCells.length - 1 ] != oCell ) ) + aCollCells[ aCollCells.length ] = oCell ; + } + + return aCollCells ; +} + +// This function is quite hard to explain. It creates a matrix representing all cells in a table. +// The difference here is that the "spanned" cells (colSpan and rowSpan) are duplicated on the matrix +// cells that are "spanned". For example, a row with 3 cells where the second cell has colSpan=2 and rowSpan=3 +// will produce a bi-dimensional matrix with the following values (representing the cells): +// Cell1, Cell2, Cell2, Cell 3 +// Cell4, Cell2, Cell2, Cell 5 +FCKTableHandler._CreateTableMap = function( table ) +{ + var aRows = table.rows ; + + // Row and Column counters. + var r = -1 ; + + var aMap = new Array() ; + + for ( var i = 0 ; i < aRows.length ; i++ ) + { + r++ ; + if ( !aMap[r] ) + aMap[r] = new Array() ; + + var c = -1 ; + + for ( var j = 0 ; j < aRows[i].cells.length ; j++ ) + { + var oCell = aRows[i].cells[j] ; + + c++ ; + while ( aMap[r][c] ) + c++ ; + + var iColSpan = isNaN( oCell.colSpan ) ? 1 : oCell.colSpan ; + var iRowSpan = isNaN( oCell.rowSpan ) ? 1 : oCell.rowSpan ; + + for ( var rs = 0 ; rs < iRowSpan ; rs++ ) + { + if ( !aMap[r + rs] ) + aMap[r + rs] = new Array() ; + + for ( var cs = 0 ; cs < iColSpan ; cs++ ) + { + aMap[r + rs][c + cs] = aRows[i].cells[j] ; + } + } + + c += iColSpan - 1 ; + } + } + return aMap ; +} + +// This function is the inverse of _CreateTableMap - it takes in a table map and converts it to an HTML table. +FCKTableHandler._InstallTableMap = function( tableMap, table ) +{ + // Clear the table of all rows first. + while ( table.rows.length > 0 ) + { + var row = table.rows[0] ; + row.parentNode.removeChild( row ) ; + } + + // Disconnect all the cells in tableMap from their parents, set all colSpan and rowSpan attributes to 1. + for ( var i = 0 ; i < tableMap.length ; i++ ) + { + for ( var j = 0 ; j < tableMap[i].length ; j++ ) + { + var cell = tableMap[i][j] ; + if ( cell.parentNode ) + cell.parentNode.removeChild( cell ) ; + cell.colSpan = cell.rowSpan = 1 ; + } + } + + // Scan by rows and set colSpan. + var maxCol = 0 ; + for ( var i = 0 ; i < tableMap.length ; i++ ) + { + for ( var j = 0 ; j < tableMap[i].length ; j++ ) + { + var cell = tableMap[i][j] ; + if ( ! cell) + continue ; + if ( j > maxCol ) + maxCol = j ; + if ( cell._colScanned === true ) + continue ; + if ( tableMap[i][j-1] == cell ) + cell.colSpan++ ; + if ( tableMap[i][j+1] != cell ) + cell._colScanned = true ; + } + } + + // Scan by columns and set rowSpan. + for ( var i = 0 ; i <= maxCol ; i++ ) + { + for ( var j = 0 ; j < tableMap.length ; j++ ) + { + if ( ! tableMap[j] ) + continue ; + var cell = tableMap[j][i] ; + if ( ! cell || cell._rowScanned === true ) + continue ; + if ( tableMap[j-1] && tableMap[j-1][i] == cell ) + cell.rowSpan++ ; + if ( ! tableMap[j+1] || tableMap[j+1][i] != cell ) + cell._rowScanned = true ; + } + } + + // Clear all temporary flags. + for ( var i = 0 ; i < tableMap.length ; i++ ) + { + for ( var j = 0 ; j < tableMap[i].length ; j++) + { + var cell = tableMap[i][j] ; + if ( FCKBrowserInfo.IsIE ) + { + cell.removeAttribute( '_colScanned' ) ; + cell.removeAttribute( '_rowScanned' ) ; + } + else + { + delete cell._colScanned ; + delete cell._rowScanned ; + } + } + } + + // Insert physical rows and columns to the table. + for ( var i = 0 ; i < tableMap.length ; i++ ) + { + var rowObj = FCKTools.GetElementDocument( table ).createElement( 'tr' ) ; + for ( var j = 0 ; j < tableMap[i].length ; ) + { + var cell = tableMap[i][j] ; + if ( tableMap[i-1] && tableMap[i-1][j] == cell ) + { + j += cell.colSpan ; + continue ; + } + rowObj.appendChild( cell ) ; + j += cell.colSpan ; + if ( cell.colSpan == 1 ) + cell.removeAttribute( 'colspan' ) ; + if ( cell.rowSpan == 1 ) + cell.removeAttribute( 'rowspan' ) ; + } + table.appendChild( rowObj ) ; + } +} + +FCKTableHandler._MoveCaretToCell = function ( refCell, toStart ) +{ + var range = new FCKDomRange( FCK.EditorWindow ) ; + range.MoveToNodeContents( refCell ) ; + range.Collapse( toStart ) ; + range.Select() ; +} + +FCKTableHandler.ClearRow = function( tr ) +{ + // Get the array of row's cells. + var aCells = tr.cells ; + + // Replace the contents of each cell with "nothing". + for ( var i = 0 ; i < aCells.length ; i++ ) + { + aCells[i].innerHTML = '' ; + + if ( FCKBrowserInfo.IsGeckoLike ) + FCKTools.AppendBogusBr( aCells[i] ) ; + } +} + +FCKTableHandler.GetMergeRightTarget = function() +{ + var cells = this.GetSelectedCells() ; + if ( cells.length != 1 ) + return null ; + + var refCell = cells[0] ; + var tableMap = this._CreateTableMap( refCell.parentNode.parentNode ) ; + var rowIdx = refCell.parentNode.rowIndex ; + var colIdx = this._GetCellIndexSpan( tableMap, rowIdx, refCell ) ; + var nextColIdx = colIdx + ( isNaN( refCell.colSpan ) ? 1 : refCell.colSpan ) ; + var nextCell = tableMap[rowIdx][nextColIdx] ; + + if ( ! nextCell ) + return null ; + + // The two cells must have the same vertical geometry, otherwise merging does not make sense. + this._MarkCells( [refCell, nextCell], '_SizeTest' ) ; + var refGeometry = this._GetMarkerGeometry( tableMap, rowIdx, colIdx, '_SizeTest' ) ; + var nextGeometry = this._GetMarkerGeometry( tableMap, rowIdx, nextColIdx, '_SizeTest' ) ; + this._UnmarkCells( [refCell, nextCell], '_SizeTest' ) ; + + if ( refGeometry.height != nextGeometry.height || refGeometry.y != nextGeometry.y ) + return null ; + + return { 'refCell' : refCell, 'nextCell' : nextCell, 'tableMap' : tableMap } ; +} + +FCKTableHandler.GetMergeDownTarget = function() +{ + var cells = this.GetSelectedCells() ; + if ( cells.length != 1 ) + return null ; + + var refCell = cells[0] ; + var tableMap = this._CreateTableMap( refCell.parentNode.parentNode ) ; + var rowIdx = refCell.parentNode.rowIndex ; + var colIdx = this._GetCellIndexSpan( tableMap, rowIdx, refCell ) ; + var newRowIdx = rowIdx + ( isNaN( refCell.rowSpan ) ? 1 : refCell.rowSpan ) ; + if ( ! tableMap[newRowIdx] ) + return null ; + + var nextCell = tableMap[newRowIdx][colIdx] ; + + if ( ! nextCell ) + return null ; + + // The two cells must have the same horizontal geometry, otherwise merging does not makes sense. + this._MarkCells( [refCell, nextCell], '_SizeTest' ) ; + var refGeometry = this._GetMarkerGeometry( tableMap, rowIdx, colIdx, '_SizeTest' ) ; + var nextGeometry = this._GetMarkerGeometry( tableMap, newRowIdx, colIdx, '_SizeTest' ) ; + this._UnmarkCells( [refCell, nextCell], '_SizeTest' ) ; + + if ( refGeometry.width != nextGeometry.width || refGeometry.x != nextGeometry.x ) + return null ; + + return { 'refCell' : refCell, 'nextCell' : nextCell, 'tableMap' : tableMap } ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcktablehandler_gecko.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcktablehandler_gecko.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcktablehandler_gecko.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,56 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Manage table operations (non-IE). + */ + +FCKTableHandler.GetSelectedCells = function() +{ + var aCells = new Array() ; + + var oSelection = FCKSelection.GetSelection() ; + + // If the selection is a text. + if ( oSelection.rangeCount == 1 && oSelection.anchorNode.nodeType == 3 ) + { + var oParent = FCKTools.GetElementAscensor( oSelection.anchorNode, 'TD,TH' ) ; + + if ( oParent ) + aCells[0] = oParent ; + + return aCells ; + } + + for ( var i = 0 ; i < oSelection.rangeCount ; i++ ) + { + var oRange = oSelection.getRangeAt(i) ; + var oCell ; + + if ( oRange.startContainer.tagName.Equals( 'TD', 'TH' ) ) + oCell = oRange.startContainer ; + else + oCell = oRange.startContainer.childNodes[ oRange.startOffset ] ; + + if ( oCell.tagName.Equals( 'TD', 'TH' ) ) + aCells[aCells.length] = oCell ; + } + + return aCells ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcktablehandler_ie.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcktablehandler_ie.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcktablehandler_ie.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,64 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Manage table operations (IE specific). + */ + +FCKTableHandler.GetSelectedCells = function() +{ + if ( FCKSelection.GetType() == 'Control' ) + { + var td = FCKSelection.MoveToAncestorNode( 'TD' ) ; + return td ? [ td ] : [] ; + } + + var aCells = new Array() ; + + var oRange = FCKSelection.GetSelection().createRange() ; +// var oParent = oRange.parentElement() ; + var oParent = FCKSelection.GetParentElement() ; + + if ( oParent && oParent.tagName.Equals( 'TD', 'TH' ) ) + aCells[0] = oParent ; + else + { + oParent = FCKSelection.MoveToAncestorNode( 'TABLE' ) ; + + if ( oParent ) + { + // Loops throw all cells checking if the cell is, or part of it, is inside the selection + // and then add it to the selected cells collection. + for ( var i = 0 ; i < oParent.cells.length ; i++ ) + { + var oCellRange = FCK.EditorDocument.body.createTextRange() ; + oCellRange.moveToElementText( oParent.cells[i] ) ; + + if ( oRange.inRange( oCellRange ) + || ( oRange.compareEndPoints('StartToStart',oCellRange) >= 0 && oRange.compareEndPoints('StartToEnd',oCellRange) <= 0 ) + || ( oRange.compareEndPoints('EndToStart',oCellRange) >= 0 && oRange.compareEndPoints('EndToEnd',oCellRange) <= 0 ) ) + { + aCells[aCells.length] = oParent.cells[i] ; + } + } + } + } + + return aCells ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcktoolbaritems.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcktoolbaritems.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcktoolbaritems.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,123 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Toolbar items definitions. + */ + +var FCKToolbarItems = new Object() ; +FCKToolbarItems.LoadedItems = new Object() ; + +FCKToolbarItems.RegisterItem = function( itemName, item ) +{ + this.LoadedItems[ itemName ] = item ; +} + +FCKToolbarItems.GetItem = function( itemName ) +{ + var oItem = FCKToolbarItems.LoadedItems[ itemName ] ; + + if ( oItem ) + return oItem ; + + switch ( itemName ) + { + case 'Source' : oItem = new FCKToolbarButton( 'Source' , FCKLang.Source, null, FCK_TOOLBARITEM_ICONTEXT, true, true, 1 ) ; break ; + case 'DocProps' : oItem = new FCKToolbarButton( 'DocProps' , FCKLang.DocProps, null, null, null, null, 2 ) ; break ; + case 'Save' : oItem = new FCKToolbarButton( 'Save' , FCKLang.Save, null, null, true, null, 3 ) ; break ; + case 'NewPage' : oItem = new FCKToolbarButton( 'NewPage' , FCKLang.NewPage, null, null, true, null, 4 ) ; break ; + case 'Preview' : oItem = new FCKToolbarButton( 'Preview' , FCKLang.Preview, null, null, true, null, 5 ) ; break ; + case 'Templates' : oItem = new FCKToolbarButton( 'Templates' , FCKLang.Templates, null, null, null, null, 6 ) ; break ; + case 'About' : oItem = new FCKToolbarButton( 'About' , FCKLang.About, null, null, true, null, 47 ) ; break ; + + case 'Cut' : oItem = new FCKToolbarButton( 'Cut' , FCKLang.Cut, null, null, false, true, 7 ) ; break ; + case 'Copy' : oItem = new FCKToolbarButton( 'Copy' , FCKLang.Copy, null, null, false, true, 8 ) ; break ; + case 'Paste' : oItem = new FCKToolbarButton( 'Paste' , FCKLang.Paste, null, null, false, true, 9 ) ; break ; + case 'PasteText' : oItem = new FCKToolbarButton( 'PasteText' , FCKLang.PasteText, null, null, false, true, 10 ) ; break ; + case 'PasteWord' : oItem = new FCKToolbarButton( 'PasteWord' , FCKLang.PasteWord, null, null, false, true, 11 ) ; break ; + case 'Print' : oItem = new FCKToolbarButton( 'Print' , FCKLang.Print, null, null, false, true, 12 ) ; break ; + case 'SpellCheck' : oItem = new FCKToolbarButton( 'SpellCheck', FCKLang.SpellCheck, null, null, null, null, 13 ) ; break ; + case 'Undo' : oItem = new FCKToolbarButton( 'Undo' , FCKLang.Undo, null, null, false, true, 14 ) ; break ; + case 'Redo' : oItem = new FCKToolbarButton( 'Redo' , FCKLang.Redo, null, null, false, true, 15 ) ; break ; + case 'SelectAll' : oItem = new FCKToolbarButton( 'SelectAll' , FCKLang.SelectAll, null, null, true, null, 18 ) ; break ; + case 'RemoveFormat' : oItem = new FCKToolbarButton( 'RemoveFormat', FCKLang.RemoveFormat, null, null, false, true, 19 ) ; break ; + case 'FitWindow' : oItem = new FCKToolbarButton( 'FitWindow' , FCKLang.FitWindow, null, null, true, true, 66 ) ; break ; + + case 'Bold' : oItem = new FCKToolbarButton( 'Bold' , FCKLang.Bold, null, null, false, true, 20 ) ; break ; + case 'Italic' : oItem = new FCKToolbarButton( 'Italic' , FCKLang.Italic, null, null, false, true, 21 ) ; break ; + case 'Underline' : oItem = new FCKToolbarButton( 'Underline' , FCKLang.Underline, null, null, false, true, 22 ) ; break ; + case 'StrikeThrough' : oItem = new FCKToolbarButton( 'StrikeThrough' , FCKLang.StrikeThrough, null, null, false, true, 23 ) ; break ; + case 'Subscript' : oItem = new FCKToolbarButton( 'Subscript' , FCKLang.Subscript, null, null, false, true, 24 ) ; break ; + case 'Superscript' : oItem = new FCKToolbarButton( 'Superscript' , FCKLang.Superscript, null, null, false, true, 25 ) ; break ; + + case 'OrderedList' : oItem = new FCKToolbarButton( 'InsertOrderedList' , FCKLang.NumberedListLbl, FCKLang.NumberedList, null, false, true, 26 ) ; break ; + case 'UnorderedList' : oItem = new FCKToolbarButton( 'InsertUnorderedList' , FCKLang.BulletedListLbl, FCKLang.BulletedList, null, false, true, 27 ) ; break ; + case 'Outdent' : oItem = new FCKToolbarButton( 'Outdent' , FCKLang.DecreaseIndent, null, null, false, true, 28 ) ; break ; + case 'Indent' : oItem = new FCKToolbarButton( 'Indent' , FCKLang.IncreaseIndent, null, null, false, true, 29 ) ; break ; + case 'Blockquote' : oItem = new FCKToolbarButton( 'Blockquote' , FCKLang.Blockquote, null, null, false, true, 73 ) ; break ; + + case 'Link' : oItem = new FCKToolbarButton( 'Link' , FCKLang.InsertLinkLbl, FCKLang.InsertLink, null, false, true, 34 ) ; break ; + case 'Unlink' : oItem = new FCKToolbarButton( 'Unlink' , FCKLang.RemoveLink, null, null, false, true, 35 ) ; break ; + case 'Anchor' : oItem = new FCKToolbarButton( 'Anchor' , FCKLang.Anchor, null, null, null, null, 36 ) ; break ; + + case 'Image' : oItem = new FCKToolbarButton( 'Image' , FCKLang.InsertImageLbl, FCKLang.InsertImage, null, false, true, 37 ) ; break ; + case 'Flash' : oItem = new FCKToolbarButton( 'Flash' , FCKLang.InsertFlashLbl, FCKLang.InsertFlash, null, false, true, 38 ) ; break ; + case 'Table' : oItem = new FCKToolbarButton( 'Table' , FCKLang.InsertTableLbl, FCKLang.InsertTable, null, false, true, 39 ) ; break ; + case 'SpecialChar' : oItem = new FCKToolbarButton( 'SpecialChar' , FCKLang.InsertSpecialCharLbl, FCKLang.InsertSpecialChar, null, false, true, 42 ) ; break ; + case 'Smiley' : oItem = new FCKToolbarButton( 'Smiley' , FCKLang.InsertSmileyLbl, FCKLang.InsertSmiley, null, false, true, 41 ) ; break ; + case 'PageBreak' : oItem = new FCKToolbarButton( 'PageBreak' , FCKLang.PageBreakLbl, FCKLang.PageBreak, null, false, true, 43 ) ; break ; + + case 'Rule' : oItem = new FCKToolbarButton( 'Rule' , FCKLang.InsertLineLbl, FCKLang.InsertLine, null, false, true, 40 ) ; break ; + + case 'JustifyLeft' : oItem = new FCKToolbarButton( 'JustifyLeft' , FCKLang.LeftJustify, null, null, false, true, 30 ) ; break ; + case 'JustifyCenter' : oItem = new FCKToolbarButton( 'JustifyCenter' , FCKLang.CenterJustify, null, null, false, true, 31 ) ; break ; + case 'JustifyRight' : oItem = new FCKToolbarButton( 'JustifyRight' , FCKLang.RightJustify, null, null, false, true, 32 ) ; break ; + case 'JustifyFull' : oItem = new FCKToolbarButton( 'JustifyFull' , FCKLang.BlockJustify, null, null, false, true, 33 ) ; break ; + + case 'Style' : oItem = new FCKToolbarStyleCombo() ; break ; + case 'FontName' : oItem = new FCKToolbarFontsCombo() ; break ; + case 'FontSize' : oItem = new FCKToolbarFontSizeCombo() ; break ; + case 'FontFormat' : oItem = new FCKToolbarFontFormatCombo() ; break ; + + case 'TextColor' : oItem = new FCKToolbarPanelButton( 'TextColor', FCKLang.TextColor, null, null, 45 ) ; break ; + case 'BGColor' : oItem = new FCKToolbarPanelButton( 'BGColor' , FCKLang.BGColor, null, null, 46 ) ; break ; + + case 'Find' : oItem = new FCKToolbarButton( 'Find' , FCKLang.Find, null, null, null, null, 16 ) ; break ; + case 'Replace' : oItem = new FCKToolbarButton( 'Replace' , FCKLang.Replace, null, null, null, null, 17 ) ; break ; + + case 'Form' : oItem = new FCKToolbarButton( 'Form' , FCKLang.Form, null, null, null, null, 48 ) ; break ; + case 'Checkbox' : oItem = new FCKToolbarButton( 'Checkbox' , FCKLang.Checkbox, null, null, null, null, 49 ) ; break ; + case 'Radio' : oItem = new FCKToolbarButton( 'Radio' , FCKLang.RadioButton, null, null, null, null, 50 ) ; break ; + case 'TextField' : oItem = new FCKToolbarButton( 'TextField' , FCKLang.TextField, null, null, null, null, 51 ) ; break ; + case 'Textarea' : oItem = new FCKToolbarButton( 'Textarea' , FCKLang.Textarea, null, null, null, null, 52 ) ; break ; + case 'HiddenField' : oItem = new FCKToolbarButton( 'HiddenField' , FCKLang.HiddenField, null, null, null, null, 56 ) ; break ; + case 'Button' : oItem = new FCKToolbarButton( 'Button' , FCKLang.Button, null, null, null, null, 54 ) ; break ; + case 'Select' : oItem = new FCKToolbarButton( 'Select' , FCKLang.SelectionField, null, null, null, null, 53 ) ; break ; + case 'ImageButton' : oItem = new FCKToolbarButton( 'ImageButton' , FCKLang.ImageButton, null, null, null, null, 55 ) ; break ; + case 'ShowBlocks' : oItem = new FCKToolbarButton( 'ShowBlocks' , FCKLang.ShowBlocks, null, null, null, true, 72 ) ; break ; + + default: + alert( FCKLang.UnknownToolbarItem.replace( /%1/g, itemName ) ) ; + return null ; + } + + FCKToolbarItems.LoadedItems[ itemName ] = oItem ; + + return oItem ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcktoolbarset.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcktoolbarset.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcktoolbarset.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,399 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Defines the FCKToolbarSet object that is used to load and draw the + * toolbar. + */ + +function FCKToolbarSet_Create( overhideLocation ) +{ + var oToolbarSet ; + + var sLocation = overhideLocation || FCKConfig.ToolbarLocation ; + switch ( sLocation ) + { + case 'In' : + document.getElementById( 'xToolbarRow' ).style.display = '' ; + oToolbarSet = new FCKToolbarSet( document ) ; + break ; + case 'None' : + oToolbarSet = new FCKToolbarSet( document ) ; + break ; + +// case 'OutTop' : + // Not supported. + + default : + FCK.Events.AttachEvent( 'OnBlur', FCK_OnBlur ) ; + FCK.Events.AttachEvent( 'OnFocus', FCK_OnFocus ) ; + + var eToolbarTarget ; + + // Out:[TargetWindow]([TargetId]) + var oOutMatch = sLocation.match( /^Out:(.+)\((\w+)\)$/ ) ; + if ( oOutMatch ) + { + if ( FCKBrowserInfo.IsAIR ) + FCKAdobeAIR.ToolbarSet_GetOutElement( window, oOutMatch ) ; + else + eToolbarTarget = eval( 'parent.' + oOutMatch[1] ).document.getElementById( oOutMatch[2] ) ; + } + else + { + // Out:[TargetId] + oOutMatch = sLocation.match( /^Out:(\w+)$/ ) ; + if ( oOutMatch ) + eToolbarTarget = parent.document.getElementById( oOutMatch[1] ) ; + } + + if ( !eToolbarTarget ) + { + alert( 'Invalid value for "ToolbarLocation"' ) ; + return arguments.callee( 'In' ); + } + + // If it is a shared toolbar, it may be already available in the target element. + oToolbarSet = eToolbarTarget.__FCKToolbarSet ; + if ( oToolbarSet ) + break ; + + // Create the IFRAME that will hold the toolbar inside the target element. + var eToolbarIFrame = FCKTools.GetElementDocument( eToolbarTarget ).createElement( 'iframe' ) ; + eToolbarIFrame.src = 'javascript:void(0)' ; + eToolbarIFrame.frameBorder = 0 ; + eToolbarIFrame.width = '100%' ; + eToolbarIFrame.height = '10' ; + eToolbarTarget.appendChild( eToolbarIFrame ) ; + eToolbarIFrame.unselectable = 'on' ; + + // Write the basic HTML for the toolbar (copy from the editor main page). + var eTargetDocument = eToolbarIFrame.contentWindow.document ; + + // Workaround for Safari 12256. Ticket #63 + var sBase = '' ; + if ( FCKBrowserInfo.IsSafari ) + sBase = '<base href="' + window.document.location + '">' ; + + // Initialize the IFRAME document body. + eTargetDocument.open() ; + eTargetDocument.write( '<html><head>' + sBase + '<script type="text/javascript"> var adjust = function() { window.frameElement.height = document.body.scrollHeight ; }; ' + + 'window.onresize = window.onload = ' + + 'function(){' // poll scrollHeight until it no longer changes for 1 sec. + + 'var timer = null;' + + 'var lastHeight = -1;' + + 'var lastChange = 0;' + + 'var poller = function(){' + + 'var currentHeight = document.body.scrollHeight || 0;' + + 'var currentTime = (new Date()).getTime();' + + 'if (currentHeight != lastHeight){' + + 'lastChange = currentTime;' + + 'adjust();' + + 'lastHeight = document.body.scrollHeight;' + + '}' + + 'if (lastChange < currentTime - 1000) clearInterval(timer);' + + '};' + + 'timer = setInterval(poller, 100);' + + '}' + + '</script></head><body style="overflow: hidden">' + document.getElementById( 'xToolbarSpace' ).innerHTML + '</body></html>' ) ; + eTargetDocument.close() ; + + if( FCKBrowserInfo.IsAIR ) + FCKAdobeAIR.ToolbarSet_InitOutFrame( eTargetDocument ) ; + + FCKTools.AddEventListener( eTargetDocument, 'contextmenu', FCKTools.CancelEvent ) ; + + // Load external resources (must be done here, otherwise Firefox will not + // have the document DOM ready to be used right away. + FCKTools.AppendStyleSheet( eTargetDocument, FCKConfig.SkinEditorCSS ) ; + + oToolbarSet = eToolbarTarget.__FCKToolbarSet = new FCKToolbarSet( eTargetDocument ) ; + oToolbarSet._IFrame = eToolbarIFrame ; + + if ( FCK.IECleanup ) + FCK.IECleanup.AddItem( eToolbarTarget, FCKToolbarSet_Target_Cleanup ) ; + } + + oToolbarSet.CurrentInstance = FCK ; + if ( !oToolbarSet.ToolbarItems ) + oToolbarSet.ToolbarItems = FCKToolbarItems ; + + FCK.AttachToOnSelectionChange( oToolbarSet.RefreshItemsState ) ; + + return oToolbarSet ; +} + +function FCK_OnBlur( editorInstance ) +{ + var eToolbarSet = editorInstance.ToolbarSet ; + + if ( eToolbarSet.CurrentInstance == editorInstance ) + eToolbarSet.Disable() ; +} + +function FCK_OnFocus( editorInstance ) +{ + var oToolbarset = editorInstance.ToolbarSet ; + var oInstance = editorInstance || FCK ; + + // Unregister the toolbar window from the current instance. + oToolbarset.CurrentInstance.FocusManager.RemoveWindow( oToolbarset._IFrame.contentWindow ) ; + + // Set the new current instance. + oToolbarset.CurrentInstance = oInstance ; + + // Register the toolbar window in the current instance. + oInstance.FocusManager.AddWindow( oToolbarset._IFrame.contentWindow, true ) ; + + oToolbarset.Enable() ; +} + +function FCKToolbarSet_Cleanup() +{ + this._TargetElement = null ; + this._IFrame = null ; +} + +function FCKToolbarSet_Target_Cleanup() +{ + this.__FCKToolbarSet = null ; +} + +var FCKToolbarSet = function( targetDocument ) +{ + this._Document = targetDocument ; + + // Get the element that will hold the elements structure. + this._TargetElement = targetDocument.getElementById( 'xToolbar' ) ; + + // Setup the expand and collapse handlers. + var eExpandHandle = targetDocument.getElementById( 'xExpandHandle' ) ; + var eCollapseHandle = targetDocument.getElementById( 'xCollapseHandle' ) ; + + eExpandHandle.title = FCKLang.ToolbarExpand ; + FCKTools.AddEventListener( eExpandHandle, 'click', FCKToolbarSet_Expand_OnClick ) ; + + eCollapseHandle.title = FCKLang.ToolbarCollapse ; + FCKTools.AddEventListener( eCollapseHandle, 'click', FCKToolbarSet_Collapse_OnClick ) ; + + // Set the toolbar state at startup. + if ( !FCKConfig.ToolbarCanCollapse || FCKConfig.ToolbarStartExpanded ) + this.Expand() ; + else + this.Collapse() ; + + // Enable/disable the collapse handler + eCollapseHandle.style.display = FCKConfig.ToolbarCanCollapse ? '' : 'none' ; + + if ( FCKConfig.ToolbarCanCollapse ) + eCollapseHandle.style.display = '' ; + else + targetDocument.getElementById( 'xTBLeftBorder' ).style.display = '' ; + + // Set the default properties. + this.Toolbars = new Array() ; + this.IsLoaded = false ; + + if ( FCK.IECleanup ) + FCK.IECleanup.AddItem( this, FCKToolbarSet_Cleanup ) ; +} + +function FCKToolbarSet_Expand_OnClick() +{ + FCK.ToolbarSet.Expand() ; +} + +function FCKToolbarSet_Collapse_OnClick() +{ + FCK.ToolbarSet.Collapse() ; +} + +FCKToolbarSet.prototype.Expand = function() +{ + this._ChangeVisibility( false ) ; +} + +FCKToolbarSet.prototype.Collapse = function() +{ + this._ChangeVisibility( true ) ; +} + +FCKToolbarSet.prototype._ChangeVisibility = function( collapse ) +{ + this._Document.getElementById( 'xCollapsed' ).style.display = collapse ? '' : 'none' ; + this._Document.getElementById( 'xExpanded' ).style.display = collapse ? 'none' : '' ; + + if ( FCKBrowserInfo.IsGecko ) + { + // I had to use "setTimeout" because Gecko was not responding in a right + // way when calling window.onresize() directly. + FCKTools.RunFunction( window.onresize ) ; + } +} + +FCKToolbarSet.prototype.Load = function( toolbarSetName ) +{ + this.Name = toolbarSetName ; + + this.Items = new Array() ; + + // Reset the array of toolbar items that are active only on WYSIWYG mode. + this.ItemsWysiwygOnly = new Array() ; + + // Reset the array of toolbar items that are sensitive to the cursor position. + this.ItemsContextSensitive = new Array() ; + + // Cleanup the target element. + this._TargetElement.innerHTML = '' ; + + var ToolbarSet = FCKConfig.ToolbarSets[toolbarSetName] ; + + if ( !ToolbarSet ) + { + alert( FCKLang.UnknownToolbarSet.replace( /%1/g, toolbarSetName ) ) ; + return ; + } + + this.Toolbars = new Array() ; + + for ( var x = 0 ; x < ToolbarSet.length ; x++ ) + { + var oToolbarItems = ToolbarSet[x] ; + + // If the configuration for the toolbar is missing some element or has any extra comma + // this item won't be valid, so skip it and keep on processing. + if ( !oToolbarItems ) + continue ; + + var oToolbar ; + + if ( typeof( oToolbarItems ) == 'string' ) + { + if ( oToolbarItems == '/' ) + oToolbar = new FCKToolbarBreak() ; + } + else + { + oToolbar = new FCKToolbar() ; + + for ( var j = 0 ; j < oToolbarItems.length ; j++ ) + { + var sItem = oToolbarItems[j] ; + + if ( sItem == '-') + oToolbar.AddSeparator() ; + else + { + var oItem = FCKToolbarItems.GetItem( sItem ) ; + if ( oItem ) + { + oToolbar.AddItem( oItem ) ; + + this.Items.push( oItem ) ; + + if ( !oItem.SourceView ) + this.ItemsWysiwygOnly.push( oItem ) ; + + if ( oItem.ContextSensitive ) + this.ItemsContextSensitive.push( oItem ) ; + } + } + } + + // oToolbar.AddTerminator() ; + } + + oToolbar.Create( this._TargetElement ) ; + + this.Toolbars[ this.Toolbars.length ] = oToolbar ; + } + + FCKTools.DisableSelection( this._Document.getElementById( 'xCollapseHandle' ).parentNode ) ; + + if ( FCK.Status != FCK_STATUS_COMPLETE ) + FCK.Events.AttachEvent( 'OnStatusChange', this.RefreshModeState ) ; + else + this.RefreshModeState() ; + + this.IsLoaded = true ; + this.IsEnabled = true ; + + FCKTools.RunFunction( this.OnLoad ) ; +} + +FCKToolbarSet.prototype.Enable = function() +{ + if ( this.IsEnabled ) + return ; + + this.IsEnabled = true ; + + var aItems = this.Items ; + for ( var i = 0 ; i < aItems.length ; i++ ) + aItems[i].RefreshState() ; +} + +FCKToolbarSet.prototype.Disable = function() +{ + if ( !this.IsEnabled ) + return ; + + this.IsEnabled = false ; + + var aItems = this.Items ; + for ( var i = 0 ; i < aItems.length ; i++ ) + aItems[i].Disable() ; +} + +FCKToolbarSet.prototype.RefreshModeState = function( editorInstance ) +{ + if ( FCK.Status != FCK_STATUS_COMPLETE ) + return ; + + var oToolbarSet = editorInstance ? editorInstance.ToolbarSet : this ; + var aItems = oToolbarSet.ItemsWysiwygOnly ; + + if ( FCK.EditMode == FCK_EDITMODE_WYSIWYG ) + { + // Enable all buttons that are available on WYSIWYG mode only. + for ( var i = 0 ; i < aItems.length ; i++ ) + aItems[i].Enable() ; + + // Refresh the buttons state. + oToolbarSet.RefreshItemsState( editorInstance ) ; + } + else + { + // Refresh the buttons state. + oToolbarSet.RefreshItemsState( editorInstance ) ; + + // Disable all buttons that are available on WYSIWYG mode only. + for ( var j = 0 ; j < aItems.length ; j++ ) + aItems[j].Disable() ; + } +} + +FCKToolbarSet.prototype.RefreshItemsState = function( editorInstance ) +{ + + var aItems = ( editorInstance ? editorInstance.ToolbarSet : this ).ItemsContextSensitive ; + + for ( var i = 0 ; i < aItems.length ; i++ ) + aItems[i].RefreshState() ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcktools.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcktools.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcktools.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,740 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Utility functions. + */ + +var FCKTools = new Object() ; + +FCKTools.CreateBogusBR = function( targetDocument ) +{ + var eBR = targetDocument.createElement( 'br' ) ; +// eBR.setAttribute( '_moz_editor_bogus_node', 'TRUE' ) ; + eBR.setAttribute( 'type', '_moz' ) ; + return eBR ; +} + +/** + * Fixes relative URL entries defined inside CSS styles by appending a prefix + * to them. + * @param (String) cssStyles The CSS styles definition possibly containing url() + * paths. + * @param (String) urlFixPrefix The prefix to append to relative URLs. + */ +FCKTools.FixCssUrls = function( urlFixPrefix, cssStyles ) +{ + if ( !urlFixPrefix || urlFixPrefix.length == 0 ) + return cssStyles ; + + return cssStyles.replace( /url\s*\(([\s'"]*)(.*?)([\s"']*)\)/g, function( match, opener, path, closer ) + { + if ( /^\/|^\w?:/.test( path ) ) + return match ; + else + return 'url(' + opener + urlFixPrefix + path + closer + ')' ; + } ) ; +} + +FCKTools._GetUrlFixedCss = function( cssStyles, urlFixPrefix ) +{ + var match = cssStyles.match( /^([^|]+)\|([\s\S]*)/ ) ; + + if ( match ) + return FCKTools.FixCssUrls( match[1], match[2] ) ; + else + return cssStyles ; +} + +/** + * Appends a <link css> or <style> element to the document. + * @param (Object) documentElement The DOM document object to which append the + * stylesheet. + * @param (Variant) cssFileOrDef A String pointing to the CSS file URL or an + * Array with many CSS file URLs or the CSS definitions for the <style> + * element. + * @return {Array} An array containing all elements created in the target + * document. It may include <link> or <style> elements, depending on the + * value passed with cssFileOrDef. + */ +FCKTools.AppendStyleSheet = function( domDocument, cssFileOrArrayOrDef ) +{ + if ( !cssFileOrArrayOrDef ) + return [] ; + + if ( typeof( cssFileOrArrayOrDef ) == 'string' ) + { + // Test if the passed argument is an URL. + if ( /[\\\/\.]\w*$/.test( cssFileOrArrayOrDef ) ) + { + // The string may have several URLs separated by comma. + return this.AppendStyleSheet( domDocument, cssFileOrArrayOrDef.split(',') ) ; + } + else + return [ this.AppendStyleString( domDocument, FCKTools._GetUrlFixedCss( cssFileOrArrayOrDef ) ) ] ; + } + else + { + var styles = [] ; + for ( var i = 0 ; i < cssFileOrArrayOrDef.length ; i++ ) + styles.push( this._AppendStyleSheet( domDocument, cssFileOrArrayOrDef[i] ) ) ; + return styles ; + } +} + +FCKTools.GetStyleHtml = (function() +{ + var getStyle = function( styleDef, markTemp ) + { + if ( styleDef.length == 0 ) + return '' ; + + var temp = markTemp ? ' _fcktemp="true"' : '' ; + return '<' + 'style type="text/css"' + temp + '>' + styleDef + '<' + '/style>' ; + } + + var getLink = function( cssFileUrl, markTemp ) + { + if ( cssFileUrl.length == 0 ) + return '' ; + + var temp = markTemp ? ' _fcktemp="true"' : '' ; + return '<' + 'link href="' + cssFileUrl + '" type="text/css" rel="stylesheet" ' + temp + '/>' ; + } + + return function( cssFileOrArrayOrDef, markTemp ) + { + if ( !cssFileOrArrayOrDef ) + return '' ; + + if ( typeof( cssFileOrArrayOrDef ) == 'string' ) + { + // Test if the passed argument is an URL. + if ( /[\\\/\.]\w*$/.test( cssFileOrArrayOrDef ) ) + { + // The string may have several URLs separated by comma. + return this.GetStyleHtml( cssFileOrArrayOrDef.split(','), markTemp ) ; + } + else + return getStyle( this._GetUrlFixedCss( cssFileOrArrayOrDef ), markTemp ) ; + } + else + { + var html = '' ; + + for ( var i = 0 ; i < cssFileOrArrayOrDef.length ; i++ ) + html += getLink( cssFileOrArrayOrDef[i], markTemp ) ; + + return html ; + } + } +})() ; + +FCKTools.GetElementDocument = function ( element ) +{ + return element.ownerDocument || element.document ; +} + +// Get the window object where the element is placed in. +FCKTools.GetElementWindow = function( element ) +{ + return this.GetDocumentWindow( this.GetElementDocument( element ) ) ; +} + +FCKTools.GetDocumentWindow = function( document ) +{ + // With Safari, there is not way to retrieve the window from the document, so we must fix it. + if ( FCKBrowserInfo.IsSafari && !document.parentWindow ) + this.FixDocumentParentWindow( window.top ) ; + + return document.parentWindow || document.defaultView ; +} + +/* + This is a Safari specific function that fix the reference to the parent + window from the document object. +*/ +FCKTools.FixDocumentParentWindow = function( targetWindow ) +{ + if ( targetWindow.document ) + targetWindow.document.parentWindow = targetWindow ; + + for ( var i = 0 ; i < targetWindow.frames.length ; i++ ) + FCKTools.FixDocumentParentWindow( targetWindow.frames[i] ) ; +} + +FCKTools.HTMLEncode = function( text ) +{ + if ( !text ) + return '' ; + + text = text.replace( /&/g, '&' ) ; + text = text.replace( /</g, '<' ) ; + text = text.replace( />/g, '>' ) ; + + return text ; +} + +FCKTools.HTMLDecode = function( text ) +{ + if ( !text ) + return '' ; + + text = text.replace( />/g, '>' ) ; + text = text.replace( /</g, '<' ) ; + text = text.replace( /&/g, '&' ) ; + + return text ; +} + +FCKTools._ProcessLineBreaksForPMode = function( oEditor, text, liState, node, strArray ) +{ + var closeState = 0 ; + var blockStartTag = "<p>" ; + var blockEndTag = "</p>" ; + var lineBreakTag = "<br />" ; + if ( liState ) + { + blockStartTag = "<li>" ; + blockEndTag = "</li>" ; + closeState = 1 ; + } + + // Are we currently inside a <p> tag now? + // If yes, close it at the next double line break. + while ( node && node != oEditor.FCK.EditorDocument.body ) + { + if ( node.tagName.toLowerCase() == 'p' ) + { + closeState = 1 ; + break; + } + node = node.parentNode ; + } + + for ( var i = 0 ; i < text.length ; i++ ) + { + var c = text.charAt( i ) ; + if ( c == '\r' ) + continue ; + + if ( c != '\n' ) + { + strArray.push( c ) ; + continue ; + } + + // Now we have encountered a line break. + // Check if the next character is also a line break. + var n = text.charAt( i + 1 ) ; + if ( n == '\r' ) + { + i++ ; + n = text.charAt( i + 1 ) ; + } + if ( n == '\n' ) + { + i++ ; // ignore next character - we have already processed it. + if ( closeState ) + strArray.push( blockEndTag ) ; + strArray.push( blockStartTag ) ; + closeState = 1 ; + } + else + strArray.push( lineBreakTag ) ; + } +} + +FCKTools._ProcessLineBreaksForDivMode = function( oEditor, text, liState, node, strArray ) +{ + var closeState = 0 ; + var blockStartTag = "<div>" ; + var blockEndTag = "</div>" ; + if ( liState ) + { + blockStartTag = "<li>" ; + blockEndTag = "</li>" ; + closeState = 1 ; + } + + // Are we currently inside a <div> tag now? + // If yes, close it at the next double line break. + while ( node && node != oEditor.FCK.EditorDocument.body ) + { + if ( node.tagName.toLowerCase() == 'div' ) + { + closeState = 1 ; + break ; + } + node = node.parentNode ; + } + + for ( var i = 0 ; i < text.length ; i++ ) + { + var c = text.charAt( i ) ; + if ( c == '\r' ) + continue ; + + if ( c != '\n' ) + { + strArray.push( c ) ; + continue ; + } + + if ( closeState ) + { + if ( strArray[ strArray.length - 1 ] == blockStartTag ) + { + // A div tag must have some contents inside for it to be visible. + strArray.push( " " ) ; + } + strArray.push( blockEndTag ) ; + } + strArray.push( blockStartTag ) ; + closeState = 1 ; + } + if ( closeState ) + strArray.push( blockEndTag ) ; +} + +FCKTools._ProcessLineBreaksForBrMode = function( oEditor, text, liState, node, strArray ) +{ + var closeState = 0 ; + var blockStartTag = "<br />" ; + var blockEndTag = "" ; + if ( liState ) + { + blockStartTag = "<li>" ; + blockEndTag = "</li>" ; + closeState = 1 ; + } + + for ( var i = 0 ; i < text.length ; i++ ) + { + var c = text.charAt( i ) ; + if ( c == '\r' ) + continue ; + + if ( c != '\n' ) + { + strArray.push( c ) ; + continue ; + } + + if ( closeState && blockEndTag.length ) + strArray.push ( blockEndTag ) ; + strArray.push( blockStartTag ) ; + closeState = 1 ; + } +} + +FCKTools.ProcessLineBreaks = function( oEditor, oConfig, text ) +{ + var enterMode = oConfig.EnterMode.toLowerCase() ; + var strArray = [] ; + + // Is the caret or selection inside an <li> tag now? + var liState = 0 ; + var range = new oEditor.FCKDomRange( oEditor.FCK.EditorWindow ) ; + range.MoveToSelection() ; + var node = range._Range.startContainer ; + while ( node && node.nodeType != 1 ) + node = node.parentNode ; + if ( node && node.tagName.toLowerCase() == 'li' ) + liState = 1 ; + + if ( enterMode == 'p' ) + this._ProcessLineBreaksForPMode( oEditor, text, liState, node, strArray ) ; + else if ( enterMode == 'div' ) + this._ProcessLineBreaksForDivMode( oEditor, text, liState, node, strArray ) ; + else if ( enterMode == 'br' ) + this._ProcessLineBreaksForBrMode( oEditor, text, liState, node, strArray ) ; + return strArray.join( "" ) ; +} + +/** + * Adds an option to a SELECT element. + */ +FCKTools.AddSelectOption = function( selectElement, optionText, optionValue ) +{ + var oOption = FCKTools.GetElementDocument( selectElement ).createElement( "OPTION" ) ; + + oOption.text = optionText ; + oOption.value = optionValue ; + + selectElement.options.add(oOption) ; + + return oOption ; +} + +FCKTools.RunFunction = function( func, thisObject, paramsArray, timerWindow ) +{ + if ( func ) + this.SetTimeout( func, 0, thisObject, paramsArray, timerWindow ) ; +} + +FCKTools.SetTimeout = function( func, milliseconds, thisObject, paramsArray, timerWindow ) +{ + return ( timerWindow || window ).setTimeout( + function() + { + if ( paramsArray ) + func.apply( thisObject, [].concat( paramsArray ) ) ; + else + func.apply( thisObject ) ; + }, + milliseconds ) ; +} + +FCKTools.SetInterval = function( func, milliseconds, thisObject, paramsArray, timerWindow ) +{ + return ( timerWindow || window ).setInterval( + function() + { + func.apply( thisObject, paramsArray || [] ) ; + }, + milliseconds ) ; +} + +FCKTools.ConvertStyleSizeToHtml = function( size ) +{ + return size.EndsWith( '%' ) ? size : parseInt( size, 10 ) ; +} + +FCKTools.ConvertHtmlSizeToStyle = function( size ) +{ + return size.EndsWith( '%' ) ? size : ( size + 'px' ) ; +} + +// START iCM MODIFICATIONS +// Amended to accept a list of one or more ascensor tag names +// Amended to check the element itself before working back up through the parent hierarchy +FCKTools.GetElementAscensor = function( element, ascensorTagNames ) +{ +// var e = element.parentNode ; + var e = element ; + var lstTags = "," + ascensorTagNames.toUpperCase() + "," ; + + while ( e ) + { + if ( lstTags.indexOf( "," + e.nodeName.toUpperCase() + "," ) != -1 ) + return e ; + + e = e.parentNode ; + } + return null ; +} +// END iCM MODIFICATIONS + +FCKTools.CreateEventListener = function( func, params ) +{ + var f = function() + { + var aAllParams = [] ; + + for ( var i = 0 ; i < arguments.length ; i++ ) + aAllParams.push( arguments[i] ) ; + + func.apply( this, aAllParams.concat( params ) ) ; + } + + return f ; +} + +FCKTools.IsStrictMode = function( document ) +{ + // There is no compatMode in Safari, but it seams that it always behave as + // CSS1Compat, so let's assume it as the default for that browser. + return ( 'CSS1Compat' == ( document.compatMode || ( FCKBrowserInfo.IsSafari ? 'CSS1Compat' : null ) ) ) ; +} + +// Transforms a "arguments" object to an array. +FCKTools.ArgumentsToArray = function( args, startIndex, maxLength ) +{ + startIndex = startIndex || 0 ; + maxLength = maxLength || args.length ; + + var argsArray = new Array() ; + + for ( var i = startIndex ; i < startIndex + maxLength && i < args.length ; i++ ) + argsArray.push( args[i] ) ; + + return argsArray ; +} + +FCKTools.CloneObject = function( sourceObject ) +{ + var fCloneCreator = function() {} ; + fCloneCreator.prototype = sourceObject ; + return new fCloneCreator ; +} + +// Appends a bogus <br> at the end of the element, if not yet available. +FCKTools.AppendBogusBr = function( element ) +{ + if ( !element ) + return ; + + var eLastChild = this.GetLastItem( element.getElementsByTagName('br') ) ; + + if ( !eLastChild || ( eLastChild.getAttribute( 'type', 2 ) != '_moz' && eLastChild.getAttribute( '_moz_dirty' ) == null ) ) + { + var doc = this.GetElementDocument( element ) ; + + if ( FCKBrowserInfo.IsOpera ) + element.appendChild( doc.createTextNode('') ) ; + else + element.appendChild( this.CreateBogusBR( doc ) ) ; + } +} + +FCKTools.GetLastItem = function( list ) +{ + if ( list.length > 0 ) + return list[ list.length - 1 ] ; + + return null ; +} + +FCKTools.GetDocumentPosition = function( w, node ) +{ + var x = 0 ; + var y = 0 ; + var curNode = node ; + var prevNode = null ; + var curWindow = FCKTools.GetElementWindow( curNode ) ; + while ( curNode && !( curWindow == w && ( curNode == w.document.body || curNode == w.document.documentElement ) ) ) + { + x += curNode.offsetLeft - curNode.scrollLeft ; + y += curNode.offsetTop - curNode.scrollTop ; + + if ( ! FCKBrowserInfo.IsOpera ) + { + var scrollNode = prevNode ; + while ( scrollNode && scrollNode != curNode ) + { + x -= scrollNode.scrollLeft ; + y -= scrollNode.scrollTop ; + scrollNode = scrollNode.parentNode ; + } + } + + prevNode = curNode ; + if ( curNode.offsetParent ) + curNode = curNode.offsetParent ; + else + { + if ( curWindow != w ) + { + curNode = curWindow.frameElement ; + prevNode = null ; + if ( curNode ) + curWindow = curNode.contentWindow.parent ; + } + else + curNode = null ; + } + } + + // document.body is a special case when it comes to offsetTop and offsetLeft values. + // 1. It matters if document.body itself is a positioned element; + // 2. It matters is when we're in IE and the element has no positioned ancestor. + // Otherwise the values should be ignored. + if ( FCKDomTools.GetCurrentElementStyle( w.document.body, 'position') != 'static' + || ( FCKBrowserInfo.IsIE && FCKDomTools.GetPositionedAncestor( node ) == null ) ) + { + x += w.document.body.offsetLeft ; + y += w.document.body.offsetTop ; + } + + return { "x" : x, "y" : y } ; +} + +FCKTools.GetWindowPosition = function( w, node ) +{ + var pos = this.GetDocumentPosition( w, node ) ; + var scroll = FCKTools.GetScrollPosition( w ) ; + pos.x -= scroll.X ; + pos.y -= scroll.Y ; + return pos ; +} + +FCKTools.ProtectFormStyles = function( formNode ) +{ + if ( !formNode || formNode.nodeType != 1 || formNode.tagName.toLowerCase() != 'form' ) + return [] ; + var hijackRecord = [] ; + var hijackNames = [ 'style', 'className' ] ; + for ( var i = 0 ; i < hijackNames.length ; i++ ) + { + var name = hijackNames[i] ; + if ( formNode.elements.namedItem( name ) ) + { + var hijackNode = formNode.elements.namedItem( name ) ; + hijackRecord.push( [ hijackNode, hijackNode.nextSibling ] ) ; + formNode.removeChild( hijackNode ) ; + } + } + return hijackRecord ; +} + +FCKTools.RestoreFormStyles = function( formNode, hijackRecord ) +{ + if ( !formNode || formNode.nodeType != 1 || formNode.tagName.toLowerCase() != 'form' ) + return ; + if ( hijackRecord.length > 0 ) + { + for ( var i = hijackRecord.length - 1 ; i >= 0 ; i-- ) + { + var node = hijackRecord[i][0] ; + var sibling = hijackRecord[i][1] ; + if ( sibling ) + formNode.insertBefore( node, sibling ) ; + else + formNode.appendChild( node ) ; + } + } +} + +// Perform a one-step DFS walk. +FCKTools.GetNextNode = function( node, limitNode ) +{ + if ( node.firstChild ) + return node.firstChild ; + else if ( node.nextSibling ) + return node.nextSibling ; + else + { + var ancestor = node.parentNode ; + while ( ancestor ) + { + if ( ancestor == limitNode ) + return null ; + if ( ancestor.nextSibling ) + return ancestor.nextSibling ; + else + ancestor = ancestor.parentNode ; + } + } + return null ; +} + +FCKTools.GetNextTextNode = function( textnode, limitNode, checkStop ) +{ + node = this.GetNextNode( textnode, limitNode ) ; + if ( checkStop && node && checkStop( node ) ) + return null ; + while ( node && node.nodeType != 3 ) + { + node = this.GetNextNode( node, limitNode ) ; + if ( checkStop && node && checkStop( node ) ) + return null ; + } + return node ; +} + +/** + * Merge all objects passed by argument into a single object. + */ +FCKTools.Merge = function() +{ + var args = arguments ; + var o = args[0] ; + + for ( var i = 1 ; i < args.length ; i++ ) + { + var arg = args[i] ; + for ( var p in arg ) + o[p] = arg[p] ; + } + + return o ; +} + +/** + * Check if the passed argument is a real Array. It may not working when + * calling it cross windows. + */ +FCKTools.IsArray = function( it ) +{ + return ( it instanceof Array ) ; +} + +/** + * Appends a "length" property to an object, containing the number of + * properties available on it, excluded the append property itself. + */ +FCKTools.AppendLengthProperty = function( targetObject, propertyName ) +{ + var counter = 0 ; + + for ( var n in targetObject ) + counter++ ; + + return targetObject[ propertyName || 'length' ] = counter ; +} + +/** + * Gets the browser parsed version of a css text (style attribute value). On + * some cases, the browser makes changes to the css text, returning a different + * value. For example, hexadecimal colors get transformed to rgb(). + */ +FCKTools.NormalizeCssText = function( unparsedCssText ) +{ + // Injects the style in a temporary span object, so the browser parses it, + // retrieving its final format. + var tempSpan = document.createElement( 'span' ) ; + tempSpan.style.cssText = unparsedCssText ; + return tempSpan.style.cssText ; +} + +/** + * Binding the "this" reference to an object for a function. + */ +FCKTools.Bind = function( subject, func ) +{ + return function(){ return func.apply( subject, arguments ) ; } ; +} + +/** + * Retrieve the correct "empty iframe" URL for the current browser, which + * causes the minimum fuzz (e.g. security warnings in HTTPS, DNS error in + * IE5.5, etc.) for that browser, making the iframe ready to DOM use whithout + * having to loading an external file. + */ +FCKTools.GetVoidUrl = function() +{ + if ( FCK_IS_CUSTOM_DOMAIN ) + return "javascript: void( function(){" + + "document.open();" + + "document.write('<html><head><title></title></head><body></body></html>');" + + "document.domain = '" + FCK_RUNTIME_DOMAIN + "';" + + "document.close();" + + "}() ) ;"; + + if ( FCKBrowserInfo.IsIE ) + { + if ( FCKBrowserInfo.IsIE7 || !FCKBrowserInfo.IsIE6 ) + return "" ; // IE7+ / IE5.5 + else + return "javascript: '';" ; // IE6+ + } + + return "javascript: void(0);" ; // All other browsers. +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcktools_gecko.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcktools_gecko.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcktools_gecko.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,282 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Utility functions. (Gecko version). + */ + +FCKTools.CancelEvent = function( e ) +{ + if ( e ) + e.preventDefault() ; +} + +FCKTools.DisableSelection = function( element ) +{ + if ( FCKBrowserInfo.IsGecko ) + element.style.MozUserSelect = 'none' ; // Gecko only. + else if ( FCKBrowserInfo.IsSafari ) + element.style.KhtmlUserSelect = 'none' ; // WebKit only. + else + element.style.userSelect = 'none' ; // CSS3 (not supported yet). +} + +// Appends a CSS file to a document. +FCKTools._AppendStyleSheet = function( documentElement, cssFileUrl ) +{ + var e = documentElement.createElement( 'LINK' ) ; + e.rel = 'stylesheet' ; + e.type = 'text/css' ; + e.href = cssFileUrl ; + documentElement.getElementsByTagName("HEAD")[0].appendChild( e ) ; + return e ; +} + +// Appends a CSS style string to a document. +FCKTools.AppendStyleString = function( documentElement, cssStyles ) +{ + if ( !cssStyles ) + return null ; + + var e = documentElement.createElement( "STYLE" ) ; + e.appendChild( documentElement.createTextNode( cssStyles ) ) ; + documentElement.getElementsByTagName( "HEAD" )[0].appendChild( e ) ; + return e ; +} + +// Removes all attributes and values from the element. +FCKTools.ClearElementAttributes = function( element ) +{ + // Loop throw all attributes in the element + for ( var i = 0 ; i < element.attributes.length ; i++ ) + { + // Remove the element by name. + element.removeAttribute( element.attributes[i].name, 0 ) ; // 0 : Case Insensitive + } +} + +// Returns an Array of strings with all defined in the elements inside another element. +FCKTools.GetAllChildrenIds = function( parentElement ) +{ + // Create the array that will hold all Ids. + var aIds = new Array() ; + + // Define a recursive function that search for the Ids. + var fGetIds = function( parent ) + { + for ( var i = 0 ; i < parent.childNodes.length ; i++ ) + { + var sId = parent.childNodes[i].id ; + + // Check if the Id is defined for the element. + if ( sId && sId.length > 0 ) aIds[ aIds.length ] = sId ; + + // Recursive call. + fGetIds( parent.childNodes[i] ) ; + } + } + + // Start the recursive calls. + fGetIds( parentElement ) ; + + return aIds ; +} + +// Replaces a tag with its contents. For example "<span>My <b>tag</b></span>" +// will be replaced with "My <b>tag</b>". +FCKTools.RemoveOuterTags = function( e ) +{ + var oFragment = e.ownerDocument.createDocumentFragment() ; + + for ( var i = 0 ; i < e.childNodes.length ; i++ ) + oFragment.appendChild( e.childNodes[i].cloneNode(true) ) ; + + e.parentNode.replaceChild( oFragment, e ) ; +} + +FCKTools.CreateXmlObject = function( object ) +{ + switch ( object ) + { + case 'XmlHttp' : + return new XMLHttpRequest() ; + + case 'DOMDocument' : + // Originaly, we were had the following here: + // return document.implementation.createDocument( '', '', null ) ; + // But that doesn't work if we're running under domain relaxation mode, so we need a workaround. + // See http://ajaxian.com/archives/xml-messages-with-cross-domain-json about the trick we're using. + var doc = ( new DOMParser() ).parseFromString( '<tmp></tmp>', 'text/xml' ) ; + FCKDomTools.RemoveNode( doc.firstChild ) ; + return doc ; + } + return null ; +} + +FCKTools.GetScrollPosition = function( relativeWindow ) +{ + return { X : relativeWindow.pageXOffset, Y : relativeWindow.pageYOffset } ; +} + +FCKTools.AddEventListener = function( sourceObject, eventName, listener ) +{ + sourceObject.addEventListener( eventName, listener, false ) ; +} + +FCKTools.RemoveEventListener = function( sourceObject, eventName, listener ) +{ + sourceObject.removeEventListener( eventName, listener, false ) ; +} + +// Listeners attached with this function cannot be detached. +FCKTools.AddEventListenerEx = function( sourceObject, eventName, listener, paramsArray ) +{ + sourceObject.addEventListener( + eventName, + function( e ) + { + listener.apply( sourceObject, [ e ].concat( paramsArray || [] ) ) ; + }, + false + ) ; +} + +// Returns and object with the "Width" and "Height" properties. +FCKTools.GetViewPaneSize = function( win ) +{ + return { Width : win.innerWidth, Height : win.innerHeight } ; +} + +FCKTools.SaveStyles = function( element ) +{ + var data = FCKTools.ProtectFormStyles( element ) ; + + var oSavedStyles = new Object() ; + + if ( element.className.length > 0 ) + { + oSavedStyles.Class = element.className ; + element.className = '' ; + } + + var sInlineStyle = element.getAttribute( 'style' ) ; + + if ( sInlineStyle && sInlineStyle.length > 0 ) + { + oSavedStyles.Inline = sInlineStyle ; + element.setAttribute( 'style', '', 0 ) ; // 0 : Case Insensitive + } + + FCKTools.RestoreFormStyles( element, data ) ; + return oSavedStyles ; +} + +FCKTools.RestoreStyles = function( element, savedStyles ) +{ + var data = FCKTools.ProtectFormStyles( element ) ; + element.className = savedStyles.Class || '' ; + + if ( savedStyles.Inline ) + element.setAttribute( 'style', savedStyles.Inline, 0 ) ; // 0 : Case Insensitive + else + element.removeAttribute( 'style', 0 ) ; + FCKTools.RestoreFormStyles( element, data ) ; +} + +FCKTools.RegisterDollarFunction = function( targetWindow ) +{ + targetWindow.$ = function( id ) + { + return targetWindow.document.getElementById( id ) ; + } ; +} + +FCKTools.AppendElement = function( target, elementName ) +{ + return target.appendChild( target.ownerDocument.createElement( elementName ) ) ; +} + +// Get the coordinates of an element. +// @el : The element to get the position. +// @relativeWindow: The window to which we want the coordinates relative to. +FCKTools.GetElementPosition = function( el, relativeWindow ) +{ + // Initializes the Coordinates object that will be returned by the function. + var c = { X:0, Y:0 } ; + + var oWindow = relativeWindow || window ; + + var oOwnerWindow = FCKTools.GetElementWindow( el ) ; + + var previousElement = null ; + // Loop throw the offset chain. + while ( el ) + { + var sPosition = oOwnerWindow.getComputedStyle(el, '').position ; + + // Check for non "static" elements. + // 'FCKConfig.FloatingPanelsZIndex' -- Submenus are under a positioned IFRAME. + if ( sPosition && sPosition != 'static' && el.style.zIndex != FCKConfig.FloatingPanelsZIndex ) + break ; + + /* + FCKDebug.Output( el.tagName + ":" + "offset=" + el.offsetLeft + "," + el.offsetTop + " " + + "scroll=" + el.scrollLeft + "," + el.scrollTop ) ; + */ + + c.X += el.offsetLeft - el.scrollLeft ; + c.Y += el.offsetTop - el.scrollTop ; + + // Backtrack due to offsetParent's calculation by the browser ignores scrollLeft and scrollTop. + // Backtracking is not needed for Opera + if ( ! FCKBrowserInfo.IsOpera ) + { + var scrollElement = previousElement ; + while ( scrollElement && scrollElement != el ) + { + c.X -= scrollElement.scrollLeft ; + c.Y -= scrollElement.scrollTop ; + scrollElement = scrollElement.parentNode ; + } + } + + previousElement = el ; + if ( el.offsetParent ) + el = el.offsetParent ; + else + { + if ( oOwnerWindow != oWindow ) + { + el = oOwnerWindow.frameElement ; + previousElement = null ; + if ( el ) + oOwnerWindow = FCKTools.GetElementWindow( el ) ; + } + else + { + c.X += el.scrollLeft ; + c.Y += el.scrollTop ; + break ; + } + } + } + + // Return the Coordinates object + return c ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcktools_ie.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcktools_ie.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fcktools_ie.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,233 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Utility functions. (IE version). + */ + +FCKTools.CancelEvent = function( e ) +{ + return false ; +} + +// Appends one or more CSS files to a document. +FCKTools._AppendStyleSheet = function( documentElement, cssFileUrl ) +{ + return documentElement.createStyleSheet( cssFileUrl ).owningElement ; +} + +// Appends a CSS style string to a document. +FCKTools.AppendStyleString = function( documentElement, cssStyles ) +{ + if ( !cssStyles ) + return null ; + + var s = documentElement.createStyleSheet( "" ) ; + s.cssText = cssStyles ; + return s ; +} + +// Removes all attributes and values from the element. +FCKTools.ClearElementAttributes = function( element ) +{ + element.clearAttributes() ; +} + +FCKTools.GetAllChildrenIds = function( parentElement ) +{ + var aIds = new Array() ; + for ( var i = 0 ; i < parentElement.all.length ; i++ ) + { + var sId = parentElement.all[i].id ; + if ( sId && sId.length > 0 ) + aIds[ aIds.length ] = sId ; + } + return aIds ; +} + +FCKTools.RemoveOuterTags = function( e ) +{ + e.insertAdjacentHTML( 'beforeBegin', e.innerHTML ) ; + e.parentNode.removeChild( e ) ; +} + +FCKTools.CreateXmlObject = function( object ) +{ + var aObjs ; + + switch ( object ) + { + case 'XmlHttp' : + // Try the native XMLHttpRequest introduced with IE7. + try { return new XMLHttpRequest() ; } catch (e) {} + + aObjs = [ 'MSXML2.XmlHttp', 'Microsoft.XmlHttp' ] ; + break ; + + case 'DOMDocument' : + aObjs = [ 'MSXML2.DOMDocument', 'Microsoft.XmlDom' ] ; + break ; + } + + for ( var i = 0 ; i < 2 ; i++ ) + { + try { return new ActiveXObject( aObjs[i] ) ; } + catch (e) + {} + } + + if ( FCKLang.NoActiveX ) + { + alert( FCKLang.NoActiveX ) ; + FCKLang.NoActiveX = null ; + } + return null ; +} + +FCKTools.DisableSelection = function( element ) +{ + element.unselectable = 'on' ; + + var e, i = 0 ; + // The extra () is to avoid a warning with strict error checking. This is ok. + while ( (e = element.all[ i++ ]) ) + { + switch ( e.tagName ) + { + case 'IFRAME' : + case 'TEXTAREA' : + case 'INPUT' : + case 'SELECT' : + /* Ignore the above tags */ + break ; + default : + e.unselectable = 'on' ; + } + } +} + +FCKTools.GetScrollPosition = function( relativeWindow ) +{ + var oDoc = relativeWindow.document ; + + // Try with the doc element. + var oPos = { X : oDoc.documentElement.scrollLeft, Y : oDoc.documentElement.scrollTop } ; + + if ( oPos.X > 0 || oPos.Y > 0 ) + return oPos ; + + // If no scroll, try with the body. + return { X : oDoc.body.scrollLeft, Y : oDoc.body.scrollTop } ; +} + +FCKTools.AddEventListener = function( sourceObject, eventName, listener ) +{ + sourceObject.attachEvent( 'on' + eventName, listener ) ; +} + +FCKTools.RemoveEventListener = function( sourceObject, eventName, listener ) +{ + sourceObject.detachEvent( 'on' + eventName, listener ) ; +} + +// Listeners attached with this function cannot be detached. +FCKTools.AddEventListenerEx = function( sourceObject, eventName, listener, paramsArray ) +{ + // Ok... this is a closures party, but is the only way to make it clean of memory leaks. + var o = new Object() ; + o.Source = sourceObject ; + o.Params = paramsArray || [] ; // Memory leak if we have DOM objects here. + o.Listener = function( ev ) + { + return listener.apply( o.Source, [ ev ].concat( o.Params ) ) ; + } + + if ( FCK.IECleanup ) + FCK.IECleanup.AddItem( null, function() { o.Source = null ; o.Params = null ; } ) ; + + sourceObject.attachEvent( 'on' + eventName, o.Listener ) ; + + sourceObject = null ; // Memory leak cleaner (because of the above closure). + paramsArray = null ; // Memory leak cleaner (because of the above closure). +} + +// Returns and object with the "Width" and "Height" properties. +FCKTools.GetViewPaneSize = function( win ) +{ + var oSizeSource ; + + var oDoc = win.document.documentElement ; + if ( oDoc && oDoc.clientWidth ) // IE6 Strict Mode + oSizeSource = oDoc ; + else + oSizeSource = win.document.body ; // Other IEs + + if ( oSizeSource ) + return { Width : oSizeSource.clientWidth, Height : oSizeSource.clientHeight } ; + else + return { Width : 0, Height : 0 } ; +} + +FCKTools.SaveStyles = function( element ) +{ + var data = FCKTools.ProtectFormStyles( element ) ; + + var oSavedStyles = new Object() ; + + if ( element.className.length > 0 ) + { + oSavedStyles.Class = element.className ; + element.className = '' ; + } + + var sInlineStyle = element.style.cssText ; + + if ( sInlineStyle.length > 0 ) + { + oSavedStyles.Inline = sInlineStyle ; + element.style.cssText = '' ; + } + + FCKTools.RestoreFormStyles( element, data ) ; + return oSavedStyles ; +} + +FCKTools.RestoreStyles = function( element, savedStyles ) +{ + var data = FCKTools.ProtectFormStyles( element ) ; + element.className = savedStyles.Class || '' ; + element.style.cssText = savedStyles.Inline || '' ; + FCKTools.RestoreFormStyles( element, data ) ; +} + +FCKTools.RegisterDollarFunction = function( targetWindow ) +{ + targetWindow.$ = targetWindow.document.getElementById ; +} + +FCKTools.AppendElement = function( target, elementName ) +{ + return target.appendChild( this.GetElementDocument( target ).createElement( elementName ) ) ; +} + +// This function may be used by Regex replacements. +FCKTools.ToLowerCase = function( strValue ) +{ + return strValue.toLowerCase() ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckundo.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckundo.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckundo.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,223 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + */ + +var FCKUndo = new Object() ; + +FCKUndo.SavedData = new Array() ; +FCKUndo.CurrentIndex = -1 ; +FCKUndo.TypesCount = 0 ; +FCKUndo.Changed = false ; // Is the document changed in respect to its initial image? +FCKUndo.MaxTypes = 25 ; +FCKUndo.Typing = false ; +FCKUndo.SaveLocked = false ; + +FCKUndo._GetBookmark = function() +{ + FCKSelection.Restore() ; + + var range = new FCKDomRange( FCK.EditorWindow ) ; + try + { + // There are some tricky cases where this might fail (e.g. having a lone empty table in IE) + range.MoveToSelection() ; + } + catch ( e ) + { + return null ; + } + if ( FCKBrowserInfo.IsIE ) + { + var bookmark = range.CreateBookmark() ; + var dirtyHtml = FCK.EditorDocument.body.innerHTML ; + range.MoveToBookmark( bookmark ) ; + return [ bookmark, dirtyHtml ] ; + } + return range.CreateBookmark2() ; +} + +FCKUndo._SelectBookmark = function( bookmark ) +{ + if ( ! bookmark ) + return ; + + var range = new FCKDomRange( FCK.EditorWindow ) ; + if ( bookmark instanceof Object ) + { + if ( FCKBrowserInfo.IsIE ) + range.MoveToBookmark( bookmark[0] ) ; + else + range.MoveToBookmark2( bookmark ) ; + try + { + // this does not always succeed, there are still some tricky cases where it fails + // e.g. add a special character at end of document, undo, redo -> error + range.Select() ; + } + catch ( e ) + { + // if select restore fails, put the caret at the end of the document + range.MoveToPosition( FCK.EditorDocument.body, 4 ) ; + range.Select() ; + } + } +} + +FCKUndo._CompareCursors = function( cursor1, cursor2 ) +{ + for ( var i = 0 ; i < Math.min( cursor1.length, cursor2.length ) ; i++ ) + { + if ( cursor1[i] < cursor2[i] ) + return -1; + else if (cursor1[i] > cursor2[i] ) + return 1; + } + if ( cursor1.length < cursor2.length ) + return -1; + else if (cursor1.length > cursor2.length ) + return 1; + return 0; +} + +FCKUndo._CheckIsBookmarksEqual = function( bookmark1, bookmark2 ) +{ + if ( ! ( bookmark1 && bookmark2 ) ) + return false ; + if ( FCKBrowserInfo.IsIE ) + { + var startOffset1 = bookmark1[1].search( bookmark1[0].StartId ) ; + var startOffset2 = bookmark2[1].search( bookmark2[0].StartId ) ; + var endOffset1 = bookmark1[1].search( bookmark1[0].EndId ) ; + var endOffset2 = bookmark2[1].search( bookmark2[0].EndId ) ; + return startOffset1 == startOffset2 && endOffset1 == endOffset2 ; + } + else + { + return this._CompareCursors( bookmark1.Start, bookmark2.Start ) == 0 + && this._CompareCursors( bookmark1.End, bookmark2.End ) == 0 ; + } +} + +FCKUndo.SaveUndoStep = function() +{ + if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG || this.SaveLocked ) + return ; + + // Assume the editor content is changed when SaveUndoStep() is called after the first time. + // This also enables the undo button in toolbar. + if ( this.SavedData.length ) + this.Changed = true ; + + // Get the HTML content. + var sHtml = FCK.EditorDocument.body.innerHTML ; + var bookmark = this._GetBookmark() ; + + // Shrink the array to the current level. + this.SavedData = this.SavedData.slice( 0, this.CurrentIndex + 1 ) ; + + // Cancel operation if the new step is identical to the previous one. + if ( this.CurrentIndex > 0 + && sHtml == this.SavedData[ this.CurrentIndex ][0] + && this._CheckIsBookmarksEqual( bookmark, this.SavedData[ this.CurrentIndex ][1] ) ) + return ; + // Save the selection and caret position in the first undo level for the first change. + else if ( this.CurrentIndex == 0 && this.SavedData.length && sHtml == this.SavedData[0][0] ) + { + this.SavedData[0][1] = bookmark ; + return ; + } + + // If we reach the Maximum number of undo levels, we must remove the first + // entry of the list shifting all elements. + if ( this.CurrentIndex + 1 >= FCKConfig.MaxUndoLevels ) + this.SavedData.shift() ; + else + this.CurrentIndex++ ; + + // Save the new level in front of the actual position. + this.SavedData[ this.CurrentIndex ] = [ sHtml, bookmark ] ; + + FCK.Events.FireEvent( "OnSelectionChange" ) ; +} + +FCKUndo.CheckUndoState = function() +{ + return ( this.Changed || this.CurrentIndex > 0 ) ; +} + +FCKUndo.CheckRedoState = function() +{ + return ( this.CurrentIndex < ( this.SavedData.length - 1 ) ) ; +} + +FCKUndo.Undo = function() +{ + if ( this.CheckUndoState() ) + { + // If it is the first step. + if ( this.CurrentIndex == ( this.SavedData.length - 1 ) ) + { + // Save the actual state for a possible "Redo" call. + this.SaveUndoStep() ; + } + + // Go a step back. + this._ApplyUndoLevel( --this.CurrentIndex ) ; + + FCK.Events.FireEvent( "OnSelectionChange" ) ; + } +} + +FCKUndo.Redo = function() +{ + if ( this.CheckRedoState() ) + { + // Go a step forward. + this._ApplyUndoLevel( ++this.CurrentIndex ) ; + + FCK.Events.FireEvent( "OnSelectionChange" ) ; + } +} + +FCKUndo._ApplyUndoLevel = function( level ) +{ + var oData = this.SavedData[ level ] ; + + if ( !oData ) + return ; + + // Update the editor contents with that step data. + if ( FCKBrowserInfo.IsIE ) + { + if ( oData[1] && oData[1][1] ) + FCK.SetInnerHtml( oData[1][1] ) ; + else + FCK.SetInnerHtml( oData[0] ) ; + } + else + FCK.EditorDocument.body.innerHTML = oData[0] ; + + // Restore the selection + this._SelectBookmark( oData[1] ) ; + + this.TypesCount = 0 ; + this.Changed = false ; + this.Typing = false ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckurlparams.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckurlparams.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckurlparams.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,39 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Defines the FCKURLParams object that is used to get all parameters + * passed by the URL QueryString (after the "?"). + */ + +// #### URLParams: holds all URL passed parameters (like ?Param1=Value1&Param2=Value2) +var FCKURLParams = new Object() ; + +(function() +{ + var aParams = document.location.search.substr(1).split('&') ; + for ( var i = 0 ; i < aParams.length ; i++ ) + { + var aParam = aParams[i].split('=') ; + var sParamName = decodeURIComponent( aParam[0] ) ; + var sParamValue = decodeURIComponent( aParam[1] ) ; + + FCKURLParams[ sParamName ] = sParamValue ; + } +})(); Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckxhtml.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckxhtml.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckxhtml.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,515 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Defines the FCKXHtml object, responsible for the XHTML operations. + */ + +var FCKXHtml = new Object() ; + +FCKXHtml.CurrentJobNum = 0 ; + +FCKXHtml.GetXHTML = function( node, includeNode, format ) +{ + FCKDomTools.CheckAndRemovePaddingNode( FCKTools.GetElementDocument( node ), FCKConfig.EnterMode ) ; + FCKXHtmlEntities.Initialize() ; + + // Set the correct entity to use for empty blocks. + this._NbspEntity = ( FCKConfig.ProcessHTMLEntities? 'nbsp' : '#160' ) ; + + // Save the current IsDirty state. The XHTML processor may change the + // original HTML, dirtying it. + var bIsDirty = FCK.IsDirty() ; + + // Special blocks are blocks of content that remain untouched during the + // process. It is used for SCRIPTs and STYLEs. + FCKXHtml.SpecialBlocks = new Array() ; + + // Create the XML DOMDocument object. + this.XML = FCKTools.CreateXmlObject( 'DOMDocument' ) ; + + // Add a root element that holds all child nodes. + this.MainNode = this.XML.appendChild( this.XML.createElement( 'xhtml' ) ) ; + + FCKXHtml.CurrentJobNum++ ; + +// var dTimer = new Date() ; + + if ( includeNode ) + this._AppendNode( this.MainNode, node ) ; + else + this._AppendChildNodes( this.MainNode, node, false ) ; + + // Get the resulting XHTML as a string. + var sXHTML = this._GetMainXmlString() ; + +// alert( 'Time: ' + ( ( ( new Date() ) - dTimer ) ) + ' ms' ) ; + + this.XML = null ; + + // Safari adds xmlns="http://www.w3.org/1999/xhtml" to the root node (#963) + if ( FCKBrowserInfo.IsSafari ) + sXHTML = sXHTML.replace( /^<xhtml.*?>/, '<xhtml>' ) ; + + // Strip the "XHTML" root node. + sXHTML = sXHTML.substr( 7, sXHTML.length - 15 ).Trim() ; + + // Add a space in the tags with no closing tags, like <br/> -> <br /> + sXHTML = sXHTML.replace( FCKRegexLib.SpaceNoClose, ' />'); + + if ( FCKConfig.ForceSimpleAmpersand ) + sXHTML = sXHTML.replace( FCKRegexLib.ForceSimpleAmpersand, '&' ) ; + + if ( format ) + sXHTML = FCKCodeFormatter.Format( sXHTML ) ; + + // Now we put back the SpecialBlocks contents. + for ( var i = 0 ; i < FCKXHtml.SpecialBlocks.length ; i++ ) + { + var oRegex = new RegExp( '___FCKsi___' + i ) ; + sXHTML = sXHTML.replace( oRegex, FCKXHtml.SpecialBlocks[i] ) ; + } + + // Replace entities marker with the ampersand. + sXHTML = sXHTML.replace( FCKRegexLib.GeckoEntitiesMarker, '&' ) ; + + // Restore the IsDirty state if it was not dirty. + if ( !bIsDirty ) + FCK.ResetIsDirty() ; + + FCKDomTools.EnforcePaddingNode( FCKTools.GetElementDocument( node ), FCKConfig.EnterMode ) ; + return sXHTML ; +} + +FCKXHtml._AppendAttribute = function( xmlNode, attributeName, attributeValue ) +{ + try + { + if ( attributeValue == undefined || attributeValue == null ) + attributeValue = '' ; + else if ( attributeValue.replace ) + { + if ( FCKConfig.ForceSimpleAmpersand ) + attributeValue = attributeValue.replace( /&/g, '___FCKAmp___' ) ; + + // Entities must be replaced in the attribute values. + attributeValue = attributeValue.replace( FCKXHtmlEntities.EntitiesRegex, FCKXHtml_GetEntity ) ; + } + + // Create the attribute. + var oXmlAtt = this.XML.createAttribute( attributeName ) ; + oXmlAtt.value = attributeValue ; + + // Set the attribute in the node. + xmlNode.attributes.setNamedItem( oXmlAtt ) ; + } + catch (e) + {} +} + +FCKXHtml._AppendChildNodes = function( xmlNode, htmlNode, isBlockElement ) +{ + var oNode = htmlNode.firstChild ; + + while ( oNode ) + { + this._AppendNode( xmlNode, oNode ) ; + oNode = oNode.nextSibling ; + } + + // Trim block elements. This is also needed to avoid Firefox leaving extra + // BRs at the end of them. + if ( isBlockElement && htmlNode.tagName && htmlNode.tagName.toLowerCase() != 'pre' ) + { + FCKDomTools.TrimNode( xmlNode ) ; + + if ( FCKConfig.FillEmptyBlocks ) + { + var lastChild = xmlNode.lastChild ; + if ( lastChild && lastChild.nodeType == 1 && lastChild.nodeName == 'br' ) + this._AppendEntity( xmlNode, this._NbspEntity ) ; + } + } + + // If the resulting node is empty. + if ( xmlNode.childNodes.length == 0 ) + { + if ( isBlockElement && FCKConfig.FillEmptyBlocks ) + { + this._AppendEntity( xmlNode, this._NbspEntity ) ; + return xmlNode ; + } + + var sNodeName = xmlNode.nodeName ; + + // Some inline elements are required to have something inside (span, strong, etc...). + if ( FCKListsLib.InlineChildReqElements[ sNodeName ] ) + return null ; + + // We can't use short representation of empty elements that are not marked + // as empty in th XHTML DTD. + if ( !FCKListsLib.EmptyElements[ sNodeName ] ) + xmlNode.appendChild( this.XML.createTextNode('') ) ; + } + + return xmlNode ; +} + +FCKXHtml._AppendNode = function( xmlNode, htmlNode ) +{ + if ( !htmlNode ) + return false ; + + switch ( htmlNode.nodeType ) + { + // Element Node. + case 1 : + // If we detect a <br> inside a <pre> in Gecko, turn it into a line break instead. + // This is a workaround for the Gecko bug here: https://bugzilla.mozilla.org/show_bug.cgi?id=92921 + if ( FCKBrowserInfo.IsGecko + && htmlNode.tagName.toLowerCase() == 'br' + && htmlNode.parentNode.tagName.toLowerCase() == 'pre' ) + { + var val = '\r' ; + if ( htmlNode == htmlNode.parentNode.firstChild ) + val += '\r' ; + return FCKXHtml._AppendNode( xmlNode, this.XML.createTextNode( val ) ) ; + } + + // Here we found an element that is not the real element, but a + // fake one (like the Flash placeholder image), so we must get the real one. + if ( htmlNode.getAttribute('_fckfakelement') ) + return FCKXHtml._AppendNode( xmlNode, FCK.GetRealElement( htmlNode ) ) ; + + // Ignore bogus BR nodes in the DOM. + if ( FCKBrowserInfo.IsGecko && + htmlNode.nextSibling && + ( htmlNode.hasAttribute('_moz_editor_bogus_node') || htmlNode.getAttribute( 'type' ) == '_moz' ) ) + return false ; + + // This is for elements that are instrumental to FCKeditor and + // must be removed from the final HTML. + if ( htmlNode.getAttribute('_fcktemp') ) + return false ; + + // Get the element name. + var sNodeName = htmlNode.tagName.toLowerCase() ; + + if ( FCKBrowserInfo.IsIE ) + { + // IE doens't include the scope name in the nodeName. So, add the namespace. + if ( htmlNode.scopeName && htmlNode.scopeName != 'HTML' && htmlNode.scopeName != 'FCK' ) + sNodeName = htmlNode.scopeName.toLowerCase() + ':' + sNodeName ; + } + else + { + if ( sNodeName.StartsWith( 'fck:' ) ) + sNodeName = sNodeName.Remove( 0,4 ) ; + } + + // Check if the node name is valid, otherwise ignore this tag. + // If the nodeName starts with a slash, it is a orphan closing tag. + // On some strange cases, the nodeName is empty, even if the node exists. + if ( !FCKRegexLib.ElementName.test( sNodeName ) ) + return false ; + + // The already processed nodes must be marked to avoid then to be duplicated (bad formatted HTML). + // So here, the "mark" is checked... if the element is Ok, then mark it. + if ( htmlNode._fckxhtmljob && htmlNode._fckxhtmljob == FCKXHtml.CurrentJobNum ) + return false ; + + var oNode = this.XML.createElement( sNodeName ) ; + + // Add all attributes. + FCKXHtml._AppendAttributes( xmlNode, htmlNode, oNode, sNodeName ) ; + + htmlNode._fckxhtmljob = FCKXHtml.CurrentJobNum ; + + // Tag specific processing. + var oTagProcessor = FCKXHtml.TagProcessors[ sNodeName ] ; + + if ( oTagProcessor ) + oNode = oTagProcessor( oNode, htmlNode, xmlNode ) ; + else + oNode = this._AppendChildNodes( oNode, htmlNode, Boolean( FCKListsLib.NonEmptyBlockElements[ sNodeName ] ) ) ; + + if ( !oNode ) + return false ; + + xmlNode.appendChild( oNode ) ; + + break ; + + // Text Node. + case 3 : + if ( htmlNode.parentNode && htmlNode.parentNode.nodeName.IEquals( 'pre' ) ) + return this._AppendTextNode( xmlNode, htmlNode.nodeValue ) ; + return this._AppendTextNode( xmlNode, htmlNode.nodeValue.ReplaceNewLineChars(' ') ) ; + + // Comment + case 8 : + // IE catches the <!DOTYPE ... > as a comment, but it has no + // innerHTML, so we can catch it, and ignore it. + if ( FCKBrowserInfo.IsIE && !htmlNode.innerHTML ) + break ; + + try { xmlNode.appendChild( this.XML.createComment( htmlNode.nodeValue ) ) ; } + catch (e) { /* Do nothing... probably this is a wrong format comment. */ } + break ; + + // Unknown Node type. + default : + xmlNode.appendChild( this.XML.createComment( "Element not supported - Type: " + htmlNode.nodeType + " Name: " + htmlNode.nodeName ) ) ; + break ; + } + return true ; +} + +// Append an item to the SpecialBlocks array and returns the tag to be used. +FCKXHtml._AppendSpecialItem = function( item ) +{ + return '___FCKsi___' + FCKXHtml.SpecialBlocks.AddItem( item ) ; +} + +FCKXHtml._AppendEntity = function( xmlNode, entity ) +{ + xmlNode.appendChild( this.XML.createTextNode( '#?-:' + entity + ';' ) ) ; +} + +FCKXHtml._AppendTextNode = function( targetNode, textValue ) +{ + var bHadText = textValue.length > 0 ; + if ( bHadText ) + targetNode.appendChild( this.XML.createTextNode( textValue.replace( FCKXHtmlEntities.EntitiesRegex, FCKXHtml_GetEntity ) ) ) ; + return bHadText ; +} + +// Retrieves a entity (internal format) for a given character. +function FCKXHtml_GetEntity( character ) +{ + // We cannot simply place the entities in the text, because the XML parser + // will translate & to &. So we use a temporary marker which is replaced + // in the end of the processing. + var sEntity = FCKXHtmlEntities.Entities[ character ] || ( '#' + character.charCodeAt(0) ) ; + return '#?-:' + sEntity + ';' ; +} + +// An object that hold tag specific operations. +FCKXHtml.TagProcessors = +{ + a : function( node, htmlNode ) + { + // Firefox may create empty tags when deleting the selection in some special cases (SF-BUG 1556878). + if ( htmlNode.innerHTML.Trim().length == 0 && !htmlNode.name ) + return false ; + + var sSavedUrl = htmlNode.getAttribute( '_fcksavedurl' ) ; + if ( sSavedUrl != null ) + FCKXHtml._AppendAttribute( node, 'href', sSavedUrl ) ; + + + // Anchors with content has been marked with an additional class, now we must remove it. + if ( FCKBrowserInfo.IsIE ) + { + // Buggy IE, doesn't copy the name of changed anchors. + if ( htmlNode.name ) + FCKXHtml._AppendAttribute( node, 'name', htmlNode.name ) ; + } + + node = FCKXHtml._AppendChildNodes( node, htmlNode, false ) ; + + return node ; + }, + + area : function( node, htmlNode ) + { + var sSavedUrl = htmlNode.getAttribute( '_fcksavedurl' ) ; + if ( sSavedUrl != null ) + FCKXHtml._AppendAttribute( node, 'href', sSavedUrl ) ; + + // IE ignores the "COORDS" and "SHAPE" attribute so we must add it manually. + if ( FCKBrowserInfo.IsIE ) + { + if ( ! node.attributes.getNamedItem( 'coords' ) ) + { + var sCoords = htmlNode.getAttribute( 'coords', 2 ) ; + if ( sCoords && sCoords != '0,0,0' ) + FCKXHtml._AppendAttribute( node, 'coords', sCoords ) ; + } + + if ( ! node.attributes.getNamedItem( 'shape' ) ) + { + var sShape = htmlNode.getAttribute( 'shape', 2 ) ; + if ( sShape && sShape.length > 0 ) + FCKXHtml._AppendAttribute( node, 'shape', sShape.toLowerCase() ) ; + } + } + + return node ; + }, + + body : function( node, htmlNode ) + { + node = FCKXHtml._AppendChildNodes( node, htmlNode, false ) ; + // Remove spellchecker attributes added for Firefox when converting to HTML code (Bug #1351). + node.removeAttribute( 'spellcheck' ) ; + return node ; + }, + + // IE loses contents of iframes, and Gecko does give it back HtmlEncoded + // Note: Opera does lose the content and doesn't provide it in the innerHTML string + iframe : function( node, htmlNode ) + { + var sHtml = htmlNode.innerHTML ; + + // Gecko does give back the encoded html + if ( FCKBrowserInfo.IsGecko ) + sHtml = FCKTools.HTMLDecode( sHtml ); + + // Remove the saved urls here as the data won't be processed as nodes + sHtml = sHtml.replace( /\s_fcksavedurl="[^"]*"/g, '' ) ; + + node.appendChild( FCKXHtml.XML.createTextNode( FCKXHtml._AppendSpecialItem( sHtml ) ) ) ; + + return node ; + }, + + img : function( node, htmlNode ) + { + // The "ALT" attribute is required in XHTML. + if ( ! node.attributes.getNamedItem( 'alt' ) ) + FCKXHtml._AppendAttribute( node, 'alt', '' ) ; + + var sSavedUrl = htmlNode.getAttribute( '_fcksavedurl' ) ; + if ( sSavedUrl != null ) + FCKXHtml._AppendAttribute( node, 'src', sSavedUrl ) ; + + return node ; + }, + + // Fix orphaned <li> nodes (Bug #503). + li : function( node, htmlNode, targetNode ) + { + // If the XML parent node is already a <ul> or <ol>, then add the <li> as usual. + if ( targetNode.nodeName.IEquals( ['ul', 'ol'] ) ) + return FCKXHtml._AppendChildNodes( node, htmlNode, true ) ; + + var newTarget = FCKXHtml.XML.createElement( 'ul' ) ; + + // Reset the _fckxhtmljob so the HTML node is processed again. + htmlNode._fckxhtmljob = null ; + + // Loop through all sibling LIs, adding them to the <ul>. + do + { + FCKXHtml._AppendNode( newTarget, htmlNode ) ; + + // Look for the next element following this <li>. + do + { + htmlNode = FCKDomTools.GetNextSibling( htmlNode ) ; + + } while ( htmlNode && htmlNode.nodeType == 3 && htmlNode.nodeValue.Trim().length == 0 ) + + } while ( htmlNode && htmlNode.nodeName.toLowerCase() == 'li' ) + + return newTarget ; + }, + + // Fix nested <ul> and <ol>. + ol : function( node, htmlNode, targetNode ) + { + if ( htmlNode.innerHTML.Trim().length == 0 ) + return false ; + + var ePSibling = targetNode.lastChild ; + + if ( ePSibling && ePSibling.nodeType == 3 ) + ePSibling = ePSibling.previousSibling ; + + if ( ePSibling && ePSibling.nodeName.toUpperCase() == 'LI' ) + { + htmlNode._fckxhtmljob = null ; + FCKXHtml._AppendNode( ePSibling, htmlNode ) ; + return false ; + } + + node = FCKXHtml._AppendChildNodes( node, htmlNode ) ; + + return node ; + }, + + pre : function ( node, htmlNode ) + { + var firstChild = htmlNode.firstChild ; + + if ( firstChild && firstChild.nodeType == 3 ) + node.appendChild( FCKXHtml.XML.createTextNode( FCKXHtml._AppendSpecialItem( '\r\n' ) ) ) ; + + FCKXHtml._AppendChildNodes( node, htmlNode, true ) ; + + return node ; + }, + + script : function( node, htmlNode ) + { + // The "TYPE" attribute is required in XHTML. + if ( ! node.attributes.getNamedItem( 'type' ) ) + FCKXHtml._AppendAttribute( node, 'type', 'text/javascript' ) ; + + node.appendChild( FCKXHtml.XML.createTextNode( FCKXHtml._AppendSpecialItem( htmlNode.text ) ) ) ; + + return node ; + }, + + span : function( node, htmlNode ) + { + // Firefox may create empty tags when deleting the selection in some special cases (SF-BUG 1084404). + if ( htmlNode.innerHTML.length == 0 ) + return false ; + + node = FCKXHtml._AppendChildNodes( node, htmlNode, false ) ; + + return node ; + }, + + style : function( node, htmlNode ) + { + // The "TYPE" attribute is required in XHTML. + if ( ! node.attributes.getNamedItem( 'type' ) ) + FCKXHtml._AppendAttribute( node, 'type', 'text/css' ) ; + + var cssText = htmlNode.innerHTML ; + if ( FCKBrowserInfo.IsIE ) // Bug #403 : IE always appends a \r\n to the beginning of StyleNode.innerHTML + cssText = cssText.replace( /^(\r\n|\n|\r)/, '' ) ; + + node.appendChild( FCKXHtml.XML.createTextNode( FCKXHtml._AppendSpecialItem( cssText ) ) ) ; + + return node ; + }, + + title : function( node, htmlNode ) + { + node.appendChild( FCKXHtml.XML.createTextNode( FCK.EditorDocument.title ) ) ; + + return node ; + } +} ; + +FCKXHtml.TagProcessors.ul = FCKXHtml.TagProcessors.ol ; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckxhtml_gecko.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckxhtml_gecko.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckxhtml_gecko.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,101 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Defines the FCKXHtml object, responsible for the XHTML operations. + * Gecko specific. + */ + +FCKXHtml._GetMainXmlString = function() +{ + return ( new XMLSerializer() ).serializeToString( this.MainNode ) ; +} + +FCKXHtml._AppendAttributes = function( xmlNode, htmlNode, node ) +{ + var aAttributes = htmlNode.attributes ; + + for ( var n = 0 ; n < aAttributes.length ; n++ ) + { + var oAttribute = aAttributes[n] ; + + if ( oAttribute.specified ) + { + var sAttName = oAttribute.nodeName.toLowerCase() ; + var sAttValue ; + + // Ignore any attribute starting with "_fck". + if ( sAttName.StartsWith( '_fck' ) ) + continue ; + // There is a bug in Mozilla that returns '_moz_xxx' attributes as specified. + else if ( sAttName.indexOf( '_moz' ) == 0 ) + continue ; + // There are one cases (on Gecko) when the oAttribute.nodeValue must be used: + // - for the "class" attribute + else if ( sAttName == 'class' ) + { + sAttValue = oAttribute.nodeValue.replace( FCKRegexLib.FCK_Class, '' ) ; + if ( sAttValue.length == 0 ) + continue ; + } + // XHTML doens't support attribute minimization like "CHECKED". It must be transformed to checked="checked". + else if ( oAttribute.nodeValue === true ) + sAttValue = sAttName ; + else + sAttValue = htmlNode.getAttribute( sAttName, 2 ) ; // We must use getAttribute to get it exactly as it is defined. + + this._AppendAttribute( node, sAttName, sAttValue ) ; + } + } +} + +if ( FCKBrowserInfo.IsOpera ) +{ + // Opera moves the <FCK:meta> element outside head (#1166). + + // Save a reference to the XML <head> node, so we can use it for + // orphan <meta>s. + FCKXHtml.TagProcessors['head'] = function( node, htmlNode ) + { + FCKXHtml.XML._HeadElement = node ; + + node = FCKXHtml._AppendChildNodes( node, htmlNode, true ) ; + + return node ; + } + + // Check whether a <meta> element is outside <head>, and move it to the + // proper place. + FCKXHtml.TagProcessors['meta'] = function( node, htmlNode, xmlNode ) + { + if ( htmlNode.parentNode.nodeName.toLowerCase() != 'head' ) + { + var headElement = FCKXHtml.XML._HeadElement ; + + if ( headElement && xmlNode != headElement ) + { + delete htmlNode._fckxhtmljob ; + FCKXHtml._AppendNode( headElement, htmlNode ) ; + return null ; + } + } + + return node ; + } +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckxhtml_ie.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckxhtml_ie.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckxhtml_ie.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,203 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Defines the FCKXHtml object, responsible for the XHTML operations. + * IE specific. + */ + +FCKXHtml._GetMainXmlString = function() +{ + return this.MainNode.xml ; +} + +FCKXHtml._AppendAttributes = function( xmlNode, htmlNode, node, nodeName ) +{ + var aAttributes = htmlNode.attributes ; + + for ( var n = 0 ; n < aAttributes.length ; n++ ) + { + var oAttribute = aAttributes[n] ; + + if ( oAttribute.specified ) + { + var sAttName = oAttribute.nodeName.toLowerCase() ; + var sAttValue ; + + // Ignore any attribute starting with "_fck". + if ( sAttName.StartsWith( '_fck' ) ) + continue ; + // The following must be done because of a bug on IE regarding the style + // attribute. It returns "null" for the nodeValue. + else if ( sAttName == 'style' ) + { + var data = FCKTools.ProtectFormStyles( htmlNode ) ; + sAttValue = htmlNode.style.cssText.replace( FCKRegexLib.StyleProperties, FCKTools.ToLowerCase ) ; + FCKTools.RestoreFormStyles( htmlNode, data ) ; + } + // There are two cases when the oAttribute.nodeValue must be used: + // - for the "class" attribute + // - for events attributes (on IE only). + else if ( sAttName == 'class' ) + { + sAttValue = oAttribute.nodeValue.replace( FCKRegexLib.FCK_Class, '' ) ; + if ( sAttValue.length == 0 ) + continue ; + } + else if ( sAttName.indexOf('on') == 0 ) + sAttValue = oAttribute.nodeValue ; + else if ( nodeName == 'body' && sAttName == 'contenteditable' ) + continue ; + // XHTML doens't support attribute minimization like "CHECKED". It must be transformed to checked="checked". + else if ( oAttribute.nodeValue === true ) + sAttValue = sAttName ; + else + { + // We must use getAttribute to get it exactly as it is defined. + // There are some rare cases that IE throws an error here, so we must try/catch. + try + { + sAttValue = htmlNode.getAttribute( sAttName, 2 ) ; + } + catch (e) {} + } + this._AppendAttribute( node, sAttName, sAttValue || oAttribute.nodeValue ) ; + } + } +} + +// On very rare cases, IE is loosing the "align" attribute for DIV. (right align and apply bulleted list) +FCKXHtml.TagProcessors['div'] = function( node, htmlNode ) +{ + if ( htmlNode.align.length > 0 ) + FCKXHtml._AppendAttribute( node, 'align', htmlNode.align ) ; + + node = FCKXHtml._AppendChildNodes( node, htmlNode, true ) ; + + return node ; +} + +// IE automatically changes <FONT> tags to <FONT size=+0>. +FCKXHtml.TagProcessors['font'] = function( node, htmlNode ) +{ + if ( node.attributes.length == 0 ) + node = FCKXHtml.XML.createDocumentFragment() ; + + node = FCKXHtml._AppendChildNodes( node, htmlNode ) ; + + return node ; +} + +FCKXHtml.TagProcessors['form'] = function( node, htmlNode ) +{ + if ( htmlNode.acceptCharset && htmlNode.acceptCharset.length > 0 && htmlNode.acceptCharset != 'UNKNOWN' ) + FCKXHtml._AppendAttribute( node, 'accept-charset', htmlNode.acceptCharset ) ; + + // IE has a bug and htmlNode.attributes['name'].specified=false if there is + // no element with id="name" inside the form (#360 and SF-BUG-1155726). + var nameAtt = htmlNode.attributes['name'] ; + + if ( nameAtt && nameAtt.value.length > 0 ) + FCKXHtml._AppendAttribute( node, 'name', nameAtt.value ) ; + + node = FCKXHtml._AppendChildNodes( node, htmlNode, true ) ; + + return node ; +} + +// IE doens't see the value attribute as an attribute for the <INPUT> tag. +FCKXHtml.TagProcessors['input'] = function( node, htmlNode ) +{ + if ( htmlNode.name ) + FCKXHtml._AppendAttribute( node, 'name', htmlNode.name ) ; + + if ( htmlNode.value && !node.attributes.getNamedItem( 'value' ) ) + FCKXHtml._AppendAttribute( node, 'value', htmlNode.value ) ; + + if ( !node.attributes.getNamedItem( 'type' ) ) + FCKXHtml._AppendAttribute( node, 'type', 'text' ) ; + + return node ; +} + +FCKXHtml.TagProcessors['label'] = function( node, htmlNode ) +{ + if ( htmlNode.htmlFor.length > 0 ) + FCKXHtml._AppendAttribute( node, 'for', htmlNode.htmlFor ) ; + + node = FCKXHtml._AppendChildNodes( node, htmlNode ) ; + + return node ; +} + +// Fix behavior for IE, it doesn't read back the .name on newly created maps +FCKXHtml.TagProcessors['map'] = function( node, htmlNode ) +{ + if ( ! node.attributes.getNamedItem( 'name' ) ) + { + var name = htmlNode.name ; + if ( name ) + FCKXHtml._AppendAttribute( node, 'name', name ) ; + } + + node = FCKXHtml._AppendChildNodes( node, htmlNode, true ) ; + + return node ; +} + +FCKXHtml.TagProcessors['meta'] = function( node, htmlNode ) +{ + var oHttpEquiv = node.attributes.getNamedItem( 'http-equiv' ) ; + + if ( oHttpEquiv == null || oHttpEquiv.value.length == 0 ) + { + // Get the http-equiv value from the outerHTML. + var sHttpEquiv = htmlNode.outerHTML.match( FCKRegexLib.MetaHttpEquiv ) ; + + if ( sHttpEquiv ) + { + sHttpEquiv = sHttpEquiv[1] ; + FCKXHtml._AppendAttribute( node, 'http-equiv', sHttpEquiv ) ; + } + } + + return node ; +} + +// IE ignores the "SELECTED" attribute so we must add it manually. +FCKXHtml.TagProcessors['option'] = function( node, htmlNode ) +{ + if ( htmlNode.selected && !node.attributes.getNamedItem( 'selected' ) ) + FCKXHtml._AppendAttribute( node, 'selected', 'selected' ) ; + + node = FCKXHtml._AppendChildNodes( node, htmlNode ) ; + + return node ; +} + +// IE doens't hold the name attribute as an attribute for the <TEXTAREA> and <SELECT> tags. +FCKXHtml.TagProcessors['textarea'] = FCKXHtml.TagProcessors['select'] = function( node, htmlNode ) +{ + if ( htmlNode.name ) + FCKXHtml._AppendAttribute( node, 'name', htmlNode.name ) ; + + node = FCKXHtml._AppendChildNodes( node, htmlNode ) ; + + return node ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckxhtmlentities.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckxhtmlentities.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/_source/internals/fckxhtmlentities.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,354 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * This file define the HTML entities handled by the editor. + */ + +var FCKXHtmlEntities = new Object() ; + +FCKXHtmlEntities.Initialize = function() +{ + if ( FCKXHtmlEntities.Entities ) + return ; + + var sChars = '' ; + var oEntities, e ; + + if ( FCKConfig.ProcessHTMLEntities ) + { + FCKXHtmlEntities.Entities = { + // Latin-1 Entities + ' ':'nbsp', + '¡':'iexcl', + '¢':'cent', + '£':'pound', + '¤':'curren', + '¥':'yen', + '¦':'brvbar', + '§':'sect', + '¨':'uml', + '©':'copy', + 'ª':'ordf', + '«':'laquo', + '¬':'not', + '':'shy', + '®':'reg', + '¯':'macr', + '°':'deg', + '±':'plusmn', + '²':'sup2', + '³':'sup3', + '´':'acute', + 'µ':'micro', + '¶':'para', + '·':'middot', + '¸':'cedil', + '¹':'sup1', + 'º':'ordm', + '»':'raquo', + '¼':'frac14', + '½':'frac12', + '¾':'frac34', + '¿':'iquest', + '×':'times', + '÷':'divide', + + // Symbols + + 'ƒ':'fnof', + '•':'bull', + '…':'hellip', + '′':'prime', + '″':'Prime', + '‾':'oline', + '⁄':'frasl', + '℘':'weierp', + 'ℑ':'image', + 'ℜ':'real', + '™':'trade', + 'ℵ':'alefsym', + '←':'larr', + '↑':'uarr', + '→':'rarr', + '↓':'darr', + '↔':'harr', + '↵':'crarr', + '⇐':'lArr', + '⇑':'uArr', + '⇒':'rArr', + '⇓':'dArr', + '⇔':'hArr', + '∀':'forall', + '∂':'part', + '∃':'exist', + '∅':'empty', + '∇':'nabla', + '∈':'isin', + '∉':'notin', + '∋':'ni', + '∏':'prod', + '∑':'sum', + '−':'minus', + '∗':'lowast', + '√':'radic', + '∝':'prop', + '∞':'infin', + '∠':'ang', + '∧':'and', + '∨':'or', + '∩':'cap', + '∪':'cup', + '∫':'int', + '∴':'there4', + '∼':'sim', + '≅':'cong', + '≈':'asymp', + '≠':'ne', + '≡':'equiv', + '≤':'le', + '≥':'ge', + '⊂':'sub', + '⊃':'sup', + '⊄':'nsub', + '⊆':'sube', + '⊇':'supe', + '⊕':'oplus', + '⊗':'otimes', + '⊥':'perp', + '⋅':'sdot', + '\u2308':'lceil', + '\u2309':'rceil', + '\u230a':'lfloor', + '\u230b':'rfloor', + '\u2329':'lang', + '\u232a':'rang', + '◊':'loz', + '♠':'spades', + '♣':'clubs', + '♥':'hearts', + '♦':'diams', + + // Other Special Characters + + '"':'quot', + // '&':'amp', // This entity is automatically handled by the XHTML parser. + // '<':'lt', // This entity is automatically handled by the XHTML parser. + // '>':'gt', // This entity is automatically handled by the XHTML parser. + 'ˆ':'circ', + '˜':'tilde', + ' ':'ensp', + ' ':'emsp', + ' ':'thinsp', + '':'zwnj', + '':'zwj', + '':'lrm', + '':'rlm', + '–':'ndash', + '—':'mdash', + '‘':'lsquo', + '’':'rsquo', + '‚':'sbquo', + '“':'ldquo', + '”':'rdquo', + '„':'bdquo', + '†':'dagger', + '‡':'Dagger', + '‰':'permil', + '‹':'lsaquo', + '›':'rsaquo', + '€':'euro' + } ; + + // Process Base Entities. + for ( e in FCKXHtmlEntities.Entities ) + sChars += e ; + + // Include Latin Letters Entities. + if ( FCKConfig.IncludeLatinEntities ) + { + oEntities = { + 'À':'Agrave', + 'Á':'Aacute', + 'Â':'Acirc', + 'Ã':'Atilde', + 'Ä':'Auml', + 'Å':'Aring', + 'Æ':'AElig', + 'Ç':'Ccedil', + 'È':'Egrave', + 'É':'Eacute', + 'Ê':'Ecirc', + 'Ë':'Euml', + 'Ì':'Igrave', + 'Í':'Iacute', + 'Î':'Icirc', + 'Ï':'Iuml', + 'Ð':'ETH', + 'Ñ':'Ntilde', + 'Ò':'Ograve', + 'Ó':'Oacute', + 'Ô':'Ocirc', + 'Õ':'Otilde', + 'Ö':'Ouml', + 'Ø':'Oslash', + 'Ù':'Ugrave', + 'Ú':'Uacute', + 'Û':'Ucirc', + 'Ü':'Uuml', + 'Ý':'Yacute', + 'Þ':'THORN', + 'ß':'szlig', + 'à':'agrave', + 'á':'aacute', + 'â':'acirc', + 'ã':'atilde', + 'ä':'auml', + 'å':'aring', + 'æ':'aelig', + 'ç':'ccedil', + 'è':'egrave', + 'é':'eacute', + 'ê':'ecirc', + 'ë':'euml', + 'ì':'igrave', + 'í':'iacute', + 'î':'icirc', + 'ï':'iuml', + 'ð':'eth', + 'ñ':'ntilde', + 'ò':'ograve', + 'ó':'oacute', + 'ô':'ocirc', + 'õ':'otilde', + 'ö':'ouml', + 'ø':'oslash', + 'ù':'ugrave', + 'ú':'uacute', + 'û':'ucirc', + 'ü':'uuml', + 'ý':'yacute', + 'þ':'thorn', + 'ÿ':'yuml', + 'Œ':'OElig', + 'œ':'oelig', + 'Š':'Scaron', + 'š':'scaron', + 'Ÿ':'Yuml' + } ; + + for ( e in oEntities ) + { + FCKXHtmlEntities.Entities[ e ] = oEntities[ e ] ; + sChars += e ; + } + + oEntities = null ; + } + + // Include Greek Letters Entities. + if ( FCKConfig.IncludeGreekEntities ) + { + oEntities = { + 'Α':'Alpha', + 'Β':'Beta', + 'Γ':'Gamma', + 'Δ':'Delta', + 'Ε':'Epsilon', + 'Ζ':'Zeta', + 'Η':'Eta', + 'Θ':'Theta', + 'Ι':'Iota', + 'Κ':'Kappa', + 'Λ':'Lambda', + 'Μ':'Mu', + 'Ν':'Nu', + 'Ξ':'Xi', + 'Ο':'Omicron', + 'Π':'Pi', + 'Ρ':'Rho', + 'Σ':'Sigma', + 'Τ':'Tau', + 'Υ':'Upsilon', + 'Φ':'Phi', + 'Χ':'Chi', + 'Ψ':'Psi', + 'Ω':'Omega', + 'α':'alpha', + 'β':'beta', + 'γ':'gamma', + 'δ':'delta', + 'ε':'epsilon', + 'ζ':'zeta', + 'η':'eta', + 'θ':'theta', + 'ι':'iota', + 'κ':'kappa', + 'λ':'lambda', + 'μ':'mu', + 'ν':'nu', + 'ξ':'xi', + 'ο':'omicron', + 'π':'pi', + 'ρ':'rho', + 'ς':'sigmaf', + 'σ':'sigma', + 'τ':'tau', + 'υ':'upsilon', + 'φ':'phi', + 'χ':'chi', + 'ψ':'psi', + 'ω':'omega', + '\u03d1':'thetasym', + '\u03d2':'upsih', + '\u03d6':'piv' + } ; + + for ( e in oEntities ) + { + FCKXHtmlEntities.Entities[ e ] = oEntities[ e ] ; + sChars += e ; + } + + oEntities = null ; + } + } + else + { + FCKXHtmlEntities.Entities = {} ; + + // Even if we are not processing the entities, we must render the + // correctly. As we don't want HTML entities, let's use its numeric + // representation ( ). + sChars = ' ' ; + } + + // Create the Regex used to find entities in the text. + var sRegexPattern = '[' + sChars + ']' ; + + if ( FCKConfig.ProcessNumericEntities ) + sRegexPattern = '[^ -~]|' + sRegexPattern ; + + var sAdditional = FCKConfig.AdditionalNumericEntities ; + + if ( sAdditional && sAdditional.length > 0 ) + sRegexPattern += '|' + FCKConfig.AdditionalNumericEntities ; + + FCKXHtmlEntities.EntitiesRegex = new RegExp( sRegexPattern, 'g' ) ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/css/behaviors/disablehandles.htc =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/css/behaviors/disablehandles.htc (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/css/behaviors/disablehandles.htc 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,15 @@ +<public:component lightweight="true"> + +<script language="javascript"> + +function CancelEvent() +{ + return false ; +} + +this.onresizestart = CancelEvent ; +this.onbeforeeditfocus = CancelEvent ; + +</script> + +</public:component> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/css/behaviors/showtableborders.htc =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/css/behaviors/showtableborders.htc (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/css/behaviors/showtableborders.htc 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,36 @@ +<public:component lightweight="true"> + +<public:attach event="oncontentready" onevent="ShowBorders()" /> +<public:attach event="onpropertychange" onevent="OnPropertyChange()" /> + +<script language="javascript"> + +var oClassRegex = /\s*FCK__ShowTableBorders/ ; + +function ShowBorders() +{ + if ( this.border == 0 ) + { + if ( !oClassRegex.test( this.className ) ) + this.className += ' FCK__ShowTableBorders' ; + } + else + { + if ( oClassRegex.test( this.className ) ) + { + this.className = this.className.replace( oClassRegex, '' ) ; + if ( this.className.length == 0 ) + this.removeAttribute( 'className', 0 ) ; + } + } +} + +function OnPropertyChange() +{ + if ( event.propertyName == 'border' || event.propertyName == 'className' ) + ShowBorders.call(this) ; +} + +</script> + +</public:component> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/block_address.png =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/block_address.png ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/block_blockquote.png =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/block_blockquote.png ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/block_div.png =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/block_div.png ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/block_h1.png =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/block_h1.png ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/block_h2.png =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/block_h2.png ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/block_h3.png =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/block_h3.png ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/block_h4.png =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/block_h4.png ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/block_h5.png =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/block_h5.png ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/block_h6.png =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/block_h6.png ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/block_p.png =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/block_p.png ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/block_pre.png =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/block_pre.png ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/fck_anchor.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/fck_anchor.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/fck_flashlogo.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/fck_flashlogo.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/fck_hiddenfield.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/fck_hiddenfield.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/fck_pagebreak.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/fck_pagebreak.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/fck_plugin.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/css/images/fck_plugin.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/common/fck_dialog_common.css =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/common/fck_dialog_common.css (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/common/fck_dialog_common.css 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,85 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * This is the CSS file used for interface details in some dialog + * windows. + */ + +/* ######### + * WARNING + * ######### + * When changing this file, the minified version of it must be updated in the + * fck_dialog_common.js file (see GetCommonDialogCss). + */ + +.ImagePreviewArea +{ + border: #000000 1px solid; + overflow: auto; + width: 100%; + height: 170px; + background-color: #ffffff; +} + +.FlashPreviewArea +{ + border: #000000 1px solid; + padding: 5px; + overflow: auto; + width: 100%; + height: 170px; + background-color: #ffffff; +} + +.BtnReset +{ + float: left; + background-position: center center; + background-image: url(images/reset.gif); + width: 16px; + height: 16px; + background-repeat: no-repeat; + border: 1px none; + font-size: 1px ; +} + +.BtnLocked, .BtnUnlocked +{ + float: left; + background-position: center center; + background-image: url(images/locked.gif); + width: 16px; + height: 16px; + background-repeat: no-repeat; + border: none 1px; + font-size: 1px ; +} + +.BtnUnlocked +{ + background-image: url(images/unlocked.gif); +} + +.BtnOver +{ + border: outset 1px; + cursor: pointer; + cursor: hand; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/common/fck_dialog_common.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/common/fck_dialog_common.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/common/fck_dialog_common.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,338 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Useful functions used by almost all dialog window pages. + * Dialogs should link to this file as the very first script on the page. + */ + +// Automatically detect the correct document.domain (#123). +(function() +{ + var d = document.domain ; + + while ( true ) + { + // Test if we can access a parent property. + try + { + var test = window.parent.document.domain ; + break ; + } + catch( e ) {} + + // Remove a domain part: www.mytest.example.com => mytest.example.com => example.com ... + d = d.replace( /.*?(?:\.|$)/, '' ) ; + + if ( d.length == 0 ) + break ; // It was not able to detect the domain. + + try + { + document.domain = d ; + } + catch (e) + { + break ; + } + } +})() ; + +// Attention: FCKConfig must be available in the page. +function GetCommonDialogCss( prefix ) +{ + // CSS minified by http://iceyboard.no-ip.org/projects/css_compressor + return FCKConfig.BasePath + 'dialog/common/' + '|.ImagePreviewArea{border:#000 1px solid;overflow:auto;width:100%;height:170px;background-color:#fff}.FlashPreviewArea{border:#000 1px solid;padding:5px;overflow:auto;width:100%;height:170px;background-color:#fff}.BtnReset{float:left;background-position:center center;background-image:url(images/reset.gif);width:16px;height:16px;background-repeat:no-repeat;border:1px none;font-size:1px}.BtnLocked,.BtnUnlocked{float:left;background-position:center center;background-image:url(images/locked.gif);width:16px;height:16px;background-repeat:no-repeat;border:none 1px;font-size:1px}.BtnUnlocked{background-image:url(images/unlocked.gif)}.BtnOver{border:outset 1px;cursor:pointer;cursor:hand}' ; +} + +// Gets a element by its Id. Used for shorter coding. +function GetE( elementId ) +{ + return document.getElementById( elementId ) ; +} + +function ShowE( element, isVisible ) +{ + if ( typeof( element ) == 'string' ) + element = GetE( element ) ; + element.style.display = isVisible ? '' : 'none' ; +} + +function SetAttribute( element, attName, attValue ) +{ + if ( attValue == null || attValue.length == 0 ) + element.removeAttribute( attName, 0 ) ; // 0 : Case Insensitive + else + element.setAttribute( attName, attValue, 0 ) ; // 0 : Case Insensitive +} + +function GetAttribute( element, attName, valueIfNull ) +{ + var oAtt = element.attributes[attName] ; + + if ( oAtt == null || !oAtt.specified ) + return valueIfNull ? valueIfNull : '' ; + + var oValue = element.getAttribute( attName, 2 ) ; + + if ( oValue == null ) + oValue = oAtt.nodeValue ; + + return ( oValue == null ? valueIfNull : oValue ) ; +} + +function SelectField( elementId ) +{ + var element = GetE( elementId ) ; + element.focus() ; + + // element.select may not be available for some fields (like <select>). + if ( element.select ) + element.select() ; +} + +// Functions used by text fields to accept numbers only. +var IsDigit = ( function() + { + var KeyIdentifierMap = + { + End : 35, + Home : 36, + Left : 37, + Right : 39, + 'U+00007F' : 46 // Delete + } ; + + return function ( e ) + { + if ( !e ) + e = event ; + + var iCode = ( e.keyCode || e.charCode ) ; + + if ( !iCode && e.keyIdentifier && ( e.keyIdentifier in KeyIdentifierMap ) ) + iCode = KeyIdentifierMap[ e.keyIdentifier ] ; + + return ( + ( iCode >= 48 && iCode <= 57 ) // Numbers + || (iCode >= 35 && iCode <= 40) // Arrows, Home, End + || iCode == 8 // Backspace + || iCode == 46 // Delete + || iCode == 9 // Tab + ) ; + } + } )() ; + +String.prototype.Trim = function() +{ + return this.replace( /(^\s*)|(\s*$)/g, '' ) ; +} + +String.prototype.StartsWith = function( value ) +{ + return ( this.substr( 0, value.length ) == value ) ; +} + +String.prototype.Remove = function( start, length ) +{ + var s = '' ; + + if ( start > 0 ) + s = this.substring( 0, start ) ; + + if ( start + length < this.length ) + s += this.substring( start + length , this.length ) ; + + return s ; +} + +String.prototype.ReplaceAll = function( searchArray, replaceArray ) +{ + var replaced = this ; + + for ( var i = 0 ; i < searchArray.length ; i++ ) + { + replaced = replaced.replace( searchArray[i], replaceArray[i] ) ; + } + + return replaced ; +} + +function OpenFileBrowser( url, width, height ) +{ + // oEditor must be defined. + + var iLeft = ( oEditor.FCKConfig.ScreenWidth - width ) / 2 ; + var iTop = ( oEditor.FCKConfig.ScreenHeight - height ) / 2 ; + + var sOptions = "toolbar=no,status=no,resizable=yes,dependent=yes,scrollbars=yes" ; + sOptions += ",width=" + width ; + sOptions += ",height=" + height ; + sOptions += ",left=" + iLeft ; + sOptions += ",top=" + iTop ; + + // The "PreserveSessionOnFileBrowser" because the above code could be + // blocked by popup blockers. + if ( oEditor.FCKConfig.PreserveSessionOnFileBrowser && oEditor.FCKBrowserInfo.IsIE ) + { + // The following change has been made otherwise IE will open the file + // browser on a different server session (on some cases): + // http://support.microsoft.com/default.aspx?scid=kb;en-us;831678 + // by Simone Chiaretta. + var oWindow = oEditor.window.open( url, 'FCKBrowseWindow', sOptions ) ; + + if ( oWindow ) + { + // Detect Yahoo popup blocker. + try + { + var sTest = oWindow.name ; // Yahoo returns "something", but we can't access it, so detect that and avoid strange errors for the user. + oWindow.opener = window ; + } + catch(e) + { + alert( oEditor.FCKLang.BrowseServerBlocked ) ; + } + } + else + alert( oEditor.FCKLang.BrowseServerBlocked ) ; + } + else + window.open( url, 'FCKBrowseWindow', sOptions ) ; +} + +/** + Utility function to create/update an element with a name attribute in IE, so it behaves properly when moved around + It also allows to change the name or other special attributes in an existing node + oEditor : instance of FCKeditor where the element will be created + oOriginal : current element being edited or null if it has to be created + nodeName : string with the name of the element to create + oAttributes : Hash object with the attributes that must be set at creation time in IE + Those attributes will be set also after the element has been + created for any other browser to avoid redudant code +*/ +function CreateNamedElement( oEditor, oOriginal, nodeName, oAttributes ) +{ + var oNewNode ; + + // IE doesn't allow easily to change properties of an existing object, + // so remove the old and force the creation of a new one. + var oldNode = null ; + if ( oOriginal && oEditor.FCKBrowserInfo.IsIE ) + { + // Force the creation only if some of the special attributes have changed: + var bChanged = false; + for( var attName in oAttributes ) + bChanged |= ( oOriginal.getAttribute( attName, 2) != oAttributes[attName] ) ; + + if ( bChanged ) + { + oldNode = oOriginal ; + oOriginal = null ; + } + } + + // If the node existed (and it's not IE), then we just have to update its attributes + if ( oOriginal ) + { + oNewNode = oOriginal ; + } + else + { + // #676, IE doesn't play nice with the name or type attribute + if ( oEditor.FCKBrowserInfo.IsIE ) + { + var sbHTML = [] ; + sbHTML.push( '<' + nodeName ) ; + for( var prop in oAttributes ) + { + sbHTML.push( ' ' + prop + '="' + oAttributes[prop] + '"' ) ; + } + sbHTML.push( '>' ) ; + if ( !oEditor.FCKListsLib.EmptyElements[nodeName.toLowerCase()] ) + sbHTML.push( '</' + nodeName + '>' ) ; + + oNewNode = oEditor.FCK.EditorDocument.createElement( sbHTML.join('') ) ; + // Check if we are just changing the properties of an existing node: copy its properties + if ( oldNode ) + { + CopyAttributes( oldNode, oNewNode, oAttributes ) ; + oEditor.FCKDomTools.MoveChildren( oldNode, oNewNode ) ; + oldNode.parentNode.removeChild( oldNode ) ; + oldNode = null ; + + if ( oEditor.FCK.Selection.SelectionData ) + { + // Trick to refresh the selection object and avoid error in + // fckdialog.html Selection.EnsureSelection + var oSel = oEditor.FCK.EditorDocument.selection ; + oEditor.FCK.Selection.SelectionData = oSel.createRange() ; // Now oSel.type will be 'None' reflecting the real situation + } + } + oNewNode = oEditor.FCK.InsertElement( oNewNode ) ; + + // FCK.Selection.SelectionData is broken by now since we've + // deleted the previously selected element. So we need to reassign it. + if ( oEditor.FCK.Selection.SelectionData ) + { + var range = oEditor.FCK.EditorDocument.body.createControlRange() ; + range.add( oNewNode ) ; + oEditor.FCK.Selection.SelectionData = range ; + } + } + else + { + oNewNode = oEditor.FCK.InsertElement( nodeName ) ; + } + } + + // Set the basic attributes + for( var attName in oAttributes ) + oNewNode.setAttribute( attName, oAttributes[attName], 0 ) ; // 0 : Case Insensitive + + return oNewNode ; +} + +// Copy all the attributes from one node to the other, kinda like a clone +// But oSkipAttributes is an object with the attributes that must NOT be copied +function CopyAttributes( oSource, oDest, oSkipAttributes ) +{ + var aAttributes = oSource.attributes ; + + for ( var n = 0 ; n < aAttributes.length ; n++ ) + { + var oAttribute = aAttributes[n] ; + + if ( oAttribute.specified ) + { + var sAttName = oAttribute.nodeName ; + // We can set the type only once, so do it with the proper value, not copying it. + if ( sAttName in oSkipAttributes ) + continue ; + + var sAttValue = oSource.getAttribute( sAttName, 2 ) ; + if ( sAttValue == null ) + sAttValue = oAttribute.nodeValue ; + + oDest.setAttribute( sAttName, sAttValue, 0 ) ; // 0 : Case Insensitive + } + } + // The style: + oDest.style.cssText = oSource.style.cssText ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/common/images/locked.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/common/images/locked.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/common/images/reset.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/common/images/reset.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/common/images/unlocked.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/common/images/unlocked.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_about/logo_fckeditor.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_about/logo_fckeditor.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_about/logo_fredck.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_about/logo_fredck.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_about/sponsors/spellchecker_net.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_about/sponsors/spellchecker_net.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_docprops/fck_document_preview.html =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_docprops/fck_document_preview.html (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_docprops/fck_document_preview.html 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,113 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<!-- + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Preview shown in the "Document Properties" dialog window. +--> +<html> + <head> + <title>Document Properties - Preview</title> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + <meta name="robots" content="noindex, nofollow"> + <script language="javascript"> + +var eBase = parent.FCK.EditorDocument.getElementsByTagName( 'BASE' ) ; +if ( eBase.length > 0 && eBase[0].href.length > 0 ) +{ + document.write( '<base href="' + eBase[0].href + '">' ) ; +} + +window.onload = function() +{ + if ( typeof( parent.OnPreviewLoad ) == 'function' ) + parent.OnPreviewLoad( window, document.body ) ; +} + +function SetBaseHRef( baseHref ) +{ + var eBase = document.createElement( 'BASE' ) ; + eBase.href = baseHref ; + + var eHead = document.getElementsByTagName( 'HEAD' )[0] ; + eHead.appendChild( eBase ) ; +} + +function SetLinkColor( color ) +{ + if ( color && color.length > 0 ) + document.getElementById('eLink').style.color = color ; + else + document.getElementById('eLink').style.color = window.document.linkColor ; +} + +function SetVisitedColor( color ) +{ + if ( color && color.length > 0 ) + document.getElementById('eVisited').style.color = color ; + else + document.getElementById('eVisited').style.color = window.document.vlinkColor ; +} + +function SetActiveColor( color ) +{ + if ( color && color.length > 0 ) + document.getElementById('eActive').style.color = color ; + else + document.getElementById('eActive').style.color = window.document.alinkColor ; +} + </script> + </head> + <body> + <table width="100%" height="100%" cellpadding="0" cellspacing="0" border="0"> + <tr> + <td align="center" valign="middle"> + Normal Text + </td> + <td id="eLink" align="center" valign="middle"> + <u>Link Text</u> + </td> + </tr> + <tr> + <td id="eVisited" valign="middle" align="center"> + <u>Visited Link</u> + </td> + <td id="eActive" valign="middle" align="center"> + <u>Active Link</u> + </td> + </tr> + </table> + <br> + <br> + <br> + <br> + <br> + <br> + <br> + <br> + <br> + <br> + <br> + <br> + <br> + <br> + <br> + <br> + </body> +</html> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_flash/fck_flash.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_flash/fck_flash.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_flash/fck_flash.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,292 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Scripts related to the Flash dialog window (see fck_flash.html). + */ + +var dialog = window.parent ; +var oEditor = dialog.InnerDialogLoaded() ; +var FCK = oEditor.FCK ; +var FCKLang = oEditor.FCKLang ; +var FCKConfig = oEditor.FCKConfig ; +var FCKTools = oEditor.FCKTools ; + +//#### Dialog Tabs + +// Set the dialog tabs. +dialog.AddTab( 'Info', oEditor.FCKLang.DlgInfoTab ) ; + +if ( FCKConfig.FlashUpload ) + dialog.AddTab( 'Upload', FCKLang.DlgLnkUpload ) ; + +if ( !FCKConfig.FlashDlgHideAdvanced ) + dialog.AddTab( 'Advanced', oEditor.FCKLang.DlgAdvancedTag ) ; + +// Function called when a dialog tag is selected. +function OnDialogTabChange( tabCode ) +{ + ShowE('divInfo' , ( tabCode == 'Info' ) ) ; + ShowE('divUpload' , ( tabCode == 'Upload' ) ) ; + ShowE('divAdvanced' , ( tabCode == 'Advanced' ) ) ; +} + +// Get the selected flash embed (if available). +var oFakeImage = dialog.Selection.GetSelectedElement() ; +var oEmbed ; + +if ( oFakeImage ) +{ + if ( oFakeImage.tagName == 'IMG' && oFakeImage.getAttribute('_fckflash') ) + oEmbed = FCK.GetRealElement( oFakeImage ) ; + else + oFakeImage = null ; +} + +window.onload = function() +{ + // Translate the dialog box texts. + oEditor.FCKLanguageManager.TranslatePage(document) ; + + // Load the selected element information (if any). + LoadSelection() ; + + // Show/Hide the "Browse Server" button. + GetE('tdBrowse').style.display = FCKConfig.FlashBrowser ? '' : 'none' ; + + // Set the actual uploader URL. + if ( FCKConfig.FlashUpload ) + GetE('frmUpload').action = FCKConfig.FlashUploadURL ; + + dialog.SetAutoSize( true ) ; + + // Activate the "OK" button. + dialog.SetOkButton( true ) ; + + SelectField( 'txtUrl' ) ; +} + +function LoadSelection() +{ + if ( ! oEmbed ) return ; + + GetE('txtUrl').value = GetAttribute( oEmbed, 'src', '' ) ; + GetE('txtWidth').value = GetAttribute( oEmbed, 'width', '' ) ; + GetE('txtHeight').value = GetAttribute( oEmbed, 'height', '' ) ; + + // Get Advances Attributes + GetE('txtAttId').value = oEmbed.id ; + GetE('chkAutoPlay').checked = GetAttribute( oEmbed, 'play', 'true' ) == 'true' ; + GetE('chkLoop').checked = GetAttribute( oEmbed, 'loop', 'true' ) == 'true' ; + GetE('chkMenu').checked = GetAttribute( oEmbed, 'menu', 'true' ) == 'true' ; + GetE('cmbScale').value = GetAttribute( oEmbed, 'scale', '' ).toLowerCase() ; + + GetE('txtAttTitle').value = oEmbed.title ; + + if ( oEditor.FCKBrowserInfo.IsIE ) + { + GetE('txtAttClasses').value = oEmbed.getAttribute('className') || '' ; + GetE('txtAttStyle').value = oEmbed.style.cssText ; + } + else + { + GetE('txtAttClasses').value = oEmbed.getAttribute('class',2) || '' ; + GetE('txtAttStyle').value = oEmbed.getAttribute('style',2) || '' ; + } + + UpdatePreview() ; +} + +//#### The OK button was hit. +function Ok() +{ + if ( GetE('txtUrl').value.length == 0 ) + { + dialog.SetSelectedTab( 'Info' ) ; + GetE('txtUrl').focus() ; + + alert( oEditor.FCKLang.DlgAlertUrl ) ; + + return false ; + } + + oEditor.FCKUndo.SaveUndoStep() ; + if ( !oEmbed ) + { + oEmbed = FCK.EditorDocument.createElement( 'EMBED' ) ; + oFakeImage = null ; + } + UpdateEmbed( oEmbed ) ; + + if ( !oFakeImage ) + { + oFakeImage = oEditor.FCKDocumentProcessor_CreateFakeImage( 'FCK__Flash', oEmbed ) ; + oFakeImage.setAttribute( '_fckflash', 'true', 0 ) ; + oFakeImage = FCK.InsertElement( oFakeImage ) ; + } + + oEditor.FCKEmbedAndObjectProcessor.RefreshView( oFakeImage, oEmbed ) ; + + return true ; +} + +function UpdateEmbed( e ) +{ + SetAttribute( e, 'type' , 'application/x-shockwave-flash' ) ; + SetAttribute( e, 'pluginspage' , 'http://www.macromedia.com/go/getflashplayer' ) ; + + SetAttribute( e, 'src', GetE('txtUrl').value ) ; + SetAttribute( e, "width" , GetE('txtWidth').value ) ; + SetAttribute( e, "height", GetE('txtHeight').value ) ; + + // Advances Attributes + + SetAttribute( e, 'id' , GetE('txtAttId').value ) ; + SetAttribute( e, 'scale', GetE('cmbScale').value ) ; + + SetAttribute( e, 'play', GetE('chkAutoPlay').checked ? 'true' : 'false' ) ; + SetAttribute( e, 'loop', GetE('chkLoop').checked ? 'true' : 'false' ) ; + SetAttribute( e, 'menu', GetE('chkMenu').checked ? 'true' : 'false' ) ; + + SetAttribute( e, 'title' , GetE('txtAttTitle').value ) ; + + if ( oEditor.FCKBrowserInfo.IsIE ) + { + SetAttribute( e, 'className', GetE('txtAttClasses').value ) ; + e.style.cssText = GetE('txtAttStyle').value ; + } + else + { + SetAttribute( e, 'class', GetE('txtAttClasses').value ) ; + SetAttribute( e, 'style', GetE('txtAttStyle').value ) ; + } +} + +var ePreview ; + +function SetPreviewElement( previewEl ) +{ + ePreview = previewEl ; + + if ( GetE('txtUrl').value.length > 0 ) + UpdatePreview() ; +} + +function UpdatePreview() +{ + if ( !ePreview ) + return ; + + while ( ePreview.firstChild ) + ePreview.removeChild( ePreview.firstChild ) ; + + if ( GetE('txtUrl').value.length == 0 ) + ePreview.innerHTML = ' ' ; + else + { + var oDoc = ePreview.ownerDocument || ePreview.document ; + var e = oDoc.createElement( 'EMBED' ) ; + + SetAttribute( e, 'src', GetE('txtUrl').value ) ; + SetAttribute( e, 'type', 'application/x-shockwave-flash' ) ; + SetAttribute( e, 'width', '100%' ) ; + SetAttribute( e, 'height', '100%' ) ; + + ePreview.appendChild( e ) ; + } +} + +// <embed id="ePreview" src="fck_flash/claims.swf" width="100%" height="100%" style="visibility:hidden" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer"> + +function BrowseServer() +{ + OpenFileBrowser( FCKConfig.FlashBrowserURL, FCKConfig.FlashBrowserWindowWidth, FCKConfig.FlashBrowserWindowHeight ) ; +} + +function SetUrl( url, width, height ) +{ + GetE('txtUrl').value = url ; + + if ( width ) + GetE('txtWidth').value = width ; + + if ( height ) + GetE('txtHeight').value = height ; + + UpdatePreview() ; + + dialog.SetSelectedTab( 'Info' ) ; +} + +function OnUploadCompleted( errorNumber, fileUrl, fileName, customMsg ) +{ + switch ( errorNumber ) + { + case 0 : // No errors + alert( 'Your file has been successfully uploaded' ) ; + break ; + case 1 : // Custom error + alert( customMsg ) ; + return ; + case 101 : // Custom warning + alert( customMsg ) ; + break ; + case 201 : + alert( 'A file with the same name is already available. The uploaded file has been renamed to "' + fileName + '"' ) ; + break ; + case 202 : + alert( 'Invalid file type' ) ; + return ; + case 203 : + alert( "Security error. You probably don't have enough permissions to upload. Please check your server." ) ; + return ; + case 500 : + alert( 'The connector is disabled' ) ; + break ; + default : + alert( 'Error on file upload. Error number: ' + errorNumber ) ; + return ; + } + + SetUrl( fileUrl ) ; + GetE('frmUpload').reset() ; +} + +var oUploadAllowedExtRegex = new RegExp( FCKConfig.FlashUploadAllowedExtensions, 'i' ) ; +var oUploadDeniedExtRegex = new RegExp( FCKConfig.FlashUploadDeniedExtensions, 'i' ) ; + +function CheckUpload() +{ + var sFile = GetE('txtUploadFile').value ; + + if ( sFile.length == 0 ) + { + alert( 'Please select a file to upload' ) ; + return false ; + } + + if ( ( FCKConfig.FlashUploadAllowedExtensions.length > 0 && !oUploadAllowedExtRegex.test( sFile ) ) || + ( FCKConfig.FlashUploadDeniedExtensions.length > 0 && oUploadDeniedExtRegex.test( sFile ) ) ) + { + OnUploadCompleted( 202 ) ; + return false ; + } + + return true ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_flash/fck_flash_preview.html =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_flash/fck_flash_preview.html (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_flash/fck_flash_preview.html 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,50 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<!-- + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Preview page for the Flash dialog window. +--> +<html> + <head> + <title></title> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + <meta name="robots" content="noindex, nofollow"> + <script src="../common/fck_dialog_common.js" type="text/javascript"></script> + <script language="javascript"> + +var FCKTools = window.parent.FCKTools ; +var FCKConfig = window.parent.FCKConfig ; + +// Sets the Skin CSS +document.write( FCKTools.GetStyleHtml( FCKConfig.SkinDialogCSS ) ) ; +document.write( FCKTools.GetStyleHtml( GetCommonDialogCss( '../' ) ) ) ; + +if ( window.parent.FCKConfig.BaseHref.length > 0 ) + document.write( '<base href="' + window.parent.FCKConfig.BaseHref + '">' ) ; + +window.onload = function() +{ + window.parent.SetPreviewElement( document.body ) ; +} + + </script> + </head> + <body style="COLOR: #000000; BACKGROUND-COLOR: #ffffff"></body> +</html> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_image/fck_image.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_image/fck_image.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_image/fck_image.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,504 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Scripts related to the Image dialog window (see fck_image.html). + */ + +var dialog = window.parent ; +var oEditor = dialog.InnerDialogLoaded() ; +var FCK = oEditor.FCK ; +var FCKLang = oEditor.FCKLang ; +var FCKConfig = oEditor.FCKConfig ; +var FCKDebug = oEditor.FCKDebug ; +var FCKTools = oEditor.FCKTools ; + +var bImageButton = ( document.location.search.length > 0 && document.location.search.substr(1) == 'ImageButton' ) ; + +//#### Dialog Tabs + +// Set the dialog tabs. +dialog.AddTab( 'Info', FCKLang.DlgImgInfoTab ) ; + +if ( !bImageButton && !FCKConfig.ImageDlgHideLink ) + dialog.AddTab( 'Link', FCKLang.DlgImgLinkTab ) ; + +if ( FCKConfig.ImageUpload ) + dialog.AddTab( 'Upload', FCKLang.DlgLnkUpload ) ; + +if ( !FCKConfig.ImageDlgHideAdvanced ) + dialog.AddTab( 'Advanced', FCKLang.DlgAdvancedTag ) ; + +// Function called when a dialog tag is selected. +function OnDialogTabChange( tabCode ) +{ + ShowE('divInfo' , ( tabCode == 'Info' ) ) ; + ShowE('divLink' , ( tabCode == 'Link' ) ) ; + ShowE('divUpload' , ( tabCode == 'Upload' ) ) ; + ShowE('divAdvanced' , ( tabCode == 'Advanced' ) ) ; +} + +// Get the selected image (if available). +var oImage = dialog.Selection.GetSelectedElement() ; + +if ( oImage && oImage.tagName != 'IMG' && !( oImage.tagName == 'INPUT' && oImage.type == 'image' ) ) + oImage = null ; + +// Get the active link. +var oLink = dialog.Selection.GetSelection().MoveToAncestorNode( 'A' ) ; + +var oImageOriginal ; + +function UpdateOriginal( resetSize ) +{ + if ( !eImgPreview ) + return ; + + if ( GetE('txtUrl').value.length == 0 ) + { + oImageOriginal = null ; + return ; + } + + oImageOriginal = document.createElement( 'IMG' ) ; // new Image() ; + + if ( resetSize ) + { + oImageOriginal.onload = function() + { + this.onload = null ; + ResetSizes() ; + } + } + + oImageOriginal.src = eImgPreview.src ; +} + +var bPreviewInitialized ; + +window.onload = function() +{ + // Translate the dialog box texts. + oEditor.FCKLanguageManager.TranslatePage(document) ; + + GetE('btnLockSizes').title = FCKLang.DlgImgLockRatio ; + GetE('btnResetSize').title = FCKLang.DlgBtnResetSize ; + + // Load the selected element information (if any). + LoadSelection() ; + + // Show/Hide the "Browse Server" button. + GetE('tdBrowse').style.display = FCKConfig.ImageBrowser ? '' : 'none' ; + GetE('divLnkBrowseServer').style.display = FCKConfig.LinkBrowser ? '' : 'none' ; + + UpdateOriginal() ; + + // Set the actual uploader URL. + if ( FCKConfig.ImageUpload ) + GetE('frmUpload').action = FCKConfig.ImageUploadURL ; + + dialog.SetAutoSize( true ) ; + + // Activate the "OK" button. + dialog.SetOkButton( true ) ; + + SelectField( 'txtUrl' ) ; +} + +function LoadSelection() +{ + if ( ! oImage ) return ; + + var sUrl = oImage.getAttribute( '_fcksavedurl' ) ; + if ( sUrl == null ) + sUrl = GetAttribute( oImage, 'src', '' ) ; + + GetE('txtUrl').value = sUrl ; + GetE('txtAlt').value = GetAttribute( oImage, 'alt', '' ) ; + GetE('txtVSpace').value = GetAttribute( oImage, 'vspace', '' ) ; + GetE('txtHSpace').value = GetAttribute( oImage, 'hspace', '' ) ; + GetE('txtBorder').value = GetAttribute( oImage, 'border', '' ) ; + GetE('cmbAlign').value = GetAttribute( oImage, 'align', '' ) ; + + var iWidth, iHeight ; + + var regexSize = /^\s*(\d+)px\s*$/i ; + + if ( oImage.style.width ) + { + var aMatchW = oImage.style.width.match( regexSize ) ; + if ( aMatchW ) + { + iWidth = aMatchW[1] ; + oImage.style.width = '' ; + SetAttribute( oImage, 'width' , iWidth ) ; + } + } + + if ( oImage.style.height ) + { + var aMatchH = oImage.style.height.match( regexSize ) ; + if ( aMatchH ) + { + iHeight = aMatchH[1] ; + oImage.style.height = '' ; + SetAttribute( oImage, 'height', iHeight ) ; + } + } + + GetE('txtWidth').value = iWidth ? iWidth : GetAttribute( oImage, "width", '' ) ; + GetE('txtHeight').value = iHeight ? iHeight : GetAttribute( oImage, "height", '' ) ; + + // Get Advances Attributes + GetE('txtAttId').value = oImage.id ; + GetE('cmbAttLangDir').value = oImage.dir ; + GetE('txtAttLangCode').value = oImage.lang ; + GetE('txtAttTitle').value = oImage.title ; + GetE('txtLongDesc').value = oImage.longDesc ; + + if ( oEditor.FCKBrowserInfo.IsIE ) + { + GetE('txtAttClasses').value = oImage.className || '' ; + GetE('txtAttStyle').value = oImage.style.cssText ; + } + else + { + GetE('txtAttClasses').value = oImage.getAttribute('class',2) || '' ; + GetE('txtAttStyle').value = oImage.getAttribute('style',2) ; + } + + if ( oLink ) + { + var sLinkUrl = oLink.getAttribute( '_fcksavedurl' ) ; + if ( sLinkUrl == null ) + sLinkUrl = oLink.getAttribute('href',2) ; + + GetE('txtLnkUrl').value = sLinkUrl ; + GetE('cmbLnkTarget').value = oLink.target ; + } + + UpdatePreview() ; +} + +//#### The OK button was hit. +function Ok() +{ + if ( GetE('txtUrl').value.length == 0 ) + { + dialog.SetSelectedTab( 'Info' ) ; + GetE('txtUrl').focus() ; + + alert( FCKLang.DlgImgAlertUrl ) ; + + return false ; + } + + var bHasImage = ( oImage != null ) ; + + if ( bHasImage && bImageButton && oImage.tagName == 'IMG' ) + { + if ( confirm( 'Do you want to transform the selected image on a image button?' ) ) + oImage = null ; + } + else if ( bHasImage && !bImageButton && oImage.tagName == 'INPUT' ) + { + if ( confirm( 'Do you want to transform the selected image button on a simple image?' ) ) + oImage = null ; + } + + oEditor.FCKUndo.SaveUndoStep() ; + if ( !bHasImage ) + { + if ( bImageButton ) + { + oImage = FCK.EditorDocument.createElement( 'input' ) ; + oImage.type = 'image' ; + oImage = FCK.InsertElement( oImage ) ; + } + else + oImage = FCK.InsertElement( 'img' ) ; + } + + UpdateImage( oImage ) ; + + var sLnkUrl = GetE('txtLnkUrl').value.Trim() ; + + if ( sLnkUrl.length == 0 ) + { + if ( oLink ) + FCK.ExecuteNamedCommand( 'Unlink' ) ; + } + else + { + if ( oLink ) // Modifying an existent link. + oLink.href = sLnkUrl ; + else // Creating a new link. + { + if ( !bHasImage ) + oEditor.FCKSelection.SelectNode( oImage ) ; + + oLink = oEditor.FCK.CreateLink( sLnkUrl )[0] ; + + if ( !bHasImage ) + { + oEditor.FCKSelection.SelectNode( oLink ) ; + oEditor.FCKSelection.Collapse( false ) ; + } + } + + SetAttribute( oLink, '_fcksavedurl', sLnkUrl ) ; + SetAttribute( oLink, 'target', GetE('cmbLnkTarget').value ) ; + } + + return true ; +} + +function UpdateImage( e, skipId ) +{ + e.src = GetE('txtUrl').value ; + SetAttribute( e, "_fcksavedurl", GetE('txtUrl').value ) ; + SetAttribute( e, "alt" , GetE('txtAlt').value ) ; + SetAttribute( e, "width" , GetE('txtWidth').value ) ; + SetAttribute( e, "height", GetE('txtHeight').value ) ; + SetAttribute( e, "vspace", GetE('txtVSpace').value ) ; + SetAttribute( e, "hspace", GetE('txtHSpace').value ) ; + SetAttribute( e, "border", GetE('txtBorder').value ) ; + SetAttribute( e, "align" , GetE('cmbAlign').value ) ; + + // Advances Attributes + + if ( ! skipId ) + SetAttribute( e, 'id', GetE('txtAttId').value ) ; + + SetAttribute( e, 'dir' , GetE('cmbAttLangDir').value ) ; + SetAttribute( e, 'lang' , GetE('txtAttLangCode').value ) ; + SetAttribute( e, 'title' , GetE('txtAttTitle').value ) ; + SetAttribute( e, 'longDesc' , GetE('txtLongDesc').value ) ; + + if ( oEditor.FCKBrowserInfo.IsIE ) + { + e.className = GetE('txtAttClasses').value ; + e.style.cssText = GetE('txtAttStyle').value ; + } + else + { + SetAttribute( e, 'class' , GetE('txtAttClasses').value ) ; + SetAttribute( e, 'style', GetE('txtAttStyle').value ) ; + } +} + +var eImgPreview ; +var eImgPreviewLink ; + +function SetPreviewElements( imageElement, linkElement ) +{ + eImgPreview = imageElement ; + eImgPreviewLink = linkElement ; + + UpdatePreview() ; + UpdateOriginal() ; + + bPreviewInitialized = true ; +} + +function UpdatePreview() +{ + if ( !eImgPreview || !eImgPreviewLink ) + return ; + + if ( GetE('txtUrl').value.length == 0 ) + eImgPreviewLink.style.display = 'none' ; + else + { + UpdateImage( eImgPreview, true ) ; + + if ( GetE('txtLnkUrl').value.Trim().length > 0 ) + eImgPreviewLink.href = 'javascript:void(null);' ; + else + SetAttribute( eImgPreviewLink, 'href', '' ) ; + + eImgPreviewLink.style.display = '' ; + } +} + +var bLockRatio = true ; + +function SwitchLock( lockButton ) +{ + bLockRatio = !bLockRatio ; + lockButton.className = bLockRatio ? 'BtnLocked' : 'BtnUnlocked' ; + lockButton.title = bLockRatio ? 'Lock sizes' : 'Unlock sizes' ; + + if ( bLockRatio ) + { + if ( GetE('txtWidth').value.length > 0 ) + OnSizeChanged( 'Width', GetE('txtWidth').value ) ; + else + OnSizeChanged( 'Height', GetE('txtHeight').value ) ; + } +} + +// Fired when the width or height input texts change +function OnSizeChanged( dimension, value ) +{ + // Verifies if the aspect ration has to be maintained + if ( oImageOriginal && bLockRatio ) + { + var e = dimension == 'Width' ? GetE('txtHeight') : GetE('txtWidth') ; + + if ( value.length == 0 || isNaN( value ) ) + { + e.value = '' ; + return ; + } + + if ( dimension == 'Width' ) + value = value == 0 ? 0 : Math.round( oImageOriginal.height * ( value / oImageOriginal.width ) ) ; + else + value = value == 0 ? 0 : Math.round( oImageOriginal.width * ( value / oImageOriginal.height ) ) ; + + if ( !isNaN( value ) ) + e.value = value ; + } + + UpdatePreview() ; +} + +// Fired when the Reset Size button is clicked +function ResetSizes() +{ + if ( ! oImageOriginal ) return ; + if ( oEditor.FCKBrowserInfo.IsGecko && !oImageOriginal.complete ) + { + setTimeout( ResetSizes, 50 ) ; + return ; + } + + GetE('txtWidth').value = oImageOriginal.width ; + GetE('txtHeight').value = oImageOriginal.height ; + + UpdatePreview() ; +} + +function BrowseServer() +{ + OpenServerBrowser( + 'Image', + FCKConfig.ImageBrowserURL, + FCKConfig.ImageBrowserWindowWidth, + FCKConfig.ImageBrowserWindowHeight ) ; +} + +function LnkBrowseServer() +{ + OpenServerBrowser( + 'Link', + FCKConfig.LinkBrowserURL, + FCKConfig.LinkBrowserWindowWidth, + FCKConfig.LinkBrowserWindowHeight ) ; +} + +function OpenServerBrowser( type, url, width, height ) +{ + sActualBrowser = type ; + OpenFileBrowser( url, width, height ) ; +} + +var sActualBrowser ; + +function SetUrl( url, width, height, alt ) +{ + if ( sActualBrowser == 'Link' ) + { + GetE('txtLnkUrl').value = url ; + UpdatePreview() ; + } + else + { + GetE('txtUrl').value = url ; + GetE('txtWidth').value = width ? width : '' ; + GetE('txtHeight').value = height ? height : '' ; + + if ( alt ) + GetE('txtAlt').value = alt; + + UpdatePreview() ; + UpdateOriginal( true ) ; + } + + dialog.SetSelectedTab( 'Info' ) ; +} + +function OnUploadCompleted( errorNumber, fileUrl, fileName, customMsg ) +{ + switch ( errorNumber ) + { + case 0 : // No errors + alert( 'Your file has been successfully uploaded' ) ; + break ; + case 1 : // Custom error + alert( customMsg ) ; + return ; + case 101 : // Custom warning + alert( customMsg ) ; + break ; + case 201 : + alert( 'A file with the same name is already available. The uploaded file has been renamed to "' + fileName + '"' ) ; + break ; + case 202 : + alert( 'Invalid file type' ) ; + return ; + case 203 : + alert( "Security error. You probably don't have enough permissions to upload. Please check your server." ) ; + return ; + case 500 : + alert( 'The connector is disabled' ) ; + break ; + default : + alert( 'Error on file upload. Error number: ' + errorNumber ) ; + return ; + } + + sActualBrowser = '' ; + SetUrl( fileUrl ) ; + GetE('frmUpload').reset() ; +} + +var oUploadAllowedExtRegex = new RegExp( FCKConfig.ImageUploadAllowedExtensions, 'i' ) ; +var oUploadDeniedExtRegex = new RegExp( FCKConfig.ImageUploadDeniedExtensions, 'i' ) ; + +function CheckUpload() +{ + var sFile = GetE('txtUploadFile').value ; + + if ( sFile.length == 0 ) + { + alert( 'Please select a file to upload' ) ; + return false ; + } + + if ( ( FCKConfig.ImageUploadAllowedExtensions.length > 0 && !oUploadAllowedExtRegex.test( sFile ) ) || + ( FCKConfig.ImageUploadDeniedExtensions.length > 0 && oUploadDeniedExtRegex.test( sFile ) ) ) + { + OnUploadCompleted( 202 ) ; + return false ; + } + + return true ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_image/fck_image_preview.html =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_image/fck_image_preview.html (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_image/fck_image_preview.html 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,72 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<!-- + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Preview page for the Image dialog window. + * + * Curiosity: http://en.wikipedia.org/wiki/Lorem_ipsum +--> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title></title> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <meta name="robots" content="noindex, nofollow" /> + <script src="../common/fck_dialog_common.js" type="text/javascript"></script> + <script type="text/javascript"> + +var FCKTools = window.parent.FCKTools ; +var FCKConfig = window.parent.FCKConfig ; + +// Sets the Skin CSS +document.write( FCKTools.GetStyleHtml( FCKConfig.SkinDialogCSS ) ) ; +document.write( FCKTools.GetStyleHtml( GetCommonDialogCss( '../' ) ) ) ; + +if ( window.parent.FCKConfig.BaseHref.length > 0 ) + document.write( '<base href="' + window.parent.FCKConfig.BaseHref + '">' ) ; + +window.onload = function() +{ + window.parent.SetPreviewElements( + document.getElementById( 'imgPreview' ), + document.getElementById( 'lnkPreview' ) ) ; +} + + </script> +</head> +<body style="color: #000000; background-color: #ffffff"> + <div> + <a id="lnkPreview" onclick="return false;" style="cursor: default"> + <img id="imgPreview" onload="window.parent.UpdateOriginal();" + style="display: none" alt="" /></a>Lorem ipsum dolor sit amet, consectetuer adipiscing + elit. Maecenas feugiat consequat diam. Maecenas metus. Vivamus diam purus, cursus + a, commodo non, facilisis vitae, nulla. Aenean dictum lacinia tortor. Nunc iaculis, + nibh non iaculis aliquam, orci felis euismod neque, sed ornare massa mauris sed + velit. Nulla pretium mi et risus. Fusce mi pede, tempor id, cursus ac, ullamcorper + nec, enim. Sed tortor. Curabitur molestie. Duis velit augue, condimentum at, ultrices + a, luctus ut, orci. Donec pellentesque egestas eros. Integer cursus, augue in cursus + faucibus, eros pede bibendum sem, in tempus tellus justo quis ligula. Etiam eget + tortor. Vestibulum rutrum, est ut placerat elementum, lectus nisl aliquam velit, + tempor aliquam eros nunc nonummy metus. In eros metus, gravida a, gravida sed, lobortis + id, turpis. Ut ultrices, ipsum at venenatis fringilla, sem nulla lacinia tellus, + eget aliquet turpis mauris non enim. Nam turpis. Suspendisse lacinia. Curabitur + ac tortor ut ipsum egestas elementum. Nunc imperdiet gravida mauris. + </div> +</body> +</html> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_link/fck_link.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_link/fck_link.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_link/fck_link.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,736 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Scripts related to the Link dialog window (see fck_link.html). + */ + +var dialog = window.parent ; +var oEditor = dialog.InnerDialogLoaded() ; + +var FCK = oEditor.FCK ; +var FCKLang = oEditor.FCKLang ; +var FCKConfig = oEditor.FCKConfig ; +var FCKRegexLib = oEditor.FCKRegexLib ; +var FCKTools = oEditor.FCKTools ; + +//#### Dialog Tabs + +// Set the dialog tabs. +dialog.AddTab( 'Info', FCKLang.DlgLnkInfoTab ) ; + +if ( !FCKConfig.LinkDlgHideTarget ) + dialog.AddTab( 'Target', FCKLang.DlgLnkTargetTab, true ) ; + +if ( FCKConfig.LinkUpload ) + dialog.AddTab( 'Upload', FCKLang.DlgLnkUpload, true ) ; + +if ( !FCKConfig.LinkDlgHideAdvanced ) + dialog.AddTab( 'Advanced', FCKLang.DlgAdvancedTag ) ; + +// Function called when a dialog tag is selected. +function OnDialogTabChange( tabCode ) +{ + ShowE('divInfo' , ( tabCode == 'Info' ) ) ; + ShowE('divTarget' , ( tabCode == 'Target' ) ) ; + ShowE('divUpload' , ( tabCode == 'Upload' ) ) ; + ShowE('divAttribs' , ( tabCode == 'Advanced' ) ) ; + + dialog.SetAutoSize( true ) ; +} + +//#### Regular Expressions library. +var oRegex = new Object() ; + +oRegex.UriProtocol = /^(((http|https|ftp|news):\/\/)|mailto:)/gi ; + +oRegex.UrlOnChangeProtocol = /^(http|https|ftp|news):\/\/(?=.)/gi ; + +oRegex.UrlOnChangeTestOther = /^((javascript:)|[#\/\.])/gi ; + +oRegex.ReserveTarget = /^_(blank|self|top|parent)$/i ; + +oRegex.PopupUri = /^javascript:void\(\s*window.open\(\s*'([^']+)'\s*,\s*(?:'([^']*)'|null)\s*,\s*'([^']*)'\s*\)\s*\)\s*$/ ; + +// Accessible popups +oRegex.OnClickPopup = /^\s*on[cC]lick="\s*window.open\(\s*this\.href\s*,\s*(?:'([^']*)'|null)\s*,\s*'([^']*)'\s*\)\s*;\s*return\s*false;*\s*"$/ ; + +oRegex.PopupFeatures = /(?:^|,)([^=]+)=(\d+|yes|no)/gi ; + +//#### Parser Functions + +var oParser = new Object() ; + +oParser.ParseEMailUrl = function( emailUrl ) +{ + // Initializes the EMailInfo object. + var oEMailInfo = new Object() ; + oEMailInfo.Address = '' ; + oEMailInfo.Subject = '' ; + oEMailInfo.Body = '' ; + + var oParts = emailUrl.match( /^([^\?]+)\??(.+)?/ ) ; + if ( oParts ) + { + // Set the e-mail address. + oEMailInfo.Address = oParts[1] ; + + // Look for the optional e-mail parameters. + if ( oParts[2] ) + { + var oMatch = oParts[2].match( /(^|&)subject=([^&]+)/i ) ; + if ( oMatch ) oEMailInfo.Subject = decodeURIComponent( oMatch[2] ) ; + + oMatch = oParts[2].match( /(^|&)body=([^&]+)/i ) ; + if ( oMatch ) oEMailInfo.Body = decodeURIComponent( oMatch[2] ) ; + } + } + + return oEMailInfo ; +} + +oParser.CreateEMailUri = function( address, subject, body ) +{ + var sBaseUri = 'mailto:' + address ; + + var sParams = '' ; + + if ( subject.length > 0 ) + sParams = '?subject=' + encodeURIComponent( subject ) ; + + if ( body.length > 0 ) + { + sParams += ( sParams.length == 0 ? '?' : '&' ) ; + sParams += 'body=' + encodeURIComponent( body ) ; + } + + return sBaseUri + sParams ; +} + +//#### Initialization Code + +// oLink: The actual selected link in the editor. +var oLink = dialog.Selection.GetSelection().MoveToAncestorNode( 'A' ) ; +if ( oLink ) + FCK.Selection.SelectNode( oLink ) ; + +window.onload = function() +{ + // Translate the dialog box texts. + oEditor.FCKLanguageManager.TranslatePage(document) ; + + // Fill the Anchor Names and Ids combos. + LoadAnchorNamesAndIds() ; + + // Load the selected link information (if any). + LoadSelection() ; + + // Update the dialog box. + SetLinkType( GetE('cmbLinkType').value ) ; + + // Show/Hide the "Browse Server" button. + GetE('divBrowseServer').style.display = FCKConfig.LinkBrowser ? '' : 'none' ; + + // Show the initial dialog content. + GetE('divInfo').style.display = '' ; + + // Set the actual uploader URL. + if ( FCKConfig.LinkUpload ) + GetE('frmUpload').action = FCKConfig.LinkUploadURL ; + + // Set the default target (from configuration). + SetDefaultTarget() ; + + // Activate the "OK" button. + dialog.SetOkButton( true ) ; + + // Select the first field. + switch( GetE('cmbLinkType').value ) + { + case 'url' : + SelectField( 'txtUrl' ) ; + break ; + case 'email' : + SelectField( 'txtEMailAddress' ) ; + break ; + case 'anchor' : + if ( GetE('divSelAnchor').style.display != 'none' ) + SelectField( 'cmbAnchorName' ) ; + else + SelectField( 'cmbLinkType' ) ; + } +} + +var bHasAnchors ; + +function LoadAnchorNamesAndIds() +{ + // Since version 2.0, the anchors are replaced in the DOM by IMGs so the user see the icon + // to edit them. So, we must look for that images now. + var aAnchors = new Array() ; + var i ; + var oImages = oEditor.FCK.EditorDocument.getElementsByTagName( 'IMG' ) ; + for( i = 0 ; i < oImages.length ; i++ ) + { + if ( oImages[i].getAttribute('_fckanchor') ) + aAnchors[ aAnchors.length ] = oEditor.FCK.GetRealElement( oImages[i] ) ; + } + + // Add also real anchors + var oLinks = oEditor.FCK.EditorDocument.getElementsByTagName( 'A' ) ; + for( i = 0 ; i < oLinks.length ; i++ ) + { + if ( oLinks[i].name && ( oLinks[i].name.length > 0 ) ) + aAnchors[ aAnchors.length ] = oLinks[i] ; + } + + var aIds = FCKTools.GetAllChildrenIds( oEditor.FCK.EditorDocument.body ) ; + + bHasAnchors = ( aAnchors.length > 0 || aIds.length > 0 ) ; + + for ( i = 0 ; i < aAnchors.length ; i++ ) + { + var sName = aAnchors[i].name ; + if ( sName && sName.length > 0 ) + FCKTools.AddSelectOption( GetE('cmbAnchorName'), sName, sName ) ; + } + + for ( i = 0 ; i < aIds.length ; i++ ) + { + FCKTools.AddSelectOption( GetE('cmbAnchorId'), aIds[i], aIds[i] ) ; + } + + ShowE( 'divSelAnchor' , bHasAnchors ) ; + ShowE( 'divNoAnchor' , !bHasAnchors ) ; +} + +function LoadSelection() +{ + if ( !oLink ) return ; + + var sType = 'url' ; + + // Get the actual Link href. + var sHRef = oLink.getAttribute( '_fcksavedurl' ) ; + if ( sHRef == null ) + sHRef = oLink.getAttribute( 'href' , 2 ) || '' ; + + // Look for a popup javascript link. + var oPopupMatch = oRegex.PopupUri.exec( sHRef ) ; + if( oPopupMatch ) + { + GetE('cmbTarget').value = 'popup' ; + sHRef = oPopupMatch[1] ; + FillPopupFields( oPopupMatch[2], oPopupMatch[3] ) ; + SetTarget( 'popup' ) ; + } + + // Accessible popups, the popup data is in the onclick attribute + if ( !oPopupMatch ) + { + var onclick = oLink.getAttribute( 'onclick_fckprotectedatt' ) ; + if ( onclick ) + { + // Decode the protected string + onclick = decodeURIComponent( onclick ) ; + + oPopupMatch = oRegex.OnClickPopup.exec( onclick ) ; + if( oPopupMatch ) + { + GetE( 'cmbTarget' ).value = 'popup' ; + FillPopupFields( oPopupMatch[1], oPopupMatch[2] ) ; + SetTarget( 'popup' ) ; + } + } + } + + // Search for the protocol. + var sProtocol = oRegex.UriProtocol.exec( sHRef ) ; + + if ( sProtocol ) + { + sProtocol = sProtocol[0].toLowerCase() ; + GetE('cmbLinkProtocol').value = sProtocol ; + + // Remove the protocol and get the remaining URL. + var sUrl = sHRef.replace( oRegex.UriProtocol, '' ) ; + + if ( sProtocol == 'mailto:' ) // It is an e-mail link. + { + sType = 'email' ; + + var oEMailInfo = oParser.ParseEMailUrl( sUrl ) ; + GetE('txtEMailAddress').value = oEMailInfo.Address ; + GetE('txtEMailSubject').value = oEMailInfo.Subject ; + GetE('txtEMailBody').value = oEMailInfo.Body ; + } + else // It is a normal link. + { + sType = 'url' ; + GetE('txtUrl').value = sUrl ; + } + } + else if ( sHRef.substr(0,1) == '#' && sHRef.length > 1 ) // It is an anchor link. + { + sType = 'anchor' ; + GetE('cmbAnchorName').value = GetE('cmbAnchorId').value = sHRef.substr(1) ; + } + else // It is another type of link. + { + sType = 'url' ; + + GetE('cmbLinkProtocol').value = '' ; + GetE('txtUrl').value = sHRef ; + } + + if ( !oPopupMatch ) + { + // Get the target. + var sTarget = oLink.target ; + + if ( sTarget && sTarget.length > 0 ) + { + if ( oRegex.ReserveTarget.test( sTarget ) ) + { + sTarget = sTarget.toLowerCase() ; + GetE('cmbTarget').value = sTarget ; + } + else + GetE('cmbTarget').value = 'frame' ; + GetE('txtTargetFrame').value = sTarget ; + } + } + + // Get Advances Attributes + GetE('txtAttId').value = oLink.id ; + GetE('txtAttName').value = oLink.name ; + GetE('cmbAttLangDir').value = oLink.dir ; + GetE('txtAttLangCode').value = oLink.lang ; + GetE('txtAttAccessKey').value = oLink.accessKey ; + GetE('txtAttTabIndex').value = oLink.tabIndex <= 0 ? '' : oLink.tabIndex ; + GetE('txtAttTitle').value = oLink.title ; + GetE('txtAttContentType').value = oLink.type ; + GetE('txtAttCharSet').value = oLink.charset ; + + var sClass ; + if ( oEditor.FCKBrowserInfo.IsIE ) + { + sClass = oLink.getAttribute('className',2) || '' ; + // Clean up temporary classes for internal use: + sClass = sClass.replace( FCKRegexLib.FCK_Class, '' ) ; + + GetE('txtAttStyle').value = oLink.style.cssText ; + } + else + { + sClass = oLink.getAttribute('class',2) || '' ; + GetE('txtAttStyle').value = oLink.getAttribute('style',2) || '' ; + } + GetE('txtAttClasses').value = sClass ; + + // Update the Link type combo. + GetE('cmbLinkType').value = sType ; +} + +//#### Link type selection. +function SetLinkType( linkType ) +{ + ShowE('divLinkTypeUrl' , (linkType == 'url') ) ; + ShowE('divLinkTypeAnchor' , (linkType == 'anchor') ) ; + ShowE('divLinkTypeEMail' , (linkType == 'email') ) ; + + if ( !FCKConfig.LinkDlgHideTarget ) + dialog.SetTabVisibility( 'Target' , (linkType == 'url') ) ; + + if ( FCKConfig.LinkUpload ) + dialog.SetTabVisibility( 'Upload' , (linkType == 'url') ) ; + + if ( !FCKConfig.LinkDlgHideAdvanced ) + dialog.SetTabVisibility( 'Advanced' , (linkType != 'anchor' || bHasAnchors) ) ; + + if ( linkType == 'email' ) + dialog.SetAutoSize( true ) ; +} + +//#### Target type selection. +function SetTarget( targetType ) +{ + GetE('tdTargetFrame').style.display = ( targetType == 'popup' ? 'none' : '' ) ; + GetE('tdPopupName').style.display = + GetE('tablePopupFeatures').style.display = ( targetType == 'popup' ? '' : 'none' ) ; + + switch ( targetType ) + { + case "_blank" : + case "_self" : + case "_parent" : + case "_top" : + GetE('txtTargetFrame').value = targetType ; + break ; + case "" : + GetE('txtTargetFrame').value = '' ; + break ; + } + + if ( targetType == 'popup' ) + dialog.SetAutoSize( true ) ; +} + +//#### Called while the user types the URL. +function OnUrlChange() +{ + var sUrl = GetE('txtUrl').value ; + var sProtocol = oRegex.UrlOnChangeProtocol.exec( sUrl ) ; + + if ( sProtocol ) + { + sUrl = sUrl.substr( sProtocol[0].length ) ; + GetE('txtUrl').value = sUrl ; + GetE('cmbLinkProtocol').value = sProtocol[0].toLowerCase() ; + } + else if ( oRegex.UrlOnChangeTestOther.test( sUrl ) ) + { + GetE('cmbLinkProtocol').value = '' ; + } +} + +//#### Called while the user types the target name. +function OnTargetNameChange() +{ + var sFrame = GetE('txtTargetFrame').value ; + + if ( sFrame.length == 0 ) + GetE('cmbTarget').value = '' ; + else if ( oRegex.ReserveTarget.test( sFrame ) ) + GetE('cmbTarget').value = sFrame.toLowerCase() ; + else + GetE('cmbTarget').value = 'frame' ; +} + +// Accessible popups +function BuildOnClickPopup() +{ + var sWindowName = "'" + GetE('txtPopupName').value.replace(/\W/gi, "") + "'" ; + + var sFeatures = '' ; + var aChkFeatures = document.getElementsByName( 'chkFeature' ) ; + for ( var i = 0 ; i < aChkFeatures.length ; i++ ) + { + if ( i > 0 ) sFeatures += ',' ; + sFeatures += aChkFeatures[i].value + '=' + ( aChkFeatures[i].checked ? 'yes' : 'no' ) ; + } + + if ( GetE('txtPopupWidth').value.length > 0 ) sFeatures += ',width=' + GetE('txtPopupWidth').value ; + if ( GetE('txtPopupHeight').value.length > 0 ) sFeatures += ',height=' + GetE('txtPopupHeight').value ; + if ( GetE('txtPopupLeft').value.length > 0 ) sFeatures += ',left=' + GetE('txtPopupLeft').value ; + if ( GetE('txtPopupTop').value.length > 0 ) sFeatures += ',top=' + GetE('txtPopupTop').value ; + + if ( sFeatures != '' ) + sFeatures = sFeatures + ",status" ; + + return ( "window.open(this.href," + sWindowName + ",'" + sFeatures + "'); return false" ) ; +} + +//#### Fills all Popup related fields. +function FillPopupFields( windowName, features ) +{ + if ( windowName ) + GetE('txtPopupName').value = windowName ; + + var oFeatures = new Object() ; + var oFeaturesMatch ; + while( ( oFeaturesMatch = oRegex.PopupFeatures.exec( features ) ) != null ) + { + var sValue = oFeaturesMatch[2] ; + if ( sValue == ( 'yes' || '1' ) ) + oFeatures[ oFeaturesMatch[1] ] = true ; + else if ( ! isNaN( sValue ) && sValue != 0 ) + oFeatures[ oFeaturesMatch[1] ] = sValue ; + } + + // Update all features check boxes. + var aChkFeatures = document.getElementsByName('chkFeature') ; + for ( var i = 0 ; i < aChkFeatures.length ; i++ ) + { + if ( oFeatures[ aChkFeatures[i].value ] ) + aChkFeatures[i].checked = true ; + } + + // Update position and size text boxes. + if ( oFeatures['width'] ) GetE('txtPopupWidth').value = oFeatures['width'] ; + if ( oFeatures['height'] ) GetE('txtPopupHeight').value = oFeatures['height'] ; + if ( oFeatures['left'] ) GetE('txtPopupLeft').value = oFeatures['left'] ; + if ( oFeatures['top'] ) GetE('txtPopupTop').value = oFeatures['top'] ; +} + +//#### The OK button was hit. +function Ok() +{ + var sUri, sInnerHtml ; + oEditor.FCKUndo.SaveUndoStep() ; + + switch ( GetE('cmbLinkType').value ) + { + case 'url' : + sUri = GetE('txtUrl').value ; + + if ( sUri.length == 0 ) + { + alert( FCKLang.DlnLnkMsgNoUrl ) ; + return false ; + } + + sUri = GetE('cmbLinkProtocol').value + sUri ; + + break ; + + case 'email' : + sUri = GetE('txtEMailAddress').value ; + + if ( sUri.length == 0 ) + { + alert( FCKLang.DlnLnkMsgNoEMail ) ; + return false ; + } + + sUri = oParser.CreateEMailUri( + sUri, + GetE('txtEMailSubject').value, + GetE('txtEMailBody').value ) ; + break ; + + case 'anchor' : + var sAnchor = GetE('cmbAnchorName').value ; + if ( sAnchor.length == 0 ) sAnchor = GetE('cmbAnchorId').value ; + + if ( sAnchor.length == 0 ) + { + alert( FCKLang.DlnLnkMsgNoAnchor ) ; + return false ; + } + + sUri = '#' + sAnchor ; + break ; + } + + // If no link is selected, create a new one (it may result in more than one link creation - #220). + var aLinks = oLink ? [ oLink ] : oEditor.FCK.CreateLink( sUri, true ) ; + + // If no selection, no links are created, so use the uri as the link text (by dom, 2006-05-26) + var aHasSelection = ( aLinks.length > 0 ) ; + if ( !aHasSelection ) + { + sInnerHtml = sUri; + + // Built a better text for empty links. + switch ( GetE('cmbLinkType').value ) + { + // anchor: use old behavior --> return true + case 'anchor': + sInnerHtml = sInnerHtml.replace( /^#/, '' ) ; + break ; + + // url: try to get path + case 'url': + var oLinkPathRegEx = new RegExp("//?([^?\"']+)([?].*)?$") ; + var asLinkPath = oLinkPathRegEx.exec( sUri ) ; + if (asLinkPath != null) + sInnerHtml = asLinkPath[1]; // use matched path + break ; + + // mailto: try to get email address + case 'email': + sInnerHtml = GetE('txtEMailAddress').value ; + break ; + } + + // Create a new (empty) anchor. + aLinks = [ oEditor.FCK.InsertElement( 'a' ) ] ; + } + + for ( var i = 0 ; i < aLinks.length ; i++ ) + { + oLink = aLinks[i] ; + + if ( aHasSelection ) + sInnerHtml = oLink.innerHTML ; // Save the innerHTML (IE changes it if it is like an URL). + + oLink.href = sUri ; + SetAttribute( oLink, '_fcksavedurl', sUri ) ; + + var onclick; + // Accessible popups + if( GetE('cmbTarget').value == 'popup' ) + { + onclick = BuildOnClickPopup() ; + // Encode the attribute + onclick = encodeURIComponent( " onclick=\"" + onclick + "\"" ) ; + SetAttribute( oLink, 'onclick_fckprotectedatt', onclick ) ; + } + else + { + // Check if the previous onclick was for a popup: + // In that case remove the onclick handler. + onclick = oLink.getAttribute( 'onclick_fckprotectedatt' ) ; + if ( onclick ) + { + // Decode the protected string + onclick = decodeURIComponent( onclick ) ; + + if( oRegex.OnClickPopup.test( onclick ) ) + SetAttribute( oLink, 'onclick_fckprotectedatt', '' ) ; + } + } + + oLink.innerHTML = sInnerHtml ; // Set (or restore) the innerHTML + + // Target + if( GetE('cmbTarget').value != 'popup' ) + SetAttribute( oLink, 'target', GetE('txtTargetFrame').value ) ; + else + SetAttribute( oLink, 'target', null ) ; + + // Let's set the "id" only for the first link to avoid duplication. + if ( i == 0 ) + SetAttribute( oLink, 'id', GetE('txtAttId').value ) ; + + // Advances Attributes + SetAttribute( oLink, 'name' , GetE('txtAttName').value ) ; + SetAttribute( oLink, 'dir' , GetE('cmbAttLangDir').value ) ; + SetAttribute( oLink, 'lang' , GetE('txtAttLangCode').value ) ; + SetAttribute( oLink, 'accesskey', GetE('txtAttAccessKey').value ) ; + SetAttribute( oLink, 'tabindex' , ( GetE('txtAttTabIndex').value > 0 ? GetE('txtAttTabIndex').value : null ) ) ; + SetAttribute( oLink, 'title' , GetE('txtAttTitle').value ) ; + SetAttribute( oLink, 'type' , GetE('txtAttContentType').value ) ; + SetAttribute( oLink, 'charset' , GetE('txtAttCharSet').value ) ; + + if ( oEditor.FCKBrowserInfo.IsIE ) + { + var sClass = GetE('txtAttClasses').value ; + // If it's also an anchor add an internal class + if ( GetE('txtAttName').value.length != 0 ) + sClass += ' FCK__AnchorC' ; + SetAttribute( oLink, 'className', sClass ) ; + + oLink.style.cssText = GetE('txtAttStyle').value ; + } + else + { + SetAttribute( oLink, 'class', GetE('txtAttClasses').value ) ; + SetAttribute( oLink, 'style', GetE('txtAttStyle').value ) ; + } + } + + // Select the (first) link. + oEditor.FCKSelection.SelectNode( aLinks[0] ); + + return true ; +} + +function BrowseServer() +{ + OpenFileBrowser( FCKConfig.LinkBrowserURL, FCKConfig.LinkBrowserWindowWidth, FCKConfig.LinkBrowserWindowHeight ) ; +} + +function SetUrl( url ) +{ + document.getElementById('txtUrl').value = url ; + OnUrlChange() ; + dialog.SetSelectedTab( 'Info' ) ; +} + +function OnUploadCompleted( errorNumber, fileUrl, fileName, customMsg ) +{ + switch ( errorNumber ) + { + case 0 : // No errors + alert( 'Your file has been successfully uploaded' ) ; + break ; + case 1 : // Custom error + alert( customMsg ) ; + return ; + case 101 : // Custom warning + alert( customMsg ) ; + break ; + case 201 : + alert( 'A file with the same name is already available. The uploaded file has been renamed to "' + fileName + '"' ) ; + break ; + case 202 : + alert( 'Invalid file type' ) ; + return ; + case 203 : + alert( "Security error. You probably don't have enough permissions to upload. Please check your server." ) ; + return ; + case 500 : + alert( 'The connector is disabled' ) ; + break ; + default : + alert( 'Error on file upload. Error number: ' + errorNumber ) ; + return ; + } + + SetUrl( fileUrl ) ; + GetE('frmUpload').reset() ; +} + +var oUploadAllowedExtRegex = new RegExp( FCKConfig.LinkUploadAllowedExtensions, 'i' ) ; +var oUploadDeniedExtRegex = new RegExp( FCKConfig.LinkUploadDeniedExtensions, 'i' ) ; + +function CheckUpload() +{ + var sFile = GetE('txtUploadFile').value ; + + if ( sFile.length == 0 ) + { + alert( 'Please select a file to upload' ) ; + return false ; + } + + if ( ( FCKConfig.LinkUploadAllowedExtensions.length > 0 && !oUploadAllowedExtRegex.test( sFile ) ) || + ( FCKConfig.LinkUploadDeniedExtensions.length > 0 && oUploadDeniedExtRegex.test( sFile ) ) ) + { + OnUploadCompleted( 202 ) ; + return false ; + } + + return true ; +} + +function SetDefaultTarget() +{ + var target = FCKConfig.DefaultLinkTarget || '' ; + + if ( oLink || target.length == 0 ) + return ; + + switch ( target ) + { + case '_blank' : + case '_self' : + case '_parent' : + case '_top' : + GetE('cmbTarget').value = target ; + break ; + default : + GetE('cmbTarget').value = 'frame' ; + break ; + } + + GetE('txtTargetFrame').value = target ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_select/fck_select.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_select/fck_select.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_select/fck_select.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,194 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Scripts for the fck_select.html page. + */ + +function Select( combo ) +{ + var iIndex = combo.selectedIndex ; + + oListText.selectedIndex = iIndex ; + oListValue.selectedIndex = iIndex ; + + var oTxtText = document.getElementById( "txtText" ) ; + var oTxtValue = document.getElementById( "txtValue" ) ; + + oTxtText.value = oListText.value ; + oTxtValue.value = oListValue.value ; +} + +function Add() +{ + var oTxtText = document.getElementById( "txtText" ) ; + var oTxtValue = document.getElementById( "txtValue" ) ; + + AddComboOption( oListText, oTxtText.value, oTxtText.value ) ; + AddComboOption( oListValue, oTxtValue.value, oTxtValue.value ) ; + + oListText.selectedIndex = oListText.options.length - 1 ; + oListValue.selectedIndex = oListValue.options.length - 1 ; + + oTxtText.value = '' ; + oTxtValue.value = '' ; + + oTxtText.focus() ; +} + +function Modify() +{ + var iIndex = oListText.selectedIndex ; + + if ( iIndex < 0 ) return ; + + var oTxtText = document.getElementById( "txtText" ) ; + var oTxtValue = document.getElementById( "txtValue" ) ; + + oListText.options[ iIndex ].innerHTML = HTMLEncode( oTxtText.value ) ; + oListText.options[ iIndex ].value = oTxtText.value ; + + oListValue.options[ iIndex ].innerHTML = HTMLEncode( oTxtValue.value ) ; + oListValue.options[ iIndex ].value = oTxtValue.value ; + + oTxtText.value = '' ; + oTxtValue.value = '' ; + + oTxtText.focus() ; +} + +function Move( steps ) +{ + ChangeOptionPosition( oListText, steps ) ; + ChangeOptionPosition( oListValue, steps ) ; +} + +function Delete() +{ + RemoveSelectedOptions( oListText ) ; + RemoveSelectedOptions( oListValue ) ; +} + +function SetSelectedValue() +{ + var iIndex = oListValue.selectedIndex ; + if ( iIndex < 0 ) return ; + + var oTxtValue = document.getElementById( "txtSelValue" ) ; + + oTxtValue.value = oListValue.options[ iIndex ].value ; +} + +// Moves the selected option by a number of steps (also negative) +function ChangeOptionPosition( combo, steps ) +{ + var iActualIndex = combo.selectedIndex ; + + if ( iActualIndex < 0 ) + return ; + + var iFinalIndex = iActualIndex + steps ; + + if ( iFinalIndex < 0 ) + iFinalIndex = 0 ; + + if ( iFinalIndex > ( combo.options.length - 1 ) ) + iFinalIndex = combo.options.length - 1 ; + + if ( iActualIndex == iFinalIndex ) + return ; + + var oOption = combo.options[ iActualIndex ] ; + var sText = HTMLDecode( oOption.innerHTML ) ; + var sValue = oOption.value ; + + combo.remove( iActualIndex ) ; + + oOption = AddComboOption( combo, sText, sValue, null, iFinalIndex ) ; + + oOption.selected = true ; +} + +// Remove all selected options from a SELECT object +function RemoveSelectedOptions(combo) +{ + // Save the selected index + var iSelectedIndex = combo.selectedIndex ; + + var oOptions = combo.options ; + + // Remove all selected options + for ( var i = oOptions.length - 1 ; i >= 0 ; i-- ) + { + if (oOptions[i].selected) combo.remove(i) ; + } + + // Reset the selection based on the original selected index + if ( combo.options.length > 0 ) + { + if ( iSelectedIndex >= combo.options.length ) iSelectedIndex = combo.options.length - 1 ; + combo.selectedIndex = iSelectedIndex ; + } +} + +// Add a new option to a SELECT object (combo or list) +function AddComboOption( combo, optionText, optionValue, documentObject, index ) +{ + var oOption ; + + if ( documentObject ) + oOption = documentObject.createElement("OPTION") ; + else + oOption = document.createElement("OPTION") ; + + if ( index != null ) + combo.options.add( oOption, index ) ; + else + combo.options.add( oOption ) ; + + oOption.innerHTML = optionText.length > 0 ? HTMLEncode( optionText ) : ' ' ; + oOption.value = optionValue ; + + return oOption ; +} + +function HTMLEncode( text ) +{ + if ( !text ) + return '' ; + + text = text.replace( /&/g, '&' ) ; + text = text.replace( /</g, '<' ) ; + text = text.replace( />/g, '>' ) ; + + return text ; +} + + +function HTMLDecode( text ) +{ + if ( !text ) + return '' ; + + text = text.replace( />/g, '>' ) ; + text = text.replace( /</g, '<' ) ; + text = text.replace( /&/g, '&' ) ; + + return text ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/blank.html =================================================================== Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/controlWindow.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/controlWindow.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/controlWindow.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,87 @@ +//////////////////////////////////////////////////// +// controlWindow object +//////////////////////////////////////////////////// +function controlWindow( controlForm ) { + // private properties + this._form = controlForm; + + // public properties + this.windowType = "controlWindow"; +// this.noSuggestionSelection = "- No suggestions -"; // by FredCK + this.noSuggestionSelection = FCKLang.DlgSpellNoSuggestions ; + // set up the properties for elements of the given control form + this.suggestionList = this._form.sugg; + this.evaluatedText = this._form.misword; + this.replacementText = this._form.txtsugg; + this.undoButton = this._form.btnUndo; + + // public methods + this.addSuggestion = addSuggestion; + this.clearSuggestions = clearSuggestions; + this.selectDefaultSuggestion = selectDefaultSuggestion; + this.resetForm = resetForm; + this.setSuggestedText = setSuggestedText; + this.enableUndo = enableUndo; + this.disableUndo = disableUndo; +} + +function resetForm() { + if( this._form ) { + this._form.reset(); + } +} + +function setSuggestedText() { + var slct = this.suggestionList; + var txt = this.replacementText; + var str = ""; + if( (slct.options[0].text) && slct.options[0].text != this.noSuggestionSelection ) { + str = slct.options[slct.selectedIndex].text; + } + txt.value = str; +} + +function selectDefaultSuggestion() { + var slct = this.suggestionList; + var txt = this.replacementText; + if( slct.options.length == 0 ) { + this.addSuggestion( this.noSuggestionSelection ); + } else { + slct.options[0].selected = true; + } + this.setSuggestedText(); +} + +function addSuggestion( sugg_text ) { + var slct = this.suggestionList; + if( sugg_text ) { + var i = slct.options.length; + var newOption = new Option( sugg_text, 'sugg_text'+i ); + slct.options[i] = newOption; + } +} + +function clearSuggestions() { + var slct = this.suggestionList; + for( var j = slct.length - 1; j > -1; j-- ) { + if( slct.options[j] ) { + slct.options[j] = null; + } + } +} + +function enableUndo() { + if( this.undoButton ) { + if( this.undoButton.disabled == true ) { + this.undoButton.disabled = false; + } + } +} + +function disableUndo() { + if( this.undoButton ) { + if( this.undoButton.disabled == false ) { + this.undoButton.disabled = true; + } + } +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/controls.html =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/controls.html (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/controls.html 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,153 @@ +<html> + <head> + <link rel="stylesheet" type="text/css" href="spellerStyle.css" /> + <script type="text/javascript" src="controlWindow.js"></script> + <script type="text/javascript"> +var spellerObject; +var controlWindowObj; + +if( parent.opener ) { + spellerObject = parent.opener.speller; +} + +function ignore_word() { + if( spellerObject ) { + spellerObject.ignoreWord(); + } +} + +function ignore_all() { + if( spellerObject ) { + spellerObject.ignoreAll(); + } +} + +function replace_word() { + if( spellerObject ) { + spellerObject.replaceWord(); + } +} + +function replace_all() { + if( spellerObject ) { + spellerObject.replaceAll(); + } +} + +function end_spell() { + if( spellerObject ) { + spellerObject.terminateSpell(); + } +} + +function undo() { + if( spellerObject ) { + spellerObject.undo(); + } +} + +function suggText() { + if( controlWindowObj ) { + controlWindowObj.setSuggestedText(); + } +} + +var FCKLang = window.parent.parent.FCKLang ; // by FredCK + +function init_spell() { + // By FredCK (fckLang attributes have been added to the HTML source of this page) + window.parent.parent.OnSpellerControlsLoad( this ) ; + + var controlForm = document.spellcheck; + + // create a new controlWindow object + controlWindowObj = new controlWindow( controlForm ); + + // call the init_spell() function in the parent frameset + if( parent.frames.length ) { + parent.init_spell( controlWindowObj ); + } else { + alert( 'This page was loaded outside of a frameset. It might not display properly' ); + } +} + +</script> + </head> + <body class="controlWindowBody" onLoad="init_spell();" style="OVERFLOW: hidden" scroll="no"> <!-- by FredCK --> + <form name="spellcheck"> + <table border="0" cellpadding="0" cellspacing="0" border="0" align="center"> + <tr> + <td colspan="3" class="normalLabel"><span fckLang="DlgSpellNotInDic">Not in dictionary:</span></td> + </tr> + <tr> + <td colspan="3"><input class="readonlyInput" type="text" name="misword" readonly /></td> + </tr> + <tr> + <td colspan="3" height="5"></td> + </tr> + <tr> + <td class="normalLabel"><span fckLang="DlgSpellChangeTo">Change to:</span></td> + </tr> + <tr valign="top"> + <td> + <table border="0" cellpadding="0" cellspacing="0" border="0"> + <tr> + <td class="normalLabel"> + <input class="textDefault" type="text" name="txtsugg" /> + </td> + </tr> + <tr> + <td> + <select class="suggSlct" name="sugg" size="7" onChange="suggText();" onDblClick="replace_word();"> + <option></option> + </select> + </td> + </tr> + </table> + </td> + <td> </td> + <td> + <table border="0" cellpadding="0" cellspacing="0" border="0"> + <tr> + <td> + <input class="buttonDefault" type="button" fckLang="DlgSpellBtnIgnore" value="Ignore" onClick="ignore_word();"> + </td> + <td> </td> + <td> + <input class="buttonDefault" type="button" fckLang="DlgSpellBtnIgnoreAll" value="Ignore All" onClick="ignore_all();"> + </td> + </tr> + <tr> + <td colspan="3" height="5"></td> + </tr> + <tr> + <td> + <input class="buttonDefault" type="button" fckLang="DlgSpellBtnReplace" value="Replace" onClick="replace_word();"> + </td> + <td> </td> + <td> + <input class="buttonDefault" type="button" fckLang="DlgSpellBtnReplaceAll" value="Replace All" onClick="replace_all();"> + </td> + </tr> + <tr> + <td colspan="3" height="5"></td> + </tr> + <tr> + <td> + <input class="buttonDefault" type="button" name="btnUndo" fckLang="DlgSpellBtnUndo" value="Undo" onClick="undo();" + disabled> + </td> + <td> </td> + <td> + <!-- by FredCK + <input class="buttonDefault" type="button" value="Close" onClick="end_spell();"> + --> + </td> + </tr> + </table> + </td> + </tr> + </table> + </form> + </body> +</html> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/server-scripts/spellchecker.cfm =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/server-scripts/spellchecker.cfm (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/server-scripts/spellchecker.cfm 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,148 @@ +<cfsetting enablecfoutputonly="true"> +<!--- +This code uses a CF User Defined Function and should work in CF version 5.0 +and up without alteration. + +Also if you are hosting your site at an ISP, you will have to check with them +to see if the use of <CFEXECUTE> is allowed. In most cases ISP will not allow +the use of that tag for security reasons. Clients would be able to access each +others files in certain cases. +---> + +<!--- The following variables values must reflect your installation. ---> +<cfset aspell_dir = "C:\Program Files\Aspell\bin"> +<cfset lang = "en_US"> +<cfset aspell_opts = "-a --lang=#lang# --encoding=utf-8 -H --rem-sgml-check=alt"> +<cfset tempfile_in = GetTempFile(GetTempDirectory(), "spell_")> +<cfset tempfile_out = GetTempFile(GetTempDirectory(), "spell_")> +<cfset spellercss = "../spellerStyle.css"> +<cfset word_win_src = "../wordWindow.js"> + +<cfset form.checktext = form["textinputs[]"]> + +<!--- make no difference between URL and FORM scopes ---> +<cfparam name="url.checktext" default=""> +<cfparam name="form.checktext" default="#url.checktext#"> + +<!--- Takes care of those pesky smart quotes from MS apps, replaces them with regular quotes ---> +<cfset submitted_text = ReplaceList(form.checktext,"%u201C,%u201D","%22,%22")> + +<!--- submitted_text now is ready for processing ---> + +<!--- use carat on each line to escape possible aspell commands ---> +<cfset text = ""> +<cfset CRLF = Chr(13) & Chr(10)> + +<cfloop list="#submitted_text#" index="field" delimiters=","> + <cfset text = text & "%" & CRLF + & "^A" & CRLF + & "!" & CRLF> + <!--- Strip all tags for the text. (by FredCK - #339 / #681) ---> + <cfset field = REReplace(URLDecode(field), "<[^>]+>", " ", "all")> + <cfloop list="#field#" index="line" delimiters="#CRLF#"> + <cfset text = ListAppend(text, "^" & Trim(JSStringFormat(line)), CRLF)> + </cfloop> +</cfloop> + +<!--- create temp file from the submitted text, this will be passed to aspell to be check for misspelled words ---> +<cffile action="write" file="#tempfile_in#" output="#text#" charset="utf-8"> + +<!--- execute aspell in an UTF-8 console and redirect output to a file. UTF-8 encoding is lost if done differently ---> +<cfexecute name="cmd.exe" arguments='/c type "#tempfile_in#" | "#aspell_dir#\aspell.exe" #aspell_opts# > "#tempfile_out#"' timeout="100"/> + +<!--- read output file for further processing ---> +<cffile action="read" file="#tempfile_out#" variable="food" charset="utf-8"> + +<!--- remove temp files ---> +<cffile action="delete" file="#tempfile_in#"> +<cffile action="delete" file="#tempfile_out#"> + +<cfset texts = StructNew()> +<cfset texts.textinputs = ""> +<cfset texts.words = ""> +<cfset texts.abort = ""> + +<!--- Generate Text Inputs ---> +<cfset i = 0> +<cfloop list="#submitted_text#" index="textinput"> + <cfset texts.textinputs = ListAppend(texts.textinputs, 'textinputs[#i#] = decodeURIComponent("#textinput#");', CRLF)> + <cfset i = i + 1> +</cfloop> + +<!--- Generate Words Lists ---> +<cfset word_cnt = 0> +<cfset input_cnt = -1> +<cfloop list="#food#" index="aspell_line" delimiters="#CRLF#"> + <cfset leftChar = Left(aspell_line, 1)> + <cfif leftChar eq "*"> + <cfset input_cnt = input_cnt + 1> + <cfset word_cnt = 0> + <cfset texts.words = ListAppend(texts.words, "words[#input_cnt#] = [];", CRLF)> + <cfset texts.words = ListAppend(texts.words, "suggs[#input_cnt#] = [];", CRLF)> + <cfelse> + <cfif leftChar eq "&" or leftChar eq "##"> + <!--- word that misspelled ---> + <cfset bad_word = Trim(ListGetAt(aspell_line, 2, " "))> + <cfset bad_word = Replace(bad_word, "'", "\'", "ALL")> + <!--- sugestions ---> + <cfset sug_list = Trim(ListRest(aspell_line, ":"))> + <cfset sug_list = ListQualify(Replace(sug_list, "'", "\'", "ALL"), "'")> + <!--- javascript ---> + <cfset texts.words = ListAppend(texts.words, "words[#input_cnt#][#word_cnt#] = '#bad_word#';", CRLF)> + <cfset texts.words = ListAppend(texts.words, "suggs[#input_cnt#][#word_cnt#] = [#sug_list#];", CRLF)> + <cfset word_cnt = word_cnt + 1> + </cfif> + </cfif> +</cfloop> + +<cfif texts.words eq ""> + <cfset texts.abort = "alert('Spell check complete.\n\nNo misspellings found.'); top.window.close();"> +</cfif> + +<cfcontent type="text/html; charset=utf-8"> + +<cfoutput><html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> +<link rel="stylesheet" type="text/css" href="#spellercss#" /> +<script language="javascript" src="#word_win_src#"></script> +<script language="javascript"> +var suggs = new Array(); +var words = new Array(); +var textinputs = new Array(); +var error; + +#texts.textinputs##CRLF# +#texts.words# +#texts.abort# + +var wordWindowObj = new wordWindow(); +wordWindowObj.originalSpellings = words; +wordWindowObj.suggestions = suggs; +wordWindowObj.textInputs = textinputs; + +function init_spell() { + // check if any error occured during server-side processing + if( error ) { + alert( error ); + } else { + // call the init_spell() function in the parent frameset + if (parent.frames.length) { + parent.init_spell( wordWindowObj ); + } else { + alert('This page was loaded outside of a frameset. It might not display properly'); + } + } +} +</script> + +</head> +<body onLoad="init_spell();"> + +<script type="text/javascript"> +wordWindowObj.writeBody(); +</script> + +</body> +</html></cfoutput> +<cfsetting enablecfoutputonly="false"> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/server-scripts/spellchecker.php =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/server-scripts/spellchecker.php (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/server-scripts/spellchecker.php 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,199 @@ +<?php +header('Content-type: text/html; charset=utf-8'); + +// The following variables values must reflect your installation needs. + +$aspell_prog = '"C:\Program Files\Aspell\bin\aspell.exe"'; // by FredCK (for Windows) +//$aspell_prog = 'aspell'; // by FredCK (for Linux) + +$lang = 'en_US'; +$aspell_opts = "-a --lang=$lang --encoding=utf-8 -H --rem-sgml-check=alt"; // by FredCK + +$tempfiledir = "./"; + +$spellercss = '../spellerStyle.css'; // by FredCK +$word_win_src = '../wordWindow.js'; // by FredCK + +$textinputs = $_POST['textinputs']; # array +$input_separator = "A"; + +# set the JavaScript variable to the submitted text. +# textinputs is an array, each element corresponding to the (url-encoded) +# value of the text control submitted for spell-checking +function print_textinputs_var() { + global $textinputs; + foreach( $textinputs as $key=>$val ) { + # $val = str_replace( "'", "%27", $val ); + echo "textinputs[$key] = decodeURIComponent(\"" . $val . "\");\n"; + } +} + +# make declarations for the text input index +function print_textindex_decl( $text_input_idx ) { + echo "words[$text_input_idx] = [];\n"; + echo "suggs[$text_input_idx] = [];\n"; +} + +# set an element of the JavaScript 'words' array to a misspelled word +function print_words_elem( $word, $index, $text_input_idx ) { + echo "words[$text_input_idx][$index] = '" . escape_quote( $word ) . "';\n"; +} + + +# set an element of the JavaScript 'suggs' array to a list of suggestions +function print_suggs_elem( $suggs, $index, $text_input_idx ) { + echo "suggs[$text_input_idx][$index] = ["; + foreach( $suggs as $key=>$val ) { + if( $val ) { + echo "'" . escape_quote( $val ) . "'"; + if ( $key+1 < count( $suggs )) { + echo ", "; + } + } + } + echo "];\n"; +} + +# escape single quote +function escape_quote( $str ) { + return preg_replace ( "/'/", "\\'", $str ); +} + + +# handle a server-side error. +function error_handler( $err ) { + echo "error = '" . preg_replace( "/['\\\\]/", "\\\\$0", $err ) . "';\n"; +} + +## get the list of misspelled words. Put the results in the javascript words array +## for each misspelled word, get suggestions and put in the javascript suggs array +function print_checker_results() { + + global $aspell_prog; + global $aspell_opts; + global $tempfiledir; + global $textinputs; + global $input_separator; + $aspell_err = ""; + # create temp file + $tempfile = tempnam( $tempfiledir, 'aspell_data_' ); + + # open temp file, add the submitted text. + if( $fh = fopen( $tempfile, 'w' )) { + for( $i = 0; $i < count( $textinputs ); $i++ ) { + $text = urldecode( $textinputs[$i] ); + + // Strip all tags for the text. (by FredCK - #339 / #681) + $text = preg_replace( "/<[^>]+>/", " ", $text ) ; + + $lines = explode( "\n", $text ); + fwrite ( $fh, "%\n" ); # exit terse mode + fwrite ( $fh, "^$input_separator\n" ); + fwrite ( $fh, "!\n" ); # enter terse mode + foreach( $lines as $key=>$value ) { + # use carat on each line to escape possible aspell commands + fwrite( $fh, "^$value\n" ); + } + } + fclose( $fh ); + + # exec aspell command - redirect STDERR to STDOUT + $cmd = "$aspell_prog $aspell_opts < $tempfile 2>&1"; + if( $aspellret = shell_exec( $cmd )) { + $linesout = explode( "\n", $aspellret ); + $index = 0; + $text_input_index = -1; + # parse each line of aspell return + foreach( $linesout as $key=>$val ) { + $chardesc = substr( $val, 0, 1 ); + # if '&', then not in dictionary but has suggestions + # if '#', then not in dictionary and no suggestions + # if '*', then it is a delimiter between text inputs + # if '@' then version info + if( $chardesc == '&' || $chardesc == '#' ) { + $line = explode( " ", $val, 5 ); + print_words_elem( $line[1], $index, $text_input_index ); + if( isset( $line[4] )) { + $suggs = explode( ", ", $line[4] ); + } else { + $suggs = array(); + } + print_suggs_elem( $suggs, $index, $text_input_index ); + $index++; + } elseif( $chardesc == '*' ) { + $text_input_index++; + print_textindex_decl( $text_input_index ); + $index = 0; + } elseif( $chardesc != '@' && $chardesc != "" ) { + # assume this is error output + $aspell_err .= $val; + } + } + if( $aspell_err ) { + $aspell_err = "Error executing `$cmd`\\n$aspell_err"; + error_handler( $aspell_err ); + } + } else { + error_handler( "System error: Aspell program execution failed (`$cmd`)" ); + } + } else { + error_handler( "System error: Could not open file '$tempfile' for writing" ); + } + + # close temp file, delete file + unlink( $tempfile ); +} + + +?> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> +<link rel="stylesheet" type="text/css" href="<?php echo $spellercss ?>" /> +<script language="javascript" src="<?php echo $word_win_src ?>"></script> +<script language="javascript"> +var suggs = new Array(); +var words = new Array(); +var textinputs = new Array(); +var error; +<?php + +print_textinputs_var(); + +print_checker_results(); + +?> + +var wordWindowObj = new wordWindow(); +wordWindowObj.originalSpellings = words; +wordWindowObj.suggestions = suggs; +wordWindowObj.textInputs = textinputs; + +function init_spell() { + // check if any error occured during server-side processing + if( error ) { + alert( error ); + } else { + // call the init_spell() function in the parent frameset + if (parent.frames.length) { + parent.init_spell( wordWindowObj ); + } else { + alert('This page was loaded outside of a frameset. It might not display properly'); + } + } +} + + + +</script> + +</head> +<!-- <body onLoad="init_spell();"> by FredCK --> +<body onLoad="init_spell();" bgcolor="#ffffff"> + +<script type="text/javascript"> +wordWindowObj.writeBody(); +</script> + +</body> +</html> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/server-scripts/spellchecker.pl =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/server-scripts/spellchecker.pl (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/server-scripts/spellchecker.pl 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,181 @@ +#!/usr/bin/perl + +use CGI qw/ :standard /; +use File::Temp qw/ tempfile tempdir /; + +# my $spellercss = '/speller/spellerStyle.css'; # by FredCK +my $spellercss = '../spellerStyle.css'; # by FredCK +# my $wordWindowSrc = '/speller/wordWindow.js'; # by FredCK +my $wordWindowSrc = '../wordWindow.js'; # by FredCK +my @textinputs = param( 'textinputs[]' ); # array +# my $aspell_cmd = 'aspell'; # by FredCK (for Linux) +my $aspell_cmd = '"C:\Program Files\Aspell\bin\aspell.exe"'; # by FredCK (for Windows) +my $lang = 'en_US'; +# my $aspell_opts = "-a --lang=$lang --encoding=utf-8"; # by FredCK +my $aspell_opts = "-a --lang=$lang --encoding=utf-8 -H --rem-sgml-check=alt"; # by FredCK +my $input_separator = "A"; + +# set the 'wordtext' JavaScript variable to the submitted text. +sub printTextVar { + for( my $i = 0; $i <= $#textinputs; $i++ ) { + print "textinputs[$i] = decodeURIComponent('" . escapeQuote( $textinputs[$i] ) . "')\n"; + } +} + +sub printTextIdxDecl { + my $idx = shift; + print "words[$idx] = [];\n"; + print "suggs[$idx] = [];\n"; +} + +sub printWordsElem { + my( $textIdx, $wordIdx, $word ) = @_; + print "words[$textIdx][$wordIdx] = '" . escapeQuote( $word ) . "';\n"; +} + +sub printSuggsElem { + my( $textIdx, $wordIdx, @suggs ) = @_; + print "suggs[$textIdx][$wordIdx] = ["; + for my $i ( 0..$#suggs ) { + print "'" . escapeQuote( $suggs[$i] ) . "'"; + if( $i < $#suggs ) { + print ", "; + } + } + print "];\n"; +} + +sub printCheckerResults { + my $textInputIdx = -1; + my $wordIdx = 0; + my $unhandledText; + # create temp file + my $dir = tempdir( CLEANUP => 1 ); + my( $fh, $tmpfilename ) = tempfile( DIR => $dir ); + + # temp file was created properly? + + # open temp file, add the submitted text. + for( my $i = 0; $i <= $#textinputs; $i++ ) { + $text = url_decode( $textinputs[$i] ); + # Strip all tags for the text. (by FredCK - #339 / #681) + $text =~ s/<[^>]+>/ /g; + @lines = split( /\n/, $text ); + print $fh "\%\n"; # exit terse mode + print $fh "^$input_separator\n"; + print $fh "!\n"; # enter terse mode + for my $line ( @lines ) { + # use carat on each line to escape possible aspell commands + print $fh "^$line\n"; + } + + } + # exec aspell command + my $cmd = "$aspell_cmd $aspell_opts < $tmpfilename 2>&1"; + open ASPELL, "$cmd |" or handleError( "Could not execute `$cmd`\\n$!" ) and return; + # parse each line of aspell return + for my $ret ( <ASPELL> ) { + chomp( $ret ); + # if '&', then not in dictionary but has suggestions + # if '#', then not in dictionary and no suggestions + # if '*', then it is a delimiter between text inputs + if( $ret =~ /^\*/ ) { + $textInputIdx++; + printTextIdxDecl( $textInputIdx ); + $wordIdx = 0; + + } elsif( $ret =~ /^(&|#)/ ) { + my @tokens = split( " ", $ret, 5 ); + printWordsElem( $textInputIdx, $wordIdx, $tokens[1] ); + my @suggs = (); + if( $tokens[4] ) { + @suggs = split( ", ", $tokens[4] ); + } + printSuggsElem( $textInputIdx, $wordIdx, @suggs ); + $wordIdx++; + } else { + $unhandledText .= $ret; + } + } + close ASPELL or handleError( "Error executing `$cmd`\\n$unhandledText" ) and return; +} + +sub escapeQuote { + my $str = shift; + $str =~ s/'/\\'/g; + return $str; +} + +sub handleError { + my $err = shift; + print "error = '" . escapeQuote( $err ) . "';\n"; +} + +sub url_decode { + local $_ = @_ ? shift : $_; + defined or return; + # change + signs to spaces + tr/+/ /; + # change hex escapes to the proper characters + s/%([a-fA-F0-9]{2})/pack "H2", $1/eg; + return $_; +} + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# Display HTML +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +print <<EOF; +Content-type: text/html; charset=utf-8 + +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> +<link rel="stylesheet" type="text/css" href="$spellercss"/> +<script src="$wordWindowSrc"></script> +<script type="text/javascript"> +var suggs = new Array(); +var words = new Array(); +var textinputs = new Array(); +var error; +EOF + +printTextVar(); + +printCheckerResults(); + +print <<EOF; +var wordWindowObj = new wordWindow(); +wordWindowObj.originalSpellings = words; +wordWindowObj.suggestions = suggs; +wordWindowObj.textInputs = textinputs; + + +function init_spell() { + // check if any error occured during server-side processing + if( error ) { + alert( error ); + } else { + // call the init_spell() function in the parent frameset + if (parent.frames.length) { + parent.init_spell( wordWindowObj ); + } else { + error = "This page was loaded outside of a frameset. "; + error += "It might not display properly"; + alert( error ); + } + } +} + +</script> + +</head> +<body onLoad="init_spell();"> + +<script type="text/javascript"> +wordWindowObj.writeBody(); +</script> + +</body> +</html> +EOF Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/spellChecker.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/spellChecker.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/spellChecker.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,461 @@ +//////////////////////////////////////////////////// +// spellChecker.js +// +// spellChecker object +// +// This file is sourced on web pages that have a textarea object to evaluate +// for spelling. It includes the implementation for the spellCheckObject. +// +//////////////////////////////////////////////////// + + +// constructor +function spellChecker( textObject ) { + + // public properties - configurable +// this.popUpUrl = '/speller/spellchecker.html'; // by FredCK + this.popUpUrl = 'fck_spellerpages/spellerpages/spellchecker.html'; // by FredCK + this.popUpName = 'spellchecker'; +// this.popUpProps = "menu=no,width=440,height=350,top=70,left=120,resizable=yes,status=yes"; // by FredCK + this.popUpProps = null ; // by FredCK +// this.spellCheckScript = '/speller/server-scripts/spellchecker.php'; // by FredCK + //this.spellCheckScript = '/cgi-bin/spellchecker.pl'; + + // values used to keep track of what happened to a word + this.replWordFlag = "R"; // single replace + this.ignrWordFlag = "I"; // single ignore + this.replAllFlag = "RA"; // replace all occurances + this.ignrAllFlag = "IA"; // ignore all occurances + this.fromReplAll = "~RA"; // an occurance of a "replace all" word + this.fromIgnrAll = "~IA"; // an occurance of a "ignore all" word + // properties set at run time + this.wordFlags = new Array(); + this.currentTextIndex = 0; + this.currentWordIndex = 0; + this.spellCheckerWin = null; + this.controlWin = null; + this.wordWin = null; + this.textArea = textObject; // deprecated + this.textInputs = arguments; + + // private methods + this._spellcheck = _spellcheck; + this._getSuggestions = _getSuggestions; + this._setAsIgnored = _setAsIgnored; + this._getTotalReplaced = _getTotalReplaced; + this._setWordText = _setWordText; + this._getFormInputs = _getFormInputs; + + // public methods + this.openChecker = openChecker; + this.startCheck = startCheck; + this.checkTextBoxes = checkTextBoxes; + this.checkTextAreas = checkTextAreas; + this.spellCheckAll = spellCheckAll; + this.ignoreWord = ignoreWord; + this.ignoreAll = ignoreAll; + this.replaceWord = replaceWord; + this.replaceAll = replaceAll; + this.terminateSpell = terminateSpell; + this.undo = undo; + + // set the current window's "speller" property to the instance of this class. + // this object can now be referenced by child windows/frames. + window.speller = this; +} + +// call this method to check all text boxes (and only text boxes) in the HTML document +function checkTextBoxes() { + this.textInputs = this._getFormInputs( "^text$" ); + this.openChecker(); +} + +// call this method to check all textareas (and only textareas ) in the HTML document +function checkTextAreas() { + this.textInputs = this._getFormInputs( "^textarea$" ); + this.openChecker(); +} + +// call this method to check all text boxes and textareas in the HTML document +function spellCheckAll() { + this.textInputs = this._getFormInputs( "^text(area)?$" ); + this.openChecker(); +} + +// call this method to check text boxe(s) and/or textarea(s) that were passed in to the +// object's constructor or to the textInputs property +function openChecker() { + this.spellCheckerWin = window.open( this.popUpUrl, this.popUpName, this.popUpProps ); + if( !this.spellCheckerWin.opener ) { + this.spellCheckerWin.opener = window; + } +} + +function startCheck( wordWindowObj, controlWindowObj ) { + + // set properties from args + this.wordWin = wordWindowObj; + this.controlWin = controlWindowObj; + + // reset properties + this.wordWin.resetForm(); + this.controlWin.resetForm(); + this.currentTextIndex = 0; + this.currentWordIndex = 0; + // initialize the flags to an array - one element for each text input + this.wordFlags = new Array( this.wordWin.textInputs.length ); + // each element will be an array that keeps track of each word in the text + for( var i=0; i<this.wordFlags.length; i++ ) { + this.wordFlags[i] = []; + } + + // start + this._spellcheck(); + + return true; +} + +function ignoreWord() { + var wi = this.currentWordIndex; + var ti = this.currentTextIndex; + if( !this.wordWin ) { + alert( 'Error: Word frame not available.' ); + return false; + } + if( !this.wordWin.getTextVal( ti, wi )) { + alert( 'Error: "Not in dictionary" text is missing.' ); + return false; + } + // set as ignored + if( this._setAsIgnored( ti, wi, this.ignrWordFlag )) { + this.currentWordIndex++; + this._spellcheck(); + } + return true; +} + +function ignoreAll() { + var wi = this.currentWordIndex; + var ti = this.currentTextIndex; + if( !this.wordWin ) { + alert( 'Error: Word frame not available.' ); + return false; + } + // get the word that is currently being evaluated. + var s_word_to_repl = this.wordWin.getTextVal( ti, wi ); + if( !s_word_to_repl ) { + alert( 'Error: "Not in dictionary" text is missing' ); + return false; + } + + // set this word as an "ignore all" word. + this._setAsIgnored( ti, wi, this.ignrAllFlag ); + + // loop through all the words after this word + for( var i = ti; i < this.wordWin.textInputs.length; i++ ) { + for( var j = 0; j < this.wordWin.totalWords( i ); j++ ) { + if(( i == ti && j > wi ) || i > ti ) { + // future word: set as "from ignore all" if + // 1) do not already have a flag and + // 2) have the same value as current word + if(( this.wordWin.getTextVal( i, j ) == s_word_to_repl ) + && ( !this.wordFlags[i][j] )) { + this._setAsIgnored( i, j, this.fromIgnrAll ); + } + } + } + } + + // finally, move on + this.currentWordIndex++; + this._spellcheck(); + return true; +} + +function replaceWord() { + var wi = this.currentWordIndex; + var ti = this.currentTextIndex; + if( !this.wordWin ) { + alert( 'Error: Word frame not available.' ); + return false; + } + if( !this.wordWin.getTextVal( ti, wi )) { + alert( 'Error: "Not in dictionary" text is missing' ); + return false; + } + if( !this.controlWin.replacementText ) { + return false ; + } + var txt = this.controlWin.replacementText; + if( txt.value ) { + var newspell = new String( txt.value ); + if( this._setWordText( ti, wi, newspell, this.replWordFlag )) { + this.currentWordIndex++; + this._spellcheck(); + } + } + return true; +} + +function replaceAll() { + var ti = this.currentTextIndex; + var wi = this.currentWordIndex; + if( !this.wordWin ) { + alert( 'Error: Word frame not available.' ); + return false; + } + var s_word_to_repl = this.wordWin.getTextVal( ti, wi ); + if( !s_word_to_repl ) { + alert( 'Error: "Not in dictionary" text is missing' ); + return false; + } + var txt = this.controlWin.replacementText; + if( !txt.value ) return false; + var newspell = new String( txt.value ); + + // set this word as a "replace all" word. + this._setWordText( ti, wi, newspell, this.replAllFlag ); + + // loop through all the words after this word + for( var i = ti; i < this.wordWin.textInputs.length; i++ ) { + for( var j = 0; j < this.wordWin.totalWords( i ); j++ ) { + if(( i == ti && j > wi ) || i > ti ) { + // future word: set word text to s_word_to_repl if + // 1) do not already have a flag and + // 2) have the same value as s_word_to_repl + if(( this.wordWin.getTextVal( i, j ) == s_word_to_repl ) + && ( !this.wordFlags[i][j] )) { + this._setWordText( i, j, newspell, this.fromReplAll ); + } + } + } + } + + // finally, move on + this.currentWordIndex++; + this._spellcheck(); + return true; +} + +function terminateSpell() { + // called when we have reached the end of the spell checking. + var msg = ""; // by FredCK + var numrepl = this._getTotalReplaced(); + if( numrepl == 0 ) { + // see if there were no misspellings to begin with + if( !this.wordWin ) { + msg = ""; + } else { + if( this.wordWin.totalMisspellings() ) { +// msg += "No words changed."; // by FredCK + msg += FCKLang.DlgSpellNoChanges ; // by FredCK + } else { +// msg += "No misspellings found."; // by FredCK + msg += FCKLang.DlgSpellNoMispell ; // by FredCK + } + } + } else if( numrepl == 1 ) { +// msg += "One word changed."; // by FredCK + msg += FCKLang.DlgSpellOneChange ; // by FredCK + } else { +// msg += numrepl + " words changed."; // by FredCK + msg += FCKLang.DlgSpellManyChanges.replace( /%1/g, numrepl ) ; + } + if( msg ) { +// msg += "\n"; // by FredCK + alert( msg ); + } + + if( numrepl > 0 ) { + // update the text field(s) on the opener window + for( var i = 0; i < this.textInputs.length; i++ ) { + // this.textArea.value = this.wordWin.text; + if( this.wordWin ) { + if( this.wordWin.textInputs[i] ) { + this.textInputs[i].value = this.wordWin.textInputs[i]; + } + } + } + } + + // return back to the calling window +// this.spellCheckerWin.close(); // by FredCK + if ( typeof( this.OnFinished ) == 'function' ) // by FredCK + this.OnFinished(numrepl) ; // by FredCK + + return true; +} + +function undo() { + // skip if this is the first word! + var ti = this.currentTextIndex; + var wi = this.currentWordIndex; + + if( this.wordWin.totalPreviousWords( ti, wi ) > 0 ) { + this.wordWin.removeFocus( ti, wi ); + + // go back to the last word index that was acted upon + do { + // if the current word index is zero then reset the seed + if( this.currentWordIndex == 0 && this.currentTextIndex > 0 ) { + this.currentTextIndex--; + this.currentWordIndex = this.wordWin.totalWords( this.currentTextIndex )-1; + if( this.currentWordIndex < 0 ) this.currentWordIndex = 0; + } else { + if( this.currentWordIndex > 0 ) { + this.currentWordIndex--; + } + } + } while ( + this.wordWin.totalWords( this.currentTextIndex ) == 0 + || this.wordFlags[this.currentTextIndex][this.currentWordIndex] == this.fromIgnrAll + || this.wordFlags[this.currentTextIndex][this.currentWordIndex] == this.fromReplAll + ); + + var text_idx = this.currentTextIndex; + var idx = this.currentWordIndex; + var preReplSpell = this.wordWin.originalSpellings[text_idx][idx]; + + // if we got back to the first word then set the Undo button back to disabled + if( this.wordWin.totalPreviousWords( text_idx, idx ) == 0 ) { + this.controlWin.disableUndo(); + } + + var i, j, origSpell ; + // examine what happened to this current word. + switch( this.wordFlags[text_idx][idx] ) { + // replace all: go through this and all the future occurances of the word + // and revert them all to the original spelling and clear their flags + case this.replAllFlag : + for( i = text_idx; i < this.wordWin.textInputs.length; i++ ) { + for( j = 0; j < this.wordWin.totalWords( i ); j++ ) { + if(( i == text_idx && j >= idx ) || i > text_idx ) { + origSpell = this.wordWin.originalSpellings[i][j]; + if( origSpell == preReplSpell ) { + this._setWordText ( i, j, origSpell, undefined ); + } + } + } + } + break; + + // ignore all: go through all the future occurances of the word + // and clear their flags + case this.ignrAllFlag : + for( i = text_idx; i < this.wordWin.textInputs.length; i++ ) { + for( j = 0; j < this.wordWin.totalWords( i ); j++ ) { + if(( i == text_idx && j >= idx ) || i > text_idx ) { + origSpell = this.wordWin.originalSpellings[i][j]; + if( origSpell == preReplSpell ) { + this.wordFlags[i][j] = undefined; + } + } + } + } + break; + + // replace: revert the word to its original spelling + case this.replWordFlag : + this._setWordText ( text_idx, idx, preReplSpell, undefined ); + break; + } + + // For all four cases, clear the wordFlag of this word. re-start the process + this.wordFlags[text_idx][idx] = undefined; + this._spellcheck(); + } +} + +function _spellcheck() { + var ww = this.wordWin; + + // check if this is the last word in the current text element + if( this.currentWordIndex == ww.totalWords( this.currentTextIndex) ) { + this.currentTextIndex++; + this.currentWordIndex = 0; + // keep going if we're not yet past the last text element + if( this.currentTextIndex < this.wordWin.textInputs.length ) { + this._spellcheck(); + return; + } else { + this.terminateSpell(); + return; + } + } + + // if this is after the first one make sure the Undo button is enabled + if( this.currentWordIndex > 0 ) { + this.controlWin.enableUndo(); + } + + // skip the current word if it has already been worked on + if( this.wordFlags[this.currentTextIndex][this.currentWordIndex] ) { + // increment the global current word index and move on. + this.currentWordIndex++; + this._spellcheck(); + } else { + var evalText = ww.getTextVal( this.currentTextIndex, this.currentWordIndex ); + if( evalText ) { + this.controlWin.evaluatedText.value = evalText; + ww.setFocus( this.currentTextIndex, this.currentWordIndex ); + this._getSuggestions( this.currentTextIndex, this.currentWordIndex ); + } + } +} + +function _getSuggestions( text_num, word_num ) { + this.controlWin.clearSuggestions(); + // add suggestion in list for each suggested word. + // get the array of suggested words out of the + // three-dimensional array containing all suggestions. + var a_suggests = this.wordWin.suggestions[text_num][word_num]; + if( a_suggests ) { + // got an array of suggestions. + for( var ii = 0; ii < a_suggests.length; ii++ ) { + this.controlWin.addSuggestion( a_suggests[ii] ); + } + } + this.controlWin.selectDefaultSuggestion(); +} + +function _setAsIgnored( text_num, word_num, flag ) { + // set the UI + this.wordWin.removeFocus( text_num, word_num ); + // do the bookkeeping + this.wordFlags[text_num][word_num] = flag; + return true; +} + +function _getTotalReplaced() { + var i_replaced = 0; + for( var i = 0; i < this.wordFlags.length; i++ ) { + for( var j = 0; j < this.wordFlags[i].length; j++ ) { + if(( this.wordFlags[i][j] == this.replWordFlag ) + || ( this.wordFlags[i][j] == this.replAllFlag ) + || ( this.wordFlags[i][j] == this.fromReplAll )) { + i_replaced++; + } + } + } + return i_replaced; +} + +function _setWordText( text_num, word_num, newText, flag ) { + // set the UI and form inputs + this.wordWin.setText( text_num, word_num, newText ); + // keep track of what happened to this word: + this.wordFlags[text_num][word_num] = flag; + return true; +} + +function _getFormInputs( inputPattern ) { + var inputs = new Array(); + for( var i = 0; i < document.forms.length; i++ ) { + for( var j = 0; j < document.forms[i].elements.length; j++ ) { + if( document.forms[i].elements[j].type.match( inputPattern )) { + inputs[inputs.length] = document.forms[i].elements[j]; + } + } + } + return inputs; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/spellchecker.html =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/spellchecker.html (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/spellchecker.html 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,71 @@ + +<script> + +var wordWindow = null; +var controlWindow = null; + +function init_spell( spellerWindow ) { + + if( spellerWindow ) { + if( spellerWindow.windowType == "wordWindow" ) { + wordWindow = spellerWindow; + } else if ( spellerWindow.windowType == "controlWindow" ) { + controlWindow = spellerWindow; + } + } + + if( controlWindow && wordWindow ) { + // populate the speller object and start it off! + var speller = opener.speller; + wordWindow.speller = speller; + speller.startCheck( wordWindow, controlWindow ); + } +} + +// encodeForPost +function encodeForPost( str ) { + var s = new String( str ); + s = encodeURIComponent( s ); + // additionally encode single quotes to evade any PHP + // magic_quotes_gpc setting (it inserts escape characters and + // therefore skews the btye positions of misspelled words) + return s.replace( /\'/g, '%27' ); +} + +// post the text area data to the script that populates the speller +function postWords() { + var bodyDoc = window.frames[0].document; + bodyDoc.open(); + bodyDoc.write('<html>'); + bodyDoc.write('<meta http-equiv="Content-Type" content="text/html; charset=utf-8">'); + bodyDoc.write('<link rel="stylesheet" type="text/css" href="spellerStyle.css"/>'); + if (opener) { + var speller = opener.speller; + bodyDoc.write('<body class="normalText" onLoad="document.forms[0].submit();">'); + bodyDoc.write('<p>' + window.parent.FCKLang.DlgSpellProgress + '<\/p>'); // by FredCK + bodyDoc.write('<form action="'+speller.spellCheckScript+'" method="post">'); + for( var i = 0; i < speller.textInputs.length; i++ ) { + bodyDoc.write('<input type="hidden" name="textinputs[]" value="'+encodeForPost(speller.textInputs[i].value)+'">'); + } + bodyDoc.write('<\/form>'); + bodyDoc.write('<\/body>'); + } else { + bodyDoc.write('<body class="normalText">'); + bodyDoc.write('<p><b>This page cannot be displayed<\/b><\/p><p>The window was not opened from another window.<\/p>'); + bodyDoc.write('<\/body>'); + } + bodyDoc.write('<\/html>'); + bodyDoc.close(); +} +</script> + +<html> +<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> +<head> +<title>Speller Pages</title> +</head> +<frameset rows="*,201" onLoad="postWords();"> +<frame src="blank.html"> +<frame src="controls.html"> +</frameset> +</html> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/spellerStyle.css =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/spellerStyle.css (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/spellerStyle.css 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,49 @@ +.blend { + font-family: courier new; + font-size: 10pt; + border: 0; + margin-bottom:-1; +} +.normalLabel { + font-size:8pt; +} +.normalText { + font-family:arial, helvetica, sans-serif; + font-size:10pt; + color:000000; + background-color:FFFFFF; +} +.plainText { + font-family: courier new, courier, monospace; + font-size: 10pt; + color:000000; + background-color:FFFFFF; +} +.controlWindowBody { + font-family:arial, helvetica, sans-serif; + font-size:8pt; + padding: 7px ; /* by FredCK */ + margin: 0px ; /* by FredCK */ + /* color:000000; by FredCK */ + /* background-color:DADADA; by FredCK */ +} +.readonlyInput { + background-color:DADADA; + color:000000; + font-size:8pt; + width:392px; +} +.textDefault { + font-size:8pt; + width: 200px; +} +.buttonDefault { + width:90px; + height:22px; + font-size:8pt; +} +.suggSlct { + width:200px; + margin-top:2; + font-size:8pt; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/wordWindow.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/wordWindow.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_spellerpages/spellerpages/wordWindow.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,272 @@ +//////////////////////////////////////////////////// +// wordWindow object +//////////////////////////////////////////////////// +function wordWindow() { + // private properties + this._forms = []; + + // private methods + this._getWordObject = _getWordObject; + //this._getSpellerObject = _getSpellerObject; + this._wordInputStr = _wordInputStr; + this._adjustIndexes = _adjustIndexes; + this._isWordChar = _isWordChar; + this._lastPos = _lastPos; + + // public properties + this.wordChar = /[a-zA-Z]/; + this.windowType = "wordWindow"; + this.originalSpellings = new Array(); + this.suggestions = new Array(); + this.checkWordBgColor = "pink"; + this.normWordBgColor = "white"; + this.text = ""; + this.textInputs = new Array(); + this.indexes = new Array(); + //this.speller = this._getSpellerObject(); + + // public methods + this.resetForm = resetForm; + this.totalMisspellings = totalMisspellings; + this.totalWords = totalWords; + this.totalPreviousWords = totalPreviousWords; + //this.getTextObjectArray = getTextObjectArray; + this.getTextVal = getTextVal; + this.setFocus = setFocus; + this.removeFocus = removeFocus; + this.setText = setText; + //this.getTotalWords = getTotalWords; + this.writeBody = writeBody; + this.printForHtml = printForHtml; +} + +function resetForm() { + if( this._forms ) { + for( var i = 0; i < this._forms.length; i++ ) { + this._forms[i].reset(); + } + } + return true; +} + +function totalMisspellings() { + var total_words = 0; + for( var i = 0; i < this.textInputs.length; i++ ) { + total_words += this.totalWords( i ); + } + return total_words; +} + +function totalWords( textIndex ) { + return this.originalSpellings[textIndex].length; +} + +function totalPreviousWords( textIndex, wordIndex ) { + var total_words = 0; + for( var i = 0; i <= textIndex; i++ ) { + for( var j = 0; j < this.totalWords( i ); j++ ) { + if( i == textIndex && j == wordIndex ) { + break; + } else { + total_words++; + } + } + } + return total_words; +} + +//function getTextObjectArray() { +// return this._form.elements; +//} + +function getTextVal( textIndex, wordIndex ) { + var word = this._getWordObject( textIndex, wordIndex ); + if( word ) { + return word.value; + } +} + +function setFocus( textIndex, wordIndex ) { + var word = this._getWordObject( textIndex, wordIndex ); + if( word ) { + if( word.type == "text" ) { + word.focus(); + word.style.backgroundColor = this.checkWordBgColor; + } + } +} + +function removeFocus( textIndex, wordIndex ) { + var word = this._getWordObject( textIndex, wordIndex ); + if( word ) { + if( word.type == "text" ) { + word.blur(); + word.style.backgroundColor = this.normWordBgColor; + } + } +} + +function setText( textIndex, wordIndex, newText ) { + var word = this._getWordObject( textIndex, wordIndex ); + var beginStr; + var endStr; + if( word ) { + var pos = this.indexes[textIndex][wordIndex]; + var oldText = word.value; + // update the text given the index of the string + beginStr = this.textInputs[textIndex].substring( 0, pos ); + endStr = this.textInputs[textIndex].substring( + pos + oldText.length, + this.textInputs[textIndex].length + ); + this.textInputs[textIndex] = beginStr + newText + endStr; + + // adjust the indexes on the stack given the differences in + // length between the new word and old word. + var lengthDiff = newText.length - oldText.length; + this._adjustIndexes( textIndex, wordIndex, lengthDiff ); + + word.size = newText.length; + word.value = newText; + this.removeFocus( textIndex, wordIndex ); + } +} + + +function writeBody() { + var d = window.document; + var is_html = false; + + d.open(); + + // iterate through each text input. + for( var txtid = 0; txtid < this.textInputs.length; txtid++ ) { + var end_idx = 0; + var begin_idx = 0; + d.writeln( '<form name="textInput'+txtid+'">' ); + var wordtxt = this.textInputs[txtid]; + this.indexes[txtid] = []; + + if( wordtxt ) { + var orig = this.originalSpellings[txtid]; + if( !orig ) break; + + //!!! plain text, or HTML mode? + d.writeln( '<div class="plainText">' ); + // iterate through each occurrence of a misspelled word. + for( var i = 0; i < orig.length; i++ ) { + // find the position of the current misspelled word, + // starting at the last misspelled word. + // and keep looking if it's a substring of another word + do { + begin_idx = wordtxt.indexOf( orig[i], end_idx ); + end_idx = begin_idx + orig[i].length; + // word not found? messed up! + if( begin_idx == -1 ) break; + // look at the characters immediately before and after + // the word. If they are word characters we'll keep looking. + var before_char = wordtxt.charAt( begin_idx - 1 ); + var after_char = wordtxt.charAt( end_idx ); + } while ( + this._isWordChar( before_char ) + || this._isWordChar( after_char ) + ); + + // keep track of its position in the original text. + this.indexes[txtid][i] = begin_idx; + + // write out the characters before the current misspelled word + for( var j = this._lastPos( txtid, i ); j < begin_idx; j++ ) { + // !!! html mode? make it html compatible + d.write( this.printForHtml( wordtxt.charAt( j ))); + } + + // write out the misspelled word. + d.write( this._wordInputStr( orig[i] )); + + // if it's the last word, write out the rest of the text + if( i == orig.length-1 ){ + d.write( printForHtml( wordtxt.substr( end_idx ))); + } + } + + d.writeln( '</div>' ); + + } + d.writeln( '</form>' ); + } + //for ( var j = 0; j < d.forms.length; j++ ) { + // alert( d.forms[j].name ); + // for( var k = 0; k < d.forms[j].elements.length; k++ ) { + // alert( d.forms[j].elements[k].name + ": " + d.forms[j].elements[k].value ); + // } + //} + + // set the _forms property + this._forms = d.forms; + d.close(); +} + +// return the character index in the full text after the last word we evaluated +function _lastPos( txtid, idx ) { + if( idx > 0 ) + return this.indexes[txtid][idx-1] + this.originalSpellings[txtid][idx-1].length; + else + return 0; +} + +function printForHtml( n ) { + return n ; // by FredCK +/* + var htmlstr = n; + if( htmlstr.length == 1 ) { + // do simple case statement if it's just one character + switch ( n ) { + case "\n": + htmlstr = '<br/>'; + break; + case "<": + htmlstr = '<'; + break; + case ">": + htmlstr = '>'; + break; + } + return htmlstr; + } else { + htmlstr = htmlstr.replace( /</g, '<' ); + htmlstr = htmlstr.replace( />/g, '>' ); + htmlstr = htmlstr.replace( /\n/g, '<br/>' ); + return htmlstr; + } +*/ +} + +function _isWordChar( letter ) { + if( letter.search( this.wordChar ) == -1 ) { + return false; + } else { + return true; + } +} + +function _getWordObject( textIndex, wordIndex ) { + if( this._forms[textIndex] ) { + if( this._forms[textIndex].elements[wordIndex] ) { + return this._forms[textIndex].elements[wordIndex]; + } + } + return null; +} + +function _wordInputStr( word ) { + var str = '<input readonly '; + str += 'class="blend" type="text" value="' + word + '" size="' + word.length + '">'; + return str; +} + +function _adjustIndexes( textIndex, wordIndex, lengthDiff ) { + for( var i = wordIndex + 1; i < this.originalSpellings[textIndex].length; i++ ) { + this.indexes[textIndex][i] = this.indexes[textIndex][i] + lengthDiff; + } +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_template/images/template1.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_template/images/template1.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_template/images/template2.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_template/images/template2.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_template/images/template3.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/dialog/fck_template/images/template3.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/browser.css =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/browser.css (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/browser.css 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,89 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * CSS styles used by all pages that compose the File Browser. + */ + +body +{ + background-color: #f1f1e3; +} + +form +{ + margin: 0px 0px 0px 0px ; + padding: 0px 0px 0px 0px ; +} + +.Frame +{ + background-color: #f1f1e3; + border-color: #f1f1e3; + border-right: thin inset; + border-top: thin inset; + border-left: thin inset; + border-bottom: thin inset; +} + +body.FileArea +{ + + background-color: #ffffff; + margin: 10px; +} + +body, td, input, select +{ + font-size: 11px; + font-family: 'Microsoft Sans Serif' , Arial, Helvetica, Verdana; +} + +.ActualFolder +{ + font-weight: bold; + font-size: 14px; +} + +.PopupButtons +{ + border-top: #d5d59d 1px solid; + background-color: #e3e3c7; + padding: 7px 10px 7px 10px; +} + +.Button, button +{ + border-right: #737357 1px solid; + border-top: #737357 1px solid; + border-left: #737357 1px solid; + color: #3b3b1f; + border-bottom: #737357 1px solid; + background-color: #c7c78f; +} + +.FolderListCurrentFolder img +{ + background-image: url(images/FolderOpened.gif); +} + +.FolderListFolder img +{ + background-image: url(images/Folder.gif); +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/browser.html =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/browser.html (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/browser.html 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,198 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<!-- + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * This page compose the File Browser dialog frameset. +--> +<html> + <head> + <title>FCKeditor - Resources Browser</title> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + <link href="browser.css" type="text/css" rel="stylesheet"> + <script type="text/javascript" src="js/fckxml.js"></script> + <script language="javascript"> +// Automatically detect the correct document.domain (#1919). +(function() +{ + var d = document.domain ; + + while ( true ) + { + // Test if we can access a parent property. + try + { + var test = window.opener.document.domain ; + break ; + } + catch( e ) {} + + // Remove a domain part: www.mytest.example.com => mytest.example.com => example.com ... + d = d.replace( /.*?(?:\.|$)/, '' ) ; + + if ( d.length == 0 ) + break ; // It was not able to detect the domain. + + try + { + document.domain = d ; + } + catch (e) + { + break ; + } + } +})() ; + +function GetUrlParam( paramName ) +{ + var oRegex = new RegExp( '[\?&]' + paramName + '=([^&]+)', 'i' ) ; + var oMatch = oRegex.exec( window.top.location.search ) ; + + if ( oMatch && oMatch.length > 1 ) + return decodeURIComponent( oMatch[1] ) ; + else + return '' ; +} + +var oConnector = new Object() ; +oConnector.CurrentFolder = '/' ; + +var sConnUrl = GetUrlParam( 'Connector' ) ; + +// Gecko has some problems when using relative URLs (not starting with slash). +if ( sConnUrl.substr(0,1) != '/' && sConnUrl.indexOf( '://' ) < 0 ) + sConnUrl = window.location.href.replace( /browser.html.*$/, '' ) + sConnUrl ; + +oConnector.ConnectorUrl = sConnUrl + ( sConnUrl.indexOf('?') != -1 ? '&' : '?' ) ; + +var sServerPath = GetUrlParam( 'ServerPath' ) ; +if ( sServerPath.length > 0 ) + oConnector.ConnectorUrl += 'ServerPath=' + encodeURIComponent( sServerPath ) + '&' ; + +oConnector.ResourceType = GetUrlParam( 'Type' ) ; +oConnector.ShowAllTypes = ( oConnector.ResourceType.length == 0 ) ; + +if ( oConnector.ShowAllTypes ) + oConnector.ResourceType = 'File' ; + +oConnector.SendCommand = function( command, params, callBackFunction ) +{ + var sUrl = this.ConnectorUrl + 'Command=' + command ; + sUrl += '&Type=' + this.ResourceType ; + sUrl += '&CurrentFolder=' + encodeURIComponent( this.CurrentFolder ) ; + + if ( params ) sUrl += '&' + params ; + + // Add a random salt to avoid getting a cached version of the command execution + sUrl += '&uuid=' + new Date().getTime() ; + + var oXML = new FCKXml() ; + + if ( callBackFunction ) + oXML.LoadUrl( sUrl, callBackFunction ) ; // Asynchronous load. + else + return oXML.LoadUrl( sUrl ) ; + + return null ; +} + +oConnector.CheckError = function( responseXml ) +{ + var iErrorNumber = 0 ; + var oErrorNode = responseXml.SelectSingleNode( 'Connector/Error' ) ; + + if ( oErrorNode ) + { + iErrorNumber = parseInt( oErrorNode.attributes.getNamedItem('number').value, 10 ) ; + + switch ( iErrorNumber ) + { + case 0 : + break ; + case 1 : // Custom error. Message placed in the "text" attribute. + alert( oErrorNode.attributes.getNamedItem('text').value ) ; + break ; + case 101 : + alert( 'Folder already exists' ) ; + break ; + case 102 : + alert( 'Invalid folder name' ) ; + break ; + case 103 : + alert( 'You have no permissions to create the folder' ) ; + break ; + case 110 : + alert( 'Unknown error creating folder' ) ; + break ; + default : + alert( 'Error on your request. Error number: ' + iErrorNumber ) ; + break ; + } + } + return iErrorNumber ; +} + +var oIcons = new Object() ; + +oIcons.AvailableIconsArray = [ + 'ai','avi','bmp','cs','dll','doc','exe','fla','gif','htm','html','jpg','js', + 'mdb','mp3','pdf','png','ppt','rdp','swf','swt','txt','vsd','xls','xml','zip' ] ; + +oIcons.AvailableIcons = new Object() ; + +for ( var i = 0 ; i < oIcons.AvailableIconsArray.length ; i++ ) + oIcons.AvailableIcons[ oIcons.AvailableIconsArray[i] ] = true ; + +oIcons.GetIcon = function( fileName ) +{ + var sExtension = fileName.substr( fileName.lastIndexOf('.') + 1 ).toLowerCase() ; + + if ( this.AvailableIcons[ sExtension ] == true ) + return sExtension ; + else + return 'default.icon' ; +} + +function OnUploadCompleted( errorNumber, fileUrl, fileName, customMsg ) +{ + if (errorNumber == "1") + window.frames['frmUpload'].OnUploadCompleted( errorNumber, customMsg ) ; + else + window.frames['frmUpload'].OnUploadCompleted( errorNumber, fileName ) ; +} + + </script> + </head> + <frameset cols="150,*" class="Frame" framespacing="3" bordercolor="#f1f1e3" frameborder="1"> + <frameset rows="50,*" framespacing="0"> + <frame src="frmresourcetype.html" scrolling="no" frameborder="0"> + <frame name="frmFolders" src="frmfolders.html" scrolling="auto" frameborder="1"> + </frameset> + <frameset rows="50,*,50" framespacing="0"> + <frame name="frmActualFolder" src="frmactualfolder.html" scrolling="no" frameborder="0"> + <frame name="frmResourcesList" src="frmresourceslist.html" scrolling="auto" frameborder="1"> + <frameset cols="150,*,0" framespacing="0" frameborder="0"> + <frame name="frmCreateFolder" src="frmcreatefolder.html" scrolling="no" frameborder="0"> + <frame name="frmUpload" src="frmupload.html" scrolling="no" frameborder="0"> + <frame name="frmUploadWorker" src="javascript:void(0)" scrolling="no" frameborder="0"> + </frameset> + </frameset> + </frameset> +</html> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/frmactualfolder.html =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/frmactualfolder.html (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/frmactualfolder.html 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,99 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<!-- + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * This page shows the actual folder path. +--> +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + <link href="browser.css" type="text/css" rel="stylesheet"> + <script type="text/javascript"> +// Automatically detect the correct document.domain (#1919). +(function() +{ + var d = document.domain ; + + while ( true ) + { + // Test if we can access a parent property. + try + { + var test = window.top.opener.document.domain ; + break ; + } + catch( e ) {} + + // Remove a domain part: www.mytest.example.com => mytest.example.com => example.com ... + d = d.replace( /.*?(?:\.|$)/, '' ) ; + + if ( d.length == 0 ) + break ; // It was not able to detect the domain. + + try + { + document.domain = d ; + } + catch (e) + { + break ; + } + } +})() ; + +function OnResize() +{ + divName.style.width = "1px" ; + divName.style.width = tdName.offsetWidth + "px" ; +} + +function SetCurrentFolder( resourceType, folderPath ) +{ + document.getElementById('tdName').innerHTML = folderPath ; +} + +window.onload = function() +{ + window.top.IsLoadedActualFolder = true ; +} + + </script> + </head> + <body bottomMargin="0" topMargin="0"> + <table height="100%" cellSpacing="0" cellPadding="0" width="100%" border="0"> + <tr> + <td> + <button style="WIDTH: 100%" type="button"> + <table cellSpacing="0" cellPadding="0" width="100%" border="0"> + <tr> + <td><img height="32" alt="" src="images/FolderOpened32.gif" width="32"></td> + <td> </td> + <td id="tdName" width="100%" nowrap class="ActualFolder">/</td> + <td> </td> + <td><img height="8" src="images/ButtonArrow.gif" width="12"></td> + <td> </td> + </tr> + </table> + </button> + </td> + </tr> + </table> + </body> +</html> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/frmcreatefolder.html =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/frmcreatefolder.html (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/frmcreatefolder.html 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,113 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<!-- + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Page used to create new folders in the current folder. +--> +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + <link href="browser.css" type="text/css" rel="stylesheet"> + <script type="text/javascript" src="js/common.js"></script> + <script language="javascript"> + +function SetCurrentFolder( resourceType, folderPath ) +{ + oConnector.ResourceType = resourceType ; + oConnector.CurrentFolder = folderPath ; +} + +function CreateFolder() +{ + var sFolderName ; + + while ( true ) + { + sFolderName = prompt( 'Type the name of the new folder:', '' ) ; + + if ( sFolderName == null ) + return ; + else if ( sFolderName.length == 0 ) + alert( 'Please type the folder name' ) ; + else + break ; + } + + oConnector.SendCommand( 'CreateFolder', 'NewFolderName=' + encodeURIComponent( sFolderName) , CreateFolderCallBack ) ; +} + +function CreateFolderCallBack( fckXml ) +{ + if ( oConnector.CheckError( fckXml ) == 0 ) + window.parent.frames['frmResourcesList'].Refresh() ; + + /* + // Get the current folder path. + var oNode = fckXml.SelectSingleNode( 'Connector/Error' ) ; + var iErrorNumber = parseInt( oNode.attributes.getNamedItem('number').value ) ; + + switch ( iErrorNumber ) + { + case 0 : + window.parent.frames['frmResourcesList'].Refresh() ; + break ; + case 101 : + alert( 'Folder already exists' ) ; + break ; + case 102 : + alert( 'Invalid folder name' ) ; + break ; + case 103 : + alert( 'You have no permissions to create the folder' ) ; + break ; + case 110 : + alert( 'Unknown error creating folder' ) ; + break ; + default : + alert( 'Error creating folder. Error number: ' + iErrorNumber ) ; + break ; + } + */ +} + +window.onload = function() +{ + window.top.IsLoadedCreateFolder = true ; +} + </script> + </head> + <body bottomMargin="0" topMargin="0"> + <table height="100%" cellSpacing="0" cellPadding="0" width="100%" border="0"> + <tr> + <td> + <button type="button" style="WIDTH: 100%" onclick="CreateFolder();"> + <table cellSpacing="0" cellPadding="0" border="0"> + <tr> + <td><img height="16" alt="" src="images/Folder.gif" width="16"></td> + <td> </td> + <td nowrap>Create New Folder</td> + </tr> + </table> + </button> + </td> + </tr> + </table> + </body> +</html> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/frmfolders.html =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/frmfolders.html (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/frmfolders.html 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,197 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<!-- + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * This page shows the list of folders available in the parent folder + * of the current folder. +--> +<html> + <head> + <link href="browser.css" type="text/css" rel="stylesheet"> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + <script type="text/javascript" src="js/common.js"></script> + <script language="javascript"> + +var sActiveFolder ; + +var bIsLoaded = false ; +var iIntervalId ; + +var oListManager = new Object() ; + +oListManager.Init = function() +{ + this.Table = document.getElementById('tableFiles') ; + this.UpRow = document.getElementById('trUp') ; + + this.TableRows = new Object() ; +} + +oListManager.Clear = function() +{ + // Remove all other rows available. + while ( this.Table.rows.length > 1 ) + this.Table.deleteRow(1) ; + + // Reset the TableRows collection. + this.TableRows = new Object() ; +} + +oListManager.AddItem = function( folderName, folderPath ) +{ + // Create the new row. + var oRow = this.Table.insertRow(-1) ; + oRow.className = 'FolderListFolder' ; + + // Build the link to view the folder. + var sLink = '<a href="#" onclick="OpenFolder(\'' + folderPath + '\');return false;">' ; + + // Add the folder icon cell. + var oCell = oRow.insertCell(-1) ; + oCell.width = 16 ; + oCell.innerHTML = sLink + '<img alt="" src="images/spacer.gif" width="16" height="16" border="0"></a>' ; + + // Add the folder name cell. + oCell = oRow.insertCell(-1) ; + oCell.noWrap = true ; + oCell.innerHTML = ' ' + sLink + folderName + '</a>' ; + + this.TableRows[ folderPath ] = oRow ; +} + +oListManager.ShowUpFolder = function( upFolderPath ) +{ + this.UpRow.style.display = ( upFolderPath != null ? '' : 'none' ) ; + + if ( upFolderPath != null ) + { + document.getElementById('linkUpIcon').onclick = document.getElementById('linkUp').onclick = function() + { + LoadFolders( upFolderPath ) ; + return false ; + } + } +} + +function CheckLoaded() +{ + if ( window.top.IsLoadedActualFolder + && window.top.IsLoadedCreateFolder + && window.top.IsLoadedUpload + && window.top.IsLoadedResourcesList ) + { + window.clearInterval( iIntervalId ) ; + bIsLoaded = true ; + OpenFolder( sActiveFolder ) ; + } +} + +function OpenFolder( folderPath ) +{ + sActiveFolder = folderPath ; + + if ( ! bIsLoaded ) + { + if ( ! iIntervalId ) + iIntervalId = window.setInterval( CheckLoaded, 100 ) ; + return ; + } + + // Change the style for the select row (to show the opened folder). + for ( var sFolderPath in oListManager.TableRows ) + { + oListManager.TableRows[ sFolderPath ].className = + ( sFolderPath == folderPath ? 'FolderListCurrentFolder' : 'FolderListFolder' ) ; + } + + // Set the current folder in all frames. + window.parent.frames['frmActualFolder'].SetCurrentFolder( oConnector.ResourceType, folderPath ) ; + window.parent.frames['frmCreateFolder'].SetCurrentFolder( oConnector.ResourceType, folderPath ) ; + window.parent.frames['frmUpload'].SetCurrentFolder( oConnector.ResourceType, folderPath ) ; + + // Load the resources list for this folder. + window.parent.frames['frmResourcesList'].LoadResources( oConnector.ResourceType, folderPath ) ; +} + +function LoadFolders( folderPath ) +{ + // Clear the folders list. + oListManager.Clear() ; + + // Get the parent folder path. + var sParentFolderPath ; + if ( folderPath != '/' ) + sParentFolderPath = folderPath.substring( 0, folderPath.lastIndexOf( '/', folderPath.length - 2 ) + 1 ) ; + + // Show/Hide the Up Folder. + oListManager.ShowUpFolder( sParentFolderPath ) ; + + if ( folderPath != '/' ) + { + sActiveFolder = folderPath ; + oConnector.CurrentFolder = sParentFolderPath ; + oConnector.SendCommand( 'GetFolders', null, GetFoldersCallBack ) ; + } + else + OpenFolder( '/' ) ; +} + +function GetFoldersCallBack( fckXml ) +{ + if ( oConnector.CheckError( fckXml ) != 0 ) + return ; + + // Get the current folder path. + var oNode = fckXml.SelectSingleNode( 'Connector/CurrentFolder' ) ; + var sCurrentFolderPath = oNode.attributes.getNamedItem('path').value ; + + var oNodes = fckXml.SelectNodes( 'Connector/Folders/Folder' ) ; + + for ( var i = 0 ; i < oNodes.length ; i++ ) + { + var sFolderName = oNodes[i].attributes.getNamedItem('name').value ; + oListManager.AddItem( sFolderName, sCurrentFolderPath + sFolderName + '/' ) ; + } + + OpenFolder( sActiveFolder ) ; +} + +function SetResourceType( type ) +{ + oConnector.ResourceType = type ; + LoadFolders( '/' ) ; +} + +window.onload = function() +{ + oListManager.Init() ; + LoadFolders( '/' ) ; +} + </script> + </head> + <body class="FileArea" bottomMargin="10" leftMargin="10" topMargin="10" rightMargin="10"> + <table id="tableFiles" cellSpacing="0" cellPadding="0" width="100%" border="0"> + <tr id="trUp" style="DISPLAY: none"> + <td width="16"><a id="linkUpIcon" href="#"><img alt="" src="images/FolderUp.gif" width="16" height="16" border="0"></a></td> + <td nowrap width="100%"> <a id="linkUp" href="#">..</a></td> + </tr> + </table> + </body> +</html> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/frmresourceslist.html =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/frmresourceslist.html (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/frmresourceslist.html 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,168 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<!-- + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * This page shows all resources available in a folder in the File Browser. +--> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <link href="browser.css" type="text/css" rel="stylesheet" /> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + <script type="text/javascript" src="js/common.js"></script> + <script type="text/javascript"> + +var oListManager = new Object() ; + +oListManager.Clear = function() +{ + document.body.innerHTML = '' ; +} + +function ProtectPath(path) +{ + path = path.replace( /\\/g, '\\\\') ; + path = path.replace( /'/g, '\\\'') ; + return path ; +} + +oListManager.GetFolderRowHtml = function( folderName, folderPath ) +{ + // Build the link to view the folder. + var sLink = '<a href="#" onclick="OpenFolder(\'' + ProtectPath( folderPath ) + '\');return false;">' ; + + return '<tr>' + + '<td width="16">' + + sLink + + '<img alt="" src="images/Folder.gif" width="16" height="16" border="0"><\/a>' + + '<\/td><td nowrap colspan="2"> ' + + sLink + + folderName + + '<\/a>' + + '<\/td><\/tr>' ; +} + +oListManager.GetFileRowHtml = function( fileName, fileUrl, fileSize ) +{ + // Build the link to view the folder. + var sLink = '<a href="#" onclick="OpenFile(\'' + ProtectPath( fileUrl ) + '\');return false;">' ; + + // Get the file icon. + var sIcon = oIcons.GetIcon( fileName ) ; + + return '<tr>' + + '<td width="16">' + + sLink + + '<img alt="" src="images/icons/' + sIcon + '.gif" width="16" height="16" border="0"><\/a>' + + '<\/td><td> ' + + sLink + + fileName + + '<\/a>' + + '<\/td><td align="right" nowrap> ' + + fileSize + + ' KB' + + '<\/td><\/tr>' ; +} + +function OpenFolder( folderPath ) +{ + // Load the resources list for this folder. + window.parent.frames['frmFolders'].LoadFolders( folderPath ) ; +} + +function OpenFile( fileUrl ) +{ + window.top.opener.SetUrl( encodeURI( fileUrl ).replace( '#', '%23' ) ) ; + window.top.close() ; + window.top.opener.focus() ; +} + +function LoadResources( resourceType, folderPath ) +{ + oListManager.Clear() ; + oConnector.ResourceType = resourceType ; + oConnector.CurrentFolder = folderPath ; + oConnector.SendCommand( 'GetFoldersAndFiles', null, GetFoldersAndFilesCallBack ) ; +} + +function Refresh() +{ + LoadResources( oConnector.ResourceType, oConnector.CurrentFolder ) ; +} + +function GetFoldersAndFilesCallBack( fckXml ) +{ + if ( oConnector.CheckError( fckXml ) != 0 ) + return ; + + // Get the current folder path. + var oFolderNode = fckXml.SelectSingleNode( 'Connector/CurrentFolder' ) ; + if ( oFolderNode == null ) + { + alert( 'The server didn\'t reply with a proper XML data. Please check your configuration.' ) ; + return ; + } + var sCurrentFolderPath = oFolderNode.attributes.getNamedItem('path').value ; + var sCurrentFolderUrl = oFolderNode.attributes.getNamedItem('url').value ; + +// var dTimer = new Date() ; + + var oHtml = new StringBuilder( '<table id="tableFiles" cellspacing="1" cellpadding="0" width="100%" border="0">' ) ; + + // Add the Folders. + var oNodes ; + oNodes = fckXml.SelectNodes( 'Connector/Folders/Folder' ) ; + for ( var i = 0 ; i < oNodes.length ; i++ ) + { + var sFolderName = oNodes[i].attributes.getNamedItem('name').value ; + oHtml.Append( oListManager.GetFolderRowHtml( sFolderName, sCurrentFolderPath + sFolderName + "/" ) ) ; + } + + // Add the Files. + oNodes = fckXml.SelectNodes( 'Connector/Files/File' ) ; + for ( var j = 0 ; j < oNodes.length ; j++ ) + { + var oNode = oNodes[j] ; + var sFileName = oNode.attributes.getNamedItem('name').value ; + var sFileSize = oNode.attributes.getNamedItem('size').value ; + + // Get the optional "url" attribute. If not available, build the url. + var oFileUrlAtt = oNodes[j].attributes.getNamedItem('url') ; + var sFileUrl = oFileUrlAtt != null ? oFileUrlAtt.value : sCurrentFolderUrl + sFileName ; + + oHtml.Append( oListManager.GetFileRowHtml( sFileName, sFileUrl, sFileSize ) ) ; + } + + oHtml.Append( '<\/table>' ) ; + + document.body.innerHTML = oHtml.ToString() ; + +// window.top.document.title = 'Finished processing in ' + ( ( ( new Date() ) - dTimer ) / 1000 ) + ' seconds' ; + +} + +window.onload = function() +{ + window.top.IsLoadedResourcesList = true ; +} + </script> +</head> +<body class="FileArea"> +</body> +</html> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/frmresourcetype.html =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/frmresourcetype.html (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/frmresourcetype.html 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,65 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<!-- + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * This page shows the list of available resource types. +--> +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + <link href="browser.css" type="text/css" rel="stylesheet"> + <script type="text/javascript" src="js/common.js"></script> + <script language="javascript"> + +function SetResourceType( type ) +{ + window.parent.frames["frmFolders"].SetResourceType( type ) ; +} + +var aTypes = [ + ['File','File'], + ['Image','Image'], + ['Flash','Flash'], + ['Media','Media'] +] ; + +window.onload = function() +{ + for ( var i = 0 ; i < aTypes.length ; i++ ) + { + if ( oConnector.ShowAllTypes || aTypes[i][0] == oConnector.ResourceType ) + AddSelectOption( document.getElementById('cmbType'), aTypes[i][1], aTypes[i][0] ) ; + } +} + + </script> + </head> + <body bottomMargin="0" topMargin="0"> + <table height="100%" cellSpacing="0" cellPadding="0" width="100%" border="0"> + <tr> + <td nowrap> + Resource Type<BR> + <select id="cmbType" style="WIDTH: 100%" onchange="SetResourceType(this.value);"> + </select> + </td> + </tr> + </table> + </body> +</html> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/frmupload.html =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/frmupload.html (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/frmupload.html 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,115 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<!-- + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Page used to upload new files in the current folder. +--> +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <title>File Upload</title> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + <link href="browser.css" type="text/css" rel="stylesheet" /> + <script type="text/javascript" src="js/common.js"></script> + <script type="text/javascript"> + +function SetCurrentFolder( resourceType, folderPath ) +{ + var sUrl = oConnector.ConnectorUrl + 'Command=FileUpload' ; + sUrl += '&Type=' + resourceType ; + sUrl += '&CurrentFolder=' + encodeURIComponent( folderPath ) ; + + document.getElementById('frmUpload').action = sUrl ; +} + +function OnSubmit() +{ + if ( document.getElementById('NewFile').value.length == 0 ) + { + alert( 'Please select a file from your computer' ) ; + return false ; + } + + // Set the interface elements. + document.getElementById('eUploadMessage').innerHTML = 'Upload a new file in this folder (Upload in progress, please wait...)' ; + document.getElementById('btnUpload').disabled = true ; + + return true ; +} + +function OnUploadCompleted( errorNumber, data ) +{ + // Reset the Upload Worker Frame. + window.parent.frames['frmUploadWorker'].location = 'javascript:void(0)' ; + + // Reset the upload form (On IE we must do a little trick to avoid problems). + if ( document.all ) + document.getElementById('NewFile').outerHTML = '<input id="NewFile" name="NewFile" style="WIDTH: 100%" type="file">' ; + else + document.getElementById('frmUpload').reset() ; + + // Reset the interface elements. + document.getElementById('eUploadMessage').innerHTML = 'Upload a new file in this folder' ; + document.getElementById('btnUpload').disabled = false ; + + switch ( errorNumber ) + { + case 0 : + window.parent.frames['frmResourcesList'].Refresh() ; + break ; + case 1 : // Custom error. + alert( data ) ; + break ; + case 201 : + window.parent.frames['frmResourcesList'].Refresh() ; + alert( 'A file with the same name is already available. The uploaded file has been renamed to "' + data + '"' ) ; + break ; + case 202 : + alert( 'Invalid file' ) ; + break ; + default : + alert( 'Error on file upload. Error number: ' + errorNumber ) ; + break ; + } +} + +window.onload = function() +{ + window.top.IsLoadedUpload = true ; +} + </script> + </head> + <body bottommargin="0" topmargin="0"> + <form id="frmUpload" action="" target="frmUploadWorker" method="post" enctype="multipart/form-data" onsubmit="return OnSubmit();"> + <table height="100%" cellspacing="0" cellpadding="0" width="100%" border="0"> + <tr> + <td nowrap="nowrap"> + <span id="eUploadMessage">Upload a new file in this folder</span><br> + <table cellspacing="0" cellpadding="0" width="100%" border="0"> + <tr> + <td width="100%"><input id="NewFile" name="NewFile" style="WIDTH: 100%" type="file"></td> + <td nowrap="nowrap"> <input id="btnUpload" type="submit" value="Upload"></td> + </tr> + </table> + </td> + </tr> + </table> + </form> + </body> +</html> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/ButtonArrow.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/ButtonArrow.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/Folder.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/Folder.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/Folder32.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/Folder32.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/FolderOpened.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/FolderOpened.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/FolderOpened32.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/FolderOpened32.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/FolderUp.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/FolderUp.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/ai.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/ai.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/avi.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/avi.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/bmp.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/bmp.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/cs.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/cs.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/default.icon.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/default.icon.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/dll.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/dll.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/doc.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/doc.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/exe.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/exe.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/fla.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/fla.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/gif.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/gif.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/htm.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/htm.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/html.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/html.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/jpg.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/jpg.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/js.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/js.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/mdb.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/mdb.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/mp3.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/mp3.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/pdf.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/pdf.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/png.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/png.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/ppt.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/ppt.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/rdp.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/rdp.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/swf.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/swf.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/swt.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/swt.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/txt.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/txt.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/vsd.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/vsd.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/xls.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/xls.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/xml.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/xml.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/zip.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/32/zip.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/ai.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/ai.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/avi.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/avi.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/bmp.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/bmp.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/cs.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/cs.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/default.icon.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/default.icon.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/dll.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/dll.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/doc.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/doc.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/exe.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/exe.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/fla.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/fla.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/gif.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/gif.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/htm.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/htm.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/html.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/html.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/jpg.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/jpg.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/js.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/js.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/mdb.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/mdb.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/mp3.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/mp3.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/pdf.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/pdf.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/png.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/png.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/ppt.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/ppt.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/rdp.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/rdp.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/swf.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/swf.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/swt.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/swt.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/txt.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/txt.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/vsd.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/vsd.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/xls.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/xls.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/xml.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/xml.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/zip.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/icons/zip.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/spacer.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/images/spacer.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/js/common.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/js/common.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/js/common.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,87 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Common objects and functions shared by all pages that compose the + * File Browser dialog window. + */ + +// Automatically detect the correct document.domain (#1919). +(function() +{ + var d = document.domain ; + + while ( true ) + { + // Test if we can access a parent property. + try + { + var test = window.top.opener.document.domain ; + break ; + } + catch( e ) {} + + // Remove a domain part: www.mytest.example.com => mytest.example.com => example.com ... + d = d.replace( /.*?(?:\.|$)/, '' ) ; + + if ( d.length == 0 ) + break ; // It was not able to detect the domain. + + try + { + document.domain = d ; + } + catch (e) + { + break ; + } + } +})() ; + +function AddSelectOption( selectElement, optionText, optionValue ) +{ + var oOption = document.createElement("OPTION") ; + + oOption.text = optionText ; + oOption.value = optionValue ; + + selectElement.options.add(oOption) ; + + return oOption ; +} + +var oConnector = window.parent.oConnector ; +var oIcons = window.parent.oIcons ; + + +function StringBuilder( value ) +{ + this._Strings = new Array( value || '' ) ; +} + +StringBuilder.prototype.Append = function( value ) +{ + if ( value ) + this._Strings.push( value ) ; +} + +StringBuilder.prototype.ToString = function() +{ + return this._Strings.join( '' ) ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/js/fckxml.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/js/fckxml.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/browser/default/js/fckxml.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,129 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Defines the FCKXml object that is used for XML data calls + * and XML processing. + * + * This script is shared by almost all pages that compose the + * File Browser frameset. + */ + +var FCKXml = function() +{} + +FCKXml.prototype.GetHttpRequest = function() +{ + // Gecko / IE7 + try { return new XMLHttpRequest(); } + catch(e) {} + + // IE6 + try { return new ActiveXObject( 'Msxml2.XMLHTTP' ) ; } + catch(e) {} + + // IE5 + try { return new ActiveXObject( 'Microsoft.XMLHTTP' ) ; } + catch(e) {} + + return null ; +} + +FCKXml.prototype.LoadUrl = function( urlToCall, asyncFunctionPointer ) +{ + var oFCKXml = this ; + + var bAsync = ( typeof(asyncFunctionPointer) == 'function' ) ; + + var oXmlHttp = this.GetHttpRequest() ; + + oXmlHttp.open( "GET", urlToCall, bAsync ) ; + + if ( bAsync ) + { + oXmlHttp.onreadystatechange = function() + { + if ( oXmlHttp.readyState == 4 ) + { + if ( ( oXmlHttp.status != 200 && oXmlHttp.status != 304 ) || oXmlHttp.responseXML == null || oXmlHttp.responseXML.firstChild == null ) + { + alert( 'The server didn\'t send back a proper XML response. Please contact your system administrator.\n\n' + + 'XML request error: ' + oXmlHttp.statusText + ' (' + oXmlHttp.status + ')\n\n' + + 'Requested URL:\n' + urlToCall + '\n\n' + + 'Response text:\n' + oXmlHttp.responseText ) ; + return ; + } + + oFCKXml.DOMDocument = oXmlHttp.responseXML ; + asyncFunctionPointer( oFCKXml ) ; + } + } + } + + oXmlHttp.send( null ) ; + + if ( ! bAsync ) + { + if ( oXmlHttp.status == 200 || oXmlHttp.status == 304 ) + this.DOMDocument = oXmlHttp.responseXML ; + else + { + alert( 'XML request error: ' + oXmlHttp.statusText + ' (' + oXmlHttp.status + ')' ) ; + } + } +} + +FCKXml.prototype.SelectNodes = function( xpath ) +{ + if ( navigator.userAgent.indexOf('MSIE') >= 0 ) // IE + return this.DOMDocument.selectNodes( xpath ) ; + else // Gecko + { + var aNodeArray = new Array(); + + var xPathResult = this.DOMDocument.evaluate( xpath, this.DOMDocument, + this.DOMDocument.createNSResolver(this.DOMDocument.documentElement), XPathResult.ORDERED_NODE_ITERATOR_TYPE, null) ; + if ( xPathResult ) + { + var oNode = xPathResult.iterateNext() ; + while( oNode ) + { + aNodeArray[aNodeArray.length] = oNode ; + oNode = xPathResult.iterateNext(); + } + } + return aNodeArray ; + } +} + +FCKXml.prototype.SelectSingleNode = function( xpath ) +{ + if ( navigator.userAgent.indexOf('MSIE') >= 0 ) // IE + return this.DOMDocument.selectSingleNode( xpath ) ; + else // Gecko + { + var xPathResult = this.DOMDocument.evaluate( xpath, this.DOMDocument, + this.DOMDocument.createNSResolver(this.DOMDocument.documentElement), 9, null); + + if ( xPathResult && xPathResult.singleNodeValue ) + return xPathResult.singleNodeValue ; + else + return null ; + } +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/asp/basexml.asp =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/asp/basexml.asp (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/asp/basexml.asp 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,62 @@ +<% + ' FCKeditor - The text editor for Internet - http://www.fckeditor.net + ' Copyright (C) 2003-2008 Frederico Caldeira Knabben + ' + ' == BEGIN LICENSE == + ' + ' Licensed under the terms of any of the following licenses at your + ' choice: + ' + ' - GNU General Public License Version 2 or later (the "GPL") + ' http://www.gnu.org/licenses/gpl.html + ' + ' - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + ' http://www.gnu.org/licenses/lgpl.html + ' + ' - Mozilla Public License Version 1.1 or later (the "MPL") + ' http://www.mozilla.org/MPL/MPL-1.1.html + ' + ' == END LICENSE == + ' + ' This file include the functions that create the base XML output. +%> +<% + +Sub SetXmlHeaders() + ' Cleans the response buffer. + Response.Clear() + + ' Prevent the browser from caching the result. + Response.CacheControl = "no-cache" + + ' Set the response format. + Response.CharSet = "UTF-8" + Response.ContentType = "text/xml" +End Sub + +Sub CreateXmlHeader( command, resourceType, currentFolder, url ) + ' Create the XML document header. + Response.Write "<?xml version=""1.0"" encoding=""utf-8"" ?>" + + ' Create the main "Connector" node. + Response.Write "<Connector command=""" & command & """ resourceType=""" & resourceType & """>" + + ' Add the current folder node. + Response.Write "<CurrentFolder path=""" & ConvertToXmlAttribute( currentFolder ) & """ url=""" & ConvertToXmlAttribute( url ) & """ />" +End Sub + +Sub CreateXmlFooter() + Response.Write "</Connector>" +End Sub + +Sub SendError( number, text ) + SetXmlHeaders + + ' Create the XML document header. + Response.Write "<?xml version=""1.0"" encoding=""utf-8"" ?>" + + Response.Write "<Connector><Error number=""" & number & """ text=""" & Server.HTMLEncode( text ) & """ /></Connector>" + + Response.End +End Sub +%> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/asp/class_upload.asp =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/asp/class_upload.asp (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/asp/class_upload.asp 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,353 @@ +<% + ' FCKeditor - The text editor for Internet - http://www.fckeditor.net + ' Copyright (C) 2003-2008 Frederico Caldeira Knabben + ' + ' == BEGIN LICENSE == + ' + ' Licensed under the terms of any of the following licenses at your + ' choice: + ' + ' - GNU General Public License Version 2 or later (the "GPL") + ' http://www.gnu.org/licenses/gpl.html + ' + ' - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + ' http://www.gnu.org/licenses/lgpl.html + ' + ' - Mozilla Public License Version 1.1 or later (the "MPL") + ' http://www.mozilla.org/MPL/MPL-1.1.html + ' + ' == END LICENSE == + ' + ' These are the classes used to handle ASP upload without using third + ' part components (OCX/DLL). +%> +<% +'********************************************** +' File: NetRube_Upload.asp +' Version: NetRube Upload Class Version 2.3 Build 20070528 +' Author: NetRube +' Email: NetRube@126.com +' Date: 05/28/2007 +' Comments: The code for the Upload. +' This can free usage, but please +' not to delete this copyright information. +' If you have a modification version, +' Please send out a duplicate to me. +'********************************************** +' 文件名: NetRube_Upload.asp +' 版本: NetRube Upload Class Version 2.3 Build 20070528 +' 作者: NetRube(网络乡巴佬) +' 电子邮件: NetRube@126.com +' 日期: 2007年05月28日 +' 声明: 文件上传类 +' 本上传类可以自由使用,但请保留此版权声明信息 +' 如果您对本上传类进行修改增强, +' 请发送一份给俺。 +'********************************************** + +Class NetRube_Upload + + Public File, Form + Private oSourceData + Private nMaxSize, nErr, sAllowed, sDenied, sHtmlExtensions + + Private Sub Class_Initialize + nErr = 0 + nMaxSize = 1048576 + + Set File = Server.CreateObject("Scripting.Dictionary") + File.CompareMode = 1 + Set Form = Server.CreateObject("Scripting.Dictionary") + Form.CompareMode = 1 + + Set oSourceData = Server.CreateObject("ADODB.Stream") + oSourceData.Type = 1 + oSourceData.Mode = 3 + oSourceData.Open + End Sub + + Private Sub Class_Terminate + Form.RemoveAll + Set Form = Nothing + File.RemoveAll + Set File = Nothing + + oSourceData.Close + Set oSourceData = Nothing + End Sub + + Public Property Get Version + Version = "NetRube Upload Class Version 2.3 Build 20070528" + End Property + + Public Property Get ErrNum + ErrNum = nErr + End Property + + Public Property Let MaxSize(nSize) + nMaxSize = nSize + End Property + + Public Property Let Allowed(sExt) + sAllowed = sExt + End Property + + Public Property Let Denied(sExt) + sDenied = sExt + End Property + + Public Property Let HtmlExtensions(sExt) + sHtmlExtensions = sExt + End Property + + Public Sub GetData + Dim aCType + aCType = Split(Request.ServerVariables("HTTP_CONTENT_TYPE"), ";") + if ( uBound(aCType) < 0 ) then + nErr = 1 + Exit Sub + end if + If aCType(0) <> "multipart/form-data" Then + nErr = 1 + Exit Sub + End If + + Dim nTotalSize + nTotalSize = Request.TotalBytes + If nTotalSize < 1 Then + nErr = 2 + Exit Sub + End If + If nMaxSize > 0 And nTotalSize > nMaxSize Then + nErr = 3 + Exit Sub + End If + + 'Thankful long(yrl031715@163.com) + 'Fix upload large file. + '********************************************** + ' 修正作者:long + ' 联系邮件: yrl031715@163.com + ' 修正时间:2007年5月6日 + ' 修正说明:由于iis6的Content-Length 头信息中包含的请求长度超过了 AspMaxRequestEntityAllowed 的值(默认200K), IIS 将返回一个 403 错误信息. + ' 直接导致在iis6下调试FCKeditor上传功能时,一旦文件超过200K,上传文件时文件管理器失去响应,受此影响,文件的快速上传功能也存在在缺陷。 + ' 在参考 宝玉 的 Asp无组件上传带进度条 演示程序后作出如下修改,以修正在iis6下的错误。 + + Dim nTotalBytes, nPartBytes, ReadBytes + ReadBytes = 0 + nTotalBytes = Request.TotalBytes + '循环分块读取 + Do While ReadBytes < nTotalBytes + '分块读取 + nPartBytes = 64 * 1024 '分成每块64k + If nPartBytes + ReadBytes > nTotalBytes Then + nPartBytes = nTotalBytes - ReadBytes + End If + oSourceData.Write Request.BinaryRead(nPartBytes) + ReadBytes = ReadBytes + nPartBytes + Loop + '********************************************** + oSourceData.Position = 0 + + Dim oTotalData, oFormStream, sFormHeader, sFormName, bCrLf, nBoundLen, nFormStart, nFormEnd, nPosStart, nPosEnd, sBoundary + + oTotalData = oSourceData.Read + bCrLf = ChrB(13) & ChrB(10) + sBoundary = MidB(oTotalData, 1, InStrB(1, oTotalData, bCrLf) - 1) + nBoundLen = LenB(sBoundary) + 2 + nFormStart = nBoundLen + + Set oFormStream = Server.CreateObject("ADODB.Stream") + + Do While (nFormStart + 2) < nTotalSize + nFormEnd = InStrB(nFormStart, oTotalData, bCrLf & bCrLf) + 3 + + With oFormStream + .Type = 1 + .Mode = 3 + .Open + oSourceData.Position = nFormStart + oSourceData.CopyTo oFormStream, nFormEnd - nFormStart + .Position = 0 + .Type = 2 + .CharSet = "UTF-8" + sFormHeader = .ReadText + .Close + End With + + nFormStart = InStrB(nFormEnd, oTotalData, sBoundary) - 1 + nPosStart = InStr(22, sFormHeader, " name=", 1) + 7 + nPosEnd = InStr(nPosStart, sFormHeader, """") + sFormName = Mid(sFormHeader, nPosStart, nPosEnd - nPosStart) + + If InStr(45, sFormHeader, " filename=", 1) > 0 Then + Set File(sFormName) = New NetRube_FileInfo + File(sFormName).FormName = sFormName + File(sFormName).Start = nFormEnd + File(sFormName).Size = nFormStart - nFormEnd - 2 + nPosStart = InStr(nPosEnd, sFormHeader, " filename=", 1) + 11 + nPosEnd = InStr(nPosStart, sFormHeader, """") + File(sFormName).ClientPath = Mid(sFormHeader, nPosStart, nPosEnd - nPosStart) + File(sFormName).Name = Mid(File(sFormName).ClientPath, InStrRev(File(sFormName).ClientPath, "\") + 1) + File(sFormName).Ext = LCase(Mid(File(sFormName).Name, InStrRev(File(sFormName).Name, ".") + 1)) + nPosStart = InStr(nPosEnd, sFormHeader, "Content-Type: ", 1) + 14 + nPosEnd = InStr(nPosStart, sFormHeader, vbCr) + File(sFormName).MIME = Mid(sFormHeader, nPosStart, nPosEnd - nPosStart) + Else + With oFormStream + .Type = 1 + .Mode = 3 + .Open + oSourceData.Position = nFormEnd + oSourceData.CopyTo oFormStream, nFormStart - nFormEnd - 2 + .Position = 0 + .Type = 2 + .CharSet = "UTF-8" + Form(sFormName) = .ReadText + .Close + End With + End If + + nFormStart = nFormStart + nBoundLen + Loop + + oTotalData = "" + Set oFormStream = Nothing + End Sub + + Public Sub SaveAs(sItem, sFileName) + If File(sItem).Size < 1 Then + nErr = 2 + Exit Sub + End If + + If Not IsAllowed(File(sItem).Ext) Then + nErr = 4 + Exit Sub + End If + + If InStr( LCase( sFileName ), "::$data" ) > 0 Then + nErr = 4 + Exit Sub + End If + + Dim sFileExt, iFileSize + sFileExt = File(sItem).Ext + iFileSize = File(sItem).Size + + ' Check XSS. + If Not IsHtmlExtension( sFileExt ) Then + ' Calculate the size of data to load (max 1Kb). + Dim iXSSSize + iXSSSize = iFileSize + + If iXSSSize > 1024 Then + iXSSSize = 1024 + End If + + ' Read the data. + Dim sData + oSourceData.Position = File(sItem).Start + sData = oSourceData.Read( iXSSSize ) ' Byte Array + sData = ByteArray2Text( sData ) ' String + + ' Sniff HTML data. + If SniffHtml( sData ) Then + nErr = 4 + Exit Sub + End If + End If + + Dim oFileStream + Set oFileStream = Server.CreateObject("ADODB.Stream") + With oFileStream + .Type = 1 + .Mode = 3 + .Open + oSourceData.Position = File(sItem).Start + oSourceData.CopyTo oFileStream, File(sItem).Size + .Position = 0 + .SaveToFile sFileName, 2 + .Close + End With + Set oFileStream = Nothing + End Sub + + Private Function IsAllowed(sExt) + Dim oRE + Set oRE = New RegExp + oRE.IgnoreCase = True + oRE.Global = True + + If sDenied = "" Then + oRE.Pattern = sAllowed + IsAllowed = (sAllowed = "") Or oRE.Test(sExt) + Else + oRE.Pattern = sDenied + IsAllowed = Not oRE.Test(sExt) + End If + + Set oRE = Nothing + End Function + + Private Function IsHtmlExtension( sExt ) + If sHtmlExtensions = "" Then + Exit Function + End If + + Dim oRE + Set oRE = New RegExp + oRE.IgnoreCase = True + oRE.Global = True + oRE.Pattern = sHtmlExtensions + + IsHtmlExtension = oRE.Test(sExt) + + Set oRE = Nothing + End Function + + Private Function SniffHtml( sData ) + + Dim oRE + Set oRE = New RegExp + oRE.IgnoreCase = True + oRE.Global = True + + Dim aPatterns + aPatterns = Array( "<!DOCTYPE\W*X?HTML", "<(body|head|html|img|pre|script|table|title)", "type\s*=\s*[\'""]?\s*(?:\w*/)?(?:ecma|java)", "(?:href|src|data)\s*=\s*[\'""]?\s*(?:ecma|java)script:", "url\s*\(\s*[\'""]?\s*(?:ecma|java)script:" ) + + Dim i + For i = 0 to UBound( aPatterns ) + oRE.Pattern = aPatterns( i ) + If oRE.Test( sData ) Then + SniffHtml = True + Exit Function + End If + Next + + SniffHtml = False + + End Function + + ' Thanks to http://www.ericphelps.com/q193998/index.htm + Private Function ByteArray2Text(varByteArray) + Dim strData, strBuffer, lngCounter + strData = "" + strBuffer = "" + For lngCounter = 0 to UBound(varByteArray) + strBuffer = strBuffer & Chr(255 And Ascb(Midb(varByteArray,lngCounter + 1, 1))) + 'Keep strBuffer at 1k bytes maximum + If lngCounter Mod 1024 = 0 Then + strData = strData & strBuffer + strBuffer = "" + End If + Next + ByteArray2Text = strData & strBuffer + End Function + +End Class + +Class NetRube_FileInfo + Dim FormName, ClientPath, Path, Name, Ext, Content, Size, MIME, Start +End Class +%> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/asp/commands.asp =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/asp/commands.asp (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/asp/commands.asp 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,198 @@ +<% + ' FCKeditor - The text editor for Internet - http://www.fckeditor.net + ' Copyright (C) 2003-2008 Frederico Caldeira Knabben + ' + ' == BEGIN LICENSE == + ' + ' Licensed under the terms of any of the following licenses at your + ' choice: + ' + ' - GNU General Public License Version 2 or later (the "GPL") + ' http://www.gnu.org/licenses/gpl.html + ' + ' - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + ' http://www.gnu.org/licenses/lgpl.html + ' + ' - Mozilla Public License Version 1.1 or later (the "MPL") + ' http://www.mozilla.org/MPL/MPL-1.1.html + ' + ' == END LICENSE == + ' + ' This file include the functions that handle the Command requests + ' in the ASP Connector. +%> +<% +Sub GetFolders( resourceType, currentFolder ) + ' Map the virtual path to the local server path. + Dim sServerDir + sServerDir = ServerMapFolder( resourceType, currentFolder, "GetFolders" ) + + ' Open the "Folders" node. + Response.Write "<Folders>" + + Dim oFSO, oCurrentFolder, oFolders, oFolder + Set oFSO = Server.CreateObject( "Scripting.FileSystemObject" ) + if not (oFSO.FolderExists( sServerDir ) ) then + Set oFSO = Nothing + SendError 102, currentFolder + end if + + Set oCurrentFolder = oFSO.GetFolder( sServerDir ) + Set oFolders = oCurrentFolder.SubFolders + + For Each oFolder in oFolders + Response.Write "<Folder name=""" & ConvertToXmlAttribute( oFolder.name ) & """ />" + Next + + Set oFSO = Nothing + + ' Close the "Folders" node. + Response.Write "</Folders>" +End Sub + +Sub GetFoldersAndFiles( resourceType, currentFolder ) + ' Map the virtual path to the local server path. + Dim sServerDir + sServerDir = ServerMapFolder( resourceType, currentFolder, "GetFoldersAndFiles" ) + + Dim oFSO, oCurrentFolder, oFolders, oFolder, oFiles, oFile + Set oFSO = Server.CreateObject( "Scripting.FileSystemObject" ) + if not (oFSO.FolderExists( sServerDir ) ) then + Set oFSO = Nothing + SendError 102, currentFolder + end if + + Set oCurrentFolder = oFSO.GetFolder( sServerDir ) + Set oFolders = oCurrentFolder.SubFolders + Set oFiles = oCurrentFolder.Files + + ' Open the "Folders" node. + Response.Write "<Folders>" + + For Each oFolder in oFolders + Response.Write "<Folder name=""" & ConvertToXmlAttribute( oFolder.name ) & """ />" + Next + + ' Close the "Folders" node. + Response.Write "</Folders>" + + ' Open the "Files" node. + Response.Write "<Files>" + + For Each oFile in oFiles + Dim iFileSize + iFileSize = Round( oFile.size / 1024 ) + If ( iFileSize < 1 AND oFile.size <> 0 ) Then iFileSize = 1 + + Response.Write "<File name=""" & ConvertToXmlAttribute( oFile.name ) & """ size=""" & iFileSize & """ />" + Next + + ' Close the "Files" node. + Response.Write "</Files>" +End Sub + +Sub CreateFolder( resourceType, currentFolder ) + Dim sErrorNumber + + Dim sNewFolderName + sNewFolderName = Request.QueryString( "NewFolderName" ) + sNewFolderName = SanitizeFolderName( sNewFolderName ) + + If ( sNewFolderName = "" OR InStr( 1, sNewFolderName, ".." ) > 0 ) Then + sErrorNumber = "102" + Else + ' Map the virtual path to the local server path of the current folder. + Dim sServerDir + sServerDir = ServerMapFolder( resourceType, CombinePaths(currentFolder, sNewFolderName), "CreateFolder" ) + + On Error Resume Next + + CreateServerFolder sServerDir + + Dim iErrNumber, sErrDescription + iErrNumber = err.number + sErrDescription = err.Description + + On Error Goto 0 + + Select Case iErrNumber + Case 0 + sErrorNumber = "0" + Case 52 + sErrorNumber = "102" ' Invalid Folder Name. + Case 70 + sErrorNumber = "103" ' Security Error. + Case 76 + sErrorNumber = "102" ' Path too long. + Case Else + sErrorNumber = "110" + End Select + End If + + ' Create the "Error" node. + Response.Write "<Error number=""" & sErrorNumber & """ originalNumber=""" & iErrNumber & """ originalDescription=""" & ConvertToXmlAttribute( sErrDescription ) & """ />" +End Sub + +Sub FileUpload( resourceType, currentFolder, sCommand ) + Dim oUploader + Set oUploader = New NetRube_Upload + oUploader.MaxSize = 0 + oUploader.Allowed = ConfigAllowedExtensions.Item( resourceType ) + oUploader.Denied = ConfigDeniedExtensions.Item( resourceType ) + oUploader.HtmlExtensions = ConfigHtmlExtensions + oUploader.GetData + + Dim sErrorNumber + sErrorNumber = "0" + + Dim sFileName, sOriginalFileName, sExtension + sFileName = "" + + If oUploader.ErrNum > 0 Then + sErrorNumber = "202" + Else + ' Map the virtual path to the local server path. + Dim sServerDir + sServerDir = ServerMapFolder( resourceType, currentFolder, sCommand ) + + Dim oFSO + Set oFSO = Server.CreateObject( "Scripting.FileSystemObject" ) + if not (oFSO.FolderExists( sServerDir ) ) then + sErrorNumber = "102" + else + ' Get the uploaded file name. + sFileName = oUploader.File( "NewFile" ).Name + sExtension = oUploader.File( "NewFile" ).Ext + sFileName = SanitizeFileName( sFileName ) + sOriginalFileName = sFileName + + Dim iCounter + iCounter = 0 + + Do While ( True ) + Dim sFilePath + sFilePath = sServerDir & sFileName + + If ( oFSO.FileExists( sFilePath ) ) Then + iCounter = iCounter + 1 + sFileName = RemoveExtension( sOriginalFileName ) & "(" & iCounter & ")." & sExtension + sErrorNumber = "201" + Else + oUploader.SaveAs "NewFile", sFilePath + If oUploader.ErrNum > 0 Then sErrorNumber = "202" + Exit Do + End If + Loop + end if + End If + + Set oUploader = Nothing + + dim sFileUrl + sFileUrl = CombinePaths( GetResourceTypePath( resourceType, sCommand ) , currentFolder ) + sFileUrl = CombinePaths( sFileUrl, sFileName ) + + SendUploadResults sErrorNumber, sFileUrl, sFileName, "" +End Sub + +%> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/asp/config.asp =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/asp/config.asp (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/asp/config.asp 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,128 @@ +<% + ' FCKeditor - The text editor for Internet - http://www.fckeditor.net + ' Copyright (C) 2003-2008 Frederico Caldeira Knabben + ' + ' == BEGIN LICENSE == + ' + ' Licensed under the terms of any of the following licenses at your + ' choice: + ' + ' - GNU General Public License Version 2 or later (the "GPL") + ' http://www.gnu.org/licenses/gpl.html + ' + ' - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + ' http://www.gnu.org/licenses/lgpl.html + ' + ' - Mozilla Public License Version 1.1 or later (the "MPL") + ' http://www.mozilla.org/MPL/MPL-1.1.html + ' + ' == END LICENSE == + ' + ' Configuration file for the File Manager Connector for ASP. +%> +<% + +' SECURITY: You must explicitly enable this "connector" (set it to "True"). +' WARNING: don't just set "ConfigIsEnabled = true", you must be sure that only +' authenticated users can access this file or use some kind of session checking. +Dim ConfigIsEnabled +ConfigIsEnabled = False + +' Path to user files relative to the document root. +' This setting is preserved only for backward compatibility. +' You should look at the settings for each resource type to get the full potential +Dim ConfigUserFilesPath +ConfigUserFilesPath = "/userfiles/" + +' Due to security issues with Apache modules, it is recommended to leave the +' following setting enabled. +Dim ConfigForceSingleExtension +ConfigForceSingleExtension = true + +' What the user can do with this connector +Dim ConfigAllowedCommands +ConfigAllowedCommands = "QuickUpload|FileUpload|GetFolders|GetFoldersAndFiles|CreateFolder" + +' Allowed Resource Types +Dim ConfigAllowedTypes +ConfigAllowedTypes = "File|Image|Flash|Media" + +' For security, HTML is allowed in the first Kb of data for files having the +' following extensions only. +Dim ConfigHtmlExtensions +ConfigHtmlExtensions = "html|htm|xml|xsd|txt|js" +' +' Configuration settings for each Resource Type +' +' - AllowedExtensions: the possible extensions that can be allowed. +' If it is empty then any file type can be uploaded. +' +' - DeniedExtensions: The extensions that won't be allowed. +' If it is empty then no restrictions are done here. +' +' For a file to be uploaded it has to fulfill both the AllowedExtensions +' and DeniedExtensions (that's it: not being denied) conditions. +' +' - FileTypesPath: the virtual folder relative to the document root where +' these resources will be located. +' Attention: It must start and end with a slash: '/' +' +' - FileTypesAbsolutePath: the physical path to the above folder. It must be +' an absolute path. +' If it's an empty string then it will be autocalculated. +' Useful if you are using a virtual directory, symbolic link or alias. +' Examples: 'C:\\MySite\\userfiles\\' or '/root/mysite/userfiles/'. +' Attention: The above 'FileTypesPath' must point to the same directory. +' Attention: It must end with a slash: '/' +' +' - QuickUploadPath: the virtual folder relative to the document root where +' these resources will be uploaded using the Upload tab in the resources +' dialogs. +' Attention: It must start and end with a slash: '/' +' +' - QuickUploadAbsolutePath: the physical path to the above folder. It must be +' an absolute path. +' If it's an empty string then it will be autocalculated. +' Useful if you are using a virtual directory, symbolic link or alias. +' Examples: 'C:\\MySite\\userfiles\\' or '/root/mysite/userfiles/'. +' Attention: The above 'QuickUploadPath' must point to the same directory. +' Attention: It must end with a slash: '/' +' + +Dim ConfigAllowedExtensions, ConfigDeniedExtensions, ConfigFileTypesPath, ConfigFileTypesAbsolutePath, ConfigQuickUploadPath, ConfigQuickUploadAbsolutePath +Set ConfigAllowedExtensions = CreateObject( "Scripting.Dictionary" ) +Set ConfigDeniedExtensions = CreateObject( "Scripting.Dictionary" ) +Set ConfigFileTypesPath = CreateObject( "Scripting.Dictionary" ) +Set ConfigFileTypesAbsolutePath = CreateObject( "Scripting.Dictionary" ) +Set ConfigQuickUploadPath = CreateObject( "Scripting.Dictionary" ) +Set ConfigQuickUploadAbsolutePath = CreateObject( "Scripting.Dictionary" ) + +ConfigAllowedExtensions.Add "File", "7z|aiff|asf|avi|bmp|csv|doc|fla|flv|gif|gz|gzip|jpeg|jpg|mid|mov|mp3|mp4|mpc|mpeg|mpg|ods|odt|pdf|png|ppt|pxd|qt|ram|rar|rm|rmi|rmvb|rtf|sdc|sitd|swf|sxc|sxw|tar|tgz|tif|tiff|txt|vsd|wav|wma|wmv|xls|xml|zip" +ConfigDeniedExtensions.Add "File", "" +ConfigFileTypesPath.Add "File", ConfigUserFilesPath & "file/" +ConfigFileTypesAbsolutePath.Add "File", "" +ConfigQuickUploadPath.Add "File", ConfigUserFilesPath +ConfigQuickUploadAbsolutePath.Add "File", "" + +ConfigAllowedExtensions.Add "Image", "bmp|gif|jpeg|jpg|png" +ConfigDeniedExtensions.Add "Image", "" +ConfigFileTypesPath.Add "Image", ConfigUserFilesPath & "image/" +ConfigFileTypesAbsolutePath.Add "Image", "" +ConfigQuickUploadPath.Add "Image", ConfigUserFilesPath +ConfigQuickUploadAbsolutePath.Add "Image", "" + +ConfigAllowedExtensions.Add "Flash", "swf|flv" +ConfigDeniedExtensions.Add "Flash", "" +ConfigFileTypesPath.Add "Flash", ConfigUserFilesPath & "flash/" +ConfigFileTypesAbsolutePath.Add "Flash", "" +ConfigQuickUploadPath.Add "Flash", ConfigUserFilesPath +ConfigQuickUploadAbsolutePath.Add "Flash", "" + +ConfigAllowedExtensions.Add "Media", "aiff|asf|avi|bmp|fla|flv|gif|jpeg|jpg|mid|mov|mp3|mp4|mpc|mpeg|mpg|png|qt|ram|rm|rmi|rmvb|swf|tif|tiff|wav|wma|wmv" +ConfigDeniedExtensions.Add "Media", "" +ConfigFileTypesPath.Add "Media", ConfigUserFilesPath & "media/" +ConfigFileTypesAbsolutePath.Add "Media", "" +ConfigQuickUploadPath.Add "Media", ConfigUserFilesPath +ConfigQuickUploadAbsolutePath.Add "Media", "" + +%> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/asp/connector.asp =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/asp/connector.asp (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/asp/connector.asp 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,88 @@ +<%@ CodePage=65001 Language="VBScript"%> +<% +Option Explicit +Response.Buffer = True +%> +<% + ' FCKeditor - The text editor for Internet - http://www.fckeditor.net + ' Copyright (C) 2003-2008 Frederico Caldeira Knabben + ' + ' == BEGIN LICENSE == + ' + ' Licensed under the terms of any of the following licenses at your + ' choice: + ' + ' - GNU General Public License Version 2 or later (the "GPL") + ' http://www.gnu.org/licenses/gpl.html + ' + ' - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + ' http://www.gnu.org/licenses/lgpl.html + ' + ' - Mozilla Public License Version 1.1 or later (the "MPL") + ' http://www.mozilla.org/MPL/MPL-1.1.html + ' + ' == END LICENSE == + ' + ' This is the File Manager Connector for ASP. +%> +<!--#include file="config.asp"--> +<!--#include file="util.asp"--> +<!--#include file="io.asp"--> +<!--#include file="basexml.asp"--> +<!--#include file="commands.asp"--> +<!--#include file="class_upload.asp"--> +<% + +If ( ConfigIsEnabled = False ) Then + SendError 1, "This connector is disabled. Please check the ""editor/filemanager/connectors/asp/config.asp"" file" +End If + +DoResponse + +Sub DoResponse() + Dim sCommand, sResourceType, sCurrentFolder + + ' Get the main request information. + sCommand = Request.QueryString("Command") + + sResourceType = Request.QueryString("Type") + If ( sResourceType = "" ) Then sResourceType = "File" + + sCurrentFolder = GetCurrentFolder() + + ' Check if it is an allowed command + if ( Not IsAllowedCommand( sCommand ) ) then + SendError 1, "The """ & sCommand & """ command isn't allowed" + end if + + ' Check if it is an allowed resource type. + if ( Not IsAllowedType( sResourceType ) ) Then + SendError 1, "The """ & sResourceType & """ resource type isn't allowed" + end if + + ' File Upload doesn't have to Return XML, so it must be intercepted before anything. + If ( sCommand = "FileUpload" ) Then + FileUpload sResourceType, sCurrentFolder, sCommand + Exit Sub + End If + + SetXmlHeaders + + CreateXmlHeader sCommand, sResourceType, sCurrentFolder, GetUrlFromPath( sResourceType, sCurrentFolder, sCommand) + + ' Execute the required command. + Select Case sCommand + Case "GetFolders" + GetFolders sResourceType, sCurrentFolder + Case "GetFoldersAndFiles" + GetFoldersAndFiles sResourceType, sCurrentFolder + Case "CreateFolder" + CreateFolder sResourceType, sCurrentFolder + End Select + + CreateXmlFooter + + Response.End +End Sub + +%> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/asp/io.asp =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/asp/io.asp (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/asp/io.asp 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,254 @@ +<% + ' FCKeditor - The text editor for Internet - http://www.fckeditor.net + ' Copyright (C) 2003-2008 Frederico Caldeira Knabben + ' + ' == BEGIN LICENSE == + ' + ' Licensed under the terms of any of the following licenses at your + ' choice: + ' + ' - GNU General Public License Version 2 or later (the "GPL") + ' http://www.gnu.org/licenses/gpl.html + ' + ' - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + ' http://www.gnu.org/licenses/lgpl.html + ' + ' - Mozilla Public License Version 1.1 or later (the "MPL") + ' http://www.mozilla.org/MPL/MPL-1.1.html + ' + ' == END LICENSE == + ' + ' This file include IO specific functions used by the ASP Connector. +%> +<% +function CombinePaths( sBasePath, sFolder) + CombinePaths = RemoveFromEnd( sBasePath, "/" ) & "/" & RemoveFromStart( sFolder, "/" ) +end function + +Function GetResourceTypePath( resourceType, sCommand ) + if ( sCommand = "QuickUpload") then + GetResourceTypePath = ConfigQuickUploadPath.Item( resourceType ) + else + GetResourceTypePath = ConfigFileTypesPath.Item( resourceType ) + end if +end Function + +Function GetResourceTypeDirectory( resourceType, sCommand ) + if ( sCommand = "QuickUpload") then + + if ( ConfigQuickUploadAbsolutePath.Item( resourceType ) <> "" ) then + GetResourceTypeDirectory = ConfigQuickUploadAbsolutePath.Item( resourceType ) + else + ' Map the "UserFiles" path to a local directory. + GetResourceTypeDirectory = Server.MapPath( ConfigQuickUploadPath.Item( resourceType ) ) + end if + else + if ( ConfigFileTypesAbsolutePath.Item( resourceType ) <> "" ) then + GetResourceTypeDirectory = ConfigFileTypesAbsolutePath.Item( resourceType ) + else + ' Map the "UserFiles" path to a local directory. + GetResourceTypeDirectory = Server.MapPath( ConfigFileTypesPath.Item( resourceType ) ) + end if + end if +end Function + +Function GetUrlFromPath( resourceType, folderPath, sCommand ) + GetUrlFromPath = CombinePaths( GetResourceTypePath( resourceType, sCommand ), folderPath ) +End Function + +Function RemoveExtension( fileName ) + RemoveExtension = Left( fileName, InStrRev( fileName, "." ) - 1 ) +End Function + +Function ServerMapFolder( resourceType, folderPath, sCommand ) + Dim sResourceTypePath + ' Get the resource type directory. + sResourceTypePath = GetResourceTypeDirectory( resourceType, sCommand ) + + ' Ensure that the directory exists. + CreateServerFolder sResourceTypePath + + ' Return the resource type directory combined with the required path. + ServerMapFolder = CombinePaths( sResourceTypePath, folderPath ) +End Function + +Sub CreateServerFolder( folderPath ) + Dim oFSO + Set oFSO = Server.CreateObject( "Scripting.FileSystemObject" ) + + Dim sParent + sParent = oFSO.GetParentFolderName( folderPath ) + + ' Check if the parent exists, or create it. + If ( NOT oFSO.FolderExists( sParent ) ) Then CreateServerFolder( sParent ) + + If ( oFSO.FolderExists( folderPath ) = False ) Then + On Error resume next + oFSO.CreateFolder( folderPath ) + + if err.number<>0 then + dim sErrorNumber + Dim iErrNumber, sErrDescription + iErrNumber = err.number + sErrDescription = err.Description + + On Error Goto 0 + + Select Case iErrNumber + Case 52 + sErrorNumber = "102" ' Invalid Folder Name. + Case 70 + sErrorNumber = "103" ' Security Error. + Case 76 + sErrorNumber = "102" ' Path too long. + Case Else + sErrorNumber = "110" + End Select + + SendError sErrorNumber, "CreateServerFolder(" & folderPath & ") : " & sErrDescription + end if + + End If + + Set oFSO = Nothing +End Sub + +Function IsAllowedExt( extension, resourceType ) + Dim oRE + Set oRE = New RegExp + oRE.IgnoreCase = True + oRE.Global = True + + Dim sAllowed, sDenied + sAllowed = ConfigAllowedExtensions.Item( resourceType ) + sDenied = ConfigDeniedExtensions.Item( resourceType ) + + IsAllowedExt = True + + If sDenied <> "" Then + oRE.Pattern = sDenied + IsAllowedExt = Not oRE.Test( extension ) + End If + + If IsAllowedExt And sAllowed <> "" Then + oRE.Pattern = sAllowed + IsAllowedExt = oRE.Test( extension ) + End If + + Set oRE = Nothing +End Function + +Function IsAllowedType( resourceType ) + Dim oRE + Set oRE = New RegExp + oRE.IgnoreCase = True + oRE.Global = True + oRE.Pattern = "^(" & ConfigAllowedTypes & ")$" + + IsAllowedType = oRE.Test( resourceType ) + + Set oRE = Nothing +End Function + +Function IsAllowedCommand( sCommand ) + Dim oRE + Set oRE = New RegExp + oRE.IgnoreCase = True + oRE.Global = True + oRE.Pattern = "^(" & ConfigAllowedCommands & ")$" + + IsAllowedCommand = oRE.Test( sCommand ) + + Set oRE = Nothing +End Function + +function GetCurrentFolder() + dim sCurrentFolder + sCurrentFolder = Request.QueryString("CurrentFolder") + If ( sCurrentFolder = "" ) Then sCurrentFolder = "/" + + ' Check the current folder syntax (must begin and start with a slash). + If ( Right( sCurrentFolder, 1 ) <> "/" ) Then sCurrentFolder = sCurrentFolder & "/" + If ( Left( sCurrentFolder, 1 ) <> "/" ) Then sCurrentFolder = "/" & sCurrentFolder + + ' Check for invalid folder paths (..) + If ( InStr( 1, sCurrentFolder, ".." ) <> 0 OR InStr( 1, sCurrentFolder, "\" ) <> 0) Then + SendError 102, "" + End If + + GetCurrentFolder = sCurrentFolder +end function + +' Do a cleanup of the folder name to avoid possible problems +function SanitizeFolderName( sNewFolderName ) + Dim oRegex + Set oRegex = New RegExp + oRegex.Global = True + +' remove . \ / | : ? * " < > and control characters + oRegex.Pattern = "(\.|\\|\/|\||:|\?|\*|""|\<|\>|[\u0000-\u001F]|\u007F)" + SanitizeFolderName = oRegex.Replace( sNewFolderName, "_" ) + + Set oRegex = Nothing +end function + +' Do a cleanup of the file name to avoid possible problems +function SanitizeFileName( sNewFileName ) + Dim oRegex + Set oRegex = New RegExp + oRegex.Global = True + + if ( ConfigForceSingleExtension = True ) then + oRegex.Pattern = "\.(?![^.]*$)" + sNewFileName = oRegex.Replace( sNewFileName, "_" ) + end if + +' remove \ / | : ? * " < > and control characters + oRegex.Pattern = "(\\|\/|\||:|\?|\*|""|\<|\>|[\u0000-\u001F]|\u007F)" + SanitizeFileName = oRegex.Replace( sNewFileName, "_" ) + + Set oRegex = Nothing +end function + +' This is the function that sends the results of the uploading process. +Sub SendUploadResults( errorNumber, fileUrl, fileName, customMsg ) + Response.Clear + Response.Write "<script type=""text/javascript"">" + Response.Write "(function()" + Response.Write "{" + Response.Write "var d = document.domain ;" + + Response.Write " while ( true )" + Response.Write " {" + ' Test if we can access a parent property. + Response.Write " try" + Response.Write " {" + Response.Write " var test = window.top.opener.document.domain ;" + Response.Write " break ;" + Response.Write " }" + Response.Write " catch( e ) {}" + + ' Remove a domain part: www.mytest.example.com => mytest.example.com => example.com ... + Response.Write " d = d.replace( /.*?(?:\.|$)/, '' ) ;" + + Response.Write " if ( d.length == 0 )" + ' It was not able to detect the domain. + Response.Write " break ;" + Response.Write "" + Response.Write " try" + Response.Write " {" + Response.Write " document.domain = d ;" + Response.Write " }" + Response.Write " catch (e)" + Response.Write " {" + Response.Write " break ;" + Response.Write " }" + Response.Write " }" + Response.Write "})() ;" + + Response.Write "window.parent.OnUploadCompleted(" & errorNumber & ",""" & Replace( fileUrl, """", "\""" ) & """,""" & Replace( fileName, """", "\""" ) & """,""" & Replace( customMsg , """", "\""" ) & """) ;" + Response.Write "</script>" + Response.End +End Sub + +%> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/asp/upload.asp =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/asp/upload.asp (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/asp/upload.asp 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,65 @@ +<%@ CodePage=65001 Language="VBScript"%> +<% +Option Explicit +Response.Buffer = True +%> +<% + ' FCKeditor - The text editor for Internet - http://www.fckeditor.net + ' Copyright (C) 2003-2008 Frederico Caldeira Knabben + ' + ' == BEGIN LICENSE == + ' + ' Licensed under the terms of any of the following licenses at your + ' choice: + ' + ' - GNU General Public License Version 2 or later (the "GPL") + ' http://www.gnu.org/licenses/gpl.html + ' + ' - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + ' http://www.gnu.org/licenses/lgpl.html + ' + ' - Mozilla Public License Version 1.1 or later (the "MPL") + ' http://www.mozilla.org/MPL/MPL-1.1.html + ' + ' == END LICENSE == + ' + ' This is the "File Uploader" for ASP. +%> +<!--#include file="config.asp"--> +<!--#include file="util.asp"--> +<!--#include file="io.asp"--> +<!--#include file="commands.asp"--> +<!--#include file="class_upload.asp"--> +<% + +Sub SendError( number, text ) + SendUploadResults number, "", "", text +End Sub + +' Check if this uploader has been enabled. +If ( ConfigIsEnabled = False ) Then + SendUploadResults "1", "", "", "This file uploader is disabled. Please check the ""editor/filemanager/connectors/asp/config.asp"" file" +End If + + Dim sCommand, sResourceType, sCurrentFolder + + sCommand = "QuickUpload" + + sResourceType = Request.QueryString("Type") + If ( sResourceType = "" ) Then sResourceType = "File" + + sCurrentFolder = GetCurrentFolder() + + ' Is Upload enabled? + if ( Not IsAllowedCommand( sCommand ) ) then + SendUploadResults "1", "", "", "The """ & sCommand & """ command isn't allowed" + end if + + ' Check if it is an allowed resource type. + if ( Not IsAllowedType( sResourceType ) ) Then + SendUploadResults "1", "", "", "The " & sResourceType & " resource type isn't allowed" + end if + + FileUpload sResourceType, sCurrentFolder, sCommand + +%> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/asp/util.asp =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/asp/util.asp (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/asp/util.asp 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,55 @@ +<% + ' FCKeditor - The text editor for Internet - http://www.fckeditor.net + ' Copyright (C) 2003-2008 Frederico Caldeira Knabben + ' + ' == BEGIN LICENSE == + ' + ' Licensed under the terms of any of the following licenses at your + ' choice: + ' + ' - GNU General Public License Version 2 or later (the "GPL") + ' http://www.gnu.org/licenses/gpl.html + ' + ' - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + ' http://www.gnu.org/licenses/lgpl.html + ' + ' - Mozilla Public License Version 1.1 or later (the "MPL") + ' http://www.mozilla.org/MPL/MPL-1.1.html + ' + ' == END LICENSE == + ' + ' This file include generic functions used by the ASP Connector. +%> +<% +Function RemoveFromStart( sourceString, charToRemove ) + Dim oRegex + Set oRegex = New RegExp + oRegex.Pattern = "^" & charToRemove & "+" + + RemoveFromStart = oRegex.Replace( sourceString, "" ) +End Function + +Function RemoveFromEnd( sourceString, charToRemove ) + Dim oRegex + Set oRegex = New RegExp + oRegex.Pattern = charToRemove & "+$" + + RemoveFromEnd = oRegex.Replace( sourceString, "" ) +End Function + +Function ConvertToXmlAttribute( value ) + ConvertToXmlAttribute = Replace( value, "&", "&" ) +End Function + +Function InArray( value, sourceArray ) + Dim i + For i = 0 to UBound( sourceArray ) + If sourceArray(i) = value Then + InArray = True + Exit Function + End If + Next + InArray = False +End Function + +%> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/aspx/config.ascx =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/aspx/config.ascx (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/aspx/config.ascx 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,98 @@ +<%@ Control Language="C#" EnableViewState="false" AutoEventWireup="false" Inherits="FredCK.FCKeditorV2.FileBrowser.Config" %> +<%-- + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Configuration file for the File Browser Connector for ASP.NET. +--%> +<script runat="server"> + + /** + * This function must check the user session to be sure that he/she is + * authorized to upload and access files in the File Browser. + */ + private bool CheckAuthentication() + { + // WARNING : DO NOT simply return "true". By doing so, you are allowing + // "anyone" to upload and list the files in your server. You must implement + // some kind of session validation here. Even something very simple as... + // + // return ( Session[ "IsAuthorized" ] != null && (bool)Session[ "IsAuthorized" ] == true ); + // + // ... where Session[ "IsAuthorized" ] is set to "true" as soon as the + // user logs in your system. + + return false; + } + + public override void SetConfig() + { + // SECURITY: You must explicitly enable this "connector". (Set it to "true"). + Enabled = CheckAuthentication(); + + // URL path to user files. + UserFilesPath = "/userfiles/"; + + // The connector tries to resolve the above UserFilesPath automatically. + // Use the following setting it you prefer to explicitely specify the + // absolute path. Examples: 'C:\\MySite\\userfiles\\' or '/root/mysite/userfiles/'. + // Attention: The above 'UserFilesPath' URL must point to the same directory. + UserFilesAbsolutePath = ""; + + // Due to security issues with Apache modules, it is recommended to leave the + // following setting enabled. + ForceSingleExtension = true; + + // Allowed Resource Types + AllowedTypes = new string[] { "File", "Image", "Flash", "Media" }; + + // For security, HTML is allowed in the first Kb of data for files having the + // following extensions only. + HtmlExtensions = new string[] { "html", "htm", "xml", "xsd", "txt", "js" }; + + TypeConfig[ "File" ].AllowedExtensions = new string[] { "7z", "aiff", "asf", "avi", "bmp", "csv", "doc", "fla", "flv", "gif", "gz", "gzip", "jpeg", "jpg", "mid", "mov", "mp3", "mp4", "mpc", "mpeg", "mpg", "ods", "odt", "pdf", "png", "ppt", "pxd", "qt", "ram", "rar", "rm", "rmi", "rmvb", "rtf", "sdc", "sitd", "swf", "sxc", "sxw", "tar", "tgz", "tif", "tiff", "txt", "vsd", "wav", "wma", "wmv", "xls", "xml", "zip" }; + TypeConfig[ "File" ].DeniedExtensions = new string[] { }; + TypeConfig[ "File" ].FilesPath = "%UserFilesPath%file/"; + TypeConfig[ "File" ].FilesAbsolutePath = ( UserFilesAbsolutePath == "" ? "" : "%UserFilesAbsolutePath%file/" ); + TypeConfig[ "File" ].QuickUploadPath = "%UserFilesPath%"; + TypeConfig[ "File" ].QuickUploadAbsolutePath = ( UserFilesAbsolutePath == "" ? "" : "%UserFilesAbsolutePath%" ); + + TypeConfig[ "Image" ].AllowedExtensions = new string[] { "bmp", "gif", "jpeg", "jpg", "png" }; + TypeConfig[ "Image" ].DeniedExtensions = new string[] { }; + TypeConfig[ "Image" ].FilesPath = "%UserFilesPath%image/"; + TypeConfig[ "Image" ].FilesAbsolutePath = ( UserFilesAbsolutePath == "" ? "" : "%UserFilesAbsolutePath%image/" ); + TypeConfig[ "Image" ].QuickUploadPath = "%UserFilesPath%"; + TypeConfig[ "Image" ].QuickUploadAbsolutePath = ( UserFilesAbsolutePath == "" ? "" : "%UserFilesAbsolutePath%" ); + + TypeConfig[ "Flash" ].AllowedExtensions = new string[] { "swf", "flv" }; + TypeConfig[ "Flash" ].DeniedExtensions = new string[] { }; + TypeConfig[ "Flash" ].FilesPath = "%UserFilesPath%flash/"; + TypeConfig[ "Flash" ].FilesAbsolutePath = ( UserFilesAbsolutePath == "" ? "" : "%UserFilesAbsolutePath%flash/" ); + TypeConfig[ "Flash" ].QuickUploadPath = "%UserFilesPath%"; + TypeConfig[ "Flash" ].QuickUploadAbsolutePath = ( UserFilesAbsolutePath == "" ? "" : "%UserFilesAbsolutePath%" ); + + TypeConfig[ "Media" ].AllowedExtensions = new string[] { "aiff", "asf", "avi", "bmp", "fla", "flv", "gif", "jpeg", "jpg", "mid", "mov", "mp3", "mp4", "mpc", "mpeg", "mpg", "png", "qt", "ram", "rm", "rmi", "rmvb", "swf", "tif", "tiff", "wav", "wma", "wmv" }; + TypeConfig[ "Media" ].DeniedExtensions = new string[] { }; + TypeConfig[ "Media" ].FilesPath = "%UserFilesPath%media/"; + TypeConfig[ "Media" ].FilesAbsolutePath = ( UserFilesAbsolutePath == "" ? "" : "%UserFilesAbsolutePath%media/" ); + TypeConfig[ "Media" ].QuickUploadPath = "%UserFilesPath%"; + TypeConfig[ "Media" ].QuickUploadAbsolutePath = ( UserFilesAbsolutePath == "" ? "" : "%UserFilesAbsolutePath%" ); + } + +</script> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/aspx/connector.aspx =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/aspx/connector.aspx (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/aspx/connector.aspx 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,32 @@ +<%@ Page Language="c#" Trace="false" Inherits="FredCK.FCKeditorV2.FileBrowser.Connector" AutoEventWireup="false" %> +<%@ Register Src="config.ascx" TagName="Config" TagPrefix="FCKeditor" %> +<%-- + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * This is the File Browser Connector for ASP.NET. + * + * The code of this page if included in the FCKeditor.Net package, + * in the FredCK.FCKeditorV2.dll assembly file. So to use it you must + * include that DLL in your "bin" directory. + * + * To download the FCKeditor.Net package, go to our official web site: + * http://www.fckeditor.net +--%> +<FCKeditor:Config id="Config" runat="server"></FCKeditor:Config> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/aspx/upload.aspx =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/aspx/upload.aspx (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/aspx/upload.aspx 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,32 @@ +<%@ Page Language="c#" Trace="false" Inherits="FredCK.FCKeditorV2.FileBrowser.Uploader" AutoEventWireup="false" %> +<%@ Register Src="config.ascx" TagName="Config" TagPrefix="FCKeditor" %> +<%-- + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * This is the Uploader for ASP.NET. + * + * The code of this page if included in the FCKeditor.Net package, + * in the FredCK.FCKeditorV2.dll assemblyfile. So to use it you must + * include that DLL in your "bin" directory. + * + * To download the FCKeditor.Net package, go to our official web site: + * http://www.fckeditor.net +--%> +<FCKeditor:Config id="Config" runat="server"></FCKeditor:Config> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/ImageObject.cfc =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/ImageObject.cfc (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/ImageObject.cfc 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,273 @@ +<cfcomponent name="ImageObject"> +<!--- + ImageObject.cfc written by Rick Root (rick@webworksllc.com) + + Related Web Sites: + - http://www.opensourcecf.com/imagecfc (home page) + + + This is an object oriented interface to the original + ImageCFC. + + Example Code: + + io = createObject("component","ImageObject"); + io.setOption("defaultJpegCompression",95); + io.init("#ExpandPath(".")#/emily.jpg"); + io.scaleWidth(500); + io.save("#ExpandPath(".")#/imagex1.jpg"); + + io.flipHorizontal(); + io.save("#ExpandPath(".")#/imagex2.jpg"); + io.revert(); + io.filterFastBlur(2,5); + io.save("#ExpandPath(".")#/imagex3.jpg"); + io.revert(); + io.filterPosterize(32); + io.save("#ExpandPath(".")#/imagex4.jpg"); + + + LICENSE + ------- + Copyright (c) 2006, Rick Root <rick@webworksllc.com> + All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, are permitted provided that the + following conditions are met: + + - Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + - Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + - Neither the name of the Webworks, LLC. nor the names of + its contributors may be used to endorse or promote products + derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +---> + +<cfset variables.img = ""> +<cfset variables.revertimg = ""> +<cfset variables.imageCFC = createObject("component","image")> +<cfset variables.imageInfo = structNew()> + <cfset variables.imageInfo.width = 0> + <cfset variables.imageInfo.height = 0> + <cfset variables.imageInfo.colorModel = ""> + <cfset variables.imageInfo.colorspace = ""> + <cfset variables.imageInfo.objColorModel = ""> + <cfset variables.imageInfo.objColorspace = ""> + <cfset variables.imageInfo.sampleModel = ""> + <cfset variables.imageInfo.imageType = 0> + <cfset variables.imageInfo.misc = ""> + <cfset variables.imageInfo.canModify = false> +<cfset variables.imageCFC.setOption("throwonerror",true)> + +<!--- + + init(filename) Initialize object from a file. + init(width, height) Initialize with a blank image + init(bufferedImage) Initiailize with an existing object +---> +<cffunction name="init" access="public" output="false" returnType="void"> + <cfargument name="arg1" type="any" required="yes"> + <cfargument name="arg2" type="any" required="no"> + + <cfif isDefined("arg2") and isNumeric(arg1) and isNumeric(arg2)> + <cfset arg1 = javacast("int",int(arg1))> + <cfset arg2 = javacast("int",int(arg2))> + <cfset variables.img = createObject("java","java.awt.image.BufferedImage")> + <cfset variables.img.init(arg1,arg2,variables.img.TYPE_INT_RGB)> + <cfelseif arg1.getClass().getName() eq "java.awt.image.BufferedImage"> + <cfset variables.img = arg1> + <cfelseif isSimpleValue(arg1) and len(arg1) gt 0> + <cfset imageResults = variables.imageCFC.readImage(arg1, "no")> + <cfset variables.img = imageResults.img> + <cfelse> + <cfthrow message="Object Instantiation Error" detail="You have attempted to initialize ooimage.cfc with invalid arguments. Please consult the documentation for correct initialization arguments."> + </cfif> + <cfif variables.revertimg eq ""> + <cfset variables.revertimg = variables.img> + </cfif> + <cfset variables.imageInfo = imageCFC.getImageInfo(variables.img,"")> + <cfreturn> +</cffunction> + +<cffunction name="flipHorizontal" access="public" output="true" returnType="void" hint="Flip an image horizontally."> + <cfset var imageResults = imageCFC.flipHorizontal(variables.img,"","")> + <cfset variables.revertimg = variables.img> + <cfset variables.img = imageResults.img> + <cfset variables.imageInfo = imageCFC.getImageInfo(variables.img,"")> +</cffunction> + +<cffunction name="getImageInfo" access="public" output="true" returntype="struct" hint="Returns image information."> + <cfreturn variables.imageInfo> +</cffunction> +<cffunction name="getImageObject" access="public" output="true" returntype="struct" hint="Returns a java Buffered Image Object."> + <cfreturn variables.img> +</cffunction> + +<cffunction name="flipVertical" access="public" output="true" returntype="void" hint="Flop an image vertically."> + <cfset var imageResults = imageCFC.flipVertical(variables.img,"","")> + <cfset variables.revertimg = variables.img> + <cfset variables.img = imageResults.img> + <cfset variables.imageInfo = imageCFC.getImageInfo(variables.img,"")> +</cffunction> + +<cffunction name="scaleWidth" access="public" output="true" returntype="void" hint="Scale an image to a specific width."> + <cfargument name="newWidth" required="yes" type="numeric"> + <cfset var imageResults = imageCFC.scaleWidth(variables.img,"","", newWidth)> + <cfset variables.revertimg = variables.img> + <cfset variables.img = imageResults.img> + <cfset variables.imageInfo = imageCFC.getImageInfo(variables.img,"")> + +</cffunction> + +<cffunction name="scaleHeight" access="public" output="true" returntype="void" hint="Scale an image to a specific height."> + <cfargument name="newHeight" required="yes" type="numeric"> + <cfset var imageResults = imageCFC.scaleHeight(variables.img,"","", newHeight)> + <cfset variables.revertimg = variables.img> + <cfset variables.img = imageResults.img> + <cfset variables.imageInfo = imageCFC.getImageInfo(variables.img,"")> +</cffunction> + +<cffunction name="resize" access="public" output="true" returntype="void" hint="Resize an image to a specific width and height."> + <cfargument name="newWidth" required="yes" type="numeric"> + <cfargument name="newHeight" required="yes" type="numeric"> + <cfargument name="preserveAspect" required="no" type="boolean" default="FALSE"> + <cfargument name="cropToExact" required="no" type="boolean" default="FALSE"> + + <cfset var imageResults = imageCFC.resize(variables.img,"","",newWidth,newHeight,preserveAspect,cropToExact)> + <cfset variables.revertimg = variables.img> + <cfset variables.img = imageResults.img> + <cfset variables.imageInfo = imageCFC.getImageInfo(variables.img,"")> +</cffunction> + +<cffunction name="crop" access="public" output="true" returntype="void" hint="Crop an image."> + <cfargument name="fromX" required="yes" type="numeric"> + <cfargument name="fromY" required="yes" type="numeric"> + <cfargument name="newWidth" required="yes" type="numeric"> + <cfargument name="newHeight" required="yes" type="numeric"> + <cfset var imageResults = imageCFC.crop(variables.img,"","",fromX,fromY,newWidth,newHeight)> + <cfset variables.revertimg = variables.img> + <cfset variables.img = imageResults.img> + <cfset variables.imageInfo = imageCFC.getImageInfo(variables.img,"")> + +</cffunction> + +<cffunction name="rotate" access="public" output="true" returntype="void" hint="Rotate an image (+/-)90, (+/-)180, or (+/-)270 degrees."> + <cfargument name="degrees" required="yes" type="numeric"> + <cfset var imageResults = imageCFC.rotate(variables.img,"","",degrees)> + <cfset variables.revertimg = variables.img> + <cfset variables.img = imageResults.img> + <cfset variables.imageInfo = imageCFC.getImageInfo(variables.img,"")> + +</cffunction> + +<cffunction name="setOption" access="public" output="true" returnType="void" hint="Sets values for allowed CFC options."> + <cfargument name="key" type="string" required="yes"> + <cfargument name="val" type="string" required="yes"> + <cfif lcase(trim(key)) eq "throwonerror"> + <cfthrow message="Option Configuration Error" detail="You cannot set the throwOnError option when using ImageObject.cfc"> + </cfif> + <cfset imageCFC.setOption(key, val)> + +</cffunction> + +<cffunction name="getOption" access="public" output="true" returnType="any" hint="Returns the current value for the specified CFC option."> + <cfargument name="key" type="string" required="yes"> + <cfreturn imageCFC.getOption(key)> +</cffunction> + +<cffunction name="filterFastBlur" access="public" output="true" returntype="void" hint="Internal method used for flipping and flopping images."> + <cfargument name="blurAmount" required="yes" type="numeric"> + <cfargument name="iterations" required="yes" type="numeric"> + <cfset var imageResults = imageCFC.filterFastBlur(variables.img,"","",blurAmount,iterations)> + <cfset variables.revertimg = variables.img> + <cfset variables.img = imageResults.img> + <cfset variables.imageInfo = imageCFC.getImageInfo(variables.img,"")> + +</cffunction> + +<cffunction name="filterSharpen" access="public" output="true" returntype="void" hint="Internal method used for flipping and flopping images."> + <cfset var imageResults = imageCFC.filterSharpen(variables.img,"","")> + <cfset variables.revertimg = variables.img> + <cfset variables.img = imageResults.img> + <cfset variables.imageInfo = imageCFC.getImageInfo(variables.img,"")> + +</cffunction> + + +<cffunction name="filterPosterize" access="public" output="true" returntype="void" hint="Internal method used for flipping and flopping images."> + <cfargument name="amount" required="yes" type="string"> + <cfset var imageResults = imageCFC.filterPosterize(variables.img,"","",amount)> + <cfset variables.revertimg = variables.img> + <cfset variables.img = imageResults.img> + <cfset variables.imageInfo = imageCFC.getImageInfo(variables.img,"")> +</cffunction> + + +<cffunction name="addText" access="public" output="true" returntype="void" hint="Add text to an image."> + <cfargument name="x" required="yes" type="numeric"> + <cfargument name="y" required="yes" type="numeric"> + <cfargument name="fontDetails" required="yes" type="struct"> + <cfargument name="content" required="yes" type="String"> + <cfset var imageResults = imageCFC.addText(variables.img,"","",x,y,fontDetails,content)> + <cfset variables.revertimg = variables.img> + <cfset variables.img = imageResults.img> + <cfset variables.imageInfo = imageCFC.getImageInfo(variables.img,"")> + +</cffunction> + +<cffunction name="watermark" access="public" output="false" returnType="void"> + <cfargument name="wmImage" required="yes" type="Any"> + <cfargument name="alpha" required="yes" type="numeric"> + <cfargument name="placeAtX" required="yes" type="numeric"> + <cfargument name="placeAtY" required="yes" type="numeric"> + + <cfset var imageResults = ""> + <cfif isSimpleValue(wmImage)> + <!--- filename or URL ---> + <cfset imageResults = imageCFC.watermark(variables.img,"","",wmImage,alpha,placeAtX,placeAtY)> + <cfelse> + <!--- must be a java object ---> + <cfset imageResults = imageCFC.watermark(variables.img,wmImage,"","",alpha,placeAtX,placeAtY)> + </cfif> + <cfset variables.revertimg = variables.img> + <cfset variables.img = imageResults.img> + <cfset variables.imageInfo = imageCFC.getImageInfo(variables.img,"")> + +</cffunction> + +<cffunction name="save" access="public" output="false" returnType="void"> + <cfargument name="filename" type="string" required="no"> + <cfargument name="jpegCompression" type="numeric" required="no"> + <cfif isDefined("arguments.jpegCompression") and isNumeric(arguments.jpegCompression)> + <cfset imageCFC.writeImage(filename,variables.img,jpegCompression)> + <cfelse> + <cfset imageCFC.writeImage(filename,variables.img)> + </cfif> +</cffunction> + +<cffunction name="revert" access="public" output="true" returntype="void" hint="Undo the previous manipulation."> + <cfset variables.img = variables.revertimg> + <cfset variables.imageInfo = imageCFC.getImageInfo(variables.img,"")> +</cffunction> + +</cfcomponent> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/cf5_connector.cfm =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/cf5_connector.cfm (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/cf5_connector.cfm 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,315 @@ +<cfsetting enablecfoutputonly="yes" showdebugoutput="no"> +<!--- + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * File Browser connector for ColdFusion 5. + * (based on the original CF connector by Hendrik Kramer - hk@lwd.de) + * + * Note: + * FCKeditor requires that the connector responds with UTF-8 encoded XML. + * As ColdFusion 5 does not fully support UTF-8 encoding, we force ASCII + * file and folder names in this connector to allow CF5 send a UTF-8 + * encoded response - code points under 127 in UTF-8 are stored using a + * single byte, using the same encoding as ASCII, which is damn handy. + * This is all grand for the English speakers, like meself, but I dunno + * how others are gonna take to it. Well, the previous version of this + * connector already did this with file names and nobody seemed to mind, + * so fingers-crossed nobody will mind their folder names being munged too. + * +---> + +<cfparam name="url.command"> +<cfparam name="url.type"> +<cfparam name="url.currentFolder"> +<!--- note: no serverPath url parameter - see config.cfm if you need to set the serverPath manually ---> + +<cfinclude template="config.cfm"> + +<cfscript> + userFilesPath = config.userFilesPath; + + if ( userFilesPath eq "" ) + { + userFilesPath = "/userfiles/"; + } + + // make sure the user files path is correctly formatted + userFilesPath = replace(userFilesPath, "\", "/", "ALL"); + userFilesPath = replace(userFilesPath, '//', '/', 'ALL'); + if ( right(userFilesPath,1) NEQ "/" ) + { + userFilesPath = userFilesPath & "/"; + } + if ( left(userFilesPath,1) NEQ "/" ) + { + userFilesPath = "/" & userFilesPath; + } + + // make sure the current folder is correctly formatted + url.currentFolder = replace(url.currentFolder, "\", "/", "ALL"); + url.currentFolder = replace(url.currentFolder, '//', '/', 'ALL'); + if ( right(url.currentFolder,1) neq "/" ) + { + url.currentFolder = url.currentFolder & "/"; + } + if ( left(url.currentFolder,1) neq "/" ) + { + url.currentFolder = "/" & url.currentFolder; + } + + if ( find("/",getBaseTemplatePath()) neq 0 ) + { + fs = "/"; + } + else + { + fs = "\"; + } + + // Get the base physical path to the web root for this application. The code to determine the path automatically assumes that + // the "FCKeditor" directory in the http request path is directly off the web root for the application and that it's not a + // virtual directory or a symbolic link / junction. Use the serverPath config setting to force a physical path if necessary. + if ( len(config.serverPath) ) + { + serverPath = config.serverPath; + + if ( right(serverPath,1) neq fs ) + { + serverPath = serverPath & fs; + } + } + else + { + serverPath = replaceNoCase(getBaseTemplatePath(),replace(cgi.script_name,"/",fs,"all"),"") & replace(userFilesPath,"/",fs,"all"); + } + + rootPath = left( serverPath, Len(serverPath) - Len(userFilesPath) ) ; + xmlContent = ""; // append to this string to build content +</cfscript> + +<cfset resourceTypeUrl = rereplace( replace( Config.FileTypesPath[url.type], fs, "/", "all"), "/$", "") > + +<cfif isDefined( "Config.FileTypesAbsolutePath" ) + and structkeyexists( Config.FileTypesAbsolutePath, url.type ) + and Len( Config.FileTypesAbsolutePath[url.type] )> + + <cfset userFilesServerPath = Config.FileTypesAbsolutePath[url.type] & url.currentFolder> +<cfelse> + <cftry> + <cfset userFilesServerPath = expandpath( resourceTypeUrl ) & url.currentFolder> + <!--- Catch: Parameter 1 of function ExpandPath must be a relative path ---> + <cfcatch type="any"> + <cfset userFilesServerPath = rootPath & Config.FileTypesPath[url.type] & url.currentFolder> + </cfcatch> + </cftry> +</cfif> + +<cfset userFilesServerPath = replace( userFilesServerPath, "/", fs, "all" ) > +<!--- get rid of double directory separators ---> +<cfset userFilesServerPath = replace( userFilesServerPath, fs & fs, fs, "all") > + +<cfif not config.enabled> + + <cfset xmlContent = "<Error number=""1"" text=""This connector is disabled. Please check the 'editor/filemanager/connectors/cfm/config.cfm' file"" />"> + +<cfelseif find("..",url.currentFolder) or find("\",url.currentFolder)> + + <cfset xmlContent = "<Error number=""102"" />"> + +<cfelseif isDefined("Config.ConfigAllowedCommands") and not ListFind(Config.ConfigAllowedCommands, url.command)> + + <cfset xmlContent = '<Error number="1" text="The "' & url.command & '" command isn''t allowed" />'> + +<cfelseif isDefined("Config.ConfigAllowedTypes") and not ListFind(Config.ConfigAllowedTypes, url.type)> + + <cfset xmlContent = '<Error number="1" text="The "' & url.type & '" type isn''t allowed" />'> + +</cfif> + +<cfset resourceTypeDirectory = left( userFilesServerPath, Len(userFilesServerPath) - Len(url.currentFolder) )> + +<cfif not len(xmlContent) and not directoryexists(resourceTypeDirectory)> + <!--- create directories in physical path if they don't already exist ---> + <cfset currentPath = ""> + <cftry> + <cfloop list="#resourceTypeDirectory#" index="name" delimiters="#fs#"> + <cfif currentPath eq "" and fs eq "\"> + <!--- Without checking this, we would have in Windows \C:\ ---> + <cfif not directoryExists(name)> + <cfdirectory action="create" directory="#name#" mode="755"> + </cfif> + <cfelse> + <cfif not directoryExists(currentPath & fs & name)> + <cfdirectory action="create" directory="#currentPath##fs##name#" mode="755"> + </cfif> + </cfif> + + <cfif fs eq "\" and currentPath eq ""> + <cfset currentPath = name> + <cfelse> + <cfset currentPath = currentPath & fs & name> + </cfif> + </cfloop> + + <cfcatch type="any"> + + <!--- this should only occur as a result of a permissions problem ---> + <cfset xmlContent = "<Error number=""103"" />"> + + </cfcatch> + + </cftry> +</cfif> + +<cfif not len(xmlContent)> + + <!--- no errors thus far - run command ---> + + <!--- we need to know the physical path to the current folder for all commands ---> + <cfset currentFolderPath = userFilesServerPath> + + <cfswitch expression="#url.command#"> + + <cfcase value="FileUpload"> + <cfset config_included = true > + <cfinclude template="cf5_upload.cfm"> + <cfabort> + </cfcase> + + + <cfcase value="GetFolders"> + + <!--- Sort directories first, name ascending ---> + <cfdirectory + action="list" + directory="#currentFolderPath#" + name="qDir" + sort="type,name"> + + <cfscript> + i=1; + folders = ""; + while( i lte qDir.recordCount ) { + if( not compareNoCase( qDir.type[i], "FILE" )) + break; + if( not listFind(".,..", qDir.name[i]) ) + folders = folders & '<Folder name="#HTMLEditFormat( qDir.name[i] )#" />'; + i=i+1; + } + + xmlContent = xmlContent & '<Folders>' & folders & '</Folders>'; + </cfscript> + + </cfcase> + + + <cfcase value="GetFoldersAndFiles"> + + <!--- Sort directories first, name ascending ---> + <cfdirectory + action="list" + directory="#currentFolderPath#" + name="qDir" + sort="type,name"> + + <cfscript> + i=1; + folders = ""; + files = ""; + while( i lte qDir.recordCount ) { + if( not compareNoCase( qDir.type[i], "DIR" ) and not listFind(".,..", qDir.name[i]) ) { + folders = folders & '<Folder name="#HTMLEditFormat(qDir.name[i])#" />'; + } else if( not compareNoCase( qDir.type[i], "FILE" ) ) { + fileSizeKB = round(qDir.size[i] / 1024); + files = files & '<File name="#HTMLEditFormat(qDir.name[i])#" size="#IIf( fileSizeKB GT 0, DE( fileSizeKB ), 1)#" />'; + } + i=i+1; + } + + xmlContent = xmlContent & '<Folders>' & folders & '</Folders>'; + xmlContent = xmlContent & '<Files>' & files & '</Files>'; + </cfscript> + + </cfcase> + + + <cfcase value="CreateFolder"> + + <cfparam name="url.newFolderName" default=""> + + <cfscript> + newFolderName = url.newFolderName; + if( reFind("[^A-Za-z0-9_\-\.]", newFolderName) ) { + // Munge folder name same way as we do the filename + // This means folder names are always US-ASCII so we don't have to worry about CF5 and UTF-8 + newFolderName = reReplace(newFolderName, "[^A-Za-z0-9\-\.]", "_", "all"); + newFolderName = reReplace(newFolderName, "_{2,}", "_", "all"); + newFolderName = reReplace(newFolderName, "([^_]+)_+$", "\1", "all"); + newFolderName = reReplace(newFolderName, "$_([^_]+)$", "\1", "all"); + } + </cfscript> + + <cfif not len(newFolderName) or len(newFolderName) gt 255> + <cfset errorNumber = 102> + <cfelseif directoryExists(currentFolderPath & newFolderName)> + <cfset errorNumber = 101> + <cfelseif reFind("^\.\.",newFolderName)> + <cfset errorNumber = 103> + <cfelse> + <cfset errorNumber = 0> + + <cftry> + <cfdirectory + action="create" + directory="#currentFolderPath##newFolderName#" + mode="755"> + <cfcatch> + <!--- + un-resolvable error numbers in ColdFusion: + * 102 : Invalid folder name. + * 103 : You have no permissions to create the folder. + ---> + <cfset errorNumber = 110> + </cfcatch> + </cftry> + </cfif> + + <cfset xmlContent = xmlContent & '<Error number="#errorNumber#" />'> + + </cfcase> + + <cfdefaultcase> + <cfthrow type="fckeditor.connector" message="Illegal command: #url.command#"> + </cfdefaultcase> + + </cfswitch> +</cfif> + +<cfscript> + xmlHeader = '<?xml version="1.0" encoding="utf-8" ?><Connector command="#url.command#" resourceType="#url.type#">'; + xmlHeader = xmlHeader & '<CurrentFolder path="#url.currentFolder#" url="#resourceTypeUrl##url.currentFolder#" />'; + xmlFooter = '</Connector>'; +</cfscript> + +<cfheader name="Expires" value="#GetHttpTimeString(Now())#"> +<cfheader name="Pragma" value="no-cache"> +<cfheader name="Cache-Control" value="no-cache, no-store, must-revalidate"> +<cfcontent reset="true" type="text/xml; charset=UTF-8"> +<cfoutput>#xmlHeader##xmlContent##xmlFooter#</cfoutput> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/cf5_upload.cfm =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/cf5_upload.cfm (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/cf5_upload.cfm 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,328 @@ +<cfsetting enablecfoutputonly="Yes"> +<!--- + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * This is the "File Uploader" for ColdFusion 5. + * Based on connector.cfm by Mark Woods (mark@thickpaddy.com) + * + * Note: + * FCKeditor requires that the connector responds with UTF-8 encoded XML. + * As ColdFusion 5 does not fully support UTF-8 encoding, we force ASCII + * file and folder names in this connector to allow CF5 send a UTF-8 + * encoded response - code points under 127 in UTF-8 are stored using a + * single byte, using the same encoding as ASCII, which is damn handy. + * This is all grand for the English speakers, like meself, but I dunno + * how others are gonna take to it. Well, the previous version of this + * connector already did this with file names and nobody seemed to mind, + * so fingers-crossed nobody will mind their folder names being munged too. + * +---> + +<cfparam name="url.command" default="QuickUpload"> +<cfparam name="url.type" default="File"> +<cfparam name="url.currentFolder" default="/"> + +<cfif not isDefined("config_included")> + <cfinclude template="config.cfm"> +</cfif> + +<cfscript> + function SendUploadResults(errorNumber, fileUrl, fileName, customMsg) + { + WriteOutput('<script type="text/javascript">'); + WriteOutput("(function()"& +"{"& +" var d = document.domain ;"& +""& +" while ( true )"& +" {"& + // Test if we can access a parent property. +" try"& +" {"& +" var test = window.top.opener.document.domain ;"& +" break ;"& +" }"& +" catch( e ) {}"& +""& + // Remove a domain part: www.mytest.example.com => mytest.example.com => example.com ... +" d = d.replace( /.*?(?:\.|$)/, '' ) ;"& +""& +" if ( d.length == 0 )"& + // It was not able to detect the domain. +" break ;"& +""& +" try"& +" {"& +" document.domain = d ;"& +" }"& +" catch (e)"& +" {"& +" break ;"& +" }"& +" }"& +"})() ;"); + + WriteOutput('window.parent.OnUploadCompleted(' & errorNumber & ', "' & JSStringFormat(fileUrl) & '", "' & JSStringFormat(fileName) & '", "' & JSStringFormat(customMsg) & '");' ); + WriteOutput('</script>'); + } +</cfscript> + +<cfif NOT config.enabled> + <cfset SendUploadResults(1, "", "", "This file uploader is disabled. Please check the ""editor/filemanager/connectors/cfm/config.cfm"" file")> + <cfabort> +</cfif> + +<cfif isDefined("Config.ConfigAllowedCommands") and not ListFind(Config.ConfigAllowedCommands, url.command)> + <cfset SendUploadResults(1, "", "", "The """ & url.command & """ command isn't allowed")> + <cfabort> +</cfif> + +<cfif isDefined("Config.ConfigAllowedTypes") and not ListFind(Config.ConfigAllowedTypes, url.type)> + <cfset SendUploadResults(1, "", "", "The """ & url.type & """ type isn't allowed")> + <cfabort> +</cfif> + +<cfif find( "..", url.currentFolder) or find( "\", url.currentFolder)> + <cfset SendUploadResults(102)> + <cfabort> +</cfif> + +<cfscript> + userFilesPath = config.userFilesPath; + + if ( userFilesPath eq "" ) { + userFilesPath = "/userfiles/"; + } + + // make sure the user files path is correctly formatted + userFilesPath = replace(userFilesPath, "\", "/", "ALL"); + userFilesPath = replace(userFilesPath, '//', '/', 'ALL'); + if ( right(userFilesPath,1) NEQ "/" ) { + userFilesPath = userFilesPath & "/"; + } + if ( left(userFilesPath,1) NEQ "/" ) { + userFilesPath = "/" & userFilesPath; + } + + // make sure the current folder is correctly formatted + url.currentFolder = replace(url.currentFolder, "\", "/", "ALL"); + url.currentFolder = replace(url.currentFolder, '//', '/', 'ALL'); + if ( right(url.currentFolder,1) neq "/" ) { + url.currentFolder = url.currentFolder & "/"; + } + if ( left(url.currentFolder,1) neq "/" ) { + url.currentFolder = "/" & url.currentFolder; + } + + if (find("/",getBaseTemplatePath())) { + fs = "/"; + } else { + fs = "\"; + } + + // Get the base physical path to the web root for this application. The code to determine the path automatically assumes that + // the "FCKeditor" directory in the http request path is directly off the web root for the application and that it's not a + // virtual directory or a symbolic link / junction. Use the serverPath config setting to force a physical path if necessary. + if ( len(config.serverPath) ) { + serverPath = config.serverPath; + + if ( right(serverPath,1) neq fs ) { + serverPath = serverPath & fs; + } + } else { + serverPath = replaceNoCase(getBaseTemplatePath(),replace(cgi.script_name,"/",fs,"all"),"") & replace(userFilesPath,"/",fs,"all"); + } + + rootPath = left( serverPath, Len(serverPath) - Len(userFilesPath) ) ; +</cfscript> +<cfif url.command eq "QuickUpload"> + <cfset resourceTypeUrl = rereplace( replace( Config.QuickUploadPath[url.type], fs, "/", "all"), "/$", "") > + <cfif isDefined( "Config.QuickUploadAbsolutePath" ) + and structkeyexists( Config.QuickUploadAbsolutePath, url.type ) + and Len( Config.QuickUploadAbsolutePath[url.type] )> + <cfset userFilesServerPath = Config.QuickUploadAbsolutePath[url.type] & url.currentFolder> + <cfelse> + <cftry> + <cfset userFilesServerPath = expandpath( resourceTypeUrl ) & url.currentFolder> + <!--- Catch: Parameter 1 of function ExpandPath must be a relative path ---> + <cfcatch type="any"> + <cfset userFilesServerPath = rootPath & Config.QuickUploadPath[url.type] & url.currentFolder> + </cfcatch> + </cftry> + </cfif> +<cfelse> + <cfset resourceTypeUrl = rereplace( replace( Config.FileTypesPath[url.type], fs, "/", "all"), "/$", "") > + <cfif isDefined( "Config.FileTypesAbsolutePath" ) + and structkeyexists( Config.FileTypesAbsolutePath, url.type ) + and Len( Config.FileTypesAbsolutePath[url.type] )> + <cfset userFilesServerPath = Config.FileTypesAbsolutePath[url.type] & url.currentFolder> + <cfelse> + <cftry> + <cfset userFilesServerPath = expandpath( resourceTypeUrl ) & url.currentFolder> + <!--- Catch: Parameter 1 of function ExpandPath must be a relative path ---> + <cfcatch type="any"> + <cfset userFilesServerPath = rootPath & Config.FileTypesPath[url.type] & url.currentFolder> + </cfcatch> + </cftry> + </cfif> +</cfif> + +<cfset userFilesServerPath = replace( userFilesServerPath, "/", fs, "all" ) > +<!--- get rid of double directory separators ---> +<cfset userFilesServerPath = replace( userFilesServerPath, fs & fs, fs, "all") > + +<!--- create resource type directory if not exists ---> +<cfset resourceTypeDirectory = left( userFilesServerPath, Len(userFilesServerPath) - Len(url.currentFolder) )> + +<cfif not directoryexists( resourceTypeDirectory )> + + <cfset currentPath = ""> + <cftry> + <cfloop list="#resourceTypeDirectory#" index="name" delimiters="#fs#"> + <cfif currentPath eq "" and fs eq "\"> + <!--- Without checking this, we would have in Windows \C:\ ---> + <cfif not directoryExists(name)> + <cfdirectory action="create" directory="#name#" mode="755"> + </cfif> + <cfelse> + <cfif not directoryExists(currentPath & fs & name)> + <cfdirectory action="create" directory="#currentPath##fs##name#" mode="755"> + </cfif> + </cfif> + + <cfif fs eq "\" and currentPath eq ""> + <cfset currentPath = name> + <cfelse> + <cfset currentPath = currentPath & fs & name> + </cfif> + </cfloop> + + <cfcatch type="any"> + + <!--- this should only occur as a result of a permissions problem ---> + <cfset SendUploadResults(103)> + <cfabort> + + </cfcatch> + + </cftry> +</cfif> + +<cfset currentFolderPath = userFilesServerPath> +<cfset resourceType = url.type> + +<cfset fileName = ""> +<cfset fileExt = ""> + +<!--- Can be overwritten. The last value will be sent with the result ---> +<cfset customMsg = ""> + +<cftry> + <!--- first upload the file with an unique filename ---> + <cffile action="upload" + fileField="NewFile" + destination="#currentFolderPath#" + nameConflict="makeunique" + mode="644" + attributes="normal"> + + <cfif cffile.fileSize EQ 0> + <cfthrow> + </cfif> + + <cfset lAllowedExtensions = config.allowedExtensions[#resourceType#]> + <cfset lDeniedExtensions = config.deniedExtensions[#resourceType#]> + + <cfif ( len(lAllowedExtensions) and not listFindNoCase(lAllowedExtensions,cffile.ServerFileExt) ) + or ( len(lDeniedExtensions) and listFindNoCase(lDeniedExtensions,cffile.ServerFileExt) )> + + <cfset errorNumber = "202"> + <cffile action="delete" file="#cffile.ServerDirectory##fs##cffile.ServerFile#"> + + <cfelse> + + <cfscript> + errorNumber = 0; + fileName = cffile.ClientFileName ; + fileExt = cffile.ServerFileExt ; + fileExisted = false ; + + // munge filename for html download. Only a-z, 0-9, _, - and . are allowed + if( reFind("[^A-Za-z0-9_\-\.]", fileName) ) { + fileName = reReplace(fileName, "[^A-Za-z0-9\-\.]", "_", "ALL"); + fileName = reReplace(fileName, "_{2,}", "_", "ALL"); + fileName = reReplace(fileName, "([^_]+)_+$", "\1", "ALL"); + fileName = reReplace(fileName, "$_([^_]+)$", "\1", "ALL"); + } + + // remove additional dots from file name + if( isDefined("Config.ForceSingleExtension") and Config.ForceSingleExtension ) + fileName = replace( fileName, '.', "_", "all" ) ; + + // When the original filename already exists, add numbers (0), (1), (2), ... at the end of the filename. + if( compare( cffile.ServerFileName, fileName ) ) { + counter = 0; + tmpFileName = fileName; + while( fileExists("#currentFolderPath##fileName#.#fileExt#") ) { + fileExisted = true ; + counter = counter + 1 ; + fileName = tmpFileName & '(#counter#)' ; + } + } + </cfscript> + + <!--- Rename the uploaded file, if neccessary ---> + <cfif compare(cffile.ServerFileName,fileName)> + + <cfif fileExisted> + <cfset errorNumber = "201"> + </cfif> + <cffile + action="rename" + source="#currentFolderPath##cffile.ServerFileName#.#cffile.ServerFileExt#" + destination="#currentFolderPath##fileName#.#fileExt#" + mode="644" + attributes="normal"> + + </cfif> + + </cfif> + + <cfcatch type="any"> + + <cfset errorNumber = "1"> + <cfset customMsg = cfcatch.message > + + </cfcatch> +</cftry> + +<cfif errorNumber EQ 0> + <!--- file was uploaded succesfully ---> + <cfset SendUploadResults(errorNumber, '#resourceTypeUrl##url.currentFolder##fileName#.#fileExt#', "", "")> + <cfabort> +<cfelseif errorNumber EQ 201> + <!--- file was changed (201), submit the new filename ---> + <cfset SendUploadResults(errorNumber, '#resourceTypeUrl##url.currentFolder##fileName#.#fileExt#', replace( fileName & "." & fileExt, "'", "\'", "ALL"), customMsg)> + <cfabort> +<cfelse> + <!--- An error occured(202). Submit only the error code and a message (if available). ---> + <cfset SendUploadResults(errorNumber, '', '', customMsg)> + <cfabort> +</cfif> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/cf_basexml.cfm =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/cf_basexml.cfm (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/cf_basexml.cfm 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,68 @@ +<cfsetting enablecfoutputonly="Yes"> +<!--- + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * This file include the functions that create the base XML output by the ColdFusion Connector (MX 6.0 and above). +---> + +<cffunction name="SetXmlHeaders" returntype="void"> + <cfheader name="Expires" value="#GetHttpTimeString(Now())#"> + <cfheader name="Pragma" value="no-cache"> + <cfheader name="Cache-Control" value="no-cache, no-store, must-revalidate"> + <cfcontent reset="true" type="text/xml; charset=UTF-8"> +</cffunction> + +<cffunction name="CreateXmlHeader" returntype="void" output="true"> + <cfargument name="command" required="true"> + <cfargument name="resourceType" required="true"> + <cfargument name="currentFolder" required="true"> + + <cfset SetXmlHeaders()> + <cfoutput><?xml version="1.0" encoding="utf-8" ?></cfoutput> + <cfoutput><Connector command="#ARGUMENTS.command#" resourceType="#ARGUMENTS.resourceType#"></cfoutput> + <cfoutput><CurrentFolder path="#HTMLEditFormat(ARGUMENTS.currentFolder)#" url="#HTMLEditFormat( GetUrlFromPath( resourceType, currentFolder, command ) )#" /></cfoutput> + <cfset REQUEST.HeaderSent = true> +</cffunction> + +<cffunction name="CreateXmlFooter" returntype="void" output="true"> + <cfoutput></Connector></cfoutput> +</cffunction> + +<cffunction name="SendError" returntype="void" output="true"> + <cfargument name="number" required="true" type="Numeric"> + <cfargument name="text" required="true"> + <cfif isDefined("REQUEST.HeaderSent") and REQUEST.HeaderSent> + <cfset SendErrorNode( ARGUMENTS.number, ARGUMENTS.text )> + <cfset CreateXmlFooter() > + <cfelse> + <cfset SetXmlHeaders()> + <cfoutput><?xml version="1.0" encoding="utf-8" ?></cfoutput> + <cfoutput><Connector></cfoutput> + <cfset SendErrorNode( ARGUMENTS.number, ARGUMENTS.text )> + <cfset CreateXmlFooter() > + </cfif> + <cfabort> +</cffunction> + +<cffunction name="SendErrorNode" returntype="void" output="true"> + <cfargument name="number" required="true" type="Numeric"> + <cfargument name="text" required="true"> + <cfoutput><Error number="#ARGUMENTS.number#" text="#htmleditformat(ARGUMENTS.text)#" /></cfoutput> +</cffunction> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/cf_commands.cfm =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/cf_commands.cfm (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/cf_commands.cfm 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,230 @@ +<cfsetting enablecfoutputonly="Yes"> +<!--- + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * This file include the functions that handle the Command requests + * in the ColdFusion Connector (MX 6.0 and above). +---> + +<cffunction name="FileUpload" returntype="void" output="true"> + <cfargument name="resourceType" type="string" required="yes" default=""> + <cfargument name="currentFolder" type="string" required="yes" default=""> + <cfargument name="sCommand" type="string" required="yes" default=""> + + <cfset var sFileName = ""> + <cfset var sFilePart = ""> + <cfset var sFileExt = ""> + <cfset var sFileUrl = ""> + <cfset var sTempDir = ""> + <cfset var sTempFilePath = ""> + <cfset var errorNumber = 0> + <cfset var customMsg = 0> + <cfset var counter = 0> + <cfset var destination = ""> + + <cftry> + <cfif isDefined( "REQUEST.Config.TempDirectory" )> + <cfset sTempDir = REQUEST.Config.TempDirectory> + <cfelse> + <cfset sTempDir = GetTempDirectory()> + </cfif> + <cfif NOT DirectoryExists (sTempDir)> + <cfthrow message="Invalid temporary directory: #sTempDir#"> + </cfif> + + <cffile action="UPLOAD" filefield="NewFile" destination="#sTempDir#" nameconflict="makeunique" mode="0755" /> + <cfset sTempFilePath = CFFILE.ServerDirectory & REQUEST.fs & CFFILE.ServerFile> + + <!--- Map the virtual path to the local server path. ---> + <cfset sServerDir = ServerMapFolder( ARGUMENTS.resourceType, ARGUMENTS.currentFolder, ARGUMENTS.sCommand) > + <!--- Get the uploaded file name. ---> + <cfset sFileName = SanitizeFileName( CFFILE.ClientFile ) > + <cfset sOriginalFileName = sFileName > + + <cfif isDefined( "REQUEST.Config.SecureImageUploads" ) and REQUEST.Config.SecureImageUploads> + <cfif not IsImageValid( sTempFilePath, CFFILE.ClientFileExt )> + <cftry> + <cffile action="delete" file="#sTempFilePath#"> + <cfcatch type="any"> + </cfcatch> + </cftry> + <cfthrow errorcode="202" type="fckeditor"> + </cfif> + </cfif> + + <cfif isDefined( "REQUEST.Config.HtmlExtensions" ) and not listFindNoCase( REQUEST.Config.HtmlExtensions, CFFILE.ClientFileExt )> + <cfif DetectHtml( sTempFilePath )> + <cftry> + <cffile action="delete" file="#sTempFilePath#"> + <cfcatch type="any"> + </cfcatch> + </cftry> + <cfthrow errorcode="202" type="fckeditor"> + </cfif> + </cfif> + + <cfif not IsAllowedExt( CFFILE.ClientFileExt, ARGUMENTS.resourceType )> + <cftry> + <cffile action="delete" file="#sTempFilePath#"> + <cfcatch type="any"> + </cfcatch> + </cftry> + <cfthrow errorcode="202" type="fckeditor"> + </cfif> + + <!--- When the original filename already exists, add numbers (0), (1), (2), ... at the end of the filename. ---> + <cfscript> + sFileExt = GetExtension( sFileName ) ; + sFilePart = RemoveExtension( sFileName ); + while( fileExists( sServerDir & sFileName ) ) + { + counter = counter + 1; + sFileName = sFilePart & '(#counter#).' & CFFILE.ClientFileExt; + errorNumber = 201; + } + </cfscript> + + <cfset destination = sServerDir & sFileName> + + <cflock name="#destination#" timeout="30" type="Exclusive"> + <cftry> + <cffile action="move" source="#sTempFilePath#" destination="#destination#" mode="755"> + <!--- omit CF 6.1 error during moving uploaded file, just copy that file instead of moving ---> + <cfcatch type="any"> + <cffile action="copy" source="#sTempFilePath#" destination="#destination#" mode="755"> + </cfcatch> + </cftry> + </cflock> + + <cfset sFileUrl = CombinePaths( GetResourceTypePath( ARGUMENTS.resourceType, sCommand ) , ARGUMENTS.currentFolder ) > + <cfset sFileUrl = CombinePaths( sFileUrl , sFileName ) > + + <cfcatch type="fckeditor"> + <cfset errorNumber = CFCATCH.ErrorCode> + </cfcatch> + + <cfcatch type="any"> + <cfset errorNumber = "1"> + <cfset customMsg = CFCATCH.Message > + </cfcatch> + + </cftry> + + <cfset SendUploadResults( errorNumber, sFileUrl, sFileName, customMsg ) > +</cffunction> + +<cffunction name="GetFolders" returntype="void" output="true"> + <cfargument name="resourceType" type="String" required="true"> + <cfargument name="currentFolder" type="String" required="true"> + + <cfset var i = 1> + <cfset var folders = ""> + <!--- Map the virtual path to the local server path ---> + <cfset var sServerDir = ServerMapFolder( ARGUMENTS.resourceType, ARGUMENTS.currentFolder, "GetFolders" ) > + + <!--- Sort directories first, name ascending ---> + <cfdirectory action="list" directory="#sServerDir#" name="qDir" sort="type,name"> + <cfscript> + while( i lte qDir.recordCount ) + { + if( compareNoCase( qDir.type[i], "FILE" ) and not listFind( ".,..", qDir.name[i] ) ) + { + folders = folders & '<Folder name="#HTMLEditFormat( qDir.name[i] )#" />' ; + } + i = i + 1; + } + </cfscript> + <cfoutput><Folders>#folders#</Folders></cfoutput> +</cffunction> + +<cffunction name="GetFoldersAndfiles" returntype="void" output="true"> + <cfargument name="resourceType" type="String" required="true"> + <cfargument name="currentFolder" type="String" required="true"> + + <cfset var i = 1> + <cfset var folders = ""> + <cfset var files = ""> + <!--- Map the virtual path to the local server path ---> + <cfset var sServerDir = ServerMapFolder( ARGUMENTS.resourceType, ARGUMENTS.currentFolder, "GetFolders" ) > + + <!--- Sort directories first, name ascending ---> + <cfdirectory action="list" directory="#sServerDir#" name="qDir" sort="type,name"> + <cfscript> + while( i lte qDir.recordCount ) + { + if( not compareNoCase( qDir.type[i], "DIR" ) and not listFind( ".,..", qDir.name[i] ) ) + { + folders = folders & '<Folder name="#HTMLEditFormat(qDir.name[i])#" />' ; + } + else if( not compareNoCase( qDir.type[i], "FILE" ) ) + { + fileSizeKB = round(qDir.size[i] / 1024) ; + files = files & '<File name="#HTMLEditFormat(qDir.name[i])#" size="#IIf( fileSizeKB GT 0, DE( fileSizeKB ), 1)#" />' ; + } + i = i + 1 ; + } + </cfscript> + <cfoutput><Folders>#folders#</Folders></cfoutput> + <cfoutput><Files>#files#</Files></cfoutput> +</cffunction> + +<cffunction name="CreateFolder" returntype="void" output="true"> + <cfargument name="resourceType" required="true" type="string"> + <cfargument name="currentFolder" required="true" type="string"> + + <cfset var sNewFolderName = url.newFolderName > + <cfset var sServerDir = "" > + <cfset var errorNumber = 0> + <cfset var sErrorMsg = ""> + <cfset var currentFolderPath = ServerMapFolder( ARGUMENTS.resourceType, ARGUMENTS.currentFolder, 'CreateFolder' )> + + <cfparam name="url.newFolderName" default=""> + + <cfscript> + sNewFolderName = SanitizeFolderName( sNewFolderName ) ; + </cfscript> + + <cfif not len( sNewFolderName ) or len( sNewFolderName ) gt 255> + <cfset errorNumber = 102> + <cfelseif directoryExists( currentFolderPath & sNewFolderName )> + <cfset errorNumber = 101> + <cfelseif find( "..", sNewFolderName )> + <cfset errorNumber = 103> + <cfelse> + <cfset errorNumber = 0> + + <!--- Map the virtual path to the local server path of the current folder. ---> + <cfset sServerDir = currentFolderPath & sNewFolderName > + + <cftry> + <cfdirectory action="create" directory="#currentFolderPath##sNewFolderName#" mode="755"> + <cfcatch type="any"> + <!--- + un-resolvable error numbers in ColdFusion: + * 102 : Invalid folder name. + * 103 : You have no permissions to create the folder. + ---> + <cfset errorNumber = 110> + </cfcatch> + </cftry> + </cfif> + + <cfoutput><Error number="#errorNumber#" originalDescription="#HTMLEditFormat(sErrorMsg)#" /></cfoutput> +</cffunction> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/cf_connector.cfm =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/cf_connector.cfm (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/cf_connector.cfm 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,89 @@ +<cfsetting enablecfoutputonly="yes" showdebugoutput="no"> +<!--- + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * File Browser connector for ColdFusion (MX 6.0 and above). + * (based on the original CF connector by Hendrik Kramer - hk@lwd.de) + * +---> + +<cfparam name="url.command"> +<cfparam name="url.type"> +<cfparam name="url.currentFolder"> + +<!--- note: no serverPath url parameter - see config.cfm if you need to set the serverPath manually ---> + +<cfinclude template="config.cfm"> +<cfinclude template="cf_util.cfm"> +<cfinclude template="cf_io.cfm"> +<cfinclude template="cf_basexml.cfm"> +<cfinclude template="cf_commands.cfm"> + +<cfif not Config.Enabled> + <cfset SendError( 1, 'This connector is disabled. Please check the "editor/filemanager/connectors/cfm/config.cfm" file' )> +</cfif> + +<cfset REQUEST.Config = Config> +<cfif find( "/", getBaseTemplatePath() ) > + <cfset REQUEST.Fs = "/"> +<cfelse> + <cfset REQUEST.Fs = "\"> +</cfif> + +<cfset DoResponse() > + +<cffunction name="DoResponse" output="true" returntype="void"> + + <!--- Get the main request informaiton. ---> + <cfset var sCommand = "#URL.Command#" > + <cfset var sResourceType = URL.Type > + <cfset var sCurrentFolder = GetCurrentFolder() > + + <!--- Check if it is an allowed command ---> + <cfif not IsAllowedCommand( sCommand ) > + <cfset SendError( 1, "The """ & sCommand & """ command isn't allowed" ) > + </cfif> + + <!--- Check if it is an allowed type. ---> + <cfif not IsAllowedType( sResourceType ) > + <cfset SendError( 1, 'Invalid type specified' ) > + </cfif> + + <!--- File Upload doesn't have to Return XML, so it must be intercepted before anything. ---> + <cfif sCommand eq "FileUpload"> + <cfset FileUpload( sResourceType, sCurrentFolder, sCommand )> + <cfabort> + </cfif> + + <cfset CreateXmlHeader( sCommand, sResourceType, sCurrentFolder )> + + <!--- Execute the required command. ---> + <cfif sCommand eq "GetFolders"> + <cfset GetFolders( sResourceType, sCurrentFolder ) > + <cfelseif sCommand eq "GetFoldersAndFiles"> + <cfset GetFoldersAndFiles( sResourceType, sCurrentFolder ) > + <cfelseif sCommand eq "CreateFolder"> + <cfset CreateFolder( sResourceType, sCurrentFolder ) > + </cfif> + + <cfset CreateXmlFooter()> + + <cfexit> +</cffunction> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/cf_io.cfm =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/cf_io.cfm (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/cf_io.cfm 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,319 @@ +<cfsetting enablecfoutputonly="Yes"> +<!--- + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * This file include IO specific functions used by the ColdFusion Connector (MX 6.0 and above). + * +---> + +<cffunction name="CombinePaths" returntype="String" output="true"> + <cfargument name="sBasePath" required="true"> + <cfargument name="sFolder" required="true"> + <cfset sBasePath = RemoveFromEnd( sBasePath, "/" )> + <cfset sBasePath = RemoveFromEnd( sBasePath, "\" )> + <cfreturn sBasePath & "/" & RemoveFromStart( ARGUMENTS.sFolder, '/' )> +</cffunction> + +<cffunction name="GetResourceTypePath" returntype="String" output="false"> + <cfargument name="resourceType" required="true"> + <cfargument name="sCommand" required="true"> + + <cfif ARGUMENTS.sCommand eq "QuickUpload"> + <cfreturn REQUEST.Config['QuickUploadPath'][ARGUMENTS.resourceType]> + <cfelse> + <cfreturn REQUEST.Config['FileTypesPath'][ARGUMENTS.resourceType]> + </cfif> +</cffunction> + +<cffunction name="GetResourceTypeDirectory" returntype="String" output="false"> + <cfargument name="resourceType" required="true"> + <cfargument name="sCommand" required="true"> + + <cfif ARGUMENTS.sCommand eq "QuickUpload"> + <cfif isDefined( "REQUEST.Config.QuickUploadAbsolutePath" ) + and structkeyexists( REQUEST.Config.QuickUploadAbsolutePath, ARGUMENTS.resourceType ) + and Len( REQUEST.Config.QuickUploadAbsolutePath[ARGUMENTS.resourceType] )> + <cfreturn REQUEST.Config.QuickUploadAbsolutePath[ARGUMENTS.resourceType]> + </cfif> + + <cfreturn expandpath( REQUEST.Config.QuickUploadPath[ARGUMENTS.resourceType] )> + <cfelse> + <cfif isDefined( "REQUEST.Config.FileTypesAbsolutePath" ) + and structkeyexists( REQUEST.Config.FileTypesAbsolutePath, ARGUMENTS.resourceType ) + and Len( REQUEST.Config.FileTypesAbsolutePath[ARGUMENTS.resourceType] )> + <cfreturn REQUEST.Config.FileTypesAbsolutePath[ARGUMENTS.resourceType]> + </cfif> + + <cfreturn expandpath( REQUEST.Config.FileTypesPath[ARGUMENTS.resourceType] )> + </cfif> +</cffunction> + +<cffunction name="GetUrlFromPath" returntype="String" output="false"> + <cfargument name="resourceType" required="true"> + <cfargument name="folderPath" required="true"> + <cfargument name="sCommand" required="true"> + + <cfreturn CombinePaths( GetResourceTypePath( ARGUMENTS.resourceType, ARGUMENTS.sCommand ), ARGUMENTS.folderPath )> +</cffunction> + +<cffunction name="RemoveExtension" output="false" returntype="String"> + <cfargument name="fileName" required="true"> + <cfset var pos = find( ".", reverse ( ARGUMENTS.fileName ) )> + + <cfreturn mid( ARGUMENTS.fileName, 1, Len( ARGUMENTS.fileName ) - pos ) > +</cffunction> + +<cffunction name="GetExtension" output="false" returntype="String"> + <cfargument name="fileName" required="true"> + <cfset var pos = find( ".", reverse ( ARGUMENTS.fileName ) )> + + <cfif not pos> + <cfreturn ""> + </cfif> + + <cfreturn mid( ARGUMENTS.fileName, pos, Len( ARGUMENTS.fileName ) - pos ) > +</cffunction> + +<cffunction name="ServerMapFolder" returntype="String" output="false"> + <cfargument name="resourceType" required="true"> + <cfargument name="folderPath" required="true"> + <cfargument name="sCommand" required="true"> + + <!--- Get the resource type directory. ---> + <cfset var sResourceTypePath = GetResourceTypeDirectory( ARGUMENTS.resourceType, ARGUMENTS.sCommand ) > + <!--- Ensure that the directory exists. ---> + <cfset var sErrorMsg = CreateServerFolder( sResourceTypePath ) > + + <cfif sErrorMsg neq ''> + <cfset SendError( 1, 'Error creating folder "' & sResourceTypePath & '" (' & sErrorMsg & ')' )> + </cfif> + + <!--- Return the resource type directory combined with the required path. ---> + <cfreturn CombinePaths( sResourceTypePath , ARGUMENTS.folderPath )> +</cffunction> + +<cffunction name="GetParentFolder" returntype="string" output="false"> + <cfargument name="folderPath" required="true"> + + <cfreturn rereplace(ARGUMENTS.folderPath, "[/\\\\][^/\\\\]+[/\\\\]?$", "")> +</cffunction> + +<cffunction name="CreateServerFolder" returntype="String" output="false"> + <cfargument name="folderPath"> + + <!--- Ensure the folder path has no double-slashes, or mkdir may fail on certain platforms ---> + <cfset folderPath = rereplace(ARGUMENTS.folderPath, "//+", "/", "all")> + + <cfif directoryexists(ARGUMENTS.folderPath) or fileexists(ARGUMENTS.folderPath)> + <cfreturn ""> + <cfelse> + <cftry> + <cfdirectory action="create" mode="0755" directory="#ARGUMENTS.folderPath#"> + <cfcatch type="any"> + <cfreturn CFCATCH.Message> + </cfcatch> + </cftry> + </cfif> + + <cfreturn ""> +</cffunction> + +<cffunction name="IsAllowedExt" returntype="boolean" output="false"> + <cfargument name="sExtension" required="true"> + <cfargument name="resourceType" required="true"> + + <cfif isDefined( "REQUEST.Config.AllowedExtensions." & ARGUMENTS.resourceType ) + and listLen( REQUEST.Config.AllowedExtensions[ARGUMENTS.resourceType] ) + and not listFindNoCase( REQUEST.Config.AllowedExtensions[ARGUMENTS.resourceType], ARGUMENTS.sExtension )> + <cfreturn false> + </cfif> + + <cfif isDefined( "REQUEST.Config.DeniedExtensions." & ARGUMENTS.resourceType ) + and listLen( REQUEST.Config.DeniedExtensions[ARGUMENTS.resourceType] ) + and listFindNoCase( REQUEST.Config.DeniedExtensions[ARGUMENTS.resourceType], ARGUMENTS.sExtension )> + <cfreturn false> + </cfif> + + <cfreturn true> +</cffunction> + +<cffunction name="IsAllowedType" returntype="boolean" output="false"> + <cfargument name="resourceType"> + + <cfif not listFindNoCase( REQUEST.Config.ConfigAllowedTypes, ARGUMENTS.resourceType )> + <cfreturn false> + </cfif> + + <cfreturn true> +</cffunction> + +<cffunction name="IsAllowedCommand" returntype="boolean" output="true"> + <cfargument name="sCommand" required="true" type="String"> + + <cfif not listFindNoCase( REQUEST.Config.ConfigAllowedCommands, ARGUMENTS.sCommand )> + <cfreturn false> + </cfif> + + <cfreturn true> +</cffunction> + +<cffunction name="GetCurrentFolder" returntype="String" output="true"> + <cfset var sCurrentFolder = "/"> + + <cfif isDefined( "URL.CurrentFolder" )> + <cfset sCurrentFolder = URL.CurrentFolder> + </cfif> + + <!--- Check the current folder syntax (must begin and start with a slash). ---> + <cfif not refind( "/$", sCurrentFolder)> + <cfset sCurrentFolder = sCurrentFolder & "/"> + </cfif> + + <cfif not refind( "^/", sCurrentFolder )> + <cfset sCurrentFolder = "/" & sCurrentFolder> + </cfif> + + <!--- Ensure the folder path has no double-slashes, or mkdir may fail on certain platforms ---> + <cfset sCurrentFolder = rereplace( sCurrentFolder, "//+", "/", "all" )> + + <cfif find( "..", sCurrentFolder) or find( "\", sCurrentFolder) > + <cfset SendError( 102, "" )> + </cfif> + + <cfreturn sCurrentFolder> +</cffunction> + +<cffunction name="SanitizeFolderName" returntype="String" output="false"> + <cfargument name="sNewFolderName" required="true"> + + <!--- Do a cleanup of the folder name to avoid possible problems ---> + <!--- Remove . \ / | : ? * " < > and control characters ---> + <cfset sNewFolderName = rereplace( sNewFolderName, '\.+|\\+|\/+|\|+|\:+|\?+|\*+|"+|<+|>+|[[:cntrl:]]+', "_", "all" )> + + <cfreturn sNewFolderName> +</cffunction> + +<cffunction name="BinaryFileRead" returntype="String" output="true"> + <cfargument name="fileName" required="true" type="string"> + <cfargument name="bytes" required="true" type="Numeric"> + + <cfscript> + var chunk = ""; + var fileReaderClass = ""; + var fileReader = ""; + var file = ""; + var done = false; + var counter = 0; + var byteArray = ""; + + if( not fileExists( ARGUMENTS.fileName ) ) + { + return "" ; + } + + if (REQUEST.CFVersion gte 8) + { + file = FileOpen( ARGUMENTS.fileName, "readbinary" ) ; + byteArray = FileRead( file, 1024 ) ; + chunk = toString( toBinary( toBase64( byteArray ) ) ) ; + FileClose( file ) ; + } + else + { + fileReaderClass = createObject("java", "java.io.FileInputStream"); + fileReader = fileReaderClass.init(fileName); + + while(not done) + { + char = fileReader.read(); + counter = counter + 1; + if ( char eq -1 or counter eq ARGUMENTS.bytes) + { + done = true; + } + else + { + chunk = chunk & chr(char) ; + } + } + } + </cfscript> + + <cfreturn chunk> +</cffunction> + +<cffunction name="SendUploadResults" returntype="String" output="true"> + <cfargument name="errorNumber" required="true" type="Numeric"> + <cfargument name="fileUrl" required="false" type="String" default=""> + <cfargument name="fileName" required="false" type="String" default=""> + <cfargument name="customMsg" required="false" type="String" default=""> + + <cfoutput> +<script type="text/javascript"> +(function() +{ + var d = document.domain ; + + while ( true ) + { + // Test if we can access a parent property. + try + { + var test = window.top.opener.document.domain ; + break ; + } + catch( e ) {} + + // Remove a domain part: www.mytest.example.com => mytest.example.com => example.com ... + d = d.replace( /.*?(?:\.|$)/, '' ) ; + + if ( d.length == 0 ) + break ; // It was not able to detect the domain. + + try + { + document.domain = d ; + } + catch (e) + { + break ; + } + } +})() ; + + window.parent.OnUploadCompleted( #errorNumber#, "#JSStringFormat(fileUrl)#", "#JSStringFormat(fileName)#", "#JSStringFormat(customMsg)#" ); + </script> + </cfoutput> + <cfabort> +</cffunction> + +<cffunction name="SanitizeFileName" returntype="String" output="false"> + <cfargument name="sNewFileName" required="true"> + + <cfif isDefined("REQUEST.Config.ForceSingleExtension") and REQUEST.Config.ForceSingleExtension> + <cfset sNewFileName = rereplace( sNewFileName, '\.(?![^.]*$)', "_", "all" )> + </cfif> + + <!--- Do a cleanup of the file name to avoid possible problems ---> + <!--- Remove \ / | : ? * " < > and control characters ---> + <cfset sNewFileName = rereplace( sNewFileName, '\\[.]+|\\+|\/+|\|+|\:+|\?+|\*+|"+|<+|>+|[[:cntrl:]]+', "_", "all" )> + + <cfreturn sNewFileName> +</cffunction> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/cf_upload.cfm =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/cf_upload.cfm (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/cf_upload.cfm 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,72 @@ +<cfsetting enablecfoutputonly="yes" showdebugoutput="no"> +<!--- + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * File Browser connector for ColdFusion (MX 6.0 and above). + * (based on the original CF connector by Hendrik Kramer - hk@lwd.de) +---> + +<cfparam name="url.type" default="File"> +<cfparam name="url.currentFolder" default="/"> + +<!--- note: no serverPath url parameter - see config.cfm if you need to set the serverPath manually ---> + +<cfinclude template="config.cfm"> +<cfinclude template="cf_util.cfm"> +<cfinclude template="cf_io.cfm"> +<cfinclude template="cf_commands.cfm"> + +<cffunction name="SendError" returntype="void" output="true"> + <cfargument name="number" required="true" type="Numeric"> + <cfargument name="text" required="true"> + <cfreturn SendUploadResults( "#ARGUMENTS.number#", "", "", "ARGUMENTS.text" )> +</cffunction> + +<cfset REQUEST.Config = Config> +<cfif find( "/", getBaseTemplatePath() ) > + <cfset REQUEST.Fs = "/"> +<cfelse> + <cfset REQUEST.Fs = "\"> +</cfif> + +<cfif not Config.Enabled> + <cfset SendUploadResults( '1', '', '', 'This file uploader is disabled. Please check the "editor/filemanager/connectors/cfm/config.cfm" file' )> +</cfif> + +<cfset sCommand = 'QuickUpload'> +<cfset sType = "File"> + +<cfif isDefined( "URL.Type" )> + <cfset sType = URL.Type> +</cfif> + +<cfset sCurrentFolder = GetCurrentFolder()> + +<!--- Is enabled the upload? ---> +<cfif not IsAllowedCommand( sCommand )> + <cfset SendUploadResults( "1", "", "", "The """ & sCommand & """ command isn't allowed" )> +</cfif> + +<!--- Check if it is an allowed type. ---> +<cfif not IsAllowedType( sType )> + <cfset SendUploadResults( "1", "", "", "Invalid type specified" ) > +</cfif> + +<cfset FileUpload( sType, sCurrentFolder, sCommand )> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/cf_util.cfm =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/cf_util.cfm (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/cf_util.cfm 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,131 @@ +<cfsetting enablecfoutputonly="Yes"> +<!--- + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * This file include generic functions used by the ColdFusion Connector (MX 6.0 and above). +---> + +<cffunction name="RemoveFromStart" output="false" returntype="String"> + <cfargument name="sourceString" type="String"> + <cfargument name="charToRemove" type="String"> + + <cfif left(ARGUMENTS.sourceString, 1) eq ARGUMENTS.charToRemove> + <cfreturn mid( ARGUMENTS.sourceString, 2, len(ARGUMENTS.sourceString) -1 )> + </cfif> + + <cfreturn ARGUMENTS.sourceString> +</cffunction> + +<cffunction name="RemoveFromEnd" output="false" returntype="String"> + <cfargument name="sourceString" type="String"> + <cfargument name="charToRemove" type="String"> + + <cfif right(ARGUMENTS.sourceString, 1) eq ARGUMENTS.charToRemove> + <cfreturn mid( ARGUMENTS.sourceString, 1, len(ARGUMENTS.sourceString) -1 )> + </cfif> + + <cfreturn ARGUMENTS.sourceString> +</cffunction> + +<!--- +Check file content. +Currently this function validates only image files. +Returns false if file is invalid. +detectionLevel: + 0 = none + 1 = check image size for images, + 2 = use DetectHtml for images +----> +<cffunction name="IsImageValid" returntype="boolean" output="true"> + <cfargument name="filePath" required="true" type="String"> + <cfargument name="extension" required="true" type="String"> + + <cfset var imageCFC = ""> + <cfset var imageInfo = ""> + + <cfif not ListFindNoCase("gif,jpeg,jpg,png,swf,psd,bmp,iff,tiff,tif,swc,jpc,jp2,jpx,jb2,xmb,wbmp", ARGUMENTS.extension)> + <cfreturn true> + </cfif> + + <cftry> + <cfif REQUEST.CFVersion gte 8> + <cfset objImage = ImageRead(ARGUMENTS.filePath) > + <cfset imageInfo = ImageInfo(objImage)> + <!--- <cfimage action="info" source="#ARGUMENTS.filePath#" structName="imageInfo" /> ---> + <cfelse> + <cfset imageCFC = createObject("component", "image")> + <cfset imageInfo = imageCFC.getImageInfo("", ARGUMENTS.filePath)> + </cfif> + + <cfif imageInfo.height lte 0 or imageInfo.width lte 0> + <cfreturn false> + </cfif> + <cfcatch type="any"> + <cfreturn false> + </cfcatch> + </cftry> + + <cfreturn true> +</cffunction> + +<!--- + Detect HTML in the first KB to prevent against potential security issue with + IE/Safari/Opera file type auto detection bug. + Returns true if file contain insecure HTML code at the beginning. +---> +<cffunction name="DetectHtml" output="false" returntype="boolean"> + <cfargument name="filePath" required="true" type="String"> + + <cfset var tags = "<body,<head,<html,<img,<pre,<script,<table,<title"> + <cfset var chunk = lcase( Trim( BinaryFileRead( ARGUMENTS.filePath, 1024 ) ) )> + + <cfif not Len(chunk)> + <cfreturn false> + </cfif> + + <cfif refind('<!doctype\W*x?html', chunk)> + <cfreturn true> + </cfif> + + <cfloop index = "tag" list = "#tags#"> + <cfif find( tag, chunk )> + <cfreturn true> + </cfif> + </cfloop> + + <!--- type = javascript ---> + <cfif refind('type\s*=\s*[''"]?\s*(?:\w*/)?(?:ecma|java)', chunk)> + <cfreturn true> + </cfif> > + + <!--- href = javascript ---> + <!--- src = javascript ---> + <!--- data = javascript ---> + <cfif refind('(?:href|src|data)\s*=\s*[\''"]?\s*(?:ecma|java)script:', chunk)> + <cfreturn true> + </cfif> + + <!--- url(javascript ---> + <cfif refind('url\s*\(\s*[\''"]?\s*(?:ecma|java)script:', chunk)> + <cfreturn true> + </cfif> + + <cfreturn false> +</cffunction> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/config.cfm =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/config.cfm (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/config.cfm 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,189 @@ +<cfsetting enablecfoutputonly="Yes"> +<!--- + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Configuration file for the ColdFusion Connector (all versions). +---> + +<cfscript> + Config = StructNew() ; + + // SECURITY: You must explicitly enable this "connector". (Set enabled to "true") + Config.Enabled = false ; + + + // Path to uploaded files relative to the document root. + Config.UserFilesPath = "/userfiles/" ; + + // Use this to force the server path if FCKeditor is not running directly off + // the root of the application or the FCKeditor directory in the URL is a virtual directory + // or a symbolic link / junction + // Example: C:\inetpub\wwwroot\myDocs\ + Config.ServerPath = "" ; + + // Due to security issues with Apache modules, it is recommended to leave the + // following setting enabled. + Config.ForceSingleExtension = true ; + + // Perform additional checks for image files - if set to true, validate image size + // (This feature works in MX 6.0 and above) + Config.SecureImageUploads = true; + + // What the user can do with this connector + Config.ConfigAllowedCommands = "QuickUpload,FileUpload,GetFolders,GetFoldersAndFiles,CreateFolder" ; + + //Allowed Resource Types + Config.ConfigAllowedTypes = "File,Image,Flash,Media" ; + + // For security, HTML is allowed in the first Kb of data for files having the + // following extensions only. + // (This feature works in MX 6.0 and above)) + Config.HtmlExtensions = "html,htm,xml,xsd,txt,js" ; + + //Due to known issues with GetTempDirectory function, it is + //recommended to set this vairiable to a valid directory + //instead of using the GetTempDirectory function + //(used by MX 6.0 and above) + Config.TempDirectory = GetTempDirectory(); + +// Configuration settings for each Resource Type +// +// - AllowedExtensions: the possible extensions that can be allowed. +// If it is empty then any file type can be uploaded. +// - DeniedExtensions: The extensions that won't be allowed. +// If it is empty then no restrictions are done here. +// +// For a file to be uploaded it has to fulfill both the AllowedExtensions +// and DeniedExtensions (that's it: not being denied) conditions. +// +// - FileTypesPath: the virtual folder relative to the document root where +// these resources will be located. +// Attention: It must start and end with a slash: '/' +// +// - FileTypesAbsolutePath: the physical path to the above folder. It must be +// an absolute path. +// If it's an empty string then it will be autocalculated. +// Usefull if you are using a virtual directory, symbolic link or alias. +// Examples: 'C:\\MySite\\userfiles\\' or '/root/mysite/userfiles/'. +// Attention: The above 'FileTypesPath' must point to the same directory. +// Attention: It must end with a slash: '/' +// +// +// - QuickUploadPath: the virtual folder relative to the document root where +// these resources will be uploaded using the Upload tab in the resources +// dialogs. +// Attention: It must start and end with a slash: '/' +// +// - QuickUploadAbsolutePath: the physical path to the above folder. It must be +// an absolute path. +// If it's an empty string then it will be autocalculated. +// Usefull if you are using a virtual directory, symbolic link or alias. +// Examples: 'C:\\MySite\\userfiles\\' or '/root/mysite/userfiles/'. +// Attention: The above 'QuickUploadPath' must point to the same directory. +// Attention: It must end with a slash: '/' + + Config.AllowedExtensions = StructNew() ; + Config.DeniedExtensions = StructNew() ; + Config.FileTypesPath = StructNew() ; + Config.FileTypesAbsolutePath = StructNew() ; + Config.QuickUploadPath = StructNew() ; + Config.QuickUploadAbsolutePath = StructNew() ; + + Config.AllowedExtensions["File"] = "7z,aiff,asf,avi,bmp,csv,doc,fla,flv,gif,gz,gzip,jpeg,jpg,mid,mov,mp3,mp4,mpc,mpeg,mpg,ods,odt,pdf,png,ppt,pxd,qt,ram,rar,rm,rmi,rmvb,rtf,sdc,sitd,swf,sxc,sxw,tar,tgz,tif,tiff,txt,vsd,wav,wma,wmv,xls,xml,zip" ; + Config.DeniedExtensions["File"] = "" ; + Config.FileTypesPath["File"] = Config.UserFilesPath & 'file/' ; + Config.FileTypesAbsolutePath["File"] = iif( Config.ServerPath eq "", de(""), de(Config.ServerPath & 'file/') ) ; + Config.QuickUploadPath["File"] = Config.FileTypesPath["File"] ; + Config.QuickUploadAbsolutePath["File"] = Config.FileTypesAbsolutePath["File"] ; + + Config.AllowedExtensions["Image"] = "bmp,gif,jpeg,jpg,png" ; + Config.DeniedExtensions["Image"] = "" ; + Config.FileTypesPath["Image"] = Config.UserFilesPath & 'image/' ; + Config.FileTypesAbsolutePath["Image"] = iif( Config.ServerPath eq "", de(""), de(Config.ServerPath & 'image/') ) ; + Config.QuickUploadPath["Image"] = Config.FileTypesPath["Image"] ; + Config.QuickUploadAbsolutePath["Image"] = Config.FileTypesAbsolutePath["Image"] ; + + Config.AllowedExtensions["Flash"] = "swf,flv" ; + Config.DeniedExtensions["Flash"] = "" ; + Config.FileTypesPath["Flash"] = Config.UserFilesPath & 'flash/' ; + Config.FileTypesAbsolutePath["Flash"] = iif( Config.ServerPath eq "", de(""), de(Config.ServerPath & 'flash/') ) ; + Config.QuickUploadPath["Flash"] = Config.FileTypesPath["Flash"] ; + Config.QuickUploadAbsolutePath["Flash"] = Config.FileTypesAbsolutePath["Flash"] ; + + Config.AllowedExtensions["Media"] = "aiff,asf,avi,bmp,fla,flv,gif,jpeg,jpg,mid,mov,mp3,mp4,mpc,mpeg,mpg,png,qt,ram,rm,rmi,rmvb,swf,tif,tiff,wav,wma,wmv" ; + Config.DeniedExtensions["Media"] = "" ; + Config.FileTypesPath["Media"] = Config.UserFilesPath & 'media/' ; + Config.FileTypesAbsolutePath["Media"] = iif( Config.ServerPath eq "", de(""), de(Config.ServerPath & 'media/') ) ; + Config.QuickUploadPath["Media"] = Config.FileTypesPath["Media"] ; + Config.QuickUploadAbsolutePath["Media"] = Config.FileTypesAbsolutePath["Media"] ; +</cfscript> + +<cftry> +<!--- code to maintain backwards compatibility with previous version of cfm connector ---> +<cfif isDefined("application.userFilesPath")> + + <cflock scope="application" type="readonly" timeout="5"> + <cfset config.userFilesPath = application.userFilesPath> + </cflock> + +<cfelseif isDefined("server.userFilesPath")> + + <cflock scope="server" type="readonly" timeout="5"> + <cfset config.userFilesPath = server.userFilesPath> + </cflock> + +</cfif> + +<!--- look for config struct in application and server scopes ---> +<cfif isDefined("application.FCKeditor") and isStruct(application.FCKeditor)> + + <cflock scope="application" type="readonly" timeout="5"> + <cfset variables.FCKeditor = duplicate(application.FCKeditor)> + </cflock> + +<cfelseif isDefined("server.FCKeditor") and isStruct(server.FCKeditor)> + + <cflock scope="server" type="readonly" timeout="5"> + <cfset variables.FCKeditor = duplicate(server.FCKeditor)> + </cflock> + +</cfif> + <!--- catch potential "The requested scope application has not been enabled" exception ---> + <cfcatch type="any"> + </cfcatch> +</cftry> + +<cfif isDefined("FCKeditor")> + + <!--- copy key values from external to local config (i.e. override default config as required) ---> + <cfscript> + function structCopyKeys(stFrom, stTo) { + for ( key in stFrom ) { + if ( isStruct(stFrom[key]) ) { + structCopyKeys(stFrom[key],stTo[key]); + } else { + stTo[key] = stFrom[key]; + } + } + } + structCopyKeys(FCKeditor, config); + </cfscript> + +</cfif> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/connector.cfm =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/connector.cfm (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/connector.cfm 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,32 @@ +<cfsetting enablecfoutputonly="Yes"> +<!--- + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * File Browser connector for ColdFusion (all versions). + * +---> + +<cfset REQUEST.CFVersion = Left( SERVER.COLDFUSION.PRODUCTVERSION, Find( ",", SERVER.COLDFUSION.PRODUCTVERSION ) - 1 )> +<cfif REQUEST.CFVersion lte 5> + <cfinclude template="cf5_connector.cfm"> +<cfelse> + <cfinclude template="cf_connector.cfm"> +</cfif> +<cfabort> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/image.cfc =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/image.cfc (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/image.cfc 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,1324 @@ +<!--- + image.cfc v2.19, written by Rick Root (rick@webworksllc.com) + Derivative of work originally done originally by James Dew. + + Related Web Sites: + - http://www.opensourcecf.com/imagecfc (home page) + - http://www.cfopen.org/projects/imagecfc (project page) + + LICENSE + ------- + Copyright (c) 2007, Rick Root <rick@webworksllc.com> + All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, are permitted provided that the + following conditions are met: + + - Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + - Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + - Neither the name of the Webworks, LLC. nor the names of + its contributors may be used to endorse or promote products + derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + ============================================================ + This is a derivative work. Following is the original + Copyright notice. + ============================================================ + + Copyright (c) 2004 James F. Dew <jdew@yggdrasil.ca> + + Permission to use, copy, modify, and distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +---> +<!--- + SPECIAL NOTE FOR HEADLESS SYSTEMS + --------------------------------- + If you get a "cannot connect to X11 server" when running certain + parts of this component under Bluedragon (Linux), you must + add "-Djava.awt.headless=true" to the java startup line in + <bluedragon>/bin/StartBluedragon.sh. This isssue is discussed + in the Bluedragon Installation Guide section 3.8.1 for + Bluedragon 6.2.1. + + Bluedragon may also report a ClassNotFound exception when trying + to instantiate the java.awt.image.BufferedImage class. This is + most likely the same issue. + + If you get "This graphics environment can be used only in the + software emulation mode" when calling certain parts of this + component under Coldfusion MX, you should refer to Technote + ID #18747: http://www.macromedia.com/go/tn_18747 +---> + +<cfcomponent displayname="Image"> + +<cfset variables.throwOnError = "Yes"> +<cfset variables.defaultJpegCompression = "90"> +<cfset variables.interpolation = "bicubic"> +<cfset variables.textAntiAliasing = "Yes"> +<cfset variables.tempDirectory = "#expandPath(".")#"> + +<cfset variables.javanulls = "no"> +<cftry> + <cfset nullvalue = javacast("null","")> + <cfset variables.javanulls = "yes"> + <cfcatch type="any"> + <cfset variables.javanulls = "no"> + <!--- javacast null not supported, so filters won't work ---> + </cfcatch> +</cftry> +<!--- +<cfif javanulls> + <cfset variables.blurFilter = createObject("component","blurFilter")> + <cfset variables.sharpenFilter = createObject("component","sharpenFilter")> + <cfset variables.posterizeFilter = createObject("component","posterizeFilter")> +</cfif> +---> + +<cfset variables.Math = createobject("java", "java.lang.Math")> +<cfset variables.arrObj = createobject("java", "java.lang.reflect.Array")> +<cfset variables.floatClass = createobject("java", "java.lang.Float").TYPE> +<cfset variables.intClass = createobject("java", "java.lang.Integer").TYPE> +<cfset variables.shortClass = createobject("java", "java.lang.Short").TYPE> + +<cffunction name="getImageInfo" access="public" output="true" returntype="struct" hint="Rotate an image (+/-)90, (+/-)180, or (+/-)270 degrees."> + <cfargument name="objImage" required="yes" type="Any"> + <cfargument name="inputFile" required="yes" type="string"> + + <cfset var retVal = StructNew()> + <cfset var loadImage = StructNew()> + <cfset var img = ""> + + <cfset retVal.errorCode = 0> + <cfset retVal.errorMessage = ""> + + <cfif inputFile neq ""> + <cfset loadImage = readImage(inputFile, "NO")> + <cfif loadImage.errorCode is 0> + <cfset img = loadImage.img> + <cfelse> + <cfset retVal = throw(loadImage.errorMessage)> + <cfreturn retVal> + </cfif> + <cfset retVal.metaData = getImageMetadata(loadImage.inFile)> + <cfelse> + <cfset img = objImage> + <cfset retVal.metadata = getImageMetadata("")> + </cfif> + <cftry> + <cfset retVal.width = img.getWidth()> + <cfset retVal.height = img.getHeight()> + <cfset retVal.colorModel = img.getColorModel().toString()> + <cfset retVal.colorspace = img.getColorModel().getColorSpace().toString()> + <cfset retVal.objColorModel = img.getColorModel()> + <cfset retVal.objColorspace = img.getColorModel().getColorSpace()> + <cfset retVal.sampleModel = img.getSampleModel().toString()> + <cfset retVal.imageType = img.getType()> + <cfset retVal.misc = img.toString()> + <cfset retVal.canModify = true> + <cfreturn retVal> + <cfcatch type="any"> + <cfset retVal = throw( "#cfcatch.message#: #cfcatch.detail#")> + <cfreturn retVal> + </cfcatch> + </cftry> +</cffunction> + +<cffunction name="getImageMetadata" access="private" output="false" returntype="query"> + <cfargument name="inFile" required="yes" type="Any"><!--- java.io.File ---> + + <cfset var retQry = queryNew("dirName,tagName,tagValue")> + <cfset var paths = arrayNew(1)> + <cfset var loader = ""> + <cfset var JpegMetadatareader = ""> + <cfset var myMetadata = ""> + <cfset var directories = ""> + <cfset var currentDirectory = ""> + <cfset var tags = ""> + <cfset var currentTag = ""> + <cfset var tagName = ""> + + <cftry> + <cfscript> + paths = arrayNew(1); + paths[1] = expandPath("metadata-extractor-2.3.1.jar"); + loader = createObject("component", "javaloader.JavaLoader").init(paths); + + //at this stage we only have access to the class, but we don't have an instance + JpegMetadataReader = loader.create("com.drew.imaging.jpeg.JpegMetadataReader"); + + myMetaData = JpegMetadataReader.readMetadata(inFile); + directories = myMetaData.getDirectoryIterator(); + while (directories.hasNext()) { + currentDirectory = directories.next(); + tags = currentDirectory.getTagIterator(); + while (tags.hasNext()) { + currentTag = tags.next(); + if (currentTag.getTagName() DOES NOT CONTAIN "Unknown") { //leave out the junk data + queryAddRow(retQry); + querySetCell(retQry,"dirName",replace(currentTag.getDirectoryName(),' ','_','ALL')); + tagName = replace(currentTag.getTagName(),' ','','ALL'); + tagName = replace(tagName,'/','','ALL'); + querySetCell(retQry,"tagName",tagName); + querySetCell(retQry,"tagValue",currentTag.getDescription()); + } + } + } + return retQry; + </cfscript> + <cfcatch type="any"> + <cfreturn retQry /> + </cfcatch> + </cftry> +</cffunction> + +<cffunction name="flipHorizontal" access="public" output="true" returntype="struct" hint="Flip an image horizontally."> + <cfargument name="objImage" required="yes" type="Any"> + <cfargument name="inputFile" required="yes" type="string"> + <cfargument name="outputFile" required="yes" type="string"> + <cfargument name="jpegCompression" required="no" type="numeric" default="#variables.defaultJpegCompression#"> + + <cfreturn flipflop(objImage, inputFile, outputFile, "horizontal", jpegCompression)> +</cffunction> + +<cffunction name="flipVertical" access="public" output="true" returntype="struct" hint="Flop an image vertically."> + <cfargument name="objImage" required="yes" type="Any"> + <cfargument name="inputFile" required="yes" type="string"> + <cfargument name="outputFile" required="yes" type="string"> + <cfargument name="jpegCompression" required="no" type="numeric" default="#variables.defaultJpegCompression#"> + + <cfreturn flipflop(objImage, inputFile, outputFile, "vertical", jpegCompression)> +</cffunction> + +<cffunction name="scaleWidth" access="public" output="true" returntype="struct" hint="Scale an image to a specific width."> + <cfargument name="objImage" required="yes" type="Any"> + <cfargument name="inputFile" required="yes" type="string"> + <cfargument name="outputFile" required="yes" type="string"> + <cfargument name="newWidth" required="yes" type="numeric"> + <cfargument name="jpegCompression" required="no" type="numeric" default="#variables.defaultJpegCompression#"> + + <cfreturn resize(objImage, inputFile, outputFile, newWidth, 0, "false", "false", jpegCompression)> +</cffunction> + +<cffunction name="scaleHeight" access="public" output="true" returntype="struct" hint="Scale an image to a specific height."> + <cfargument name="objImage" required="yes" type="Any"> + <cfargument name="inputFile" required="yes" type="string"> + <cfargument name="outputFile" required="yes" type="string"> + <cfargument name="newHeight" required="yes" type="numeric"> + <cfargument name="jpegCompression" required="no" type="numeric" default="#variables.defaultJpegCompression#"> + + <cfreturn resize(objImage, inputFile, outputFile, 0, newHeight, "false", "false", jpegCompression)> +</cffunction> + +<cffunction name="resize" access="public" output="true" returntype="struct" hint="Resize an image to a specific width and height."> + <cfargument name="objImage" required="yes" type="Any"> + <cfargument name="inputFile" required="yes" type="string"> + <cfargument name="outputFile" required="yes" type="string"> + <cfargument name="newWidth" required="yes" type="numeric"> + <cfargument name="newHeight" required="yes" type="numeric"> + <cfargument name="preserveAspect" required="no" type="boolean" default="FALSE"> + <cfargument name="cropToExact" required="no" type="boolean" default="FALSE"> + <cfargument name="jpegCompression" required="no" type="numeric" default="#variables.defaultJpegCompression#"> + + <cfset var retVal = StructNew()> + <cfset var loadImage = StructNew()> + <cfset var saveImage = StructNew()> + <cfset var at = ""> + <cfset var op = ""> + <cfset var w = ""> + <cfset var h = ""> + <cfset var scale = 1> + <cfset var scaleX = 1> + <cfset var scaleY = 1> + <cfset var resizedImage = ""> + <cfset var rh = getRenderingHints()> + <cfset var specifiedWidth = arguments.newWidth> + <cfset var specifiedHeight = arguments.newHeight> + <cfset var imgInfo = ""> + <cfset var img = ""> + <cfset var cropImageResult = ""> + <cfset var cropOffsetX = ""> + <cfset var cropOffsetY = ""> + + <cfset retVal.errorCode = 0> + <cfset retVal.errorMessage = ""> + + <cfif inputFile neq ""> + <cfset loadImage = readImage(inputFile, "NO")> + <cfif loadImage.errorCode is 0> + <cfset img = loadImage.img> + <cfelse> + <cfset retVal = throw(loadImage.errorMessage)> + <cfreturn retVal> + </cfif> + <cfelse> + <cfset img = objImage> + </cfif> + <cfif img.getType() eq 0> + <cfset img = convertImageObject(img,img.TYPE_3BYTE_BGR)> + </cfif> + <cfscript> + resizedImage = CreateObject("java", "java.awt.image.BufferedImage"); + at = CreateObject("java", "java.awt.geom.AffineTransform"); + op = CreateObject("java", "java.awt.image.AffineTransformOp"); + + w = img.getWidth(); + h = img.getHeight(); + + if (preserveAspect and cropToExact and newHeight gt 0 and newWidth gt 0) + { + if (w / h gt newWidth / newHeight){ + newWidth = 0; + } else if (w / h lt newWidth / newHeight){ + newHeight = 0; + } + } else if (preserveAspect and newHeight gt 0 and newWidth gt 0) { + if (w / h gt newWidth / newHeight){ + newHeight = 0; + } else if (w / h lt newWidth / newHeight){ + newWidth = 0; + } + } + if (newWidth gt 0 and newHeight eq 0) { + scale = newWidth / w; + w = newWidth; + h = round(h*scale); + } else if (newHeight gt 0 and newWidth eq 0) { + scale = newHeight / h; + h = newHeight; + w = round(w*scale); + } else if (newHeight gt 0 and newWidth gt 0) { + w = newWidth; + h = newHeight; + } else { + retVal = throw( retVal.errorMessage); + return retVal; + } + resizedImage.init(javacast("int",w),javacast("int",h),img.getType()); + + w = w / img.getWidth(); + h = h / img.getHeight(); + + + + op.init(at.getScaleInstance(javacast("double",w),javacast("double",h)), rh); + // resizedImage = op.createCompatibleDestImage(img, img.getColorModel()); + op.filter(img, resizedImage); + + imgInfo = getimageinfo(resizedImage, ""); + if (imgInfo.errorCode gt 0) + { + return imgInfo; + } + + cropOffsetX = max( Int( (imgInfo.width/2) - (newWidth/2) ), 0 ); + cropOffsetY = max( Int( (imgInfo.height/2) - (newHeight/2) ), 0 ); + // There is a chance that the image is exactly the correct + // width and height and don't need to be cropped + if + ( + preserveAspect and cropToExact + and + (imgInfo.width IS NOT specifiedWidth OR imgInfo.height IS NOT specifiedHeight) + ) + { + // Get the correct offset to get the center of the image + cropOffsetX = max( Int( (imgInfo.width/2) - (specifiedWidth/2) ), 0 ); + cropOffsetY = max( Int( (imgInfo.height/2) - (specifiedHeight/2) ), 0 ); + + cropImageResult = crop( resizedImage, "", "", cropOffsetX, cropOffsetY, specifiedWidth, specifiedHeight ); + if ( cropImageResult.errorCode GT 0) + { + return cropImageResult; + } else { + resizedImage = cropImageResult.img; + } + } + if (outputFile eq "") + { + retVal.img = resizedImage; + return retVal; + } else { + saveImage = writeImage(outputFile, resizedImage, jpegCompression); + if (saveImage.errorCode gt 0) + { + return saveImage; + } else { + return retVal; + } + } + </cfscript> +</cffunction> + +<cffunction name="crop" access="public" output="true" returntype="struct" hint="Crop an image."> + <cfargument name="objImage" required="yes" type="Any"> + <cfargument name="inputFile" required="yes" type="string"> + <cfargument name="outputFile" required="yes" type="string"> + <cfargument name="fromX" required="yes" type="numeric"> + <cfargument name="fromY" required="yes" type="numeric"> + <cfargument name="newWidth" required="yes" type="numeric"> + <cfargument name="newHeight" required="yes" type="numeric"> + <cfargument name="jpegCompression" required="no" type="numeric" default="#variables.defaultJpegCompression#"> + + <cfset var retVal = StructNew()> + <cfset var loadImage = StructNew()> + <cfset var saveImage = StructNew()> + <cfset var croppedImage = ""> + <cfset var rh = getRenderingHints()> + <cfset var img = ""> + + <cfset retVal.errorCode = 0> + <cfset retVal.errorMessage = ""> + + <cfif inputFile neq ""> + <cfset loadImage = readImage(inputFile, "NO")> + <cfif loadImage.errorCode is 0> + <cfset img = loadImage.img> + <cfelse> + <cfset retVal = throw(loadImage.errorMessage)> + <cfreturn retVal> + </cfif> + <cfelse> + <cfset img = objImage> + </cfif> + <cfif img.getType() eq 0> + <cfset img = convertImageObject(img,img.TYPE_3BYTE_BGR)> + </cfif> + <cfscript> + if (fromX + newWidth gt img.getWidth() + OR + fromY + newHeight gt img.getHeight() + ) + { + retval = throw( "The cropped image dimensions go beyond the original image dimensions."); + return retVal; + } + croppedImage = img.getSubimage(javaCast("int", fromX), javaCast("int", fromY), javaCast("int", newWidth), javaCast("int", newHeight) ); + if (outputFile eq "") + { + retVal.img = croppedImage; + return retVal; + } else { + saveImage = writeImage(outputFile, croppedImage, jpegCompression); + if (saveImage.errorCode gt 0) + { + return saveImage; + } else { + return retVal; + } + } + </cfscript> +</cffunction> + +<cffunction name="rotate" access="public" output="true" returntype="struct" hint="Rotate an image (+/-)90, (+/-)180, or (+/-)270 degrees."> + <cfargument name="objImage" required="yes" type="Any"> + <cfargument name="inputFile" required="yes" type="string"> + <cfargument name="outputFile" required="yes" type="string"> + <cfargument name="degrees" required="yes" type="numeric"> + <cfargument name="jpegCompression" required="no" type="numeric" default="#variables.defaultJpegCompression#"> + + <cfset var retVal = StructNew()> + <cfset var img = ""> + <cfset var loadImage = StructNew()> + <cfset var saveImage = StructNew()> + <cfset var at = ""> + <cfset var op = ""> + <cfset var w = 0> + <cfset var h = 0> + <cfset var iw = 0> + <cfset var ih = 0> + <cfset var x = 0> + <cfset var y = 0> + <cfset var rotatedImage = ""> + <cfset var rh = getRenderingHints()> + + <cfset retVal.errorCode = 0> + <cfset retVal.errorMessage = ""> + + <cfif inputFile neq ""> + <cfset loadImage = readImage(inputFile, "NO")> + <cfif loadImage.errorCode is 0> + <cfset img = loadImage.img> + <cfelse> + <cfset retVal = throw(loadImage.errorMessage)> + <cfreturn retVal> + </cfif> + <cfelse> + <cfset img = objImage> + </cfif> + <cfif img.getType() eq 0> + <cfset img = convertImageObject(img,img.TYPE_3BYTE_BGR)> + </cfif> + <cfif ListFind("-270,-180,-90,90,180,270",degrees) is 0> + <cfset retVal = throw( "At this time, image.cfc only supports rotating images in 90 degree increments.")> + <cfreturn retVal> + </cfif> + + <cfscript> + rotatedImage = CreateObject("java", "java.awt.image.BufferedImage"); + at = CreateObject("java", "java.awt.geom.AffineTransform"); + op = CreateObject("java", "java.awt.image.AffineTransformOp"); + + iw = img.getWidth(); h = iw; + ih = img.getHeight(); w = ih; + + if(arguments.degrees eq 180) { w = iw; h = ih; } + + x = (w/2)-(iw/2); + y = (h/2)-(ih/2); + + rotatedImage.init(javacast("int",w),javacast("int",h),img.getType()); + + at.rotate(arguments.degrees * 0.0174532925,w/2,h/2); + at.translate(x,y); + op.init(at, rh); + + op.filter(img, rotatedImage); + + if (outputFile eq "") + { + retVal.img = rotatedImage; + return retVal; + } else { + saveImage = writeImage(outputFile, rotatedImage, jpegCompression); + if (saveImage.errorCode gt 0) + { + return saveImage; + } else { + return retVal; + } + } + </cfscript> +</cffunction> + +<cffunction name="convert" access="public" output="true" returntype="struct" hint="Convert an image from one format to another."> + <cfargument name="objImage" required="yes" type="Any"> + <cfargument name="inputFile" required="yes" type="string"> + <cfargument name="outputFile" required="yes" type="string"> + <cfargument name="jpegCompression" required="no" type="numeric" default="#variables.defaultJpegCompression#"> + + <cfset var retVal = StructNew()> + <cfset var loadImage = StructNew()> + <cfset var saveImage = StructNew()> + <cfset var img = ""> + + <cfset retVal.errorCode = 0> + <cfset retVal.errorMessage = ""> + + <cfif inputFile neq ""> + <cfset loadImage = readImage(inputFile, "NO")> + <cfif loadImage.errorCode is 0> + <cfset img = loadImage.img> + <cfelse> + <cfset retVal = throw(loadImage.errorMessage)> + <cfreturn retVal> + </cfif> + <cfelse> + <cfset img = objImage> + </cfif> + + <cfscript> + if (outputFile eq "") + { + retVal = throw( "The convert method requires a valid output filename."); + return retVal; + } else { + saveImage = writeImage(outputFile, img, jpegCompression); + if (saveImage.errorCode gt 0) + { + return saveImage; + } else { + return retVal; + } + } + </cfscript> +</cffunction> + +<cffunction name="setOption" access="public" output="true" returnType="void" hint="Sets values for allowed CFC options."> + <cfargument name="key" type="string" required="yes"> + <cfargument name="val" type="string" required="yes"> + + <cfset var validKeys = "interpolation,textantialiasing,throwonerror,defaultJpegCompression"> + <cfset arguments.key = lcase(trim(arguments.key))> + <cfset arguments.val = lcase(trim(arguments.val))> + <cfif listFind(validKeys, arguments.key) gt 0> + <cfset variables[arguments.key] = arguments.val> + </cfif> +</cffunction> + +<cffunction name="getOption" access="public" output="true" returnType="any" hint="Returns the current value for the specified CFC option."> + <cfargument name="key" type="string" required="yes"> + + <cfset var validKeys = "interpolation,textantialiasing,throwonerror,defaultJpegCompression"> + <cfset arguments.key = lcase(trim(arguments.key))> + <cfif listFindNoCase(validKeys, arguments.key) gt 0> + <cfreturn variables[arguments.key]> + <cfelse> + <cfreturn ""> + </cfif> +</cffunction> + +<cffunction name="getRenderingHints" access="private" output="true" returnType="any" hint="Internal method controls various aspects of rendering quality."> + <cfset var rh = CreateObject("java","java.awt.RenderingHints")> + <cfset var initMap = CreateObject("java","java.util.HashMap")> + <cfset initMap.init()> + <cfset rh.init(initMap)> + <cfset rh.put(rh.KEY_ALPHA_INTERPOLATION, rh.VALUE_ALPHA_INTERPOLATION_QUALITY)> <!--- QUALITY, SPEED, DEFAULT ---> + <cfset rh.put(rh.KEY_ANTIALIASING, rh.VALUE_ANTIALIAS_ON)> <!--- ON, OFF, DEFAULT ---> + <cfset rh.put(rh.KEY_COLOR_RENDERING, rh.VALUE_COLOR_RENDER_QUALITY)> <!--- QUALITY, SPEED, DEFAULT ---> + <cfset rh.put(rh.KEY_DITHERING, rh.VALUE_DITHER_DEFAULT)> <!--- DISABLE, ENABLE, DEFAULT ---> + <cfset rh.put(rh.KEY_RENDERING, rh.VALUE_RENDER_QUALITY)> <!--- QUALITY, SPEED, DEFAULT ---> + <cfset rh.put(rh.KEY_FRACTIONALMETRICS, rh.VALUE_FRACTIONALMETRICS_DEFAULT)> <!--- DISABLE, ENABLE, DEFAULT ---> + <cfset rh.put(rh.KEY_STROKE_CONTROL, rh.VALUE_STROKE_DEFAULT)> + + <cfif variables.textAntiAliasing> + <cfset rh.put(rh.KEY_TEXT_ANTIALIASING, rh.VALUE_TEXT_ANTIALIAS_ON)> + <cfelse> + <cfset rh.put(rh.KEY_TEXT_ANTIALIASING, rh.VALUE_TEXT_ANTIALIAS_OFF)> + </cfif> + + <cfif variables.interpolation eq "nearest_neighbor"> + <cfset rh.put(rh.KEY_INTERPOLATION, rh.VALUE_INTERPOLATION_NEAREST_NEIGHBOR)> + <cfelseif variables.interpolation eq "bilinear"> + <cfset rh.put(rh.KEY_INTERPOLATION, rh.VALUE_INTERPOLATION_BILINEAR)> + <cfelse> + <cfset rh.put(rh.KEY_INTERPOLATION, rh.VALUE_INTERPOLATION_BICUBIC)> + </cfif> + + <cfreturn rh> +</cffunction> + +<cffunction name="readImage" access="public" output="true" returntype="struct" hint="Reads an image from a local file. Requires an absolute path."> + <cfargument name="source" required="yes" type="string"> + <cfargument name="forModification" required="no" type="boolean" default="yes"> + + <cfif isURL(source)> + <cfreturn readImageFromURL(source, forModification)> + <cfelse> + <cfreturn readImageFromFile(source, forModification)> + </cfif> +</cffunction> + +<cffunction name="readImageFromFile" access="private" output="true" returntype="struct" hint="Reads an image from a local file. Requires an absolute path."> + <cfargument name="inputFile" required="yes" type="string"> + <cfargument name="forModification" required="no" type="boolean" default="yes"> + + <cfset var retVal = StructNew()> + <cfset var img = ""> + <cfset var inFile = ""> + <cfset var filename = getFileFromPath(inputFile)> + <cfset var extension = lcase(listLast(inputFile,"."))> + <cfset var imageIO = CreateObject("java", "javax.imageio.ImageIO")> + <cfset var validExtensionsToRead = ArrayToList(imageIO.getReaderFormatNames())> + + <cfset retVal.errorCode = 0> + <cfset retVal.errorMessage = ""> + + <cfif not fileExists(arguments.inputFile)> + <cfset retVal = throw("The specified file #Chr(34)##arguments.inputFile##Chr(34)# could not be found.")> + <cfreturn retVal> + <cfelseif listLen(filename,".") lt 2> + <cfset retVal = throw("Sorry, image files without extensions cannot be manipulated.")> + <cfreturn retVal> + <cfelseif listFindNoCase(validExtensionsToRead, extension) is 0> + <cfset retVal = throw("Java is unable to read #extension# files.")> + <cfreturn retVal> + <cfelseif NOT fileExists(arguments.inputFile)> + <cfset retVal = throw("The specified input file does not exist.")> + <cfreturn retVal> + <cfelse> + <cfset img = CreateObject("java", "java.awt.image.BufferedImage")> + <cfset inFile = CreateObject("java", "java.io.File")> + <cfset inFile.init(arguments.inputFile)> + <cfif NOT inFile.canRead()> + <cfset retVal = throw("Unable to open source file #Chr(34)##arguments.inputFile##Chr(34)#.")> + <cfreturn retVal> + <cfelse> + <cftry> + <cfset img = imageIO.read(inFile)> + <cfcatch type="any"> + <cfset retval = throw("An error occurred attempting to read the specified image. #cfcatch.message# - #cfcatch.detail#")> + <cfreturn retVal> + </cfcatch> + </cftry> + <cfset retVal.img = img> + <cfset retVal.inFile = inFile> + <cfreturn retVal> + </cfif> + </cfif> +</cffunction> + +<cffunction name="readImageFromURL" access="private" output="true" returntype="struct" hint="Read an image from a URL. Requires an absolute URL."> + <cfargument name="inputURL" required="yes" type="string"> + <cfargument name="forModification" required="no" type="boolean" default="yes"> + + <cfset var retVal = StructNew()> + <cfset var img = CreateObject("java", "java.awt.image.BufferedImage")> + <cfset var inURL = CreateObject("java", "java.net.URL")> + <cfset var imageIO = CreateObject("java", "javax.imageio.ImageIO")> + + <cfset retVal.errorCode = 0> + <cfset retVal.errorMessage = ""> + + + <cfset inURL.init(arguments.inputURL)> + <cftry> + <cfset img = imageIO.read(inURL)> + <cfcatch type="any"> + <cfset retval = throw("An error occurred attempting to read the specified image. #cfcatch.message# - #cfcatch.detail#")> + <cfreturn retVal> + </cfcatch> + </cftry> + <cfset retVal.img = img> + <cfreturn retVal> +</cffunction> + +<cffunction name="writeImage" access="public" output="true" returntype="struct" hint="Write an image to disk."> + <cfargument name="outputFile" required="yes" type="string"> + <cfargument name="img" required="yes" type="any"> + <cfargument name="jpegCompression" required="no" type="numeric" default="#variables.defaultJpegCompression#"> + + <cfset var retVal = StructNew()> + <cfset var outFile = ""> + <cfset var filename = getFileFromPath(outputFile)> + <cfset var extension = lcase(listLast(filename,"."))> + <cfset var imageIO = CreateObject("java", "javax.imageio.ImageIO")> + <cfset var validExtensionsToWrite = ArrayToList(imageIO.getWriterFormatNames())> + <!--- used for jpeg output method ---> + <cfset var out = ""> + <cfset var fos = ""> + <cfset var JPEGCodec = ""> + <cfset var encoder = ""> + <cfset var param = ""> + <cfset var quality = javacast("float", jpegCompression/100)> + <cfset var tempOutputFile = "#variables.tempDirectory#\#createUUID()#.#extension#"> + + <cfset retVal.errorCode = 0> + <cfset retVal.errorMessage = ""> + + <cfif listFindNoCase(validExtensionsToWrite, extension) eq 0> + <cfset throw("Java is unable to write #extension# files. Valid formats include: #validExtensionsToWrite#")> + </cfif> + + <cfif extension neq "jpg" and extension neq "jpeg"> + <!--- + Simple output method for non jpeg images + ---> + <cfset outFile = CreateObject("java", "java.io.File")> + <cfset outFile.init(tempOutputFile)> + <cfset imageIO.write(img, extension, outFile)> + <cfelse> + <cfscript> + /* + JPEG output method handles compression + */ + out = createObject("java", "java.io.BufferedOutputStream"); + fos = createObject("java", "java.io.FileOutputStream"); + fos.init(tempOutputFile); + out.init(fos); + JPEGCodec = createObject("java", "com.sun.image.codec.jpeg.JPEGCodec"); + encoder = JPEGCodec.createJPEGEncoder(out); + param = encoder.getDefaultJPEGEncodeParam(img); + param.setQuality(quality, false); + encoder.setJPEGEncodeParam(param); + encoder.encode(img); + out.close(); + </cfscript> + </cfif> + <!--- move file to its final destination ---> + <cffile action="MOVE" source="#tempOutputFile#" destination="#arguments.outputFile#"> + <cfreturn retVal> +</cffunction> + +<cffunction name="flipflop" access="private" output="true" returntype="struct" hint="Internal method used for flipping and flopping images."> + <cfargument name="objImage" required="yes" type="Any"> + <cfargument name="inputFile" required="yes" type="string"> + <cfargument name="outputFile" required="yes" type="string"> + <cfargument name="direction" required="yes" type="string"><!--- horizontal or vertical ---> + <cfargument name="jpegCompression" required="no" type="numeric" default="#variables.defaultJpegCompression#"> + + <cfset var retVal = StructNew()> + <cfset var loadImage = StructNew()> + <cfset var saveImage = StructNew()> + <cfset var flippedImage = ""> + <cfset var rh = getRenderingHints()> + <cfset var img = ""> + + <cfset retVal.errorCode = 0> + <cfset retVal.errorMessage = ""> + + <cfif inputFile neq ""> + <cfset loadImage = readImage(inputFile, "NO")> + <cfif loadImage.errorCode is 0> + <cfset img = loadImage.img> + <cfelse> + <cfset retVal = throw(loadImage.errorMessage)> + <cfreturn retVal> + </cfif> + <cfelse> + <cfset img = objImage> + </cfif> + <cfif img.getType() eq 0> + <cfset img = convertImageObject(img,img.TYPE_3BYTE_BGR)> + </cfif> + <cfscript> + flippedImage = CreateObject("java", "java.awt.image.BufferedImage"); + at = CreateObject("java", "java.awt.geom.AffineTransform"); + op = CreateObject("java", "java.awt.image.AffineTransformOp"); + + flippedImage.init(img.getWidth(), img.getHeight(), img.getType()); + + if (direction eq "horizontal") { + at = at.getScaleInstance(-1, 1); + at.translate(-img.getWidth(), 0); + } else { + at = at.getScaleInstance(1,-1); + at.translate(0, -img.getHeight()); + } + op.init(at, rh); + op.filter(img, flippedImage); + + if (outputFile eq "") + { + retVal.img = flippedImage; + return retVal; + } else { + saveImage = writeImage(outputFile, flippedImage, jpegCompression); + if (saveImage.errorCode gt 0) + { + return saveImage; + } else { + return retVal; + } + } + </cfscript> +</cffunction> + + + +<cffunction name="filterFastBlur" access="public" output="true" returntype="struct" hint="Internal method used for flipping and flopping images."> + <cfargument name="objImage" required="yes" type="Any"> + <cfargument name="inputFile" required="yes" type="string"> + <cfargument name="outputFile" required="yes" type="string"> + <cfargument name="blurAmount" required="yes" type="numeric"> + <cfargument name="iterations" required="yes" type="numeric"> + <cfargument name="jpegCompression" required="no" type="numeric" default="#variables.defaultJpegCompression#"> + + <cfset var retVal = StructNew()> + <cfset var loadImage = StructNew()> + <cfset var saveImage = StructNew()> + <cfset var srcImage = ""> + <cfset var destImage = ""> + <cfset var rh = getRenderingHints()> + + <cfset retVal.errorCode = 0> + <cfset retVal.errorMessage = ""> + + <cfif NOT variables.javanulls> + <cfset throw("Sorry, but the blur filter is not supported on this platform.")> + </cfif> + <cfif inputFile neq ""> + <cfset loadImage = readImage(inputFile, "NO")> + <cfif loadImage.errorCode is 0> + <cfset srcImage = loadImage.img> + <cfelse> + <cfset retVal = throw(loadImage.errorMessage)> + <cfreturn retVal> + </cfif> + <cfelse> + <cfset srcImage = objImage> + </cfif> + <cfif srcImage.getType() eq 0> + <cfset srcImage = convertImageObject(srcImage,srcImage.TYPE_3BYTE_BGR)> + </cfif> + + <cfscript> + + // initialize the blur filter + variables.blurFilter.init(arguments.blurAmount); + // move the source image into the destination image + // so we can repeatedly blur it. + destImage = srcImage; + + for (i=1; i lte iterations; i=i+1) + { + // do the blur i times + destImage = variables.blurFilter.filter(destImage); + } + + + if (outputFile eq "") + { + // return the image object + retVal.img = destImage; + return retVal; + } else { + // write the image object to the specified file. + saveImage = writeImage(outputFile, destImage, jpegCompression); + if (saveImage.errorCode gt 0) + { + return saveImage; + } else { + return retVal; + } + } + </cfscript> +</cffunction> + +<cffunction name="filterSharpen" access="public" output="true" returntype="struct" hint="Internal method used for flipping and flopping images."> + <cfargument name="objImage" required="yes" type="Any"> + <cfargument name="inputFile" required="yes" type="string"> + <cfargument name="outputFile" required="yes" type="string"> + <cfargument name="jpegCompression" required="no" type="numeric" default="#variables.defaultJpegCompression#"> + + <cfset var retVal = StructNew()> + <cfset var loadImage = StructNew()> + <cfset var saveImage = StructNew()> + <cfset var srcImage = ""> + <cfset var destImage = ""> + <cfset var rh = getRenderingHints()> + + <cfset retVal.errorCode = 0> + <cfset retVal.errorMessage = ""> + + <cfif NOT variables.javanulls> + <cfset throw("Sorry, but the blur filter is not supported on this platform.")> + </cfif> + + <cfif inputFile neq ""> + <cfset loadImage = readImage(inputFile, "NO")> + <cfif loadImage.errorCode is 0> + <cfset srcImage = loadImage.img> + <cfelse> + <cfset retVal = throw(loadImage.errorMessage)> + <cfreturn retVal> + </cfif> + <cfelse> + <cfset srcImage = objImage> + </cfif> + <cfif srcImage.getType() eq 0> + <cfset srcImage = convertImageObject(srcImage,srcImage.TYPE_3BYTE_BGR)> + </cfif> + + <cfscript> + // initialize the sharpen filter + variables.sharpenFilter.init(); + + destImage = variables.sharpenFilter.filter(srcImage); + + + if (outputFile eq "") + { + // return the image object + retVal.img = destImage; + return retVal; + } else { + // write the image object to the specified file. + saveImage = writeImage(outputFile, destImage, jpegCompression); + if (saveImage.errorCode gt 0) + { + return saveImage; + } else { + return retVal; + } + } + </cfscript> +</cffunction> + + +<cffunction name="filterPosterize" access="public" output="true" returntype="struct" hint="Internal method used for flipping and flopping images."> + <cfargument name="objImage" required="yes" type="Any"> + <cfargument name="inputFile" required="yes" type="string"> + <cfargument name="outputFile" required="yes" type="string"> + <cfargument name="amount" required="yes" type="string"> + <cfargument name="jpegCompression" required="no" type="numeric" default="#variables.defaultJpegCompression#"> + + <cfset var retVal = StructNew()> + <cfset var loadImage = StructNew()> + <cfset var saveImage = StructNew()> + <cfset var srcImage = ""> + <cfset var destImage = ""> + <cfset var rh = getRenderingHints()> + + <cfset retVal.errorCode = 0> + <cfset retVal.errorMessage = ""> + + <cfif NOT variables.javanulls> + <cfset throw("Sorry, but the blur filter is not supported on this platform.")> + </cfif> + + <cfif inputFile neq ""> + <cfset loadImage = readImage(inputFile, "NO")> + <cfif loadImage.errorCode is 0> + <cfset srcImage = loadImage.img> + <cfelse> + <cfset retVal = throw(loadImage.errorMessage)> + <cfreturn retVal> + </cfif> + <cfelse> + <cfset srcImage = objImage> + </cfif> + <cfif srcImage.getType() eq 0> + <cfset srcImage = convertImageObject(srcImage,srcImage.TYPE_3BYTE_BGR)> + </cfif> + <cfif srcImage.getType() neq 5> + <cfset throw("ImageCFC cannot posterize this image type (#srcImage.getType()#)")> + </cfif> + <cfscript> + // initialize the posterize filter + variables.posterizeFilter.init(arguments.amount); + + destImage = variables.posterizeFilter.filter(srcImage); + + + if (outputFile eq "") + { + // return the image object + retVal.img = destImage; + return retVal; + } else { + // write the image object to the specified file. + saveImage = writeImage(outputFile, destImage, jpegCompression); + if (saveImage.errorCode gt 0) + { + return saveImage; + } else { + return retVal; + } + } + </cfscript> +</cffunction> + + +<cffunction name="addText" access="public" output="true" returntype="struct" hint="Add text to an image."> + <cfargument name="objImage" required="yes" type="Any"> + <cfargument name="inputFile" required="yes" type="string"> + <cfargument name="outputFile" required="yes" type="string"> + <cfargument name="x" required="yes" type="numeric"> + <cfargument name="y" required="yes" type="numeric"> + <cfargument name="fontDetails" required="yes" type="struct"> + <cfargument name="content" required="yes" type="String"> + <cfargument name="jpegCompression" required="no" type="numeric" default="#variables.defaultJpegCompression#"> + + <cfset var retVal = StructNew()> + <cfset var loadImage = StructNew()> + <cfset var img = ""> + <cfset var saveImage = StructNew()> + <cfset var g2d = ""> + <cfset var bgImage = ""> + <cfset var fontImage = ""> + <cfset var overlayImage = ""> + <cfset var Color = ""> + <cfset var font = ""> + <cfset var font_stream = ""> + <cfset var ac = ""> + <cfset var rgb = ""> + + <cfset retVal.errorCode = 0> + <cfset retVal.errorMessage = ""> + + <cfparam name="arguments.fontDetails.size" default="12"> + <cfparam name="arguments.fontDetails.color" default="black"> + <cfparam name="arguments.fontDetails.fontFile" default=""> + <cfparam name="arguments.fontDetails.fontName" default="serif"> + + <cfif arguments.fontDetails.fontFile neq "" and not fileExists(arguments.fontDetails.fontFile)> + <cfset retVal = throw("The specified font file #Chr(34)##arguments.inputFile##Chr(34)# could not be found on the server.")> + <cfreturn retVal> + </cfif> + <cftry> + <cfset rgb = getRGB(arguments.fontDetails.color)> + <cfcatch type="any"> + <cfset retVal = throw("Invalid color #Chr(34)##arguments.fontDetails.color##Chr(34)#")> + <cfreturn retVal> + </cfcatch> + </cftry> + <cfif inputFile neq ""> + <cfset loadImage = readImage(inputFile, "NO")> + <cfif loadImage.errorCode is 0> + <cfset img = loadImage.img> + <cfelse> + <cfset retVal = throw(loadImage.errorMessage)> + <cfreturn retVal> + </cfif> + <cfelse> + <cfset img = objImage> + </cfif> + <cfif img.getType() eq 0> + <cfset img = convertImageObject(img,img.TYPE_3BYTE_BGR)> + </cfif> + <cfscript> + // load objects + bgImage = CreateObject("java", "java.awt.image.BufferedImage"); + fontImage = CreateObject("java", "java.awt.image.BufferedImage"); + overlayImage = CreateObject("java", "java.awt.image.BufferedImage"); + Color = CreateObject("java","java.awt.Color"); + font = createObject("java","java.awt.Font"); + font_stream = createObject("java","java.io.FileInputStream"); + ac = CreateObject("Java", "java.awt.AlphaComposite"); + + // set up basic needs + fontColor = Color.init(javacast("int", rgb.red), javacast("int", rgb.green), javacast("int", rgb.blue)); + + if (fontDetails.fontFile neq "") + { + font_stream.init(arguments.fontDetails.fontFile); + font = font.createFont(font.TRUETYPE_FONT, font_stream); + font = font.deriveFont(javacast("float",arguments.fontDetails.size)); + } else { + font.init(fontDetails.fontName, evaluate(fontDetails.style), fontDetails.size); + } + // get font metrics using a 1x1 bufferedImage + fontImage.init(1,1,img.getType()); + g2 = fontImage.createGraphics(); + g2.setRenderingHints(getRenderingHints()); + fc = g2.getFontRenderContext(); + bounds = font.getStringBounds(content,fc); + + g2 = img.createGraphics(); + g2.setRenderingHints(getRenderingHints()); + g2.setFont(font); + g2.setColor(fontColor); + // in case you want to change the alpha + // g2.setComposite(ac.getInstance(ac.SRC_OVER, 0.50)); + + // the location (arguments.fontDetails.size+y) doesn't really work + // the way I want it to. + g2.drawString(content,javacast("int",x),javacast("int",arguments.fontDetails.size+y)); + + if (outputFile eq "") + { + retVal.img = img; + return retVal; + } else { + saveImage = writeImage(outputFile, img, jpegCompression); + if (saveImage.errorCode gt 0) + { + return saveImage; + } else { + return retVal; + } + } + </cfscript> +</cffunction> + +<cffunction name="watermark" access="public" output="false"> + <cfargument name="objImage1" required="yes" type="Any"> + <cfargument name="objImage2" required="yes" type="Any"> + <cfargument name="inputFile1" required="yes" type="string"> + <cfargument name="inputFile2" required="yes" type="string"> + <cfargument name="alpha" required="yes" type="numeric"> + <cfargument name="placeAtX" required="yes" type="numeric"> + <cfargument name="placeAtY" required="yes" type="numeric"> + <cfargument name="outputFile" required="yes" type="string"> + <cfargument name="jpegCompression" required="no" type="numeric" default="#variables.defaultJpegCompression#"> + + <cfset var retVal = StructNew()> + <cfset var loadImage = StructNew()> + <cfset var originalImage = ""> + <cfset var wmImage = ""> + <cfset var saveImage = StructNew()> + <cfset var ac = ""> + <cfset var rh = getRenderingHints()> + + <cfset retVal.errorCode = 0> + <cfset retVal.errorMessage = ""> + + <cfif inputFile1 neq ""> + <cfset loadImage = readImage(inputFile1, "NO")> + <cfif loadImage.errorCode is 0> + <cfset originalImage = loadImage.img> + <cfelse> + <cfset retVal = throw(loadImage.errorMessage)> + <cfreturn retVal> + </cfif> + <cfelse> + <cfset originalImage = objImage1> + </cfif> + <cfif originalImage.getType() eq 0> + <cfset originalImage = convertImageObject(originalImage,originalImage.TYPE_3BYTE_BGR)> + </cfif> + + <cfif inputFile2 neq ""> + <cfset loadImage = readImage(inputFile2, "NO")> + <cfif loadImage.errorCode is 0> + <cfset wmImage = loadImage.img> + <cfelse> + <cfset retVal = throw(loadImage.errorMessage)> + <cfreturn retVal> + </cfif> + <cfelse> + <cfset wmImage = objImage2> + </cfif> + <cfif wmImage.getType() eq 0> + <cfset wmImage = convertImageObject(wmImage,wmImage.TYPE_3BYTE_BGR)> + </cfif> + + + <cfscript> + at = CreateObject("java", "java.awt.geom.AffineTransform"); + op = CreateObject("java", "java.awt.image.AffineTransformOp"); + ac = CreateObject("Java", "java.awt.AlphaComposite"); + gfx = originalImage.getGraphics(); + gfx.setComposite(ac.getInstance(ac.SRC_OVER, alpha)); + + at.init(); + // op.init(at,op.TYPE_BILINEAR); + op.init(at, rh); + + gfx.drawImage(wmImage, op, javaCast("int",arguments.placeAtX), javacast("int", arguments.placeAtY)); + + gfx.dispose(); + + if (outputFile eq "") + { + retVal.img = originalImage; + return retVal; + } else { + saveImage = writeImage(outputFile, originalImage, jpegCompression); + if (saveImage.errorCode gt 0) + { + return saveImage; + } else { + return retVal; + } + } + </cfscript> +</cffunction> + +<cffunction name="isURL" access="private" output="false" returnType="boolean"> + <cfargument name="stringToCheck" required="yes" type="string"> + <cfif REFindNoCase("^(((https?:)\/\/))[-[:alnum:]\?%,\.\/#!@:=\+~_]+[A-Za-z0-9\/]$",stringToCheck) NEQ 0> + <cfreturn true> + <cfelse> + <cfreturn false> + </cfif> +</cffunction> + +<!--- function returns RGB values in a structure for hex or the 16 + HTML named colors ---> +<cffunction name="getRGB" access="private" output="true" returnType="struct"> + <cfargument name="color" type="string" required="yes"> + + <cfset var retVal = structNew()> + <cfset var cnt = 0> + <cfset var namedColors = "aqua,black,blue,fuchsia,gray,green,lime,maroon,navy,olive,purple,red,silver,teal,white,yellow"> + <cfset var namedColorsHexValues = "00ffff,000000,0000ff,ff00ff,808080,008000,00ff00,800000,000080,808080,ff0000,c0c0c0,008080,ffffff,ffff00"> + + <cfset retVal.red = 0> + <cfset retVal.green = 0> + <cfset retVal.blue = 0> + + <cfset arguments.color = trim(arguments.color)> + <cfif len(arguments.color) is 0> + <cfreturn retVal> + <cfelseif listFind(namedColors, arguments.color) gt 0> + <cfset arguments.color = listGetAt(namedColorsHexValues, listFind(namedColors, arguments.color))> + </cfif> + <cfif left(arguments.color,1) eq "##"> + <cfset arguments.color = right(arguments.color,len(arguments.color)-1)> + </cfif> + <cfif len(arguments.color) neq 6> + <cfreturn retVal> + <cfelse> + <cftry> + <cfset retVal.red = InputBaseN(mid(arguments.color,1,2),16)> + <cfset retVal.green = InputBaseN(mid(arguments.color,3,2),16)> + <cfset retVal.blue = InputBaseN(mid(arguments.color,5,2),16)> + <cfcatch type="any"> + <cfset retVal.red = 0> + <cfset retVal.green = 0> + <cfset retVal.blue = 0> + <cfreturn retVal> + </cfcatch> + </cftry> + </cfif> + <cfreturn retVal> +</cffunction> + +<cffunction name="throw" access="private" output="false" returnType="struct"> + <cfargument name="detail" type="string" required="yes"> + <cfargument name="force" type="boolean" required="no" default="no"> + + <cfset var retVal = StructNew()> + + <cfif variables.throwOnError or arguments.force> + <cfthrow detail="#arguments.detail#" message="#arguments.detail#"> + <cfelse> + <cfset retVal.errorCode = 1> + <cfset retVal.errorMessage = arguments.detail> + <cfreturn retVal> + </cfif> +</cffunction> + +<cffunction name="debugDump" access="private"> + <cfdump var="#arguments#"><cfabort> +</cffunction> + +<cffunction name="convertImageObject" access="private" output="false" returnType="any"> + <cfargument name="bImage" type="Any" required="yes"> + <cfargument name="type" type="numeric" required="yes"> + + <cfscript> + // convert the image to a specified BufferedImage type and return it + + var width = bImage.getWidth(); + var height = bImage.getHeight(); + var newImage = createObject("java","java.awt.image.BufferedImage").init(javacast("int",width), javacast("int",height), javacast("int",type)); + // int[] rgbArray = new int[width*height]; + var rgbArray = variables.arrObj.newInstance(variables.intClass, javacast("int",width*height)); + + bImage.getRGB( + javacast("int",0), + javacast("int",0), + javacast("int",width), + javacast("int",height), + rgbArray, + javacast("int",0), + javacast("int",width) + ); + newImage.setRGB( + javacast("int",0), + javacast("int",0), + javacast("int",width), + javacast("int",height), + rgbArray, + javacast("int",0), + javacast("int",width) + ); + return newImage; + </cfscript> + +</cffunction> + +</cfcomponent> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/upload.cfm =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/upload.cfm (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/cfm/upload.cfm 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,31 @@ +<cfsetting enablecfoutputonly="Yes"> +<!--- + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * This is the "File Uploader" for ColdFusion (all versions). + * +---> + +<cfset REQUEST.CFVersion = Left( SERVER.COLDFUSION.PRODUCTVERSION, Find( ",", SERVER.COLDFUSION.PRODUCTVERSION ) - 1 )> +<cfif REQUEST.CFVersion lte 5> + <cfinclude template="cf5_upload.cfm"> +<cfelse> + <cfinclude template="cf_upload.cfm"> +</cfif> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/lasso/config.lasso =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/lasso/config.lasso (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/lasso/config.lasso 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,65 @@ +[//lasso +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Configuration file for the File Manager Connector for Lasso. + */ + + /*..................................................................... + The connector uses the file tags, which require authentication. Enter a + valid username and password from Lasso admin for a group with file tags + permissions for uploads and the path you define in UserFilesPath below. + */ + + var('connection') = array( + -username='xxxxxxxx', + -password='xxxxxxxx' + ); + + + /*..................................................................... + Set the base path for files that users can upload and browse (relative + to server root). + + Set which file extensions are allowed and/or denied for each file type. + */ + var('config') = map( + 'Enabled' = false, + 'UserFilesPath' = '/userfiles/', + 'Subdirectories' = map( + 'File' = 'File/', + 'Image' = 'Image/', + 'Flash' = 'Flash/', + 'Media' = 'Media/' + ), + 'AllowedExtensions' = map( + 'File' = array('7z','aiff','asf','avi','bmp','csv','doc','fla','flv','gif','gz','gzip','jpeg','jpg','mid','mov','mp3','mp4','mpc','mpeg','mpg','ods','odt','pdf','png','ppt','pxd','qt','ram','rar','rm','rmi','rmvb','rtf','sdc','sitd','swf','sxc','sxw','tar','tgz','tif','tiff','txt','vsd','wav','wma','wmv','xls','xml','zip'), + 'Image' = array('bmp','gif','jpeg','jpg','png'), + 'Flash' = array('swf','flv'), + 'Media' = array('aiff','asf','avi','bmp','fla','flv','gif','jpeg','jpg','mid','mov','mp3','mp4','mpc','mpeg','mpg','png','qt','ram','rm','rmi','rmvb','swf','tif','tiff','wav','wma','wmv') + ), + 'DeniedExtensions' = map( + 'File' = array(), + 'Image' = array(), + 'Flash' = array(), + 'Media' = array() + ) + ); +] Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/lasso/connector.lasso =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/lasso/connector.lasso (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/lasso/connector.lasso 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,322 @@ +[//lasso +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * This is the File Manager Connector for Lasso. + */ + + /*..................................................................... + Include global configuration. See config.lasso for details. + */ + include('config.lasso'); + + + /*..................................................................... + Translate current date/time to GMT for custom header. + */ + var('headerDate') = date_localtogmt(date)->format('%a, %d %b %Y %T GMT'); + + + /*..................................................................... + Convert query string parameters to variables and initialize output. + */ + var( + 'Command' = action_param('Command'), + 'Type' = action_param('Type'), + 'CurrentFolder' = action_param('CurrentFolder'), + 'ServerPath' = action_param('ServerPath'), + 'NewFolderName' = action_param('NewFolderName'), + 'NewFile' = null, + 'NewFileName' = string, + 'OrigFilePath' = string, + 'NewFilePath' = string, + 'commandData' = string, + 'folders' = '\t<Folders>\n', + 'files' = '\t<Files>\n', + 'errorNumber' = integer, + 'responseType' = 'xml', + 'uploadResult' = '0' + ); + + /*..................................................................... + Custom tag sets the HTML response. + */ + + define_tag( + 'htmlreply', + -namespace='fck_', + -priority='replace', + -required='uploadResult', + -optional='NewFilePath', + -type='string', + -description='Sets the HTML response for the FCKEditor File Upload feature.' + ); + $__html_reply__ = '\ +<script type="text/javascript"> +(function() +{ + var d = document.domain ; + + while ( true ) + { + // Test if we can access a parent property. + try + { + var test = window.top.opener.document.domain ; + break ; + } + catch( e ) {} + + // Remove a domain part: www.mytest.example.com => mytest.example.com => example.com ... + d = d.replace( /.*?(?:\\.|$)/, "" ) ; + + if ( d.length == 0 ) + break ; // It was not able to detect the domain. + + try + { + document.domain = d ; + } + catch (e) + { + break ; + } + } +})() ; +'; + if($uploadResult == '0' || $uploadResult == '201'); + $__html_reply__ = $__html_reply__ + '\ + window.parent.OnUploadCompleted(' + $uploadResult + ',\'' + $NewFilePath + '\',\'' + $NewFilePath->split('/')->last + '\'); +</script> + '; + else; + $__html_reply__ = $__html_reply__ + '\ + window.parent.OnUploadCompleted(' + $uploadResult + '); +</script> + '; + /if; + /define_tag; + + + /*..................................................................... + Calculate the path to the current folder. + */ + $ServerPath == '' ? $ServerPath = $config->find('UserFilesPath'); + + var('currentFolderURL' = $ServerPath + + $config->find('Subdirectories')->find(action_param('Type')) + + $CurrentFolder + ); + + if($CurrentFolder->(Find: '..') || $CurrentFolder->(Find: '\\')); + if($Command == 'FileUpload'); + $responseType = 'html'; + $uploadResult = '102'; + fck_htmlreply( + -uploadResult=$uploadResult + ); + else; + $errorNumber = 102; + $commandData += '<Error number="' + $errorNumber + '" />\n'; + /if; + else; + + /*..................................................................... + Build the appropriate response per the 'Command' parameter. Wrap the + entire process in an inline for file tag permissions. + */ + inline($connection); + select($Command); + /*............................................................. + List all subdirectories in the 'Current Folder' directory. + */ + case('GetFolders'); + $commandData += '\t<Folders>\n'; + + iterate(file_listdirectory($currentFolderURL), local('this')); + #this->endswith('/') ? $commandData += '\t\t<Folder name="' + #this->removetrailing('/')& + '" />\n'; + /iterate; + + $commandData += '\t</Folders>\n'; + + + /*............................................................. + List both files and folders in the 'Current Folder' directory. + Include the file sizes in kilobytes. + */ + case('GetFoldersAndFiles'); + iterate(file_listdirectory($currentFolderURL), local('this')); + if(#this->endswith('/')); + $folders += '\t\t<Folder name="' + #this->removetrailing('/')& + '" />\n'; + else; + local('size') = file_getsize($currentFolderURL + #this) / 1024; + $files += '\t\t<File name="' + #this + '" size="' + #size + '" />\n'; + /if; + /iterate; + + $folders += '\t</Folders>\n'; + $files += '\t</Files>\n'; + + $commandData += $folders + $files; + + + /*............................................................. + Create a directory 'NewFolderName' within the 'Current Folder.' + */ + case('CreateFolder'); + $NewFolderName = (String_ReplaceRegExp: $NewFolderName, -find='\\.|\\\\|\\/|\\||\\:|\\?|\\*|"|<|>', -replace='_'); + var('newFolder' = $currentFolderURL + $NewFolderName + '/'); + file_create($newFolder); + + + /*......................................................... + Map Lasso's file error codes to FCKEditor's error codes. + */ + select(file_currenterror( -errorcode)); + case(0); + $errorNumber = 0; + case( -9983); + $errorNumber = 101; + case( -9976); + $errorNumber = 102; + case( -9977); + $errorNumber = 102; + case( -9961); + $errorNumber = 103; + case; + $errorNumber = 110; + /select; + + $commandData += '<Error number="' + $errorNumber + '" />\n'; + + + /*............................................................. + Process an uploaded file. + */ + case('FileUpload'); + /*......................................................... + This is the only command that returns an HTML response. + */ + $responseType = 'html'; + + + /*......................................................... + Was a file actually uploaded? + */ + if(file_uploads->size); + $NewFile = file_uploads->get(1); + else; + $uploadResult = '202'; + /if; + + if($uploadResult == '0'); + /*..................................................... + Split the file's extension from the filename in order + to follow the API's naming convention for duplicate + files. (Test.txt, Test(1).txt, Test(2).txt, etc.) + */ + $NewFileName = $NewFile->find('OrigName'); + $NewFileName = (String_ReplaceRegExp: $NewFileName, -find='\\\\|\\/|\\||\\:|\\?|\\*|"|<|>', -replace='_'); + $OrigFilePath = $currentFolderURL + $NewFileName; + $NewFilePath = $OrigFilePath; + local('fileExtension') = '.' + $NewFile->find('OrigExtension'); + #fileExtension = (String_ReplaceRegExp: #fileExtension, -find='\\\\|\\/|\\||\\:|\\?|\\*|"|<|>', -replace='_'); + local('shortFileName') = $NewFileName->removetrailing(#fileExtension)&; + + + /*..................................................... + Make sure the file extension is allowed. + */ + if($config->find('DeniedExtensions')->find($Type) >> $NewFile->find('OrigExtension')); + $uploadResult = '202'; + else; + /*................................................. + Rename the target path until it is unique. + */ + while(file_exists($NewFilePath)); + $NewFilePath = $currentFolderURL + #shortFileName + '(' + loop_count + ')' + #fileExtension; + /while; + + + /*................................................. + Copy the uploaded file to its final location. + */ + file_copy($NewFile->find('path'), $NewFilePath); + + + /*................................................. + Set the error code for the response. Note whether + the file had to be renamed. + */ + select(file_currenterror( -errorcode)); + case(0); + $OrigFilePath != $NewFilePath ? $uploadResult = 201; + case; + $uploadResult = file_currenterror( -errorcode); + /select; + /if; + /if; + fck_htmlreply( + -uploadResult=$uploadResult, + -NewFilePath=$NewFilePath + ); + /select; + /inline; + /if; + + /*..................................................................... + Send a custom header for xml responses. + */ + if($responseType == 'xml'); + header; +] +HTTP/1.0 200 OK +Date: [$headerDate] +Server: Lasso Professional [lasso_version( -lassoversion)] +Expires: Mon, 26 Jul 1997 05:00:00 GMT +Last-Modified: [$headerDate] +Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 +Pragma: no-cache +Keep-Alive: timeout=15, max=98 +Connection: Keep-Alive +Content-Type: text/xml; charset=utf-8 +[//lasso +/header; + + /* + Set the content type encoding for Lasso. + */ + content_type('text/xml; charset=utf-8'); + + /* + Wrap the response as XML and output. + */ + $__html_reply__ = '\ +<?xml version="1.0" encoding="utf-8" ?> +<Connector command="' + $Command + '" resourceType="' + $Type + '">'; + + if($errorNumber != '102'); + $__html_reply__ += '<CurrentFolder path="' + $CurrentFolder + '" url="' + $currentFolderURL + '" />'; + /if; + + $__html_reply__ += $commandData + ' +</Connector>'; + /if; +] Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/lasso/upload.lasso =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/lasso/upload.lasso (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/lasso/upload.lasso 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,191 @@ +[//lasso +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * This is the "File Uploader" for Lasso. + */ + + /*..................................................................... + Include global configuration. See config.lasso for details. + */ + include('config.lasso'); + + + /*..................................................................... + Convert query string parameters to variables and initialize output. + */ + var( + 'Type' = action_param('Type'), + 'CurrentFolder' = action_param('CurrentFolder'), + 'ServerPath' = action_param('ServerPath'), + 'NewFile' = null, + 'NewFileName' = string, + 'OrigFilePath' = string, + 'NewFilePath' = string, + 'errorNumber' = 0, + 'customMsg' = '' + ); + + $Type == '' ? $Type = 'File'; + + + /*..................................................................... + Calculate the path to the current folder. + */ + $ServerPath == '' ? $ServerPath = $config->find('UserFilesPath'); + + var('currentFolderURL' = $ServerPath + + $config->find('Subdirectories')->find(action_param('Type')) + + action_param('CurrentFolder') + ); + + /*..................................................................... + Custom tag sets the HTML response. + */ + + define_tag( + 'sendresults', + -namespace='fck_', + -priority='replace', + -required='errorNumber', + -type='integer', + -optional='fileUrl', + -type='string', + -optional='fileName', + -type='string', + -optional='customMsg', + -type='string', + -description='Sets the HTML response for the FCKEditor Quick Upload feature.' + ); + $__html_reply__ = '\ +<script type="text/javascript"> +(function() +{ + var d = document.domain ; + + while ( true ) + { + // Test if we can access a parent property. + try + { + var test = window.top.opener.document.domain ; + break ; + } + catch( e ) {} + + // Remove a domain part: www.mytest.example.com => mytest.example.com => example.com ... + d = d.replace( /.*?(?:\\.|$)/, "" ) ; + + if ( d.length == 0 ) + break ; // It was not able to detect the domain. + + try + { + document.domain = d ; + } + catch (e) + { + break ; + } + } +})() ; + window.parent.OnUploadCompleted(' + #errorNumber + ',"' + + string_replace(#fileUrl, -find='"', -replace='\\"') + '","' + + string_replace(#fileName, -find='"', -replace='\\"') + '","' + + string_replace(#customMsg, -find='"', -replace='\\"') + '"); +</script> + '; + /define_tag; + + if($CurrentFolder->(Find: '..') || $CurrentFolder->(Find: '\\')); + $errorNumber = 102; + /if; + + if($config->find('Enabled')); + /*................................................................. + Process an uploaded file. + */ + inline($connection); + /*............................................................. + Was a file actually uploaded? + */ + if($errorNumber != '102'); + file_uploads->size ? $NewFile = file_uploads->get(1) | $errorNumber = 202; + /if; + + if($errorNumber == 0); + /*......................................................... + Split the file's extension from the filename in order + to follow the API's naming convention for duplicate + files. (Test.txt, Test(1).txt, Test(2).txt, etc.) + */ + $NewFileName = $NewFile->find('OrigName'); + $OrigFilePath = $currentFolderURL + $NewFileName; + $NewFilePath = $OrigFilePath; + local('fileExtension') = '.' + $NewFile->find('OrigExtension'); + local('shortFileName') = $NewFileName->removetrailing(#fileExtension)&; + + + /*......................................................... + Make sure the file extension is allowed. + */ + + if($config->find('DeniedExtensions')->find($Type) >> $NewFile->find('OrigExtension')); + $errorNumber = 202; + else; + /*..................................................... + Rename the target path until it is unique. + */ + while(file_exists($NewFilePath)); + $NewFileName = #shortFileName + '(' + loop_count + ')' + #fileExtension; + $NewFilePath = $currentFolderURL + $NewFileName; + /while; + + + /*..................................................... + Copy the uploaded file to its final location. + */ + file_copy($NewFile->find('path'), $NewFilePath); + + + /*..................................................... + Set the error code for the response. + */ + select(file_currenterror( -errorcode)); + case(0); + $OrigFilePath != $NewFilePath ? $errorNumber = 201; + case; + $errorNumber = 202; + /select; + /if; + /if; + /inline; + else; + $errorNumber = 1; + $customMsg = 'This file uploader is disabled. Please check the "editor/filemanager/upload/lasso/config.lasso" file.'; + /if; + + fck_sendresults( + -errorNumber=$errorNumber, + -fileUrl=$NewFilePath, + -fileName=$NewFileName, + -customMsg=$customMsg + ); +] Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/perl/basexml.pl =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/perl/basexml.pl (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/perl/basexml.pl 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,63 @@ +##### +# FCKeditor - The text editor for Internet - http://www.fckeditor.net +# Copyright (C) 2003-2008 Frederico Caldeira Knabben +# +# == BEGIN LICENSE == +# +# Licensed under the terms of any of the following licenses at your +# choice: +# +# - GNU General Public License Version 2 or later (the "GPL") +# http://www.gnu.org/licenses/gpl.html +# +# - GNU Lesser General Public License Version 2.1 or later (the "LGPL") +# http://www.gnu.org/licenses/lgpl.html +# +# - Mozilla Public License Version 1.1 or later (the "MPL") +# http://www.mozilla.org/MPL/MPL-1.1.html +# +# == END LICENSE == +# +# This is the File Manager Connector for Perl. +##### + +sub CreateXmlHeader +{ + local($command,$resourceType,$currentFolder) = @_; + + # Create the XML document header. + print '<?xml version="1.0" encoding="utf-8" ?>'; + + # Create the main "Connector" node. + print '<Connector command="' . $command . '" resourceType="' . $resourceType . '">'; + + # Add the current folder node. + print '<CurrentFolder path="' . ConvertToXmlAttribute($currentFolder) . '" url="' . ConvertToXmlAttribute(GetUrlFromPath($resourceType,$currentFolder)) . '" />'; +} + +sub CreateXmlFooter +{ + print '</Connector>'; +} + +sub SendError +{ + local( $number, $text ) = @_; + + print << "_HTML_HEAD_"; +Content-Type:text/xml; charset=utf-8 +Pragma: no-cache +Cache-Control: no-cache +Expires: Thu, 01 Dec 1994 16:00:00 GMT + +_HTML_HEAD_ + + # Create the XML document header + print '<?xml version="1.0" encoding="utf-8" ?>' ; + + print '<Connector><Error number="' . $number . '" text="' . &specialchar_cnv( $text ) . '" /></Connector>' ; + + exit ; +} + +1; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/perl/commands.pl =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/perl/commands.pl (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/perl/commands.pl 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,214 @@ +##### +# FCKeditor - The text editor for Internet - http://www.fckeditor.net +# Copyright (C) 2003-2008 Frederico Caldeira Knabben +# +# == BEGIN LICENSE == +# +# Licensed under the terms of any of the following licenses at your +# choice: +# +# - GNU General Public License Version 2 or later (the "GPL") +# http://www.gnu.org/licenses/gpl.html +# +# - GNU Lesser General Public License Version 2.1 or later (the "LGPL") +# http://www.gnu.org/licenses/lgpl.html +# +# - Mozilla Public License Version 1.1 or later (the "MPL") +# http://www.mozilla.org/MPL/MPL-1.1.html +# +# == END LICENSE == +# +# This is the File Manager Connector for Perl. +##### + +sub GetFolders +{ + + local($resourceType, $currentFolder) = @_; + + # Map the virtual path to the local server path. + $sServerDir = &ServerMapFolder($resourceType, $currentFolder); + print "<Folders>"; # Open the "Folders" node. + + opendir(DIR,"$sServerDir"); + @files = grep(!/^\.\.?$/,readdir(DIR)); + closedir(DIR); + + foreach $sFile (@files) { + if($sFile != '.' && $sFile != '..' && (-d "$sServerDir$sFile")) { + $cnv_filename = &ConvertToXmlAttribute($sFile); + print '<Folder name="' . $cnv_filename . '" />'; + } + } + print "</Folders>"; # Close the "Folders" node. +} + +sub GetFoldersAndFiles +{ + + local($resourceType, $currentFolder) = @_; + # Map the virtual path to the local server path. + $sServerDir = &ServerMapFolder($resourceType,$currentFolder); + + # Initialize the output buffers for "Folders" and "Files". + $sFolders = '<Folders>'; + $sFiles = '<Files>'; + + opendir(DIR,"$sServerDir"); + @files = grep(!/^\.\.?$/,readdir(DIR)); + closedir(DIR); + + foreach $sFile (@files) { + if($sFile ne '.' && $sFile ne '..') { + if(-d "$sServerDir$sFile") { + $cnv_filename = &ConvertToXmlAttribute($sFile); + $sFolders .= '<Folder name="' . $cnv_filename . '" />' ; + } else { + ($iFileSize,$refdate,$filedate,$fileperm) = (stat("$sServerDir$sFile"))[7,8,9,2]; + if($iFileSize > 0) { + $iFileSize = int($iFileSize / 1024); + if($iFileSize < 1) { + $iFileSize = 1; + } + } + $cnv_filename = &ConvertToXmlAttribute($sFile); + $sFiles .= '<File name="' . $cnv_filename . '" size="' . $iFileSize . '" />' ; + } + } + } + print $sFolders ; + print '</Folders>'; # Close the "Folders" node. + print $sFiles ; + print '</Files>'; # Close the "Files" node. +} + +sub CreateFolder +{ + + local($resourceType, $currentFolder) = @_; + $sErrorNumber = '0' ; + $sErrorMsg = '' ; + + if($FORM{'NewFolderName'} ne "") { + $sNewFolderName = $FORM{'NewFolderName'}; + $sNewFolderName =~ s/\.|\\|\/|\||\:|\?|\*|\"|<|>|[[:cntrl:]]/_/g; + # Map the virtual path to the local server path of the current folder. + $sServerDir = &ServerMapFolder($resourceType, $currentFolder); + if(-w $sServerDir) { + $sServerDir .= $sNewFolderName; + $sErrorMsg = &CreateServerFolder($sServerDir); + if($sErrorMsg == 0) { + $sErrorNumber = '0'; + } elsif($sErrorMsg eq 'Invalid argument' || $sErrorMsg eq 'No such file or directory') { + $sErrorNumber = '102'; #// Path too long. + } else { + $sErrorNumber = '110'; + } + } else { + $sErrorNumber = '103'; + } + } else { + $sErrorNumber = '102' ; + } + # Create the "Error" node. + $cnv_errmsg = &ConvertToXmlAttribute($sErrorMsg); + print '<Error number="' . $sErrorNumber . '" originalDescription="' . $cnv_errmsg . '" />'; +} + +sub FileUpload +{ +eval("use File::Copy;"); + + local($resourceType, $currentFolder) = @_; + + $sErrorNumber = '0' ; + $sFileName = '' ; + if($new_fname) { + # Map the virtual path to the local server path. + $sServerDir = &ServerMapFolder($resourceType,$currentFolder); + + # Get the uploaded file name. + $sFileName = $new_fname; + $sFileName =~ s/\\|\/|\||\:|\?|\*|\"|<|>|[[:cntrl:]]/_/g; + $sOriginalFileName = $sFileName; + + $iCounter = 0; + while(1) { + $sFilePath = $sServerDir . $sFileName; + if(-e $sFilePath) { + $iCounter++ ; + ($path,$BaseName,$ext) = &RemoveExtension($sOriginalFileName); + $sFileName = $BaseName . '(' . $iCounter . ').' . $ext; + $sErrorNumber = '201'; + } else { + copy("$img_dir/$new_fname","$sFilePath"); + if (defined $CHMOD_ON_UPLOAD) { + if ($CHMOD_ON_UPLOAD) { + umask(000); + chmod($CHMOD_ON_UPLOAD,$sFilePath); + } + } + else { + umask(000); + chmod(0777,$sFilePath); + } + unlink("$img_dir/$new_fname"); + last; + } + } + } else { + $sErrorNumber = '202' ; + } + $sFileName =~ s/"/\\"/g; + + SendUploadResults($sErrorNumber, $resourceType.$currentFolder.$sFileName, $sFileName, ''); +} + +sub SendUploadResults +{ + + local($sErrorNumber, $sFileUrl, $sFileName, $customMsg) = @_; + + print <<EOF; +Content-type: text/html + +<script type="text/javascript"> +// Automatically detect the correct document.domain (#1919). +(function() +{ + var d = document.domain ; + + while ( true ) + { + // Test if we can access a parent property. + try + { + var test = window.top.opener.document.domain ; + break ; + } + catch( e ) {} + + // Remove a domain part: www.mytest.example.com => mytest.example.com => example.com ... + d = d.replace( /.*?(?:\\.|\$)/, '' ) ; + + if ( d.length == 0 ) + break ; // It was not able to detect the domain. + + try + { + document.domain = d ; + } + catch (e) + { + break ; + } + } +})() ; + +EOF + print 'window.parent.OnUploadCompleted(' . $sErrorNumber . ',"' . JS_cnv($sFileUrl) . '","' . JS_cnv($sFileName) . '","' . JS_cnv($customMsg) . '") ;'; + print '</script>'; + exit ; +} + +1; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/perl/connector.cgi =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/perl/connector.cgi (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/perl/connector.cgi 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,136 @@ +#!/usr/bin/env perl + +##### +# FCKeditor - The text editor for Internet - http://www.fckeditor.net +# Copyright (C) 2003-2008 Frederico Caldeira Knabben +# +# == BEGIN LICENSE == +# +# Licensed under the terms of any of the following licenses at your +# choice: +# +# - GNU General Public License Version 2 or later (the "GPL") +# http://www.gnu.org/licenses/gpl.html +# +# - GNU Lesser General Public License Version 2.1 or later (the "LGPL") +# http://www.gnu.org/licenses/lgpl.html +# +# - Mozilla Public License Version 1.1 or later (the "MPL") +# http://www.mozilla.org/MPL/MPL-1.1.html +# +# == END LICENSE == +# +# This is the File Manager Connector for Perl. +##### + +## +# ATTENTION: To enable this connector, look for the "SECURITY" comment in this file. +## + +## START: Hack for Windows (Not important to understand the editor code... Perl specific). +if(Windows_check()) { + chdir(GetScriptPath($0)); +} + +sub Windows_check +{ + # IIS,PWS(NT/95) + $www_server_os = $^O; + # Win98 & NT(SP4) + if($www_server_os eq "") { $www_server_os= $ENV{'OS'}; } + # AnHTTPd/Omni/IIS + if($ENV{'SERVER_SOFTWARE'} =~ /AnWeb|Omni|IIS\//i) { $www_server_os= 'win'; } + # Win Apache + if($ENV{'WINDIR'} ne "") { $www_server_os= 'win'; } + if($www_server_os=~ /win/i) { return(1); } + return(0); +} + +sub GetScriptPath { + local($path) = @_; + if($path =~ /[\:\/\\]/) { $path =~ s/(.*?)[\/\\][^\/\\]+$/$1/; } else { $path = '.'; } + $path; +} +## END: Hack for IIS + +require 'util.pl'; +require 'io.pl'; +require 'basexml.pl'; +require 'commands.pl'; +require 'upload_fck.pl'; + +## +# SECURITY: REMOVE/COMMENT THE FOLLOWING LINE TO ENABLE THIS CONNECTOR. +## + &SendError( 1, 'This connector is disabled. Please check the "editor/filemanager/connectors/perl/connector.cgi" file' ) ; + + &read_input(); + + if($FORM{'ServerPath'} ne "") { + $GLOBALS{'UserFilesPath'} = $FORM{'ServerPath'}; + if(!($GLOBALS{'UserFilesPath'} =~ /\/$/)) { + $GLOBALS{'UserFilesPath'} .= '/' ; + } + } else { + $GLOBALS{'UserFilesPath'} = '/userfiles/'; + } + + # Map the "UserFiles" path to a local directory. + $rootpath = &GetRootPath(); + $GLOBALS{'UserFilesDirectory'} = $rootpath . $GLOBALS{'UserFilesPath'}; + + &DoResponse(); + +sub DoResponse +{ + + if($FORM{'Command'} eq "" || $FORM{'Type'} eq "" || $FORM{'CurrentFolder'} eq "") { + return ; + } + # Get the main request informaiton. + $sCommand = $FORM{'Command'}; + $sResourceType = $FORM{'Type'}; + $sCurrentFolder = $FORM{'CurrentFolder'}; + + # Check the current folder syntax (must begin and start with a slash). + if(!($sCurrentFolder =~ /\/$/)) { + $sCurrentFolder .= '/'; + } + if(!($sCurrentFolder =~ /^\//)) { + $sCurrentFolder = '/' . $sCurrentFolder; + } + + # Check for invalid folder paths (..) + if ( $sCurrentFolder =~ /(?:\.\.|\\)/ ) { + SendError( 102, "" ) ; + } + + # File Upload doesn't have to Return XML, so it must be intercepted before anything. + if($sCommand eq 'FileUpload') { + FileUpload($sResourceType,$sCurrentFolder); + return ; + } + + print << "_HTML_HEAD_"; +Content-Type:text/xml; charset=utf-8 +Pragma: no-cache +Cache-Control: no-cache +Expires: Thu, 01 Dec 1994 16:00:00 GMT + +_HTML_HEAD_ + + &CreateXmlHeader($sCommand,$sResourceType,$sCurrentFolder); + + # Execute the required command. + if($sCommand eq 'GetFolders') { + &GetFolders($sResourceType,$sCurrentFolder); + } elsif($sCommand eq 'GetFoldersAndFiles') { + &GetFoldersAndFiles($sResourceType,$sCurrentFolder); + } elsif($sCommand eq 'CreateFolder') { + &CreateFolder($sResourceType,$sCurrentFolder); + } + + &CreateXmlFooter(); + + exit ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/perl/io.pl =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/perl/io.pl (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/perl/io.pl 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,141 @@ +##### +# FCKeditor - The text editor for Internet - http://www.fckeditor.net +# Copyright (C) 2003-2008 Frederico Caldeira Knabben +# +# == BEGIN LICENSE == +# +# Licensed under the terms of any of the following licenses at your +# choice: +# +# - GNU General Public License Version 2 or later (the "GPL") +# http://www.gnu.org/licenses/gpl.html +# +# - GNU Lesser General Public License Version 2.1 or later (the "LGPL") +# http://www.gnu.org/licenses/lgpl.html +# +# - Mozilla Public License Version 1.1 or later (the "MPL") +# http://www.mozilla.org/MPL/MPL-1.1.html +# +# == END LICENSE == +# +# This is the File Manager Connector for Perl. +##### + +sub GetUrlFromPath +{ + local($resourceType, $folderPath) = @_; + + if($resourceType eq '') { + $rmpath = &RemoveFromEnd($GLOBALS{'UserFilesPath'},'/'); + return("$rmpath$folderPath"); + } else { + return("$GLOBALS{'UserFilesPath'}$resourceType$folderPath"); + } +} + +sub RemoveExtension +{ + local($fileName) = @_; + local($path, $base, $ext); + if($fileName !~ /\./) { + $fileName .= '.'; + } + if($fileName =~ /([^\\\/]*)\.(.*)$/) { + $base = $1; + $ext = $2; + if($fileName =~ /(.*)$base\.$ext$/) { + $path = $1; + } + } + return($path,$base,$ext); + +} + +sub ServerMapFolder +{ + local($resourceType,$folderPath) = @_; + + # Get the resource type directory. + $sResourceTypePath = $GLOBALS{'UserFilesDirectory'} . $resourceType . '/'; + + # Ensure that the directory exists. + &CreateServerFolder($sResourceTypePath); + + # Return the resource type directory combined with the required path. + $rmpath = &RemoveFromStart($folderPath,'/'); + return("$sResourceTypePath$rmpath"); +} + +sub GetParentFolder +{ + local($folderPath) = @_; + + $folderPath =~ s/[\/][^\/]+[\/]?$//g; + return $folderPath; +} + +sub CreateServerFolder +{ + local($folderPath) = @_; + + $sParent = &GetParentFolder($folderPath); + # Check if the parent exists, or create it. + if(!(-e $sParent)) { + $sErrorMsg = &CreateServerFolder($sParent); + if($sErrorMsg == 1) { + return(1); + } + } + if(!(-e $folderPath)) { + if (defined $CHMOD_ON_FOLDER_CREATE && !$CHMOD_ON_FOLDER_CREATE) { + mkdir("$folderPath"); + } + else { + umask(000); + if (defined $CHMOD_ON_FOLDER_CREATE) { + mkdir("$folderPath",$CHMOD_ON_FOLDER_CREATE); + } + else { + mkdir("$folderPath",0777); + } + } + + return(0); + } else { + return(1); + } +} + +sub GetRootPath +{ +#use Cwd; + +# my $dir = getcwd; +# print $dir; +# $dir =~ s/$ENV{'DOCUMENT_ROOT'}//g; +# print $dir; +# return($dir); + +# $wk = $0; +# $wk =~ s/\/connector\.cgi//g; +# if($wk) { +# $current_dir = $wk; +# } else { +# $current_dir = `pwd`; +# } +# return($current_dir); +use Cwd; + + if($ENV{'DOCUMENT_ROOT'}) { + $dir = $ENV{'DOCUMENT_ROOT'}; + } else { + my $dir = getcwd; + $workdir =~ s/\/connector\.cgi//g; + $dir =~ s/$workdir//g; + } + return($dir); + + + +} +1; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/perl/upload.cgi =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/perl/upload.cgi (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/perl/upload.cgi 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,117 @@ +#!/usr/bin/env perl + +##### +# FCKeditor - The text editor for Internet - http://www.fckeditor.net +# Copyright (C) 2003-2008 Frederico Caldeira Knabben +# +# == BEGIN LICENSE == +# +# Licensed under the terms of any of the following licenses at your +# choice: +# +# - GNU General Public License Version 2 or later (the "GPL") +# http://www.gnu.org/licenses/gpl.html +# +# - GNU Lesser General Public License Version 2.1 or later (the "LGPL") +# http://www.gnu.org/licenses/lgpl.html +# +# - Mozilla Public License Version 1.1 or later (the "MPL") +# http://www.mozilla.org/MPL/MPL-1.1.html +# +# == END LICENSE == +# +# This is the File Manager Connector for Perl. +##### + +## +# ATTENTION: To enable this connector, look for the "SECURITY" comment in this file. +## + +## START: Hack for Windows (Not important to understand the editor code... Perl specific). +if(Windows_check()) { + chdir(GetScriptPath($0)); +} + +sub Windows_check +{ + # IIS,PWS(NT/95) + $www_server_os = $^O; + # Win98 & NT(SP4) + if($www_server_os eq "") { $www_server_os= $ENV{'OS'}; } + # AnHTTPd/Omni/IIS + if($ENV{'SERVER_SOFTWARE'} =~ /AnWeb|Omni|IIS\//i) { $www_server_os= 'win'; } + # Win Apache + if($ENV{'WINDIR'} ne "") { $www_server_os= 'win'; } + if($www_server_os=~ /win/i) { return(1); } + return(0); +} + +sub GetScriptPath { + local($path) = @_; + if($path =~ /[\:\/\\]/) { $path =~ s/(.*?)[\/\\][^\/\\]+$/$1/; } else { $path = '.'; } + $path; +} +## END: Hack for IIS + +require 'util.pl'; +require 'io.pl'; +require 'basexml.pl'; +require 'commands.pl'; +require 'upload_fck.pl'; + +## +# SECURITY: REMOVE/COMMENT THE FOLLOWING LINE TO ENABLE THIS CONNECTOR. +## + &SendUploadResults(1, '', '', 'This connector is disabled. Please check the "editor/filemanager/connectors/perl/upload.cgi" file' ) ; + + &read_input(); + + if($FORM{'ServerPath'} ne "") { + $GLOBALS{'UserFilesPath'} = $FORM{'ServerPath'}; + if(!($GLOBALS{'UserFilesPath'} =~ /\/$/)) { + $GLOBALS{'UserFilesPath'} .= '/' ; + } + } else { + $GLOBALS{'UserFilesPath'} = '/userfiles/'; + } + + # Map the "UserFiles" path to a local directory. + $rootpath = &GetRootPath(); + $GLOBALS{'UserFilesDirectory'} = $rootpath . $GLOBALS{'UserFilesPath'}; + + &DoResponse(); + +sub DoResponse +{ + # Get the main request information. + $sCommand = 'FileUpload'; #$FORM{'Command'}; + $sResourceType = $FORM{'Type'}; + $sCurrentFolder = $FORM{'CurrentFolder'}; + + if ($sResourceType eq '') { + $sResourceType = 'File' ; + } + if ($sCurrentFolder eq '') { + $sCurrentFolder = '/' ; + } + + # Check the current folder syntax (must begin and start with a slash). + if(!($sCurrentFolder =~ /\/$/)) { + $sCurrentFolder .= '/'; + } + if(!($sCurrentFolder =~ /^\//)) { + $sCurrentFolder = '/' . $sCurrentFolder; + } + + # Check for invalid folder paths (..) + if ( $sCurrentFolder =~ /(?:\.\.|\\)/ ) { + SendError( 102, "" ) ; + } + + # File Upload doesn't have to Return XML, so it must be intercepted before anything. + if($sCommand eq 'FileUpload') { + FileUpload($sResourceType,$sCurrentFolder); + return ; + } + +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/perl/upload_fck.pl =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/perl/upload_fck.pl (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/perl/upload_fck.pl 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,686 @@ +##### +# FCKeditor - The text editor for Internet - http://www.fckeditor.net +# Copyright (C) 2003-2008 Frederico Caldeira Knabben +# +# == BEGIN LICENSE == +# +# Licensed under the terms of any of the following licenses at your +# choice: +# +# - GNU General Public License Version 2 or later (the "GPL") +# http://www.gnu.org/licenses/gpl.html +# +# - GNU Lesser General Public License Version 2.1 or later (the "LGPL") +# http://www.gnu.org/licenses/lgpl.html +# +# - Mozilla Public License Version 1.1 or later (the "MPL") +# http://www.mozilla.org/MPL/MPL-1.1.html +# +# == END LICENSE == +# +# This is the File Manager Connector for Perl. +##### + +# image data save dir +$img_dir = './temp/'; + + +# File size max(unit KB) +$MAX_CONTENT_SIZE = 30000; + +# After file is uploaded, sometimes it is required to change its permissions +# so that it was possible to access it at the later time. +# If possible, it is recommended to set more restrictive permissions, like 0755. +# Set to 0 to disable this feature. +$CHMOD_ON_UPLOAD = 0777; + +# See comments above. +# Used when creating folders that does not exist. +$CHMOD_ON_FOLDER_CREATE = 0755; + +# Filelock (1=use,0=not use) +$PM{'flock'} = '1'; + + +# upload Content-Type list +my %UPLOAD_CONTENT_TYPE_LIST = ( + 'image/(x-)?png' => 'png', # PNG image + 'image/p?jpe?g' => 'jpg', # JPEG image + 'image/gif' => 'gif', # GIF image + 'image/x-xbitmap' => 'xbm', # XBM image + + 'image/(x-(MS-)?)?bmp' => 'bmp', # Windows BMP image + 'image/pict' => 'pict', # Macintosh PICT image + 'image/tiff' => 'tif', # TIFF image + 'application/pdf' => 'pdf', # PDF image + 'application/x-shockwave-flash' => 'swf', # Shockwave Flash + + 'video/(x-)?msvideo' => 'avi', # Microsoft Video + 'video/quicktime' => 'mov', # QuickTime Video + 'video/mpeg' => 'mpeg', # MPEG Video + 'video/x-mpeg2' => 'mpv2', # MPEG2 Video + + 'audio/(x-)?midi?' => 'mid', # MIDI Audio + 'audio/(x-)?wav' => 'wav', # WAV Audio + 'audio/basic' => 'au', # ULAW Audio + 'audio/mpeg' => 'mpga', # MPEG Audio + + 'application/(x-)?zip(-compressed)?' => 'zip', # ZIP Compress + + 'text/html' => 'html', # HTML + 'text/plain' => 'txt', # TEXT + '(?:application|text)/(?:rtf|richtext)' => 'rtf', # RichText + + 'application/msword' => 'doc', # Microsoft Word + 'application/vnd.ms-excel' => 'xls', # Microsoft Excel + + '' +); + +# Upload is permitted. +# A regular expression is possible. +my %UPLOAD_EXT_LIST = ( + 'png' => 'PNG image', + 'p?jpe?g|jpe|jfif|pjp' => 'JPEG image', + 'gif' => 'GIF image', + 'xbm' => 'XBM image', + + 'bmp|dib|rle' => 'Windows BMP image', + 'pi?ct' => 'Macintosh PICT image', + 'tiff?' => 'TIFF image', + 'pdf' => 'PDF image', + 'swf' => 'Shockwave Flash', + + 'avi' => 'Microsoft Video', + 'moo?v|qt' => 'QuickTime Video', + 'm(p(e?gv?|e|v)|1v)' => 'MPEG Video', + 'mp(v2|2v)' => 'MPEG2 Video', + + 'midi?|kar|smf|rmi|mff' => 'MIDI Audio', + 'wav' => 'WAVE Audio', + 'au|snd' => 'ULAW Audio', + 'mp(e?ga|2|a|3)|abs' => 'MPEG Audio', + + 'zip' => 'ZIP Compress', + 'lzh' => 'LZH Compress', + 'cab' => 'CAB Compress', + + 'd?html?' => 'HTML', + 'rtf|rtx' => 'RichText', + 'txt|text' => 'Text', + + '' +); + + +# sjis or euc +my $CHARCODE = 'sjis'; + +$TRANS_2BYTE_CODE = 0; + +############################################################################## +# Summary +# +# Form Read input +# +# Parameters +# Returns +# Memo +############################################################################## +sub read_input +{ +eval("use File::Copy;"); +eval("use File::Path;"); + + my ($FORM) = @_; + + if (defined $CHMOD_ON_FOLDER_CREATE && !$CHMOD_ON_FOLDER_CREATE) { + mkdir("$img_dir"); + } + else { + umask(000); + if (defined $CHMOD_ON_FOLDER_CREATE) { + mkdir("$img_dir",$CHMOD_ON_FOLDER_CREATE); + } + else { + mkdir("$img_dir",0777); + } + } + + undef $img_data_exists; + undef @NEWFNAMES; + undef @NEWFNAME_DATA; + + if($ENV{'CONTENT_LENGTH'} > 10000000 || $ENV{'CONTENT_LENGTH'} > $MAX_CONTENT_SIZE * 1024) { + &upload_error( + 'Size Error', + sprintf( + "Transmitting size is too large.MAX <strong>%d KB</strong> Now Size <strong>%d KB</strong>(<strong>%d bytes</strong> Over)", + $MAX_CONTENT_SIZE, + int($ENV{'CONTENT_LENGTH'} / 1024), + $ENV{'CONTENT_LENGTH'} - $MAX_CONTENT_SIZE * 1024 + ) + ); + } + + my $Buffer; + if($ENV{'CONTENT_TYPE'} =~ /multipart\/form-data/) { + # METHOD POST only + return unless($ENV{'CONTENT_LENGTH'}); + + binmode(STDIN); + # STDIN A pause character is detected.'(MacIE3.0 boundary of $ENV{'CONTENT_TYPE'} cannot be trusted.) + my $Boundary = <STDIN>; + $Boundary =~ s/\x0D\x0A//; + $Boundary = quotemeta($Boundary); + while(<STDIN>) { + if(/^\s*Content-Disposition:/i) { + my($name,$ContentType,$FileName); + # form data get + if(/\bname="([^"]+)"/i || /\bname=([^\s:;]+)/i) { + $name = $1; + $name =~ tr/+/ /; + $name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; + &Encode(\$name); + } + if(/\bfilename="([^"]*)"/i || /\bfilename=([^\s:;]*)/i) { + $FileName = $1 || 'unknown'; + } + # head read + while(<STDIN>) { + last if(! /\w/); + if(/^\s*Content-Type:\s*"([^"]+)"/i || /^\s*Content-Type:\s*([^\s:;]+)/i) { + $ContentType = $1; + } + } + # body read + $value = ""; + while(<STDIN>) { + last if(/^$Boundary/o); + $value .= $_; + }; + $lastline = $_; + $value =~s /\x0D\x0A$//; + if($value ne '') { + if($FileName || $ContentType) { + $img_data_exists = 1; + ( + $FileName, # + $Ext, # + $Length, # + $ImageWidth, # + $ImageHeight, # + $ContentName # + ) = &CheckContentType(\$value,$FileName,$ContentType); + + $FORM{$name} = $FileName; + $new_fname = $FileName; + push(@NEWFNAME_DATA,"$FileName\t$Ext\t$Length\t$ImageWidth\t$ImageHeight\t$ContentName"); + + # Multi-upload correspondence + push(@NEWFNAMES,$new_fname); + open(OUT,">$img_dir/$new_fname"); + binmode(OUT); + eval "flock(OUT,2);" if($PM{'flock'} == 1); + print OUT $value; + eval "flock(OUT,8);" if($PM{'flock'} == 1); + close(OUT); + + } elsif($name) { + $value =~ tr/+/ /; + $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; + &Encode(\$value,'trans'); + $FORM{$name} .= "\0" if(defined($FORM{$name})); + $FORM{$name} .= $value; + } + } + }; + last if($lastline =~ /^$Boundary\-\-/o); + } + } elsif($ENV{'CONTENT_LENGTH'}) { + read(STDIN,$Buffer,$ENV{'CONTENT_LENGTH'}); + } + foreach(split(/&/,$Buffer),split(/&/,$ENV{'QUERY_STRING'})) { + my($name, $value) = split(/=/); + $name =~ tr/+/ /; + $name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; + $value =~ tr/+/ /; + $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; + + &Encode(\$name); + &Encode(\$value,'trans'); + $FORM{$name} .= "\0" if(defined($FORM{$name})); + $FORM{$name} .= $value; + + } + +} + +############################################################################## +# Summary +# +# CheckContentType +# +# Parameters +# Returns +# Memo +############################################################################## +sub CheckContentType +{ + + my($DATA,$FileName,$ContentType) = @_; + my($Ext,$ImageWidth,$ImageHeight,$ContentName,$Infomation); + my $DataLength = length($$DATA); + + # An unknown file type + + $_ = $ContentType; + my $UnknownType = ( + !$_ + || /^application\/(x-)?macbinary$/i + || /^application\/applefile$/i + || /^application\/octet-stream$/i + || /^text\/plane$/i + || /^x-unknown-content-type/i + ); + + # MacBinary(Mac Unnecessary data are deleted.) + if($UnknownType || $ENV{'HTTP_USER_AGENT'} =~ /Macintosh|Mac_/) { + if($DataLength > 128 && !unpack("C",substr($$DATA,0,1)) && !unpack("C",substr($$DATA,74,1)) && !unpack("C",substr($$DATA,82,1)) ) { + my $MacBinary_ForkLength = unpack("N", substr($$DATA, 83, 4)); # ForkLength Get + my $MacBinary_FileName = quotemeta(substr($$DATA, 2, unpack("C",substr($$DATA, 1, 1)))); + if($MacBinary_FileName && $MacBinary_ForkLength && $DataLength >= $MacBinary_ForkLength + 128 + && ($FileName =~ /$MacBinary_FileName/i || substr($$DATA,102,4) eq 'mBIN')) { # DATA TOP 128byte MacBinary!! + $$DATA = substr($$DATA,128,$MacBinary_ForkLength); + my $ResourceLength = $DataLength - $MacBinary_ForkLength - 128; + $DataLength = $MacBinary_ForkLength; + } + } + } + + # A file name is changed into EUC. +# &jcode::convert(\$FileName,'euc',$FormCodeDefault); +# &jcode::h2z_euc(\$FileName); + $FileName =~ s/^.*\\//; # Windows, Mac + $FileName =~ s/^.*\///; # UNIX + $FileName =~ s/&/&/g; + $FileName =~ s/"/"/g; + $FileName =~ s/</</g; + $FileName =~ s/>/>/g; +# +# if($CHARCODE ne 'euc') { +# &jcode::convert(\$FileName,$CHARCODE,'euc'); +# } + + # An extension is extracted and it changes into a small letter. + my $FileExt; + if($FileName =~ /\.(\w+)$/) { + $FileExt = $1; + $FileExt =~ tr/A-Z/a-z/; + } + + # Executable file detection (ban on upload) + if($$DATA =~ /^MZ/) { + $Ext = 'exe'; + } + # text + if(!$Ext && ($UnknownType || $ContentType =~ /^text\//i || $ContentType =~ /^application\/(?:rtf|richtext)$/i || $ContentType =~ /^image\/x-xbitmap$/i) + && ! $$DATA =~ /[\000-\006\177\377]/) { +# $$DATA =~ s/\x0D\x0A/\n/g; +# $$DATA =~ tr/\x0D\x0A/\n\n/; +# +# if( +# $$DATA =~ /<\s*SCRIPT(?:.|\n)*?>/i +# || $$DATA =~ /<\s*(?:.|\n)*?\bONLOAD\s*=(?:.|\n)*?>/i +# || $$DATA =~ /<\s*(?:.|\n)*?\bONCLICK\s*=(?:.|\n)*?>/i +# ) { +# $Infomation = '(JavaScript contains)'; +# } +# if($$DATA =~ /<\s*TABLE(?:.|\n)*?>/i +# || $$DATA =~ /<\s*BLINK(?:.|\n)*?>/i +# || $$DATA =~ /<\s*MARQUEE(?:.|\n)*?>/i +# || $$DATA =~ /<\s*OBJECT(?:.|\n)*?>/i +# || $$DATA =~ /<\s*EMBED(?:.|\n)*?>/i +# || $$DATA =~ /<\s*FRAME(?:.|\n)*?>/i +# || $$DATA =~ /<\s*APPLET(?:.|\n)*?>/i +# || $$DATA =~ /<\s*FORM(?:.|\n)*?>/i +# || $$DATA =~ /<\s*(?:.|\n)*?\bSRC\s*=(?:.|\n)*?>/i +# || $$DATA =~ /<\s*(?:.|\n)*?\bDYNSRC\s*=(?:.|\n)*?>/i +# ) { +# $Infomation = '(the HTML tag which is not safe is included)'; +# } + + if($FileExt =~ /^txt$/i || $FileExt =~ /^cgi$/i || $FileExt =~ /^pl$/i) { # Text File + $Ext = 'txt'; + } elsif($ContentType =~ /^text\/html$/i || $FileExt =~ /html?/i || $$DATA =~ /<\s*HTML(?:.|\n)*?>/i) { # HTML File + $Ext = 'html'; + } elsif($ContentType =~ /^image\/x-xbitmap$/i || $FileExt =~ /^xbm$/i) { # XBM(x-BitMap) Image + my $XbmName = $1; + my ($XbmWidth, $XbmHeight); + if($$DATA =~ /\#define\s*$XbmName\_width\s*(\d+)/i) { + $XbmWidth = $1; + } + if($$DATA =~ /\#define\s*$XbmName\_height\s*(\d+)/i) { + $XbmHeight = $1; + } + if($XbmWidth && $XbmHeight) { + $Ext = 'xbm'; + $ImageWidth = $XbmWidth; + $ImageHeight = $XbmHeight; + } + } else { # + $Ext = 'txt'; + } + } + + # image + if(!$Ext && ($UnknownType || $ContentType =~ /^image\//i)) { + # PNG + if($$DATA =~ /^\x89PNG\x0D\x0A\x1A\x0A/) { + if(substr($$DATA, 12, 4) eq 'IHDR') { + $Ext = 'png'; + ($ImageWidth, $ImageHeight) = unpack("N2", substr($$DATA, 16, 8)); + } + } elsif($$DATA =~ /^GIF8(?:9|7)a/) { # GIF89a(modified), GIF89a, GIF87a + $Ext = 'gif'; + ($ImageWidth, $ImageHeight) = unpack("v2", substr($$DATA, 6, 4)); + } elsif($$DATA =~ /^II\x2a\x00\x08\x00\x00\x00/ || $$DATA =~ /^MM\x00\x2a\x00\x00\x00\x08/) { # TIFF + $Ext = 'tif'; + } elsif($$DATA =~ /^BM/) { # BMP + $Ext = 'bmp'; + } elsif($$DATA =~ /^\xFF\xD8\xFF/ || $$DATA =~ /JFIF/) { # JPEG + my $HeaderPoint = index($$DATA, "\xFF\xD8\xFF", 0); + my $Point = $HeaderPoint + 2; + while($Point < $DataLength) { + my($Maker, $MakerType, $MakerLength) = unpack("C2n",substr($$DATA,$Point,4)); + if($Maker != 0xFF || $MakerType == 0xd9 || $MakerType == 0xda) { + last; + } elsif($MakerType >= 0xC0 && $MakerType <= 0xC3) { + $Ext = 'jpg'; + ($ImageHeight, $ImageWidth) = unpack("n2", substr($$DATA, $Point + 5, 4)); + if($HeaderPoint > 0) { + $$DATA = substr($$DATA, $HeaderPoint); + $DataLength = length($$DATA); + } + last; + } else { + $Point += $MakerLength + 2; + } + } + } + } + + # audio + if(!$Ext && ($UnknownType || $ContentType =~ /^audio\//i)) { + # MIDI Audio + if($$DATA =~ /^MThd/) { + $Ext = 'mid'; + } elsif($$DATA =~ /^\x2esnd/) { # ULAW Audio + $Ext = 'au'; + } elsif($$DATA =~ /^RIFF/ || $$DATA =~ /^ID3/ && $$DATA =~ /RIFF/) { + my $HeaderPoint = index($$DATA, "RIFF", 0); + $_ = substr($$DATA, $HeaderPoint + 8, 8); + if(/^WAVEfmt $/) { + # WAVE + if(unpack("V",substr($$DATA, $HeaderPoint + 16, 4)) == 16) { + $Ext = 'wav'; + } else { # RIFF WAVE MP3 + $Ext = 'mp3'; + } + } elsif(/^RMIDdata$/) { # RIFF MIDI + $Ext = 'rmi'; + } elsif(/^RMP3data$/) { # RIFF MP3 + $Ext = 'rmp'; + } + if($ContentType =~ /^audio\//i) { + $Infomation .= '(RIFF '. substr($$DATA, $HeaderPoint + 8, 4). ')'; + } + } + } + + # a binary file + unless ($Ext) { + # PDF image + if($$DATA =~ /^\%PDF/) { + # Picture size is not measured. + $Ext = 'pdf'; + } elsif($$DATA =~ /^FWS/) { # Shockwave Flash + $Ext = 'swf'; + } elsif($$DATA =~ /^RIFF/ || $$DATA =~ /^ID3/ && $$DATA =~ /RIFF/) { + my $HeaderPoint = index($$DATA, "RIFF", 0); + $_ = substr($$DATA,$HeaderPoint + 8, 8); + # AVI + if(/^AVI LIST$/) { + $Ext = 'avi'; + } + if($ContentType =~ /^video\//i) { + $Infomation .= '(RIFF '. substr($$DATA, $HeaderPoint + 8, 4). ')'; + } + } elsif($$DATA =~ /^PK/) { # ZIP Compress File + $Ext = 'zip'; + } elsif($$DATA =~ /^MSCF/) { # CAB Compress File + $Ext = 'cab'; + } elsif($$DATA =~ /^Rar\!/) { # RAR Compress File + $Ext = 'rar'; + } elsif(substr($$DATA, 2, 5) =~ /^\-lh(\d+|d)\-$/) { # LHA Compress File + $Infomation .= "(lh$1)"; + $Ext = 'lzh'; + } elsif(substr($$DATA, 325, 25) eq "Apple Video Media Handler" || substr($$DATA, 325, 30) eq "Apple \x83\x72\x83\x66\x83\x49\x81\x45\x83\x81\x83\x66\x83\x42\x83\x41\x83\x6E\x83\x93\x83\x68\x83\x89") { + # QuickTime + $Ext = 'mov'; + } + } + + # Header analysis failure + unless ($Ext) { + # It will be followed if it applies for the MIME type from the browser. + foreach (keys %UPLOAD_CONTENT_TYPE_LIST) { + next unless ($_); + if($ContentType =~ /^$_$/i) { + $Ext = $UPLOAD_CONTENT_TYPE_LIST{$_}; + $ContentName = &CheckContentExt($Ext); + if( + grep {$_ eq $Ext;} ( + 'png', + 'gif', + 'jpg', + 'xbm', + 'tif', + 'bmp', + 'pdf', + 'swf', + 'mov', + 'zip', + 'cab', + 'lzh', + 'rar', + 'mid', + 'rmi', + 'au', + 'wav', + 'avi', + 'exe' + ) + ) { + $Infomation .= ' / Header analysis failure'; + } + if($Ext ne $FileExt && &CheckContentExt($FileExt) eq $ContentName) { + $Ext = $FileExt; + } + last; + } + } + # a MIME type is unknown--It judges from an extension. + unless ($Ext) { + $ContentName = &CheckContentExt($FileExt); + if($ContentName) { + $Ext = $FileExt; + $Infomation .= ' / MIME type is unknown('. $ContentType. ')'; + last; + } + } + } + +# $ContentName = &CheckContentExt($Ext) unless($ContentName); +# if($Ext && $ContentName) { +# $ContentName .= $Infomation; +# } else { +# &upload_error( +# 'Extension Error', +# "$FileName A not corresponding extension ($Ext)<BR>The extension which can be responded ". join(',', sort values(%UPLOAD_EXT_LIST)) +# ); +# } + +# # SSI Tag Deletion +# if($Ext =~ /.?html?/ && $$DATA =~ /<\!/) { +# foreach ( +# 'config', +# 'echo', +# 'exec', +# 'flastmod', +# 'fsize', +# 'include' +# ) { +# $$DATA =~ s/\#\s*$_/\&\#35\;$_/ig +# } +# } + + return ( + $FileName, + $Ext, + int($DataLength / 1024 + 1), + $ImageWidth, + $ImageHeight, + $ContentName + ); +} + +############################################################################## +# Summary +# +# Extension discernment +# +# Parameters +# Returns +# Memo +############################################################################## + +sub CheckContentExt +{ + + my($Ext) = @_; + my $ContentName; + foreach (keys %UPLOAD_EXT_LIST) { + next unless ($_); + if($_ && $Ext =~ /^$_$/) { + $ContentName = $UPLOAD_EXT_LIST{$_}; + last; + } + } + return $ContentName; + +} + +############################################################################## +# Summary +# +# Form decode +# +# Parameters +# Returns +# Memo +############################################################################## +sub Encode +{ + + my($value,$Trans) = @_; + +# my $FormCode = &jcode::getcode($value) || $FormCodeDefault; +# $FormCodeDefault ||= $FormCode; +# +# if($Trans && $TRANS_2BYTE_CODE) { +# if($FormCode ne 'euc') { +# &jcode::convert($value, 'euc', $FormCode); +# } +# &jcode::tr( +# $value, +# "\xA3\xB0-\xA3\xB9\xA3\xC1-\xA3\xDA\xA3\xE1-\xA3\xFA", +# '0-9A-Za-z' +# ); +# if($CHARCODE ne 'euc') { +# &jcode::convert($value,$CHARCODE,'euc'); +# } +# } else { +# if($CHARCODE ne $FormCode) { +# &jcode::convert($value,$CHARCODE,$FormCode); +# } +# } +# if($CHARCODE eq 'euc') { +# &jcode::h2z_euc($value); +# } elsif($CHARCODE eq 'sjis') { +# &jcode::h2z_sjis($value); +# } + +} + +############################################################################## +# Summary +# +# Error Msg +# +# Parameters +# Returns +# Memo +############################################################################## + +sub upload_error +{ + + local($error_message) = $_[0]; + local($error_message2) = $_[1]; + + print "Content-type: text/html\n\n"; + print<<EOF; +<HTML> +<HEAD> +<TITLE>Error Message</TITLE></HEAD> +<BODY> +<table border="1" cellspacing="10" cellpadding="10"> + <TR bgcolor="#0000B0"> + <TD bgcolor="#0000B0" NOWRAP><font size="-1" color="white"><B>Error Message</B></font></TD> + </TR> +</table> +<UL> +<H4> $error_message </H4> +$error_message2 <BR> +</UL> +</BODY> +</HTML> +EOF + &rm_tmp_uploaded_files; # Image Temporary deletion + exit; +} + +############################################################################## +# Summary +# +# Image Temporary deletion +# +# Parameters +# Returns +# Memo +############################################################################## + +sub rm_tmp_uploaded_files +{ + if($img_data_exists == 1){ + sleep 1; + foreach $fname_list(@NEWFNAMES) { + if(-e "$img_dir/$fname_list") { + unlink("$img_dir/$fname_list"); + } + } + } + +} +1; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/perl/util.pl =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/perl/util.pl (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/perl/util.pl 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,68 @@ +##### +# FCKeditor - The text editor for Internet - http://www.fckeditor.net +# Copyright (C) 2003-2008 Frederico Caldeira Knabben +# +# == BEGIN LICENSE == +# +# Licensed under the terms of any of the following licenses at your +# choice: +# +# - GNU General Public License Version 2 or later (the "GPL") +# http://www.gnu.org/licenses/gpl.html +# +# - GNU Lesser General Public License Version 2.1 or later (the "LGPL") +# http://www.gnu.org/licenses/lgpl.html +# +# - Mozilla Public License Version 1.1 or later (the "MPL") +# http://www.mozilla.org/MPL/MPL-1.1.html +# +# == END LICENSE == +# +# This is the File Manager Connector for Perl. +##### + +sub RemoveFromStart +{ + local($sourceString, $charToRemove) = @_; + $sPattern = '^' . $charToRemove . '+' ; + $sourceString =~ s/^$charToRemove+//g; + return $sourceString; +} + +sub RemoveFromEnd +{ + local($sourceString, $charToRemove) = @_; + $sPattern = $charToRemove . '+$' ; + $sourceString =~ s/$charToRemove+$//g; + return $sourceString; +} + +sub ConvertToXmlAttribute +{ + local($value) = @_; + return $value; +# return utf8_encode(htmlspecialchars($value)); + +} + +sub specialchar_cnv +{ + local($ch) = @_; + + $ch =~ s/&/&/g; # & + $ch =~ s/\"/"/g; #" + $ch =~ s/\'/'/g; # ' + $ch =~ s/</</g; # < + $ch =~ s/>/>/g; # > + return($ch); +} + +sub JS_cnv +{ + local($ch) = @_; + + $ch =~ s/\"/\\\"/g; #" + return($ch); +} + +1; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/php/basexml.php =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/php/basexml.php (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/php/basexml.php 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,93 @@ +<?php +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * These functions define the base of the XML response sent by the PHP + * connector. + */ + +function SetXmlHeaders() +{ + ob_end_clean() ; + + // Prevent the browser from caching the result. + // Date in the past + header('Expires: Mon, 26 Jul 1997 05:00:00 GMT') ; + // always modified + header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT') ; + // HTTP/1.1 + header('Cache-Control: no-store, no-cache, must-revalidate') ; + header('Cache-Control: post-check=0, pre-check=0', false) ; + // HTTP/1.0 + header('Pragma: no-cache') ; + + // Set the response format. + header( 'Content-Type: text/xml; charset=utf-8' ) ; +} + +function CreateXmlHeader( $command, $resourceType, $currentFolder ) +{ + SetXmlHeaders() ; + + // Create the XML document header. + echo '<?xml version="1.0" encoding="utf-8" ?>' ; + + // Create the main "Connector" node. + echo '<Connector command="' . $command . '" resourceType="' . $resourceType . '">' ; + + // Add the current folder node. + echo '<CurrentFolder path="' . ConvertToXmlAttribute( $currentFolder ) . '" url="' . ConvertToXmlAttribute( GetUrlFromPath( $resourceType, $currentFolder, $command ) ) . '" />' ; + + $GLOBALS['HeaderSent'] = true ; +} + +function CreateXmlFooter() +{ + echo '</Connector>' ; +} + +function SendError( $number, $text ) +{ + if ( isset( $GLOBALS['HeaderSent'] ) && $GLOBALS['HeaderSent'] ) + { + SendErrorNode( $number, $text ) ; + CreateXmlFooter() ; + } + else + { + SetXmlHeaders() ; + + // Create the XML document header + echo '<?xml version="1.0" encoding="utf-8" ?>' ; + + echo '<Connector>' ; + + SendErrorNode( $number, $text ) ; + + echo '</Connector>' ; + } + exit ; +} + +function SendErrorNode( $number, $text ) +{ + echo '<Error number="' . $number . '" text="' . htmlspecialchars( $text ) . '" />' ; +} +?> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/php/commands.php =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/php/commands.php (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/php/commands.php 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,273 @@ +<?php +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * This is the File Manager Connector for PHP. + */ + +function GetFolders( $resourceType, $currentFolder ) +{ + // Map the virtual path to the local server path. + $sServerDir = ServerMapFolder( $resourceType, $currentFolder, 'GetFolders' ) ; + + // Array that will hold the folders names. + $aFolders = array() ; + + $oCurrentFolder = opendir( $sServerDir ) ; + + while ( $sFile = readdir( $oCurrentFolder ) ) + { + if ( $sFile != '.' && $sFile != '..' && is_dir( $sServerDir . $sFile ) ) + $aFolders[] = '<Folder name="' . ConvertToXmlAttribute( $sFile ) . '" />' ; + } + + closedir( $oCurrentFolder ) ; + + // Open the "Folders" node. + echo "<Folders>" ; + + natcasesort( $aFolders ) ; + foreach ( $aFolders as $sFolder ) + echo $sFolder ; + + // Close the "Folders" node. + echo "</Folders>" ; +} + +function GetFoldersAndFiles( $resourceType, $currentFolder ) +{ + // Map the virtual path to the local server path. + $sServerDir = ServerMapFolder( $resourceType, $currentFolder, 'GetFoldersAndFiles' ) ; + + // Arrays that will hold the folders and files names. + $aFolders = array() ; + $aFiles = array() ; + + $oCurrentFolder = opendir( $sServerDir ) ; + + while ( $sFile = readdir( $oCurrentFolder ) ) + { + if ( $sFile != '.' && $sFile != '..' ) + { + if ( is_dir( $sServerDir . $sFile ) ) + $aFolders[] = '<Folder name="' . ConvertToXmlAttribute( $sFile ) . '" />' ; + else + { + $iFileSize = @filesize( $sServerDir . $sFile ) ; + if ( !$iFileSize ) { + $iFileSize = 0 ; + } + if ( $iFileSize > 0 ) + { + $iFileSize = round( $iFileSize / 1024 ) ; + if ( $iFileSize < 1 ) $iFileSize = 1 ; + } + + $aFiles[] = '<File name="' . ConvertToXmlAttribute( $sFile ) . '" size="' . $iFileSize . '" />' ; + } + } + } + + // Send the folders + natcasesort( $aFolders ) ; + echo '<Folders>' ; + + foreach ( $aFolders as $sFolder ) + echo $sFolder ; + + echo '</Folders>' ; + + // Send the files + natcasesort( $aFiles ) ; + echo '<Files>' ; + + foreach ( $aFiles as $sFiles ) + echo $sFiles ; + + echo '</Files>' ; +} + +function CreateFolder( $resourceType, $currentFolder ) +{ + if (!isset($_GET)) { + global $_GET; + } + $sErrorNumber = '0' ; + $sErrorMsg = '' ; + + if ( isset( $_GET['NewFolderName'] ) ) + { + $sNewFolderName = $_GET['NewFolderName'] ; + $sNewFolderName = SanitizeFolderName( $sNewFolderName ) ; + + if ( strpos( $sNewFolderName, '..' ) !== FALSE ) + $sErrorNumber = '102' ; // Invalid folder name. + else + { + // Map the virtual path to the local server path of the current folder. + $sServerDir = ServerMapFolder( $resourceType, $currentFolder, 'CreateFolder' ) ; + + if ( is_writable( $sServerDir ) ) + { + $sServerDir .= $sNewFolderName ; + + $sErrorMsg = CreateServerFolder( $sServerDir ) ; + + switch ( $sErrorMsg ) + { + case '' : + $sErrorNumber = '0' ; + break ; + case 'Invalid argument' : + case 'No such file or directory' : + $sErrorNumber = '102' ; // Path too long. + break ; + default : + $sErrorNumber = '110' ; + break ; + } + } + else + $sErrorNumber = '103' ; + } + } + else + $sErrorNumber = '102' ; + + // Create the "Error" node. + echo '<Error number="' . $sErrorNumber . '" originalDescription="' . ConvertToXmlAttribute( $sErrorMsg ) . '" />' ; +} + +function FileUpload( $resourceType, $currentFolder, $sCommand ) +{ + if (!isset($_FILES)) { + global $_FILES; + } + $sErrorNumber = '0' ; + $sFileName = '' ; + + if ( isset( $_FILES['NewFile'] ) && !is_null( $_FILES['NewFile']['tmp_name'] ) ) + { + global $Config ; + + $oFile = $_FILES['NewFile'] ; + + // Map the virtual path to the local server path. + $sServerDir = ServerMapFolder( $resourceType, $currentFolder, $sCommand ) ; + + // Get the uploaded file name. + $sFileName = $oFile['name'] ; + $sFileName = SanitizeFileName( $sFileName ) ; + + $sOriginalFileName = $sFileName ; + + // Get the extension. + $sExtension = substr( $sFileName, ( strrpos($sFileName, '.') + 1 ) ) ; + $sExtension = strtolower( $sExtension ) ; + + if ( isset( $Config['SecureImageUploads'] ) ) + { + if ( ( $isImageValid = IsImageValid( $oFile['tmp_name'], $sExtension ) ) === false ) + { + $sErrorNumber = '202' ; + } + } + + if ( isset( $Config['HtmlExtensions'] ) ) + { + if ( !IsHtmlExtension( $sExtension, $Config['HtmlExtensions'] ) && + ( $detectHtml = DetectHtml( $oFile['tmp_name'] ) ) === true ) + { + $sErrorNumber = '202' ; + } + } + + // Check if it is an allowed extension. + if ( !$sErrorNumber && IsAllowedExt( $sExtension, $resourceType ) ) + { + $iCounter = 0 ; + + while ( true ) + { + $sFilePath = $sServerDir . $sFileName ; + + if ( is_file( $sFilePath ) ) + { + $iCounter++ ; + $sFileName = RemoveExtension( $sOriginalFileName ) . '(' . $iCounter . ').' . $sExtension ; + $sErrorNumber = '201' ; + } + else + { + move_uploaded_file( $oFile['tmp_name'], $sFilePath ) ; + + if ( is_file( $sFilePath ) ) + { + if ( isset( $Config['ChmodOnUpload'] ) && !$Config['ChmodOnUpload'] ) + { + break ; + } + + $permissions = 0777; + + if ( isset( $Config['ChmodOnUpload'] ) && $Config['ChmodOnUpload'] ) + { + $permissions = $Config['ChmodOnUpload'] ; + } + + $oldumask = umask(0) ; + chmod( $sFilePath, $permissions ) ; + umask( $oldumask ) ; + } + + break ; + } + } + + if ( file_exists( $sFilePath ) ) + { + //previous checks failed, try once again + if ( isset( $isImageValid ) && $isImageValid === -1 && IsImageValid( $sFilePath, $sExtension ) === false ) + { + @unlink( $sFilePath ) ; + $sErrorNumber = '202' ; + } + else if ( isset( $detectHtml ) && $detectHtml === -1 && DetectHtml( $sFilePath ) === true ) + { + @unlink( $sFilePath ) ; + $sErrorNumber = '202' ; + } + } + } + else + $sErrorNumber = '202' ; + } + else + $sErrorNumber = '202' ; + + + $sFileUrl = CombinePaths( GetResourceTypePath( $resourceType, $sCommand ) , $currentFolder ) ; + $sFileUrl = CombinePaths( $sFileUrl, $sFileName ) ; + + SendUploadResults( $sErrorNumber, $sFileUrl, $sFileName ) ; + + exit ; +} +?> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/php/config.php =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/php/config.php (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/php/config.php 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,151 @@ +<?php +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Configuration file for the File Manager Connector for PHP. + */ + +global $Config ; + +// SECURITY: You must explicitly enable this "connector". (Set it to "true"). +// WARNING: don't just set "$Config['Enabled'] = true ;", you must be sure that only +// authenticated users can access this file or use some kind of session checking. +$Config['Enabled'] = false ; + + +// Path to user files relative to the document root. +$Config['UserFilesPath'] = '/userfiles/' ; + +// Fill the following value it you prefer to specify the absolute path for the +// user files directory. Useful if you are using a virtual directory, symbolic +// link or alias. Examples: 'C:\\MySite\\userfiles\\' or '/root/mysite/userfiles/'. +// Attention: The above 'UserFilesPath' must point to the same directory. +$Config['UserFilesAbsolutePath'] = '' ; + +// Due to security issues with Apache modules, it is recommended to leave the +// following setting enabled. +$Config['ForceSingleExtension'] = true ; + +// Perform additional checks for image files. +// If set to true, validate image size (using getimagesize). +$Config['SecureImageUploads'] = true; + +// What the user can do with this connector. +$Config['ConfigAllowedCommands'] = array('QuickUpload', 'FileUpload', 'GetFolders', 'GetFoldersAndFiles', 'CreateFolder') ; + +// Allowed Resource Types. +$Config['ConfigAllowedTypes'] = array('File', 'Image', 'Flash', 'Media') ; + +// For security, HTML is allowed in the first Kb of data for files having the +// following extensions only. +$Config['HtmlExtensions'] = array("html", "htm", "xml", "xsd", "txt", "js") ; + +// After file is uploaded, sometimes it is required to change its permissions +// so that it was possible to access it at the later time. +// If possible, it is recommended to set more restrictive permissions, like 0755. +// Set to 0 to disable this feature. +// Note: not needed on Windows-based servers. +$Config['ChmodOnUpload'] = 0777 ; + +// See comments above. +// Used when creating folders that does not exist. +$Config['ChmodOnFolderCreate'] = 0777 ; + +/* + Configuration settings for each Resource Type + + - AllowedExtensions: the possible extensions that can be allowed. + If it is empty then any file type can be uploaded. + - DeniedExtensions: The extensions that won't be allowed. + If it is empty then no restrictions are done here. + + For a file to be uploaded it has to fulfill both the AllowedExtensions + and DeniedExtensions (that's it: not being denied) conditions. + + - FileTypesPath: the virtual folder relative to the document root where + these resources will be located. + Attention: It must start and end with a slash: '/' + + - FileTypesAbsolutePath: the physical path to the above folder. It must be + an absolute path. + If it's an empty string then it will be autocalculated. + Useful if you are using a virtual directory, symbolic link or alias. + Examples: 'C:\\MySite\\userfiles\\' or '/root/mysite/userfiles/'. + Attention: The above 'FileTypesPath' must point to the same directory. + Attention: It must end with a slash: '/' + + - QuickUploadPath: the virtual folder relative to the document root where + these resources will be uploaded using the Upload tab in the resources + dialogs. + Attention: It must start and end with a slash: '/' + + - QuickUploadAbsolutePath: the physical path to the above folder. It must be + an absolute path. + If it's an empty string then it will be autocalculated. + Useful if you are using a virtual directory, symbolic link or alias. + Examples: 'C:\\MySite\\userfiles\\' or '/root/mysite/userfiles/'. + Attention: The above 'QuickUploadPath' must point to the same directory. + Attention: It must end with a slash: '/' + + NOTE: by default, QuickUploadPath and QuickUploadAbsolutePath point to + "userfiles" directory to maintain backwards compatibility with older versions of FCKeditor. + This is fine, but you in some cases you will be not able to browse uploaded files using file browser. + Example: if you click on "image button", select "Upload" tab and send image + to the server, image will appear in FCKeditor correctly, but because it is placed + directly in /userfiles/ directory, you'll be not able to see it in built-in file browser. + The more expected behaviour would be to send images directly to "image" subfolder. + To achieve that, simply change + $Config['QuickUploadPath']['Image'] = $Config['UserFilesPath'] ; + $Config['QuickUploadAbsolutePath']['Image'] = $Config['UserFilesAbsolutePath'] ; + into: + $Config['QuickUploadPath']['Image'] = $Config['FileTypesPath']['Image'] ; + $Config['QuickUploadAbsolutePath']['Image'] = $Config['FileTypesAbsolutePath']['Image'] ; + +*/ + +$Config['AllowedExtensions']['File'] = array('7z', 'aiff', 'asf', 'avi', 'bmp', 'csv', 'doc', 'fla', 'flv', 'gif', 'gz', 'gzip', 'jpeg', 'jpg', 'mid', 'mov', 'mp3', 'mp4', 'mpc', 'mpeg', 'mpg', 'ods', 'odt', 'pdf', 'png', 'ppt', 'pxd', 'qt', 'ram', 'rar', 'rm', 'rmi', 'rmvb', 'rtf', 'sdc', 'sitd', 'swf', 'sxc', 'sxw', 'tar', 'tgz', 'tif', 'tiff', 'txt', 'vsd', 'wav', 'wma', 'wmv', 'xls', 'xml', 'zip') ; +$Config['DeniedExtensions']['File'] = array() ; +$Config['FileTypesPath']['File'] = $Config['UserFilesPath'] . 'file/' ; +$Config['FileTypesAbsolutePath']['File']= ($Config['UserFilesAbsolutePath'] == '') ? '' : $Config['UserFilesAbsolutePath'].'file/' ; +$Config['QuickUploadPath']['File'] = $Config['UserFilesPath'] ; +$Config['QuickUploadAbsolutePath']['File']= $Config['UserFilesAbsolutePath'] ; + +$Config['AllowedExtensions']['Image'] = array('bmp','gif','jpeg','jpg','png') ; +$Config['DeniedExtensions']['Image'] = array() ; +$Config['FileTypesPath']['Image'] = $Config['UserFilesPath'] . 'image/' ; +$Config['FileTypesAbsolutePath']['Image']= ($Config['UserFilesAbsolutePath'] == '') ? '' : $Config['UserFilesAbsolutePath'].'image/' ; +$Config['QuickUploadPath']['Image'] = $Config['UserFilesPath'] ; +$Config['QuickUploadAbsolutePath']['Image']= $Config['UserFilesAbsolutePath'] ; + +$Config['AllowedExtensions']['Flash'] = array('swf','flv') ; +$Config['DeniedExtensions']['Flash'] = array() ; +$Config['FileTypesPath']['Flash'] = $Config['UserFilesPath'] . 'flash/' ; +$Config['FileTypesAbsolutePath']['Flash']= ($Config['UserFilesAbsolutePath'] == '') ? '' : $Config['UserFilesAbsolutePath'].'flash/' ; +$Config['QuickUploadPath']['Flash'] = $Config['UserFilesPath'] ; +$Config['QuickUploadAbsolutePath']['Flash']= $Config['UserFilesAbsolutePath'] ; + +$Config['AllowedExtensions']['Media'] = array('aiff', 'asf', 'avi', 'bmp', 'fla', 'flv', 'gif', 'jpeg', 'jpg', 'mid', 'mov', 'mp3', 'mp4', 'mpc', 'mpeg', 'mpg', 'png', 'qt', 'ram', 'rm', 'rmi', 'rmvb', 'swf', 'tif', 'tiff', 'wav', 'wma', 'wmv') ; +$Config['DeniedExtensions']['Media'] = array() ; +$Config['FileTypesPath']['Media'] = $Config['UserFilesPath'] . 'media/' ; +$Config['FileTypesAbsolutePath']['Media']= ($Config['UserFilesAbsolutePath'] == '') ? '' : $Config['UserFilesAbsolutePath'].'media/' ; +$Config['QuickUploadPath']['Media'] = $Config['UserFilesPath'] ; +$Config['QuickUploadAbsolutePath']['Media']= $Config['UserFilesAbsolutePath'] ; + +?> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/php/connector.php =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/php/connector.php (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/php/connector.php 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,87 @@ +<?php +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * This is the File Manager Connector for PHP. + */ + +ob_start() ; + +require('./config.php') ; +require('./util.php') ; +require('./io.php') ; +require('./basexml.php') ; +require('./commands.php') ; +require('./phpcompat.php') ; + +if ( !$Config['Enabled'] ) + SendError( 1, 'This connector is disabled. Please check the "editor/filemanager/connectors/php/config.php" file' ) ; + +DoResponse() ; + +function DoResponse() +{ + if (!isset($_GET)) { + global $_GET; + } + if ( !isset( $_GET['Command'] ) || !isset( $_GET['Type'] ) || !isset( $_GET['CurrentFolder'] ) ) + return ; + + // Get the main request informaiton. + $sCommand = $_GET['Command'] ; + $sResourceType = $_GET['Type'] ; + $sCurrentFolder = GetCurrentFolder() ; + + // Check if it is an allowed command + if ( ! IsAllowedCommand( $sCommand ) ) + SendError( 1, 'The "' . $sCommand . '" command isn\'t allowed' ) ; + + // Check if it is an allowed type. + if ( !IsAllowedType( $sResourceType ) ) + SendError( 1, 'Invalid type specified' ) ; + + // File Upload doesn't have to Return XML, so it must be intercepted before anything. + if ( $sCommand == 'FileUpload' ) + { + FileUpload( $sResourceType, $sCurrentFolder, $sCommand ) ; + return ; + } + + CreateXmlHeader( $sCommand, $sResourceType, $sCurrentFolder ) ; + + // Execute the required command. + switch ( $sCommand ) + { + case 'GetFolders' : + GetFolders( $sResourceType, $sCurrentFolder ) ; + break ; + case 'GetFoldersAndFiles' : + GetFoldersAndFiles( $sResourceType, $sCurrentFolder ) ; + break ; + case 'CreateFolder' : + CreateFolder( $sResourceType, $sCurrentFolder ) ; + break ; + } + + CreateXmlFooter() ; + + exit ; +} +?> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/php/io.php =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/php/io.php (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/php/io.php 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,320 @@ +<?php +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * This is the File Manager Connector for PHP. + */ +function CombinePaths( $sBasePath, $sFolder ) +{ + return RemoveFromEnd( $sBasePath, '/' ) . '/' . RemoveFromStart( $sFolder, '/' ) ; +} +function GetResourceTypePath( $resourceType, $sCommand ) +{ + global $Config ; + + if ( $sCommand == "QuickUpload") + return $Config['QuickUploadPath'][$resourceType] ; + else + return $Config['FileTypesPath'][$resourceType] ; +} + +function GetResourceTypeDirectory( $resourceType, $sCommand ) +{ + global $Config ; + if ( $sCommand == "QuickUpload") + { + if ( strlen( $Config['QuickUploadAbsolutePath'][$resourceType] ) > 0 ) + return $Config['QuickUploadAbsolutePath'][$resourceType] ; + + // Map the "UserFiles" path to a local directory. + return Server_MapPath( $Config['QuickUploadPath'][$resourceType] ) ; + } + else + { + if ( strlen( $Config['FileTypesAbsolutePath'][$resourceType] ) > 0 ) + return $Config['FileTypesAbsolutePath'][$resourceType] ; + + // Map the "UserFiles" path to a local directory. + return Server_MapPath( $Config['FileTypesPath'][$resourceType] ) ; + } +} + +function GetUrlFromPath( $resourceType, $folderPath, $sCommand ) +{ + return CombinePaths( GetResourceTypePath( $resourceType, $sCommand ), $folderPath ) ; +} + +function RemoveExtension( $fileName ) +{ + return substr( $fileName, 0, strrpos( $fileName, '.' ) ) ; +} + +function ServerMapFolder( $resourceType, $folderPath, $sCommand ) +{ + // Get the resource type directory. + $sResourceTypePath = GetResourceTypeDirectory( $resourceType, $sCommand ) ; + + // Ensure that the directory exists. + $sErrorMsg = CreateServerFolder( $sResourceTypePath ) ; + if ( $sErrorMsg != '' ) + SendError( 1, "Error creating folder \"{$sResourceTypePath}\" ({$sErrorMsg})" ) ; + + // Return the resource type directory combined with the required path. + return CombinePaths( $sResourceTypePath , $folderPath ) ; +} + +function GetParentFolder( $folderPath ) +{ + $sPattern = "-[/\\\\][^/\\\\]+[/\\\\]?$-" ; + return preg_replace( $sPattern, '', $folderPath ) ; +} + +function CreateServerFolder( $folderPath, $lastFolder = null ) +{ + global $Config ; + $sParent = GetParentFolder( $folderPath ) ; + + // Ensure the folder path has no double-slashes, or mkdir may fail on certain platforms + while ( strpos($folderPath, '//') !== false ) + { + $folderPath = str_replace( '//', '/', $folderPath ) ; + } + + // Check if the parent exists, or create it. + if ( !file_exists( $sParent ) ) + { + //prevents agains infinite loop when we can't create root folder + if ( !is_null( $lastFolder ) && $lastFolder === $sParent) { + return "Can't create $folderPath directory" ; + } + + $sErrorMsg = CreateServerFolder( $sParent, $folderPath ) ; + if ( $sErrorMsg != '' ) + return $sErrorMsg ; + } + + if ( !file_exists( $folderPath ) ) + { + // Turn off all error reporting. + error_reporting( 0 ) ; + + $php_errormsg = '' ; + // Enable error tracking to catch the error. + ini_set( 'track_errors', '1' ) ; + + if ( isset( $Config['ChmodOnFolderCreate'] ) && !$Config['ChmodOnFolderCreate'] ) + { + mkdir( $folderPath ) ; + } + else + { + $permissions = 0777 ; + if ( isset( $Config['ChmodOnFolderCreate'] ) ) + { + $permissions = $Config['ChmodOnFolderCreate'] ; + } + // To create the folder with 0777 permissions, we need to set umask to zero. + $oldumask = umask(0) ; + mkdir( $folderPath, $permissions ) ; + umask( $oldumask ) ; + } + + $sErrorMsg = $php_errormsg ; + + // Restore the configurations. + ini_restore( 'track_errors' ) ; + ini_restore( 'error_reporting' ) ; + + return $sErrorMsg ; + } + else + return '' ; +} + +function GetRootPath() +{ + if (!isset($_SERVER)) { + global $_SERVER; + } + $sRealPath = realpath( './' ) ; + + $sSelfPath = $_SERVER['PHP_SELF'] ; + $sSelfPath = substr( $sSelfPath, 0, strrpos( $sSelfPath, '/' ) ) ; + + $sSelfPath = str_replace( '/', DIRECTORY_SEPARATOR, $sSelfPath ) ; + + $position = strpos( $sRealPath, $sSelfPath ) ; + + // This can check only that this script isn't run from a virtual dir + // But it avoids the problems that arise if it isn't checked + if ( $position === false || $position <> strlen( $sRealPath ) - strlen( $sSelfPath ) ) + SendError( 1, 'Sorry, can\'t map "UserFilesPath" to a physical path. You must set the "UserFilesAbsolutePath" value in "editor/filemanager/connectors/php/config.php".' ) ; + + return substr( $sRealPath, 0, $position ) ; +} + +// Emulate the asp Server.mapPath function. +// given an url path return the physical directory that it corresponds to +function Server_MapPath( $path ) +{ + // This function is available only for Apache + if ( function_exists( 'apache_lookup_uri' ) ) + { + $info = apache_lookup_uri( $path ) ; + return $info->filename . $info->path_info ; + } + + // This isn't correct but for the moment there's no other solution + // If this script is under a virtual directory or symlink it will detect the problem and stop + return GetRootPath() . $path ; +} + +function IsAllowedExt( $sExtension, $resourceType ) +{ + global $Config ; + // Get the allowed and denied extensions arrays. + $arAllowed = $Config['AllowedExtensions'][$resourceType] ; + $arDenied = $Config['DeniedExtensions'][$resourceType] ; + + if ( count($arAllowed) > 0 && !in_array( $sExtension, $arAllowed ) ) + return false ; + + if ( count($arDenied) > 0 && in_array( $sExtension, $arDenied ) ) + return false ; + + return true ; +} + +function IsAllowedType( $resourceType ) +{ + global $Config ; + if ( !in_array( $resourceType, $Config['ConfigAllowedTypes'] ) ) + return false ; + + return true ; +} + +function IsAllowedCommand( $sCommand ) +{ + global $Config ; + + if ( !in_array( $sCommand, $Config['ConfigAllowedCommands'] ) ) + return false ; + + return true ; +} + +function GetCurrentFolder() +{ + if (!isset($_GET)) { + global $_GET; + } + $sCurrentFolder = isset( $_GET['CurrentFolder'] ) ? $_GET['CurrentFolder'] : '/' ; + + // Check the current folder syntax (must begin and start with a slash). + if ( !preg_match( '|/$|', $sCurrentFolder ) ) + $sCurrentFolder .= '/' ; + if ( strpos( $sCurrentFolder, '/' ) !== 0 ) + $sCurrentFolder = '/' . $sCurrentFolder ; + + // Ensure the folder path has no double-slashes + while ( strpos ($sCurrentFolder, '//') !== false ) { + $sCurrentFolder = str_replace ('//', '/', $sCurrentFolder) ; + } + + // Check for invalid folder paths (..) + if ( strpos( $sCurrentFolder, '..' ) || strpos( $sCurrentFolder, "\\" )) + SendError( 102, '' ) ; + + return $sCurrentFolder ; +} + +// Do a cleanup of the folder name to avoid possible problems +function SanitizeFolderName( $sNewFolderName ) +{ + $sNewFolderName = stripslashes( $sNewFolderName ) ; + + // Remove . \ / | : ? * " < > + $sNewFolderName = preg_replace( '/\\.|\\\\|\\/|\\||\\:|\\?|\\*|"|<|>|[[:cntrl:]]/', '_', $sNewFolderName ) ; + + return $sNewFolderName ; +} + +// Do a cleanup of the file name to avoid possible problems +function SanitizeFileName( $sNewFileName ) +{ + global $Config ; + + $sNewFileName = stripslashes( $sNewFileName ) ; + + // Replace dots in the name with underscores (only one dot can be there... security issue). + if ( $Config['ForceSingleExtension'] ) + $sNewFileName = preg_replace( '/\\.(?![^.]*$)/', '_', $sNewFileName ) ; + + // Remove \ / | : ? * " < > + $sNewFileName = preg_replace( '/\\\\|\\/|\\||\\:|\\?|\\*|"|<|>|[[:cntrl:]]/', '_', $sNewFileName ) ; + + return $sNewFileName ; +} + +// This is the function that sends the results of the uploading process. +function SendUploadResults( $errorNumber, $fileUrl = '', $fileName = '', $customMsg = '' ) +{ + echo <<<EOF +<script type="text/javascript"> +(function() +{ + var d = document.domain ; + + while ( true ) + { + // Test if we can access a parent property. + try + { + var test = window.top.opener.document.domain ; + break ; + } + catch( e ) {} + + // Remove a domain part: www.mytest.example.com => mytest.example.com => example.com ... + d = d.replace( /.*?(?:\.|$)/, '' ) ; + + if ( d.length == 0 ) + break ; // It was not able to detect the domain. + + try + { + document.domain = d ; + } + catch (e) + { + break ; + } + } +})() ; + +EOF; + $rpl = array( '\\' => '\\\\', '"' => '\\"' ) ; + echo 'window.parent.OnUploadCompleted(' . $errorNumber . ',"' . strtr( $fileUrl, $rpl ) . '","' . strtr( $fileName, $rpl ) . '", "' . strtr( $customMsg, $rpl ) . '") ;' ; + echo '</script>' ; + exit ; +} + +?> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/php/phpcompat.php =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/php/phpcompat.php (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/php/phpcompat.php 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,17 @@ +<?php + +if ( !isset( $_SERVER ) ) { + $_SERVER = $HTTP_SERVER_VARS ; +} +if ( !isset( $_GET ) ) { + $_GET = $HTTP_GET_VARS ; +} +if ( !isset( $_FILES ) ) { + $_FILES = $HTTP_POST_FILES ; +} + +if ( !defined( 'DIRECTORY_SEPARATOR' ) ) { + define( 'DIRECTORY_SEPARATOR', + strtoupper(substr(PHP_OS, 0, 3) == 'WIN') ? '\\' : '/' + ) ; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/php/upload.php =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/php/upload.php (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/php/upload.php 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,59 @@ +<?php +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * This is the "File Uploader" for PHP. + */ + +require('./config.php') ; +require('./util.php') ; +require('./io.php') ; +require('./commands.php') ; +require('./phpcompat.php') ; + +function SendError( $number, $text ) +{ + SendUploadResults( $number, '', '', $text ) ; +} + + +// Check if this uploader has been enabled. +if ( !$Config['Enabled'] ) + SendUploadResults( '1', '', '', 'This file uploader is disabled. Please check the "editor/filemanager/connectors/php/config.php" file' ) ; + +$sCommand = 'QuickUpload' ; + +// The file type (from the QueryString, by default 'File'). +$sType = isset( $_GET['Type'] ) ? $_GET['Type'] : 'File' ; + +$sCurrentFolder = GetCurrentFolder() ; + +// Is enabled the upload? +if ( ! IsAllowedCommand( $sCommand ) ) + SendUploadResults( '1', '', '', 'The ""' . $sCommand . '"" command isn\'t allowed' ) ; + +// Check if it is an allowed type. +if ( !IsAllowedType( $sType ) ) + SendUploadResults( 1, '', '', 'Invalid type specified' ) ; + + +FileUpload( $sType, $sCurrentFolder, $sCommand ) + +?> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/php/util.php =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/php/util.php (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/php/util.php 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,220 @@ +<?php +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Utility functions for the File Manager Connector for PHP. + */ + +function RemoveFromStart( $sourceString, $charToRemove ) +{ + $sPattern = '|^' . $charToRemove . '+|' ; + return preg_replace( $sPattern, '', $sourceString ) ; +} + +function RemoveFromEnd( $sourceString, $charToRemove ) +{ + $sPattern = '|' . $charToRemove . '+$|' ; + return preg_replace( $sPattern, '', $sourceString ) ; +} + +function FindBadUtf8( $string ) +{ + $regex = + '([\x00-\x7F]'. + '|[\xC2-\xDF][\x80-\xBF]'. + '|\xE0[\xA0-\xBF][\x80-\xBF]'. + '|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}'. + '|\xED[\x80-\x9F][\x80-\xBF]'. + '|\xF0[\x90-\xBF][\x80-\xBF]{2}'. + '|[\xF1-\xF3][\x80-\xBF]{3}'. + '|\xF4[\x80-\x8F][\x80-\xBF]{2}'. + '|(.{1}))'; + + while (preg_match('/'.$regex.'/S', $string, $matches)) { + if ( isset($matches[2])) { + return true; + } + $string = substr($string, strlen($matches[0])); + } + + return false; +} + +function ConvertToXmlAttribute( $value ) +{ + if ( defined( 'PHP_OS' ) ) + { + $os = PHP_OS ; + } + else + { + $os = php_uname() ; + } + + if ( strtoupper( substr( $os, 0, 3 ) ) === 'WIN' || FindBadUtf8( $value ) ) + { + return ( utf8_encode( htmlspecialchars( $value ) ) ) ; + } + else + { + return ( htmlspecialchars( $value ) ) ; + } +} + +/** + * Check whether given extension is in html etensions list + * + * @param string $ext + * @param array $htmlExtensions + * @return boolean + */ +function IsHtmlExtension( $ext, $htmlExtensions ) +{ + if ( !$htmlExtensions || !is_array( $htmlExtensions ) ) + { + return false ; + } + $lcaseHtmlExtensions = array() ; + foreach ( $htmlExtensions as $key => $val ) + { + $lcaseHtmlExtensions[$key] = strtolower( $val ) ; + } + return in_array( $ext, $lcaseHtmlExtensions ) ; +} + +/** + * Detect HTML in the first KB to prevent against potential security issue with + * IE/Safari/Opera file type auto detection bug. + * Returns true if file contain insecure HTML code at the beginning. + * + * @param string $filePath absolute path to file + * @return boolean + */ +function DetectHtml( $filePath ) +{ + $fp = @fopen( $filePath, 'rb' ) ; + + //open_basedir restriction, see #1906 + if ( $fp === false || !flock( $fp, LOCK_SH ) ) + { + return -1 ; + } + + $chunk = fread( $fp, 1024 ) ; + flock( $fp, LOCK_UN ) ; + fclose( $fp ) ; + + $chunk = strtolower( $chunk ) ; + + if (!$chunk) + { + return false ; + } + + $chunk = trim( $chunk ) ; + + if ( preg_match( "/<!DOCTYPE\W*X?HTML/sim", $chunk ) ) + { + return true; + } + + $tags = array( '<body', '<head', '<html', '<img', '<pre', '<script', '<table', '<title' ) ; + + foreach( $tags as $tag ) + { + if( false !== strpos( $chunk, $tag ) ) + { + return true ; + } + } + + //type = javascript + if ( preg_match( '!type\s*=\s*[\'"]?\s*(?:\w*/)?(?:ecma|java)!sim', $chunk ) ) + { + return true ; + } + + //href = javascript + //src = javascript + //data = javascript + if ( preg_match( '!(?:href|src|data)\s*=\s*[\'"]?\s*(?:ecma|java)script:!sim', $chunk ) ) + { + return true ; + } + + //url(javascript + if ( preg_match( '!url\s*\(\s*[\'"]?\s*(?:ecma|java)script:!sim', $chunk ) ) + { + return true ; + } + + return false ; +} + +/** + * Check file content. + * Currently this function validates only image files. + * Returns false if file is invalid. + * + * @param string $filePath absolute path to file + * @param string $extension file extension + * @param integer $detectionLevel 0 = none, 1 = use getimagesize for images, 2 = use DetectHtml for images + * @return boolean + */ +function IsImageValid( $filePath, $extension ) +{ + if (!@is_readable($filePath)) { + return -1; + } + + $imageCheckExtensions = array('gif', 'jpeg', 'jpg', 'png', 'swf', 'psd', 'bmp', 'iff'); + + // version_compare is available since PHP4 >= 4.0.7 + if ( function_exists( 'version_compare' ) ) { + $sCurrentVersion = phpversion(); + if ( version_compare( $sCurrentVersion, "4.2.0" ) >= 0 ) { + $imageCheckExtensions[] = "tiff"; + $imageCheckExtensions[] = "tif"; + } + if ( version_compare( $sCurrentVersion, "4.3.0" ) >= 0 ) { + $imageCheckExtensions[] = "swc"; + } + if ( version_compare( $sCurrentVersion, "4.3.2" ) >= 0 ) { + $imageCheckExtensions[] = "jpc"; + $imageCheckExtensions[] = "jp2"; + $imageCheckExtensions[] = "jpx"; + $imageCheckExtensions[] = "jb2"; + $imageCheckExtensions[] = "xbm"; + $imageCheckExtensions[] = "wbmp"; + } + } + + if ( !in_array( $extension, $imageCheckExtensions ) ) { + return true; + } + + if ( @getimagesize( $filePath ) === false ) { + return false ; + } + + return true; +} + +?> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/config.py =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/config.py (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/config.py 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,146 @@ +#!/usr/bin/env python +""" + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Configuration file for the File Manager Connector for Python +""" + +# INSTALLATION NOTE: You must set up your server environment accordingly to run +# python scripts. This connector requires Python 2.4 or greater. +# +# Supported operation modes: +# * WSGI (recommended): You'll need apache + mod_python + modpython_gateway +# or any web server capable of the WSGI python standard +# * Plain Old CGI: Any server capable of running standard python scripts +# (although mod_python is recommended for performance) +# This was the previous connector version operation mode +# +# If you're using Apache web server, replace the htaccess.txt to to .htaccess, +# and set the proper options and paths. +# For WSGI and mod_python, you may need to download modpython_gateway from: +# http://projects.amor.org/misc/svn/modpython_gateway.py and copy it in this +# directory. + + +# SECURITY: You must explicitly enable this "connector". (Set it to "True"). +# WARNING: don't just set "ConfigIsEnabled = True", you must be sure that only +# authenticated users can access this file or use some kind of session checking. +Enabled = False + +# Path to user files relative to the document root. +UserFilesPath = '/userfiles/' + +# Fill the following value it you prefer to specify the absolute path for the +# user files directory. Useful if you are using a virtual directory, symbolic +# link or alias. Examples: 'C:\\MySite\\userfiles\\' or '/root/mysite/userfiles/'. +# Attention: The above 'UserFilesPath' must point to the same directory. +# WARNING: GetRootPath may not work in virtual or mod_python configurations, and +# may not be thread safe. Use this configuration parameter instead. +UserFilesAbsolutePath = '' + +# Due to security issues with Apache modules, it is recommended to leave the +# following setting enabled. +ForceSingleExtension = True + +# What the user can do with this connector +ConfigAllowedCommands = [ 'QuickUpload', 'FileUpload', 'GetFolders', 'GetFoldersAndFiles', 'CreateFolder' ] + +# Allowed Resource Types +ConfigAllowedTypes = ['File', 'Image', 'Flash', 'Media'] + +# After file is uploaded, sometimes it is required to change its permissions +# so that it was possible to access it at the later time. +# If possible, it is recommended to set more restrictive permissions, like 0755. +# Set to 0 to disable this feature. +# Note: not needed on Windows-based servers. +ChmodOnUpload = 0755 + +# See comments above. +# Used when creating folders that does not exist. +ChmodOnFolderCreate = 0755 + +# Do not touch this 3 lines, see "Configuration settings for each Resource Type" +AllowedExtensions = {}; DeniedExtensions = {}; +FileTypesPath = {}; FileTypesAbsolutePath = {}; +QuickUploadPath = {}; QuickUploadAbsolutePath = {}; + +# Configuration settings for each Resource Type +# +# - AllowedExtensions: the possible extensions that can be allowed. +# If it is empty then any file type can be uploaded. +# - DeniedExtensions: The extensions that won't be allowed. +# If it is empty then no restrictions are done here. +# +# For a file to be uploaded it has to fulfill both the AllowedExtensions +# and DeniedExtensions (that's it: not being denied) conditions. +# +# - FileTypesPath: the virtual folder relative to the document root where +# these resources will be located. +# Attention: It must start and end with a slash: '/' +# +# - FileTypesAbsolutePath: the physical path to the above folder. It must be +# an absolute path. +# If it's an empty string then it will be autocalculated. +# Useful if you are using a virtual directory, symbolic link or alias. +# Examples: 'C:\\MySite\\userfiles\\' or '/root/mysite/userfiles/'. +# Attention: The above 'FileTypesPath' must point to the same directory. +# Attention: It must end with a slash: '/' +# +# +# - QuickUploadPath: the virtual folder relative to the document root where +# these resources will be uploaded using the Upload tab in the resources +# dialogs. +# Attention: It must start and end with a slash: '/' +# +# - QuickUploadAbsolutePath: the physical path to the above folder. It must be +# an absolute path. +# If it's an empty string then it will be autocalculated. +# Useful if you are using a virtual directory, symbolic link or alias. +# Examples: 'C:\\MySite\\userfiles\\' or '/root/mysite/userfiles/'. +# Attention: The above 'QuickUploadPath' must point to the same directory. +# Attention: It must end with a slash: '/' + +AllowedExtensions['File'] = ['7z','aiff','asf','avi','bmp','csv','doc','fla','flv','gif','gz','gzip','jpeg','jpg','mid','mov','mp3','mp4','mpc','mpeg','mpg','ods','odt','pdf','png','ppt','pxd','qt','ram','rar','rm','rmi','rmvb','rtf','sdc','sitd','swf','sxc','sxw','tar','tgz','tif','tiff','txt','vsd','wav','wma','wmv','xls','xml','zip'] +DeniedExtensions['File'] = [] +FileTypesPath['File'] = UserFilesPath + 'file/' +FileTypesAbsolutePath['File'] = (not UserFilesAbsolutePath == '') and (UserFilesAbsolutePath + 'file/') or '' +QuickUploadPath['File'] = FileTypesPath['File'] +QuickUploadAbsolutePath['File'] = FileTypesAbsolutePath['File'] + +AllowedExtensions['Image'] = ['bmp','gif','jpeg','jpg','png'] +DeniedExtensions['Image'] = [] +FileTypesPath['Image'] = UserFilesPath + 'image/' +FileTypesAbsolutePath['Image'] = (not UserFilesAbsolutePath == '') and UserFilesAbsolutePath + 'image/' or '' +QuickUploadPath['Image'] = FileTypesPath['Image'] +QuickUploadAbsolutePath['Image']= FileTypesAbsolutePath['Image'] + +AllowedExtensions['Flash'] = ['swf','flv'] +DeniedExtensions['Flash'] = [] +FileTypesPath['Flash'] = UserFilesPath + 'flash/' +FileTypesAbsolutePath['Flash'] = ( not UserFilesAbsolutePath == '') and UserFilesAbsolutePath + 'flash/' or '' +QuickUploadPath['Flash'] = FileTypesPath['Flash'] +QuickUploadAbsolutePath['Flash']= FileTypesAbsolutePath['Flash'] + +AllowedExtensions['Media'] = ['aiff','asf','avi','bmp','fla', 'flv','gif','jpeg','jpg','mid','mov','mp3','mp4','mpc','mpeg','mpg','png','qt','ram','rm','rmi','rmvb','swf','tif','tiff','wav','wma','wmv'] +DeniedExtensions['Media'] = [] +FileTypesPath['Media'] = UserFilesPath + 'media/' +FileTypesAbsolutePath['Media'] = ( not UserFilesAbsolutePath == '') and UserFilesAbsolutePath + 'media/' or '' +QuickUploadPath['Media'] = FileTypesPath['Media'] +QuickUploadAbsolutePath['Media']= FileTypesAbsolutePath['Media'] Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/connector.py =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/connector.py (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/connector.py 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,118 @@ +#!/usr/bin/env python + +""" +FCKeditor - The text editor for Internet - http://www.fckeditor.net +Copyright (C) 2003-2008 Frederico Caldeira Knabben + +== BEGIN LICENSE == + +Licensed under the terms of any of the following licenses at your +choice: + + - GNU General Public License Version 2 or later (the "GPL") + http://www.gnu.org/licenses/gpl.html + + - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + http://www.gnu.org/licenses/lgpl.html + + - Mozilla Public License Version 1.1 or later (the "MPL") + http://www.mozilla.org/MPL/MPL-1.1.html + +== END LICENSE == + +Connector for Python (CGI and WSGI). + +See config.py for configuration settings + +""" +import os + +from fckutil import * +from fckcommands import * # default command's implementation +from fckoutput import * # base http, xml and html output mixins +from fckconnector import FCKeditorConnectorBase # import base connector +import config as Config + +class FCKeditorConnector( FCKeditorConnectorBase, + GetFoldersCommandMixin, + GetFoldersAndFilesCommandMixin, + CreateFolderCommandMixin, + UploadFileCommandMixin, + BaseHttpMixin, BaseXmlMixin, BaseHtmlMixin ): + "The Standard connector class." + def doResponse(self): + "Main function. Process the request, set headers and return a string as response." + s = "" + # Check if this connector is disabled + if not(Config.Enabled): + return self.sendError(1, "This connector is disabled. Please check the connector configurations in \"editor/filemanager/connectors/py/config.py\" and try again.") + # Make sure we have valid inputs + for key in ("Command","Type","CurrentFolder"): + if not self.request.has_key (key): + return + # Get command, resource type and current folder + command = self.request.get("Command") + resourceType = self.request.get("Type") + currentFolder = getCurrentFolder(self.request.get("CurrentFolder")) + # Check for invalid paths + if currentFolder is None: + return self.sendError(102, "") + + # Check if it is an allowed command + if ( not command in Config.ConfigAllowedCommands ): + return self.sendError( 1, 'The %s command isn\'t allowed' % command ) + + if ( not resourceType in Config.ConfigAllowedTypes ): + return self.sendError( 1, 'Invalid type specified' ) + + # Setup paths + if command == "QuickUpload": + self.userFilesFolder = Config.QuickUploadAbsolutePath[resourceType] + self.webUserFilesFolder = Config.QuickUploadPath[resourceType] + else: + self.userFilesFolder = Config.FileTypesAbsolutePath[resourceType] + self.webUserFilesFolder = Config.FileTypesPath[resourceType] + + if not self.userFilesFolder: # no absolute path given (dangerous...) + self.userFilesFolder = mapServerPath(self.environ, + self.webUserFilesFolder) + # Ensure that the directory exists. + if not os.path.exists(self.userFilesFolder): + try: + self.createServerFoldercreateServerFolder( self.userFilesFolder ) + except: + return self.sendError(1, "This connector couldn\'t access to local user\'s files directories. Please check the UserFilesAbsolutePath in \"editor/filemanager/connectors/py/config.py\" and try again. ") + + # File upload doesn't have to return XML, so intercept here + if (command == "FileUpload"): + return self.uploadFile(resourceType, currentFolder) + + # Create Url + url = combinePaths( self.webUserFilesFolder, currentFolder ) + + # Begin XML + s += self.createXmlHeader(command, resourceType, currentFolder, url) + # Execute the command + selector = {"GetFolders": self.getFolders, + "GetFoldersAndFiles": self.getFoldersAndFiles, + "CreateFolder": self.createFolder, + } + s += selector[command](resourceType, currentFolder) + s += self.createXmlFooter() + return s + +# Running from command line (plain old CGI) +if __name__ == '__main__': + try: + # Create a Connector Instance + conn = FCKeditorConnector() + data = conn.doResponse() + for header in conn.headers: + print '%s: %s' % header + print + print data + except: + print "Content-Type: text/plain" + print + import cgi + cgi.print_exception() Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/fckcommands.py =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/fckcommands.py (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/fckcommands.py 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,198 @@ +#!/usr/bin/env python + +""" +FCKeditor - The text editor for Internet - http://www.fckeditor.net +Copyright (C) 2003-2008 Frederico Caldeira Knabben + +== BEGIN LICENSE == + +Licensed under the terms of any of the following licenses at your +choice: + +- GNU General Public License Version 2 or later (the "GPL") +http://www.gnu.org/licenses/gpl.html + +- GNU Lesser General Public License Version 2.1 or later (the "LGPL") +http://www.gnu.org/licenses/lgpl.html + +- Mozilla Public License Version 1.1 or later (the "MPL") +http://www.mozilla.org/MPL/MPL-1.1.html + +== END LICENSE == + +Connector for Python (CGI and WSGI). + +""" + +import os +try: # Windows needs stdio set for binary mode for file upload to work. + import msvcrt + msvcrt.setmode (0, os.O_BINARY) # stdin = 0 + msvcrt.setmode (1, os.O_BINARY) # stdout = 1 +except ImportError: + pass + +from fckutil import * +from fckoutput import * +import config as Config + +class GetFoldersCommandMixin (object): + def getFolders(self, resourceType, currentFolder): + """ + Purpose: command to recieve a list of folders + """ + # Map the virtual path to our local server + serverPath = mapServerFolder(self.userFilesFolder,currentFolder) + s = """<Folders>""" # Open the folders node + for someObject in os.listdir(serverPath): + someObjectPath = mapServerFolder(serverPath, someObject) + if os.path.isdir(someObjectPath): + s += """<Folder name="%s" />""" % ( + convertToXmlAttribute(someObject) + ) + s += """</Folders>""" # Close the folders node + return s + +class GetFoldersAndFilesCommandMixin (object): + def getFoldersAndFiles(self, resourceType, currentFolder): + """ + Purpose: command to recieve a list of folders and files + """ + # Map the virtual path to our local server + serverPath = mapServerFolder(self.userFilesFolder,currentFolder) + # Open the folders / files node + folders = """<Folders>""" + files = """<Files>""" + for someObject in os.listdir(serverPath): + someObjectPath = mapServerFolder(serverPath, someObject) + if os.path.isdir(someObjectPath): + folders += """<Folder name="%s" />""" % ( + convertToXmlAttribute(someObject) + ) + elif os.path.isfile(someObjectPath): + size = os.path.getsize(someObjectPath) + files += """<File name="%s" size="%s" />""" % ( + convertToXmlAttribute(someObject), + os.path.getsize(someObjectPath) + ) + # Close the folders / files node + folders += """</Folders>""" + files += """</Files>""" + return folders + files + +class CreateFolderCommandMixin (object): + def createFolder(self, resourceType, currentFolder): + """ + Purpose: command to create a new folder + """ + errorNo = 0; errorMsg =''; + if self.request.has_key("NewFolderName"): + newFolder = self.request.get("NewFolderName", None) + newFolder = sanitizeFolderName (newFolder) + try: + newFolderPath = mapServerFolder(self.userFilesFolder, combinePaths(currentFolder, newFolder)) + self.createServerFolder(newFolderPath) + except Exception, e: + errorMsg = str(e).decode('iso-8859-1').encode('utf-8') # warning with encodigns!!! + if hasattr(e,'errno'): + if e.errno==17: #file already exists + errorNo=0 + elif e.errno==13: # permission denied + errorNo = 103 + elif e.errno==36 or e.errno==2 or e.errno==22: # filename too long / no such file / invalid name + errorNo = 102 + else: + errorNo = 110 + else: + errorNo = 102 + return self.sendErrorNode ( errorNo, errorMsg ) + + def createServerFolder(self, folderPath): + "Purpose: physically creates a folder on the server" + # No need to check if the parent exists, just create all hierachy + + try: + permissions = Config.ChmodOnFolderCreate + if not permissions: + os.makedirs(folderPath) + except AttributeError: #ChmodOnFolderCreate undefined + permissions = 0755 + + if permissions: + oldumask = os.umask(0) + os.makedirs(folderPath,mode=0755) + os.umask( oldumask ) + +class UploadFileCommandMixin (object): + def uploadFile(self, resourceType, currentFolder): + """ + Purpose: command to upload files to server (same as FileUpload) + """ + errorNo = 0 + if self.request.has_key("NewFile"): + # newFile has all the contents we need + newFile = self.request.get("NewFile", "") + # Get the file name + newFileName = newFile.filename + newFileName = sanitizeFileName( newFileName ) + newFileNameOnly = removeExtension(newFileName) + newFileExtension = getExtension(newFileName).lower() + allowedExtensions = Config.AllowedExtensions[resourceType] + deniedExtensions = Config.DeniedExtensions[resourceType] + + if (allowedExtensions): + # Check for allowed + isAllowed = False + if (newFileExtension in allowedExtensions): + isAllowed = True + elif (deniedExtensions): + # Check for denied + isAllowed = True + if (newFileExtension in deniedExtensions): + isAllowed = False + else: + # No extension limitations + isAllowed = True + + if (isAllowed): + # Upload to operating system + # Map the virtual path to the local server path + currentFolderPath = mapServerFolder(self.userFilesFolder, currentFolder) + i = 0 + while (True): + newFilePath = os.path.join (currentFolderPath,newFileName) + if os.path.exists(newFilePath): + i += 1 + newFileName = "%s(%04d).%s" % ( + newFileNameOnly, i, newFileExtension + ) + errorNo= 201 # file renamed + else: + # Read file contents and write to the desired path (similar to php's move_uploaded_file) + fout = file(newFilePath, 'wb') + while (True): + chunk = newFile.file.read(100000) + if not chunk: break + fout.write (chunk) + fout.close() + + if os.path.exists ( newFilePath ): + doChmod = False + try: + doChmod = Config.ChmodOnUpload + permissions = Config.ChmodOnUpload + except AttributeError: #ChmodOnUpload undefined + doChmod = True + permissions = 0755 + if ( doChmod ): + oldumask = os.umask(0) + os.chmod( newFilePath, permissions ) + os.umask( oldumask ) + + newFileUrl = self.webUserFilesFolder + currentFolder + newFileName + + return self.sendUploadResults( errorNo , newFileUrl, newFileName ) + else: + return self.sendUploadResults( errorNo = 203, customMsg = "Extension not allowed" ) + else: + return self.sendUploadResults( errorNo = 202, customMsg = "No File" ) Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/fckconnector.py =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/fckconnector.py (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/fckconnector.py 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,90 @@ +#!/usr/bin/env python + +""" +FCKeditor - The text editor for Internet - http://www.fckeditor.net +Copyright (C) 2003-2008 Frederico Caldeira Knabben + +== BEGIN LICENSE == + +Licensed under the terms of any of the following licenses at your +choice: + +- GNU General Public License Version 2 or later (the "GPL") +http://www.gnu.org/licenses/gpl.html + +- GNU Lesser General Public License Version 2.1 or later (the "LGPL") +http://www.gnu.org/licenses/lgpl.html + +- Mozilla Public License Version 1.1 or later (the "MPL") +http://www.mozilla.org/MPL/MPL-1.1.html + +== END LICENSE == + +Base Connector for Python (CGI and WSGI). + +See config.py for configuration settings + +""" +import cgi, os + +from fckutil import * +from fckcommands import * # default command's implementation +from fckoutput import * # base http, xml and html output mixins +import config as Config + +class FCKeditorConnectorBase( object ): + "The base connector class. Subclass it to extend functionality (see Zope example)" + + def __init__(self, environ=None): + "Constructor: Here you should parse request fields, initialize variables, etc." + self.request = FCKeditorRequest(environ) # Parse request + self.headers = [] # Clean Headers + if environ: + self.environ = environ + else: + self.environ = os.environ + + # local functions + + def setHeader(self, key, value): + self.headers.append ((key, value)) + return + +class FCKeditorRequest(object): + "A wrapper around the request object" + def __init__(self, environ): + if environ: # WSGI + self.request = cgi.FieldStorage(fp=environ['wsgi.input'], + environ=environ, + keep_blank_values=1) + self.environ = environ + else: # plain old cgi + self.environ = os.environ + self.request = cgi.FieldStorage() + if 'REQUEST_METHOD' in self.environ and 'QUERY_STRING' in self.environ: + if self.environ['REQUEST_METHOD'].upper()=='POST': + # we are in a POST, but GET query_string exists + # cgi parses by default POST data, so parse GET QUERY_STRING too + self.get_request = cgi.FieldStorage(fp=None, + environ={ + 'REQUEST_METHOD':'GET', + 'QUERY_STRING':self.environ['QUERY_STRING'], + }, + ) + else: + self.get_request={} + + def has_key(self, key): + return self.request.has_key(key) or self.get_request.has_key(key) + + def get(self, key, default=None): + if key in self.request.keys(): + field = self.request[key] + elif key in self.get_request.keys(): + field = self.get_request[key] + else: + return default + if hasattr(field,"filename") and field.filename: #file upload, do not convert return value + return field + else: + return field.value Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/fckoutput.py =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/fckoutput.py (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/fckoutput.py 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,142 @@ +#!/usr/bin/env python + +""" +FCKeditor - The text editor for Internet - http://www.fckeditor.net +Copyright (C) 2003-2008 Frederico Caldeira Knabben + +== BEGIN LICENSE == + +Licensed under the terms of any of the following licenses at your +choice: + +- GNU General Public License Version 2 or later (the "GPL") +http://www.gnu.org/licenses/gpl.html + +- GNU Lesser General Public License Version 2.1 or later (the "LGPL") +http://www.gnu.org/licenses/lgpl.html + +- Mozilla Public License Version 1.1 or later (the "MPL") +http://www.mozilla.org/MPL/MPL-1.1.html + +== END LICENSE == + +Connector for Python (CGI and WSGI). + +""" + +from time import gmtime, strftime +import string + +def escape(text, replace=string.replace): + """ + Converts the special characters '<', '>', and '&'. + + RFC 1866 specifies that these characters be represented + in HTML as < > and & respectively. In Python + 1.5 we use the new string.replace() function for speed. + """ + text = replace(text, '&', '&') # must be done 1st + text = replace(text, '<', '<') + text = replace(text, '>', '>') + text = replace(text, '"', '"') + return text + +def convertToXmlAttribute(value): + if (value is None): + value = "" + return escape(value) + +class BaseHttpMixin(object): + def setHttpHeaders(self, content_type='text/xml'): + "Purpose: to prepare the headers for the xml to return" + # Prevent the browser from caching the result. + # Date in the past + self.setHeader('Expires','Mon, 26 Jul 1997 05:00:00 GMT') + # always modified + self.setHeader('Last-Modified',strftime("%a, %d %b %Y %H:%M:%S GMT", gmtime())) + # HTTP/1.1 + self.setHeader('Cache-Control','no-store, no-cache, must-revalidate') + self.setHeader('Cache-Control','post-check=0, pre-check=0') + # HTTP/1.0 + self.setHeader('Pragma','no-cache') + + # Set the response format. + self.setHeader( 'Content-Type', content_type + '; charset=utf-8' ) + return + +class BaseXmlMixin(object): + def createXmlHeader(self, command, resourceType, currentFolder, url): + "Purpose: returns the xml header" + self.setHttpHeaders() + # Create the XML document header + s = """<?xml version="1.0" encoding="utf-8" ?>""" + # Create the main connector node + s += """<Connector command="%s" resourceType="%s">""" % ( + command, + resourceType + ) + # Add the current folder node + s += """<CurrentFolder path="%s" url="%s" />""" % ( + convertToXmlAttribute(currentFolder), + convertToXmlAttribute(url), + ) + return s + + def createXmlFooter(self): + "Purpose: returns the xml footer" + return """</Connector>""" + + def sendError(self, number, text): + "Purpose: in the event of an error, return an xml based error" + self.setHttpHeaders() + return ("""<?xml version="1.0" encoding="utf-8" ?>""" + + """<Connector>""" + + self.sendErrorNode (number, text) + + """</Connector>""" ) + + def sendErrorNode(self, number, text): + return """<Error number="%s" text="%s" />""" % (number, convertToXmlAttribute(text)) + +class BaseHtmlMixin(object): + def sendUploadResults( self, errorNo = 0, fileUrl = '', fileName = '', customMsg = '' ): + self.setHttpHeaders("text/html") + "This is the function that sends the results of the uploading process" + return """<script type="text/javascript"> + (function() + { + var d = document.domain ; + + while ( true ) + { + // Test if we can access a parent property. + try + { + var test = window.top.opener.document.domain ; + break ; + } + catch( e ) {} + + // Remove a domain part: www.mytest.example.com => mytest.example.com => example.com ... + d = d.replace( /.*?(?:\.|$)/, '' ) ; + + if ( d.length == 0 ) + break ; // It was not able to detect the domain. + + try + { + document.domain = d ; + } + catch (e) + { + break ; + } + } + })() ; + + window.parent.OnUploadCompleted(%(errorNumber)s,"%(fileUrl)s","%(fileName)s","%(customMsg)s"); + </script>""" % { + 'errorNumber': errorNo, + 'fileUrl': fileUrl.replace ('"', '\\"'), + 'fileName': fileName.replace ( '"', '\\"' ) , + 'customMsg': customMsg.replace ( '"', '\\"' ), + } Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/fckutil.py =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/fckutil.py (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/fckutil.py 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,126 @@ +#!/usr/bin/env python + +""" +FCKeditor - The text editor for Internet - http://www.fckeditor.net +Copyright (C) 2003-2008 Frederico Caldeira Knabben + +== BEGIN LICENSE == + +Licensed under the terms of any of the following licenses at your +choice: + +- GNU General Public License Version 2 or later (the "GPL") +http://www.gnu.org/licenses/gpl.html + +- GNU Lesser General Public License Version 2.1 or later (the "LGPL") +http://www.gnu.org/licenses/lgpl.html + +- Mozilla Public License Version 1.1 or later (the "MPL") +http://www.mozilla.org/MPL/MPL-1.1.html + +== END LICENSE == + +Utility functions for the File Manager Connector for Python + +""" + +import string, re +import os +import config as Config + +# Generic manipulation functions + +def removeExtension(fileName): + index = fileName.rindex(".") + newFileName = fileName[0:index] + return newFileName + +def getExtension(fileName): + index = fileName.rindex(".") + 1 + fileExtension = fileName[index:] + return fileExtension + +def removeFromStart(string, char): + return string.lstrip(char) + +def removeFromEnd(string, char): + return string.rstrip(char) + +# Path functions + +def combinePaths( basePath, folder ): + return removeFromEnd( basePath, '/' ) + '/' + removeFromStart( folder, '/' ) + +def getFileName(filename): + " Purpose: helper function to extrapolate the filename " + for splitChar in ["/", "\\"]: + array = filename.split(splitChar) + if (len(array) > 1): + filename = array[-1] + return filename + +def sanitizeFolderName( newFolderName ): + "Do a cleanup of the folder name to avoid possible problems" + # Remove . \ / | : ? * " < > and control characters + return re.sub( '(?u)\\.|\\\\|\\/|\\||\\:|\\?|\\*|"|<|>|[^\u0000-\u001f\u007f-\u009f]', '_', newFolderName ) + +def sanitizeFileName( newFileName ): + "Do a cleanup of the file name to avoid possible problems" + # Replace dots in the name with underscores (only one dot can be there... security issue). + if ( Config.ForceSingleExtension ): # remove dots + newFileName = re.sub ( '/\\.(?![^.]*$)/', '_', newFileName ) ; + newFileName = newFileName.replace('\\','/') # convert windows to unix path + newFileName = os.path.basename (newFileName) # strip directories + # Remove \ / | : ? * + return re.sub ( '(?u)/\\\\|\\/|\\||\\:|\\?|\\*|"|<|>|[^\u0000-\u001f\u007f-\u009f]/', '_', newFileName ) + +def getCurrentFolder(currentFolder): + if not currentFolder: + currentFolder = '/' + + # Check the current folder syntax (must begin and end with a slash). + if (currentFolder[-1] <> "/"): + currentFolder += "/" + if (currentFolder[0] <> "/"): + currentFolder = "/" + currentFolder + + # Ensure the folder path has no double-slashes + while '//' in currentFolder: + currentFolder = currentFolder.replace('//','/') + + # Check for invalid folder paths (..) + if '..' in currentFolder or '\\' in currentFolder: + return None + + return currentFolder + +def mapServerPath( environ, url): + " Emulate the asp Server.mapPath function. Given an url path return the physical directory that it corresponds to " + # This isn't correct but for the moment there's no other solution + # If this script is under a virtual directory or symlink it will detect the problem and stop + return combinePaths( getRootPath(environ), url ) + +def mapServerFolder(resourceTypePath, folderPath): + return combinePaths ( resourceTypePath , folderPath ) + +def getRootPath(environ): + "Purpose: returns the root path on the server" + # WARNING: this may not be thread safe, and doesn't work w/ VirtualServer/mod_python + # Use Config.UserFilesAbsolutePath instead + + if environ.has_key('DOCUMENT_ROOT'): + return environ['DOCUMENT_ROOT'] + else: + realPath = os.path.realpath( './' ) + selfPath = environ['SCRIPT_FILENAME'] + selfPath = selfPath [ : selfPath.rfind( '/' ) ] + selfPath = selfPath.replace( '/', os.path.sep) + + position = realPath.find(selfPath) + + # This can check only that this script isn't run from a virtual dir + # But it avoids the problems that arise if it isn't checked + raise realPath + if ( position < 0 or position <> len(realPath) - len(selfPath) or realPath[ : position ]==''): + raise Exception('Sorry, can\'t map "UserFilesPath" to a physical path. You must set the "UserFilesAbsolutePath" value in "editor/filemanager/connectors/py/config.py".') + return realPath[ : position ] Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/htaccess.txt =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/htaccess.txt (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/htaccess.txt 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,23 @@ +# replace the name of this file to .htaccess (if using apache), +# and set the proper options and paths according your enviroment + +Allow from all + +# If using mod_python uncomment this: +PythonPath "[r'C:\Archivos de programa\Apache Software Foundation\Apache2.2\htdocs\fckeditor\editor\filemanager\connectors\py'] + sys.path" + + +# Recomended: WSGI application running with mod_python and modpython_gateway +SetHandler python-program +PythonHandler modpython_gateway::handler +PythonOption wsgi.application wsgi::App + + +# Emulated CGI with mod_python and cgihandler +#AddHandler mod_python .py +#PythonHandler mod_python.cgihandler + + +# Plain old CGI +#Options +ExecCGI +#AddHandler cgi-script py Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/upload.py =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/upload.py (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/upload.py 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,88 @@ +#!/usr/bin/env python + +""" +FCKeditor - The text editor for Internet - http://www.fckeditor.net +Copyright (C) 2003-2008 Frederico Caldeira Knabben + +== BEGIN LICENSE == + +Licensed under the terms of any of the following licenses at your +choice: + +- GNU General Public License Version 2 or later (the "GPL") +http://www.gnu.org/licenses/gpl.html + +- GNU Lesser General Public License Version 2.1 or later (the "LGPL") +http://www.gnu.org/licenses/lgpl.html + +- Mozilla Public License Version 1.1 or later (the "MPL") +http://www.mozilla.org/MPL/MPL-1.1.html + +== END LICENSE == + +This is the "File Uploader" for Python + +""" +import os + +from fckutil import * +from fckcommands import * # default command's implementation +from fckconnector import FCKeditorConnectorBase # import base connector +import config as Config + +class FCKeditorQuickUpload( FCKeditorConnectorBase, + UploadFileCommandMixin, + BaseHttpMixin, BaseHtmlMixin): + def doResponse(self): + "Main function. Process the request, set headers and return a string as response." + # Check if this connector is disabled + if not(Config.Enabled): + return self.sendUploadResults(1, "This file uploader is disabled. Please check the \"editor/filemanager/connectors/py/config.py\"") + command = 'QuickUpload' + # The file type (from the QueryString, by default 'File'). + resourceType = self.request.get('Type','File') + currentFolder = getCurrentFolder(self.request.get("CurrentFolder","")) + # Check for invalid paths + if currentFolder is None: + return self.sendUploadResults(102, '', '', "") + + # Check if it is an allowed command + if ( not command in Config.ConfigAllowedCommands ): + return self.sendUploadResults( 1, '', '', 'The %s command isn\'t allowed' % command ) + + if ( not resourceType in Config.ConfigAllowedTypes ): + return self.sendUploadResults( 1, '', '', 'Invalid type specified' ) + + # Setup paths + self.userFilesFolder = Config.QuickUploadAbsolutePath[resourceType] + self.webUserFilesFolder = Config.QuickUploadPath[resourceType] + if not self.userFilesFolder: # no absolute path given (dangerous...) + self.userFilesFolder = mapServerPath(self.environ, + self.webUserFilesFolder) + + # Ensure that the directory exists. + if not os.path.exists(self.userFilesFolder): + try: + self.createServerFoldercreateServerFolder( self.userFilesFolder ) + except: + return self.sendError(1, "This connector couldn\'t access to local user\'s files directories. Please check the UserFilesAbsolutePath in \"editor/filemanager/connectors/py/config.py\" and try again. ") + + # File upload doesn't have to return XML, so intercept here + return self.uploadFile(resourceType, currentFolder) + +# Running from command line (plain old CGI) +if __name__ == '__main__': + try: + # Create a Connector Instance + conn = FCKeditorQuickUpload() + data = conn.doResponse() + for header in conn.headers: + if not header is None: + print '%s: %s' % header + print + print data + except: + print "Content-Type: text/plain" + print + import cgi + cgi.print_exception() Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/wsgi.py =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/wsgi.py (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/wsgi.py 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,58 @@ +#!/usr/bin/env python + +""" +FCKeditor - The text editor for Internet - http://www.fckeditor.net +Copyright (C) 2003-2008 Frederico Caldeira Knabben + +== BEGIN LICENSE == + +Licensed under the terms of any of the following licenses at your +choice: + + - GNU General Public License Version 2 or later (the "GPL") + http://www.gnu.org/licenses/gpl.html + + - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + http://www.gnu.org/licenses/lgpl.html + + - Mozilla Public License Version 1.1 or later (the "MPL") + http://www.mozilla.org/MPL/MPL-1.1.html + +== END LICENSE == + +Connector/QuickUpload for Python (WSGI wrapper). + +See config.py for configuration settings + +""" + +from connector import FCKeditorConnector +from upload import FCKeditorQuickUpload + +import cgitb +from cStringIO import StringIO + +# Running from WSGI capable server (recomended) +def App(environ, start_response): + "WSGI entry point. Run the connector" + if environ['SCRIPT_NAME'].endswith("connector.py"): + conn = FCKeditorConnector(environ) + elif environ['SCRIPT_NAME'].endswith("upload.py"): + conn = FCKeditorQuickUpload(environ) + else: + start_response ("200 Ok", [('Content-Type','text/html')]) + yield "Unknown page requested: " + yield environ['SCRIPT_NAME'] + return + try: + # run the connector + data = conn.doResponse() + # Start WSGI response: + start_response ("200 Ok", conn.headers) + # Send response text + yield data + except: + start_response("500 Internal Server Error",[("Content-type","text/html")]) + file = StringIO() + cgitb.Hook(file = file).handle() + yield file.getvalue() Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/zope.py =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/zope.py (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/py/zope.py 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,188 @@ +#!/usr/bin/env python + +""" +FCKeditor - The text editor for Internet - http://www.fckeditor.net +Copyright (C) 2003-2008 Frederico Caldeira Knabben + +== BEGIN LICENSE == + +Licensed under the terms of any of the following licenses at your +choice: + +- GNU General Public License Version 2 or later (the "GPL") +http://www.gnu.org/licenses/gpl.html + +- GNU Lesser General Public License Version 2.1 or later (the "LGPL") +http://www.gnu.org/licenses/lgpl.html + +- Mozilla Public License Version 1.1 or later (the "MPL") +http://www.mozilla.org/MPL/MPL-1.1.html + +== END LICENSE == + +Connector for Python and Zope. + +This code was not tested at all. +It just was ported from pre 2.5 release, so for further reference see +\editor\filemanager\browser\default\connectors\py\connector.py in previous +releases. + +""" + +from fckutil import * +from connector import * +import config as Config + +class FCKeditorConnectorZope(FCKeditorConnector): + """ + Zope versiof FCKeditorConnector + """ + # Allow access (Zope) + __allow_access_to_unprotected_subobjects__ = 1 + + def __init__(self, context=None): + """ + Constructor + """ + FCKeditorConnector.__init__(self, environ=None) # call superclass constructor + # Instance Attributes + self.context = context + self.request = FCKeditorRequest(context) + + def getZopeRootContext(self): + if self.zopeRootContext is None: + self.zopeRootContext = self.context.getPhysicalRoot() + return self.zopeRootContext + + def getZopeUploadContext(self): + if self.zopeUploadContext is None: + folderNames = self.userFilesFolder.split("/") + c = self.getZopeRootContext() + for folderName in folderNames: + if (folderName <> ""): + c = c[folderName] + self.zopeUploadContext = c + return self.zopeUploadContext + + def setHeader(self, key, value): + self.context.REQUEST.RESPONSE.setHeader(key, value) + + def getFolders(self, resourceType, currentFolder): + # Open the folders node + s = "" + s += """<Folders>""" + zopeFolder = self.findZopeFolder(resourceType, currentFolder) + for (name, o) in zopeFolder.objectItems(["Folder"]): + s += """<Folder name="%s" />""" % ( + convertToXmlAttribute(name) + ) + # Close the folders node + s += """</Folders>""" + return s + + def getZopeFoldersAndFiles(self, resourceType, currentFolder): + folders = self.getZopeFolders(resourceType, currentFolder) + files = self.getZopeFiles(resourceType, currentFolder) + s = folders + files + return s + + def getZopeFiles(self, resourceType, currentFolder): + # Open the files node + s = "" + s += """<Files>""" + zopeFolder = self.findZopeFolder(resourceType, currentFolder) + for (name, o) in zopeFolder.objectItems(["File","Image"]): + s += """<File name="%s" size="%s" />""" % ( + convertToXmlAttribute(name), + ((o.get_size() / 1024) + 1) + ) + # Close the files node + s += """</Files>""" + return s + + def findZopeFolder(self, resourceType, folderName): + # returns the context of the resource / folder + zopeFolder = self.getZopeUploadContext() + folderName = self.removeFromStart(folderName, "/") + folderName = self.removeFromEnd(folderName, "/") + if (resourceType <> ""): + try: + zopeFolder = zopeFolder[resourceType] + except: + zopeFolder.manage_addProduct["OFSP"].manage_addFolder(id=resourceType, title=resourceType) + zopeFolder = zopeFolder[resourceType] + if (folderName <> ""): + folderNames = folderName.split("/") + for folderName in folderNames: + zopeFolder = zopeFolder[folderName] + return zopeFolder + + def createFolder(self, resourceType, currentFolder): + # Find out where we are + zopeFolder = self.findZopeFolder(resourceType, currentFolder) + errorNo = 0 + errorMsg = "" + if self.request.has_key("NewFolderName"): + newFolder = self.request.get("NewFolderName", None) + zopeFolder.manage_addProduct["OFSP"].manage_addFolder(id=newFolder, title=newFolder) + else: + errorNo = 102 + return self.sendErrorNode ( errorNo, errorMsg ) + + def uploadFile(self, resourceType, currentFolder, count=None): + zopeFolder = self.findZopeFolder(resourceType, currentFolder) + file = self.request.get("NewFile", None) + fileName = self.getFileName(file.filename) + fileNameOnly = self.removeExtension(fileName) + fileExtension = self.getExtension(fileName).lower() + if (count): + nid = "%s.%s.%s" % (fileNameOnly, count, fileExtension) + else: + nid = fileName + title = nid + try: + zopeFolder.manage_addProduct['OFSP'].manage_addFile( + id=nid, + title=title, + file=file.read() + ) + except: + if (count): + count += 1 + else: + count = 1 + return self.zopeFileUpload(resourceType, currentFolder, count) + return self.sendUploadResults( 0 ) + +class FCKeditorRequest(object): + "A wrapper around the request object" + def __init__(self, context=None): + r = context.REQUEST + self.request = r + + def has_key(self, key): + return self.request.has_key(key) + + def get(self, key, default=None): + return self.request.get(key, default) + +""" +Running from zope, you will need to modify this connector. +If you have uploaded the FCKeditor into Zope (like me), you need to +move this connector out of Zope, and replace the "connector" with an +alias as below. The key to it is to pass the Zope context in, as +we then have a like to the Zope context. + +## Script (Python) "connector.py" +##bind container=container +##bind context=context +##bind namespace= +##bind script=script +##bind subpath=traverse_subpath +##parameters=*args, **kws +##title=ALIAS +## + +import Products.zope as connector +return connector.FCKeditorConnectorZope(context=context).doResponse() +""" Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/test.html =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/test.html (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/test.html 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,210 @@ +<!-- + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Test page for the File Browser connectors. +--> +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>FCKeditor - Connectors Tests</title> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + <script type="text/javascript"> + +// Automatically detect the correct document.domain (#1919). +(function() +{ + var d = document.domain ; + + while ( true ) + { + // Test if we can access a parent property. + try + { + var test = window.opener.document.domain ; + break ; + } + catch( e ) {} + + // Remove a domain part: www.mytest.example.com => mytest.example.com => example.com ... + d = d.replace( /.*?(?:\.|$)/, '' ) ; + + if ( d.length == 0 ) + break ; // It was not able to detect the domain. + + try + { + document.domain = d ; + } + catch (e) + { + break ; + } + } +})() ; + +function BuildBaseUrl( command ) +{ + var sUrl = + document.getElementById('cmbConnector').value + + '?Command=' + command + + '&Type=' + document.getElementById('cmbType').value + + '&CurrentFolder=' + encodeURIComponent(document.getElementById('txtFolder').value) ; + + return sUrl ; +} + +function SetFrameUrl( url ) +{ + document.getElementById('eRunningFrame').src = url ; + + document.getElementById('eUrl').innerHTML = url ; +} + +function GetFolders() +{ + SetFrameUrl( BuildBaseUrl( 'GetFolders' ) ) ; + return false ; +} + +function GetFoldersAndFiles() +{ + SetFrameUrl( BuildBaseUrl( 'GetFoldersAndFiles' ) ) ; + return false ; +} + +function CreateFolder() +{ + var sFolder = prompt( 'Type the folder name:', 'Test Folder' ) ; + + if ( ! sFolder ) + return false ; + + var sUrl = BuildBaseUrl( 'CreateFolder' ) ; + sUrl += '&NewFolderName=' + encodeURIComponent( sFolder ) ; + + SetFrameUrl( sUrl ) ; + return false ; +} + +function OnUploadCompleted( errorNumber, fileName ) +{ + switch ( errorNumber ) + { + case 0 : + alert( 'File uploaded with no errors' ) ; + break ; + case 201 : + GetFoldersAndFiles() ; + alert( 'A file with the same name is already available. The uploaded file has been renamed to "' + fileName + '"' ) ; + break ; + case 202 : + alert( 'Invalid file' ) ; + break ; + default : + alert( 'Error on file upload. Error number: ' + errorNumber ) ; + break ; + } +} + +this.frames.frmUpload = this ; + +function SetAction() +{ + var sUrl = BuildBaseUrl( 'FileUpload' ) ; + document.getElementById('eUrl').innerHTML = sUrl ; + document.getElementById('frmUpload').action = sUrl ; +} + + </script> +</head> +<body> + <table height="100%" cellspacing="0" cellpadding="0" width="100%" border="0"> + <tr> + <td> + <table cellspacing="0" cellpadding="0" border="0"> + <tr> + <td> + Connector:<br /> + <select id="cmbConnector" name="cmbConnector"> + <option value="asp/connector.asp" selected="selected">ASP</option> + <option value="aspx/connector.aspx">ASP.Net</option> + <option value="cfm/connector.cfm">ColdFusion</option> + <option value="lasso/connector.lasso">Lasso</option> + <option value="perl/connector.cgi">Perl</option> + <option value="php/connector.php">PHP</option> + <option value="py/connector.py">Python</option> + </select> + </td> + <td> + </td> + <td> + Current Folder<br /> + <input id="txtFolder" type="text" value="/" name="txtFolder" /></td> + <td> + </td> + <td> + Resource Type<br /> + <select id="cmbType" name="cmbType"> + <option value="File" selected="selected">File</option> + <option value="Image">Image</option> + <option value="Flash">Flash</option> + <option value="Media">Media</option> + <option value="Invalid">Invalid Type (for testing)</option> + </select> + </td> + </tr> + </table> + <br /> + <table cellspacing="0" cellpadding="0" border="0"> + <tr> + <td valign="top"> + <a href="#" onclick="GetFolders();">Get Folders</a></td> + <td> + </td> + <td valign="top"> + <a href="#" onclick="GetFoldersAndFiles();">Get Folders and Files</a></td> + <td> + </td> + <td valign="top"> + <a href="#" onclick="CreateFolder();">Create Folder</a></td> + <td> + </td> + <td valign="top"> + <form id="frmUpload" action="" target="eRunningFrame" method="post" enctype="multipart/form-data"> + File Upload<br /> + <input id="txtFileUpload" type="file" name="NewFile" /> + <input type="submit" value="Upload" onclick="SetAction();" /> + </form> + </td> + </tr> + </table> + <br /> + URL: <span id="eUrl"></span> + </td> + </tr> + <tr> + <td height="100%" valign="top"> + <iframe id="eRunningFrame" src="javascript:void(0)" name="eRunningFrame" width="100%" + height="100%"></iframe> + </td> + </tr> + </table> +</body> +</html> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/uploadtest.html =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/uploadtest.html (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/filemanager/connectors/uploadtest.html 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,192 @@ +<!-- + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Test page for the "File Uploaders". +--> +<html> + <head> + <title>FCKeditor - Uploaders Tests</title> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + <script type="text/javascript"> + +// Automatically detect the correct document.domain (#1919). +(function() +{ + var d = document.domain ; + + while ( true ) + { + // Test if we can access a parent property. + try + { + var test = window.opener.document.domain ; + break ; + } + catch( e ) {} + + // Remove a domain part: www.mytest.example.com => mytest.example.com => example.com ... + d = d.replace( /.*?(?:\.|$)/, '' ) ; + + if ( d.length == 0 ) + break ; // It was not able to detect the domain. + + try + { + document.domain = d ; + } + catch (e) + { + break ; + } + } +})() ; + +function SendFile() +{ + var sUploaderUrl = cmbUploaderUrl.value ; + + if ( sUploaderUrl.length == 0 ) + sUploaderUrl = txtCustomUrl.value ; + + if ( sUploaderUrl.length == 0 ) + { + alert( 'Please provide your custom URL or select a default one' ) ; + return ; + } + + eURL.innerHTML = sUploaderUrl ; + txtUrl.value = '' ; + + var date = new Date() + + frmUpload.action = sUploaderUrl + '?time=' + date.getTime(); + if (document.getElementById('cmbType').value) { + frmUpload.action = frmUpload.action + '&Type='+document.getElementById('cmbType').value; + } + if (document.getElementById('CurrentFolder').value) { + frmUpload.action = frmUpload.action + '&CurrentFolder='+document.getElementById('CurrentFolder').value; + } + frmUpload.submit() ; +} + +function OnUploadCompleted( errorNumber, fileUrl, fileName, customMsg ) +{ + switch ( errorNumber ) + { + case 0 : // No errors + txtUrl.value = fileUrl ; + alert( 'File uploaded with no errors' ) ; + break ; + case 1 : // Custom error + alert( customMsg ) ; + break ; + case 10 : // Custom warning + txtUrl.value = fileUrl ; + alert( customMsg ) ; + break ; + case 201 : + txtUrl.value = fileUrl ; + alert( 'A file with the same name is already available. The uploaded file has been renamed to "' + fileName + '"' ) ; + break ; + case 202 : + alert( 'Invalid file' ) ; + break ; + case 203 : + alert( "Security error. You probably don't have enough permissions to upload. Please check your server." ) ; + break ; + default : + alert( 'Error on file upload. Error number: ' + errorNumber ) ; + break ; + } +} + + </script> + </head> + <body> + <table cellSpacing="0" cellPadding="0" width="100%" border="0" height="100%"> + <tr> + <td> + <table cellSpacing="0" cellPadding="0" width="100%" border="0"> + <tr> + <td nowrap> + Select the "File Uploader" to use: <br> + <select id="cmbUploaderUrl"> + <option selected value="asp/upload.asp">ASP</option> + <option value="aspx/upload.aspx">ASP.Net</option> + <option value="cfm/upload.cfm">ColdFusion</option> + <option value="lasso/upload.lasso">Lasso</option> + <option value="perl/upload.cgi">Perl</option> + <option value="php/upload.php">PHP</option> + <option value="py/upload.py">Python</option> + <option value="">(Custom)</option> + </select> + </td> + <td> + Resource Type<br /> + <select id="cmbType" name="cmbType"> + <option value="">None</option> + <option value="File">File</option> + <option value="Image">Image</option> + <option value="Flash">Flash</option> + <option value="Media">Media</option> + <option value="Invalid">Invalid Type (for testing)</option> + </select> + </td> + <td> + Current Folder: <br> + <input type="text" name="CurrentFolder" id="CurrentFolder" value="/"> + </td> + <td nowrap> </td> + <td width="100%"> + Custom Uploader URL:<BR> + <input id="txtCustomUrl" style="WIDTH: 100%; BACKGROUND-COLOR: #dcdcdc" disabled type="text"> + </td> + </tr> + </table> + <br> + <table cellSpacing="0" cellPadding="0" width="100%" border="0"> + <tr> + <td noWrap> + <form id="frmUpload" target="UploadWindow" enctype="multipart/form-data" action="" method="post"> + Upload a new file:<br> + <input type="file" name="NewFile"><br> + + <input type="button" value="Send it to the Server" onclick="SendFile();"> + </form> + </td> + <td style="WIDTH: 16px"> </td> + <td vAlign="top" width="100%"> + Uploaded File URL:<br> + <INPUT id="txtUrl" style="WIDTH: 100%" readonly type="text"> + </td> + </tr> + </table> + <br> + Post URL: <span id="eURL"> </span> + </td> + </tr> + <tr> + <td height="100%"> + <iframe name="UploadWindow" width="100%" height="100%" src="javascript:void(0)"></iframe> + </td> + </tr> + </table> + </body> +</html> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/angel_smile.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/angel_smile.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/angry_smile.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/angry_smile.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/broken_heart.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/broken_heart.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/cake.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/cake.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/confused_smile.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/confused_smile.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/cry_smile.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/cry_smile.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/devil_smile.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/devil_smile.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/embaressed_smile.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/embaressed_smile.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/envelope.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/envelope.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/heart.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/heart.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/kiss.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/kiss.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/lightbulb.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/lightbulb.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/omg_smile.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/omg_smile.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/regular_smile.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/regular_smile.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/sad_smile.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/sad_smile.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/shades_smile.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/shades_smile.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/teeth_smile.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/teeth_smile.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/thumbs_down.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/thumbs_down.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/thumbs_up.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/thumbs_up.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/tounge_smile.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/tounge_smile.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/whatchutalkingabout_smile.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/whatchutalkingabout_smile.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/wink_smile.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/images/smiley/msn/wink_smile.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/plugins/bbcode/_sample/sample.config.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/plugins/bbcode/_sample/sample.config.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/plugins/bbcode/_sample/sample.config.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,26 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Sample custom configuration settings used by the BBCode plugin. It simply + * loads the plugin. All the rest is done by the plugin itself. + */ + +// Add the BBCode plugin. +FCKConfig.Plugins.Add( 'bbcode' ) ; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/plugins/bbcode/_sample/sample.html =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/plugins/bbcode/_sample/sample.html (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/plugins/bbcode/_sample/sample.html 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,67 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<!-- + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Sample page. +--> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>FCKeditor - BBCode Sample</title> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <meta name="robots" content="noindex, nofollow" /> + <link href="../../../../_samples/sample.css" rel="stylesheet" type="text/css" /> + <script type="text/javascript" src="../../../../fckeditor.js"></script> +</head> +<body> + <h1> + FCKeditor - BBCode Sample</h1> + <p> + This is a sample of custom Data Processor implementation for (very) basic BBCode + syntax. Only <strong>[b]</strong>, <strong>[i]</strong>, <strong>[u]</strong> and + <strong>[url]</strong> may be used. It may be extended, but this is out of this + sample purpose. + </p> + <p> + Note that the input and output of the editor is not HTML, but BBCode + </p> + <hr /> + <form action="../../../../_samples/html/sampleposteddata.asp" method="post" target="_blank"> + <script type="text/javascript"> +<!-- +// Automatically calculates the editor base path based on the _samples directory. +// This is usefull only for these samples. A real application should use something like this: +// oFCKeditor.BasePath = '/fckeditor/' ; // '/fckeditor/' is the default value. +var sBasePath = document.location.pathname.substring(0,document.location.pathname.lastIndexOf('editor')) ; + +var oFCKeditor = new FCKeditor( 'FCKeditor1' ) ; +oFCKeditor.BasePath = sBasePath ; + +// Set the custom configurations file path (in this way the original file is mantained). +oFCKeditor.Config['CustomConfigurationsPath'] = sBasePath + 'editor/plugins/bbcode/_sample/sample.config.js' ; + +oFCKeditor.Value = 'This is some [b]sample text[/b]. You are using [url=http://www.fckeditor.net/]FCKeditor[/url].' ; +oFCKeditor.Create() ; +//--> + </script> + <br /> + <input type="submit" value="Submit" /> + </form> +</body> +</html> Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/plugins/placeholder/lang/de.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/plugins/placeholder/lang/de.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/plugins/placeholder/lang/de.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,27 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Placholder German language file. + */ +FCKLang.PlaceholderBtn = 'Einfügen/editieren Platzhalter' ; +FCKLang.PlaceholderDlgTitle = 'Platzhalter Eigenschaften' ; +FCKLang.PlaceholderDlgName = 'Platzhalter Name' ; +FCKLang.PlaceholderErrNoName = 'Bitte den Namen des Platzhalters schreiben' ; +FCKLang.PlaceholderErrNameInUse = 'Der angegebene Namen ist schon in Gebrauch' ; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/plugins/placeholder/lang/en.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/plugins/placeholder/lang/en.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/plugins/placeholder/lang/en.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,27 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Placholder English language file. + */ +FCKLang.PlaceholderBtn = 'Insert/Edit Placeholder' ; +FCKLang.PlaceholderDlgTitle = 'Placeholder Properties' ; +FCKLang.PlaceholderDlgName = 'Placeholder Name' ; +FCKLang.PlaceholderErrNoName = 'Please type the placeholder name' ; +FCKLang.PlaceholderErrNameInUse = 'The specified name is already in use' ; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/plugins/placeholder/lang/es.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/plugins/placeholder/lang/es.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/plugins/placeholder/lang/es.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,27 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Placholder Spanish language file. + */ +FCKLang.PlaceholderBtn = 'Insertar/Editar contenedor' ; +FCKLang.PlaceholderDlgTitle = 'Propiedades del contenedor ' ; +FCKLang.PlaceholderDlgName = 'Nombre de contenedor' ; +FCKLang.PlaceholderErrNoName = 'Por favor escriba el nombre de contenedor' ; +FCKLang.PlaceholderErrNameInUse = 'El nombre especificado ya esta en uso' ; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/plugins/placeholder/lang/fr.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/plugins/placeholder/lang/fr.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/plugins/placeholder/lang/fr.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,27 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Placeholder French language file. + */ +FCKLang.PlaceholderBtn = "Insérer/Modifier l'Espace réservé" ; +FCKLang.PlaceholderDlgTitle = "Propriétés de l'Espace réservé" ; +FCKLang.PlaceholderDlgName = "Nom de l'Espace réservé" ; +FCKLang.PlaceholderErrNoName = "Veuillez saisir le nom de l'Espace réservé" ; +FCKLang.PlaceholderErrNameInUse = "Ce nom est déjà utilisé" ; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/plugins/placeholder/lang/it.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/plugins/placeholder/lang/it.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/plugins/placeholder/lang/it.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,27 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Placholder Italian language file. + */ +FCKLang.PlaceholderBtn = 'Aggiungi/Modifica Placeholder' ; +FCKLang.PlaceholderDlgTitle = 'Proprietà del Placeholder' ; +FCKLang.PlaceholderDlgName = 'Nome del Placeholder' ; +FCKLang.PlaceholderErrNoName = 'Digitare il nome del placeholder' ; +FCKLang.PlaceholderErrNameInUse = 'Il nome inserito è già in uso' ; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/plugins/placeholder/lang/pl.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/plugins/placeholder/lang/pl.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/plugins/placeholder/lang/pl.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,27 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Placholder Polish language file. + */ +FCKLang.PlaceholderBtn = 'Wstaw/Edytuj nagłówek' ; +FCKLang.PlaceholderDlgTitle = 'Właśności nagłówka' ; +FCKLang.PlaceholderDlgName = 'Nazwa nagłówka' ; +FCKLang.PlaceholderErrNoName = 'Proszę wprowadzić nazwę nagłówka' ; +FCKLang.PlaceholderErrNameInUse = 'Podana nazwa jest już w użyciu' ; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/fck_dialog.css =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/fck_dialog.css (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/fck_dialog.css 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,402 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Styles used by the dialog boxes. + */ + +html, body +{ + background-color: transparent; + margin: 0px; + padding: 0px; +} + +body +{ + padding: 10px; +} + +body, td, input, select, textarea +{ + font-size: 11px; + font-family: 'Microsoft Sans Serif' , Arial, Helvetica, Verdana; +} + +body, .BackColor +{ + background-color: #f1f1e3; +} + +.PopupBody +{ + height: 100%; + width: 100%; + overflow: hidden; + background-color: transparent; + padding: 0px; +} + +#header +{ + cursor: move; +} + +.PopupTitle +{ + font-weight: bold; + font-size: 14pt; + color: #737357; + background-color: #e3e3c7; + padding: 3px 10px 3px 10px; +} + +.PopupButtons +{ + position: absolute; + right: 0px; + left: 0px; + bottom: 0px; + border-top: #d5d59d 1px solid; + background-color: #e3e3c7; + padding: 7px 10px 7px 10px; +} + +.Button +{ + border: #737357 1px solid; + color: #3b3b1f; + background-color: #c7c78f; +} + +#btnOk +{ + width: 100px; +} + +.DarkBackground +{ + background-color: #eaead1; +} + +.LightBackground +{ + background-color: #ffffbe; +} + +.PopupTitleBorder +{ + border-bottom: #d5d59d 1px solid; +} + +.PopupTabArea +{ + color: #737357; + background-color: #e3e3c7; +} + +.PopupTabEmptyArea +{ + padding-left: 10px; + border-bottom: #d5d59d 1px solid; +} + +.PopupTab, .PopupTabSelected +{ + border-right: #d5d59d 1px solid; + border-top: #d5d59d 1px solid; + border-left: #d5d59d 1px solid; + padding: 3px 5px 3px 5px; + color: #737357; +} + +.PopupTab +{ + margin-top: 1px; + border-bottom: #d5d59d 1px solid; + cursor: pointer; + cursor: hand; +} + +.PopupTabSelected +{ + font-weight: bold; + cursor: default; + padding-top: 4px; + border-bottom: #f1f1e3 1px solid; + background-color: #f1f1e3; +} + +.PopupSelectionBox +{ + border: #ff9933 1px solid !important; + background-color: #fffacd !important; + cursor: pointer; + cursor: hand; +} + +#tdBrowse +{ + vertical-align: bottom; +} + +/** + * Dialog frame related styles. + */ + +.contents +{ + position: absolute; + top: 2px; + left: 16px; + right: 16px; + bottom: 20px; + background-color: #f1f1e3; + overflow: hidden; + z-index: 1; +} + +.tl, .tr, .tc, .bl, .br, .bc +{ + position: absolute; + background-image: url(images/sprites.png); + background-repeat: no-repeat; +} + +* html .tl, * html .tr, * html .tc, * html .bl, * html .br, * html .bc +{ + background-image: url(images/sprites.gif); +} + +.ml, .mr +{ + position: absolute; + background-image: url(images/dialog.sides.png); + background-repeat: repeat-y; +} + +* html .ml, * html .mr +{ + background-image: url(images/dialog.sides.gif); +} + +.rtl .ml, .rtl .mr +{ + position: absolute; + background-image: url(images/dialog.sides.rtl.png); + background-repeat: repeat-y; +} + +* html .rtl .ml, * html .rtl .mr +{ + background-image: url(images/dialog.sides.gif); +} + +.tl +{ + top: 0px; + left: 0px; + width: 16px; + height: 16px; + background-position: -16px -16px; +} + +.rtl .tl +{ + background-position: -16px -397px; +} + +.tr +{ + top: 0px; + right: 0px; + width: 16px; + height: 16px; + background-position: -16px -76px; +} + +.rtl .tr +{ + background-position: -16px -457px; +} + +.tc +{ + top: 0px; + right: 16px; + left: 16px; + height: 16px; + background-position: 0px -136px; + background-repeat: repeat-x; +} + +.ml +{ + top: 16px; + left: 0px; + width: 16px; + bottom: 51px; + background-position: 0px 0px; +} + +.mr +{ + top: 16px; + right: 0px; + width: 16px; + bottom: 51px; + background-position: -16px 0px; +} + +.bl +{ + bottom: 0px; + left: 0px; + width: 30px; + height: 51px; + background-position: -16px -196px; +} + +.rtl .bl +{ + background-position: -16px -517px; +} + +.br +{ + bottom: 0px; + right: 0px; + width: 30px; + height: 51px; + background-position: -16px -263px; +} + +.rtl .br +{ + background-position: -16px -584px; +} + +.bc +{ + bottom: 0px; + right: 30px; + left: 30px; + height: 51px; + background-position: 0px -330px; + background-repeat: repeat-x; +} + +/* For IE6. Do not change it. */ +* html .blocker +{ + position: absolute; + width: 100%; + height: 100%; + z-index: 12; + filter: progid:DXImageTransform.Microsoft.Alpha(opacity=0); +} + +/* The layer used to cover the dialog when opening a child dialog. */ +.cover +{ + position: absolute; + top: 0px; + left: 14px; + right: 14px; + bottom: 18px; + z-index: 11; +} + +#closeButton +{ + position: absolute; + right: 0px; + top: 0px; + margin-top: 5px; + margin-right: 10px; + width: 20px; + height: 20px; + cursor: pointer; + background-image: url(images/sprites.png); + background-repeat: no-repeat; + background-position: -16px -651px; +} + +* html #closeButton +{ + cursor: hand; + background-image: url(images/sprites.gif); +} + +.rtl #closeButton +{ + right: auto; + left: 10px; + margin-right: 0px; +} + +#closeButton:hover +{ + background-position: -16px -687px; +} + +#throbberBlock +{ + z-index: 10; +} + +#throbberBlock div +{ + float: left; + width: 8px; + height: 9px; + margin-left: 2px; + margin-right: 2px; + font-size: 1px; /* IE6 */ +} + +/* + Color Gradient Generator: + http://www.herethere.net/~samson/php/color_gradient/?cbegin=737357&cend=E3E3C7&steps=4 +*/ + +.throbber_1 +{ + background-color: #737357; +} + +.throbber_2 +{ + background-color: #8f8f73; +} + +.throbber_3 +{ + background-color: #abab8f; +} + +.throbber_4 +{ + background-color: #c7c7ab; +} + +.throbber_5 +{ + background-color: #e3e3c7; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/fck_dialog_ie6.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/fck_dialog_ie6.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/fck_dialog_ie6.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,110 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + */ + +(function() +{ + // IE6 doens't handle absolute positioning properly (it is always in quirks + // mode). This function fixes the sizes and positions of many elements that + // compose the skin (this is skin specific). + var fixSizes = window.DoResizeFixes = function() + { + var fckDlg = window.document.body ; + + for ( var i = 0 ; i < fckDlg.childNodes.length ; i++ ) + { + var child = fckDlg.childNodes[i] ; + switch ( child.className ) + { + case 'contents' : + child.style.width = Math.max( 0, fckDlg.offsetWidth - 16 - 16 ) ; // -left -right + child.style.height = Math.max( 0, fckDlg.clientHeight - 20 - 2 ) ; // -bottom -top + break ; + + case 'blocker' : + case 'cover' : + child.style.width = Math.max( 0, fckDlg.offsetWidth - 16 - 16 + 4 ) ; // -left -right + 4 + child.style.height = Math.max( 0, fckDlg.clientHeight - 20 - 2 + 4 ) ; // -bottom -top + 4 + break ; + + case 'tr' : + child.style.left = Math.max( 0, fckDlg.clientWidth - 16 ) ; + break ; + + case 'tc' : + child.style.width = Math.max( 0, fckDlg.clientWidth - 16 - 16 ) ; + break ; + + case 'ml' : + child.style.height = Math.max( 0, fckDlg.clientHeight - 16 - 51 ) ; + break ; + + case 'mr' : + child.style.left = Math.max( 0, fckDlg.clientWidth - 16 ) ; + child.style.height = Math.max( 0, fckDlg.clientHeight - 16 - 51 ) ; + break ; + + case 'bl' : + child.style.top = Math.max( 0, fckDlg.clientHeight - 51 ) ; + break ; + + case 'br' : + child.style.left = Math.max( 0, fckDlg.clientWidth - 30 ) ; + child.style.top = Math.max( 0, fckDlg.clientHeight - 51 ) ; + break ; + + case 'bc' : + child.style.width = Math.max( 0, fckDlg.clientWidth - 30 - 30 ) ; + child.style.top = Math.max( 0, fckDlg.clientHeight - 51 ) ; + break ; + } + } + } + + var closeButtonOver = function() + { + this.style.backgroundPosition = '-16px -687px' ; + } ; + + var closeButtonOut = function() + { + this.style.backgroundPosition = '-16px -651px' ; + } ; + + var fixCloseButton = function() + { + var closeButton = document.getElementById ( 'closeButton' ) ; + + closeButton.onmouseover = closeButtonOver ; + closeButton.onmouseout = closeButtonOut ; + } + + var onLoad = function() + { + fixSizes() ; + fixCloseButton() ; + + window.attachEvent( 'onresize', fixSizes ) ; + window.detachEvent( 'onload', onLoad ) ; + } + + window.attachEvent( 'onload', onLoad ) ; + +})() ; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/fck_editor.css =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/fck_editor.css (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/fck_editor.css 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,464 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Styles used by the editor IFRAME and Toolbar. + */ + +/* + ### Basic Editor IFRAME Styles. +*/ + +body +{ + padding: 1px; + margin: 0; + background-color: #ffffff; +} + +#xEditingArea +{ + border: #696969 1px solid; +} + +.SourceField +{ + padding: 5px; + margin: 0px; + font-family: Monospace; +} + +/* + Toolbar +*/ + +.TB_ToolbarSet, .TB_Expand, .TB_Collapse +{ + cursor: default; + background-color: #efefde; +} + +.TB_ToolbarSet +{ + border-top: #efefde 1px outset; + border-bottom: #efefde 1px outset; +} + +.TB_ToolbarSet TD +{ + font-size: 11px; + font-family: 'Microsoft Sans Serif' , Tahoma, Arial, Verdana, Sans-Serif; +} + +.TB_Toolbar +{ + height: 24px; + display: inline-table; /* inline = Opera jumping buttons bug */ +} + +.TB_Separator +{ + width: 1px; + height: 16px; + margin: 2px; + background-color: #999966; +} + +.TB_Start +{ + background-image: url(images/toolbar.start.gif); + margin: 2px; + width: 3px; + background-repeat: no-repeat; + height: 16px; +} + +.TB_End +{ + display: none; +} + +.TB_ExpandImg +{ + background-image: url(images/toolbar.expand.gif); + background-repeat: no-repeat; +} + +.TB_CollapseImg +{ + background-image: url(images/toolbar.collapse.gif); + background-repeat: no-repeat; +} + +.TB_SideBorder +{ + background-color: #696969; +} + +.TB_Expand, .TB_Collapse +{ + padding: 2px 2px 2px 2px; + border: #efefde 1px outset; +} + +.TB_Collapse +{ + width: 5px; +} + +.TB_Break +{ + height: 24px; /* IE needs the height to be set, otherwise no break */ +} + +/* + Toolbar Button +*/ + +.TB_Button_On, .TB_Button_Off, .TB_Button_On_Over, .TB_Button_Off_Over, .TB_Button_Disabled +{ + border: #efefde 1px solid; /* This is the default border */ + height: 22px; /* The height is necessary, otherwise IE will not apply the alpha */ +} + +.TB_Button_On +{ + border: #316ac5 1px solid; + background-color: #c1d2ee; +} + +.TB_Button_On_Over, .TB_Button_Off_Over +{ + border: #316ac5 1px solid; + background-color: #dff1ff; +} + +.TB_Button_Off +{ + filter: alpha(opacity=70); /* IE */ + opacity: 0.70; /* Safari, Opera and Mozilla */ +} + +.TB_Button_Disabled +{ + filter: gray() alpha(opacity=30); /* IE */ + opacity: 0.30; /* Safari, Opera and Mozilla */ +} + +.TB_Button_Padding +{ + visibility: hidden; + width: 3px; + height: 22px; +} + +.TB_Button_Image +{ + overflow: hidden; + width: 16px; + height: 16px; + margin: 3px; + background-repeat: no-repeat; +} + +.TB_Button_Image img +{ + position: relative; +} + +.TB_Button_Off .TB_Button_Text +{ + background-color: #efefde; /* Needed because of a bug on Clear Type */ +} + +.TB_ConnectionLine +{ + background-color: #ffffff; + height: 1px; + margin-left: 1px; /* ltr */ + margin-right: 1px; /* rtl */ +} + +.TB_Text +{ + height: 22px; +} + +.TB_Button_Off .TB_Text +{ + background-color: #efefde ; /* Needed because of a bug on ClearType */ +} + +.TB_Button_On_Over .TB_Text +{ + background-color: #dff1ff ; /* Needed because of a bug on ClearType */ +} + +/* + Menu +*/ + +.MN_Menu +{ + border: 1px solid #8f8f73; + padding: 2px; + background-color: #ffffff; + cursor: default; +} + +.MN_Menu, .MN_Menu .MN_Label +{ + font-size: 11px; + font-family: 'Microsoft Sans Serif' , Tahoma, Arial, Verdana, Sans-Serif; +} + +.MN_Item_Padding +{ + visibility: hidden; + width: 3px; + height: 20px; +} + +.MN_Icon +{ + background-color: #e3e3c7; + text-align: center; + height: 20px; +} + +.MN_Label +{ + padding-left: 3px; + padding-right: 3px; +} + +.MN_Separator +{ + height: 3px; +} + +.MN_Separator_Line +{ + border-top: #b9b99d 1px solid; +} + +.MN_Item .MN_Icon IMG +{ + filter: alpha(opacity=70); + opacity: 0.70; +} + +.MN_Item_Over +{ + color: #ffffff; + background-color: #8f8f73; +} + +.MN_Item_Over .MN_Icon +{ + background-color: #737357; +} + +.MN_Item_Disabled IMG +{ + filter: gray() alpha(opacity=30); /* IE */ + opacity: 0.30; /* Safari, Opera and Mozilla */ +} + +.MN_Item_Disabled .MN_Label +{ + color: #b7b7b7; +} + +.MN_Arrow +{ + padding-right: 3px; + padding-left: 3px; +} + +.MN_ConnectionLine +{ + background-color: #ffffff; +} + +.Menu .TB_Button_On, .Menu .TB_Button_On_Over +{ + border: #8f8f73 1px solid; + background-color: #ffffff; +} + +/* + ### Panel Styles +*/ + +.FCK_Panel +{ + border: #8f8f73 1px solid; + padding: 2px; + background-color: #ffffff; +} + +.FCK_Panel, .FCK_Panel TD +{ + font-family: 'Microsoft Sans Serif' , Tahoma, Arial, Verdana, Sans-Serif; + font-size: 11px; +} + +/* + ### Special Combos +*/ + +.SC_Panel +{ + overflow: auto; + white-space: nowrap; + cursor: default; + border: 1px solid #8f8f73; + padding-left: 2px; + padding-right: 2px; +} + +.SC_Panel, .SC_Panel TD +{ + font-size: 11px; + font-family: 'Microsoft Sans Serif' , Tahoma, Arial, Verdana, Sans-Serif; +} + +.SC_Item, .SC_ItemSelected +{ + margin-top: 2px; + margin-bottom: 2px; + background-position: left center; + padding-left: 11px; + padding-right: 3px; + padding-top: 2px; + padding-bottom: 2px; + text-overflow: ellipsis; + overflow: hidden; + background-repeat: no-repeat; + border: #dddddd 1px solid; +} + +.SC_Item *, .SC_ItemSelected * +{ + margin-top: 0px; + margin-bottom: 0px; +} + +.SC_ItemSelected +{ + border: #9a9afb 1px solid; + background-image: url(images/toolbar.arrowright.gif); +} + +.SC_ItemOver +{ + border: #316ac5 1px solid; +} + +.SC_Field +{ + border: #b7b7a6 1px solid; + cursor: default; +} + +.SC_FieldCaption +{ + overflow: visible; + padding-right: 5px; + padding-left: 5px; + opacity: 0.75; /* Safari, Opera and Mozilla */ + filter: alpha(opacity=70); /* IE */ /* -moz-opacity: 0.75; Mozilla (Old) */ + height: 23px; + background-color: #efefde; +} + +.SC_FieldLabel +{ + white-space: nowrap; + padding: 2px; + width: 100%; + cursor: default; + background-color: #ffffff; + text-overflow: ellipsis; + overflow: hidden; +} + +.SC_FieldButton +{ + background-position: center center; + background-image: url(images/toolbar.buttonarrow.gif); + border-left: #b7b7a6 1px solid; + width: 14px; + background-repeat: no-repeat; +} + +.SC_FieldDisabled .SC_FieldButton, .SC_FieldDisabled .SC_FieldCaption, .SC_FieldDisabled .TB_ButtonType_Text +{ + opacity: 0.30; /* Safari, Opera and Mozilla */ + filter: gray() alpha(opacity=30); /* IE */ /* -moz-opacity: 0.30; Mozilla (Old) */ +} + +.SC_FieldOver +{ + border: #316ac5 1px solid; +} + +.SC_FieldOver .SC_FieldButton +{ + border-left: #316ac5 1px solid; +} + +/* + ### Color Selector Panel +*/ + +.ColorBoxBorder +{ + border: #808080 1px solid; + position: static; +} + +.ColorBox +{ + font-size: 1px; + width: 10px; + position: static; + height: 10px; +} + +.ColorDeselected, .ColorSelected +{ + cursor: default; +} + +.ColorDeselected +{ + border: #ffffff 1px solid; + padding: 2px; + float: left; +} + +.ColorSelected +{ + border: #330066 1px solid; + padding: 2px; + float: left; + background-color: #c4cdd6; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/fck_strip.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/fck_strip.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/dialog.sides.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/dialog.sides.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/dialog.sides.png =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/dialog.sides.png ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/dialog.sides.rtl.png =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/dialog.sides.rtl.png ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/sprites.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/sprites.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/sprites.png =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/sprites.png ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/toolbar.arrowright.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/toolbar.arrowright.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/toolbar.buttonarrow.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/toolbar.buttonarrow.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/toolbar.collapse.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/toolbar.collapse.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/toolbar.end.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/toolbar.end.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/toolbar.expand.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/toolbar.expand.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/toolbar.separator.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/toolbar.separator.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/toolbar.start.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/default/images/toolbar.start.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/fck_dialog.css =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/fck_dialog.css (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/fck_dialog.css 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,402 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Styles used by the dialog boxes. + */ + +html, body +{ + background-color: transparent; + margin: 0px; + padding: 0px; +} + +body +{ + padding: 10px; +} + +body, td, input, select, textarea +{ + font-size: 11px; + font-family: 'Microsoft Sans Serif' , Arial, Helvetica, Verdana; +} + +body, .BackColor +{ + background-color: #f7f8fd; +} + +.PopupBody +{ + height: 100%; + width: 100%; + overflow: hidden; + background-color: transparent; + padding: 0px; +} + +#header +{ + cursor: move; +} + +.PopupTitle +{ + font-weight: bold; + font-size: 14pt; + color: #0e3460; + background-color: #8cb2fd; + padding: 3px 10px 3px 10px; +} + +.PopupButtons +{ + position: absolute; + right: 0px; + left: 0px; + bottom: 0px; + border-top: #466ca6 1px solid; + background-color: #8cb2fd; + padding: 7px 10px 7px 10px; +} + +.Button +{ + border: #1c3460 1px solid; + color: #000a28; + background-color: #7096d3; +} + +#btnOk +{ + width: 100px; +} + +.DarkBackground +{ + background-color: #eaf2f8; +} + +.LightBackground +{ + background-color: #ffffbe; +} + +.PopupTitleBorder +{ + border-bottom: #d5d59d 1px solid; +} + +.PopupTabArea +{ + color: #0e3460; + background-color: #8cb2fd; +} + +.PopupTabEmptyArea +{ + padding-left: 10px ; + border-bottom: #466ca6 1px solid; +} + +.PopupTab, .PopupTabSelected +{ + border-right: #466ca6 1px solid; + border-top: #466ca6 1px solid; + border-left: #466ca6 1px solid; + padding: 3px 5px 3px 5px; + color: #0e3460; +} + +.PopupTab +{ + margin-top: 1px; + border-bottom: #466ca6 1px solid; + cursor: pointer; + cursor: hand; +} + +.PopupTabSelected +{ + font-weight: bold; + cursor: default; + padding-top: 4px; + border-bottom: #f7f8fd 1px solid; + background-color: #f7f8fd; +} + +.PopupSelectionBox +{ + border: #1e90ff 1px solid !important; + background-color: #add8e6 !important; + cursor: pointer; + cursor: hand; +} + +#tdBrowse +{ + vertical-align: bottom; +} + +/** + * Dialog frame related styles. + */ + +.contents +{ + position: absolute; + top: 2px; + left: 16px; + right: 16px; + bottom: 20px; + background-color: #f7f8fD; + overflow: hidden; + z-index: 1; +} + +.tl, .tr, .tc, .bl, .br, .bc +{ + position: absolute; + background-image: url(images/sprites.png); + background-repeat: no-repeat; +} + +* html .tl, * html .tr, * html .tc, * html .bl, * html .br, * html .bc +{ + background-image: url(images/sprites.gif); +} + +.ml, .mr +{ + position: absolute; + background-image: url(images/dialog.sides.png); + background-repeat: repeat-y; +} + +* html .ml, * html .mr +{ + background-image: url(images/dialog.sides.gif); +} + +.rtl .ml, .rtl .mr +{ + position: absolute; + background-image: url(images/dialog.sides.rtl.png); + background-repeat: repeat-y; +} + +* html .rtl .ml, * html .rtl .mr +{ + background-image: url(images/dialog.sides.gif); +} + +.tl +{ + top: 0px; + left: 0px; + width: 16px; + height: 16px; + background-position: -16px -16px; +} + +.rtl .tl +{ + background-position: -16px -397px; +} + +.tr +{ + top: 0px; + right: 0px; + width: 16px; + height: 16px; + background-position: -16px -76px; +} + +.rtl .tr +{ + background-position: -16px -457px; +} + +.tc +{ + top: 0px; + right: 16px; + left: 16px; + height: 16px; + background-position: 0px -136px; + background-repeat: repeat-x; +} + +.ml +{ + top: 16px; + left: 0px; + width: 16px; + bottom: 51px; + background-position: 0px 0px; +} + +.mr +{ + top: 16px; + right: 0px; + width: 16px; + bottom: 51px; + background-position: -16px 0px; +} + +.bl +{ + bottom: 0px; + left: 0px; + width: 30px; + height: 51px; + background-position: -16px -196px; +} + +.rtl .bl +{ + background-position: -16px -517px; +} + +.br +{ + bottom: 0px; + right: 0px; + width: 30px; + height: 51px; + background-position: -16px -263px; +} + +.rtl .br +{ + background-position: -16px -584px; +} + +.bc +{ + bottom: 0px; + right: 30px; + left: 30px; + height: 51px; + background-position: 0px -330px; + background-repeat: repeat-x; +} + +/* For IE6. Do not change it. */ +* html .blocker +{ + position: absolute; + width: 100%; + height: 100%; + z-index: 12; + filter: progid:DXImageTransform.Microsoft.Alpha(opacity=0); +} + +/* The layer used to cover the dialog when opening a child dialog. */ +.cover +{ + position: absolute; + top: 0px; + left: 14px; + right: 14px; + bottom: 18px; + z-index: 11; +} + +#closeButton +{ + position: absolute; + right: 0px; + top: 0px; + margin-top: 5px; + margin-right: 10px; + width: 20px; + height: 20px; + cursor: pointer; + background-image: url(images/sprites.png); + background-repeat: no-repeat; + background-position: -16px -651px; +} + +* html #closeButton +{ + cursor: hand; + background-image: url(images/sprites.gif); +} + +.rtl #closeButton +{ + right: auto; + left: 10px; + margin-right: 0px; +} + +#closeButton:hover +{ + background-position: -16px -687px; +} + +#throbberBlock +{ + z-index: 10; +} + +#throbberBlock div +{ + float: left; + width: 8px; + height: 9px; + margin-left: 2px; + margin-right: 2px; + font-size: 1px; /* IE6 */ +} + +/* + Color Gradient Generator: + http://www.herethere.net/~samson/php/color_gradient/?cbegin=0E3460&cend=8cb2fd&steps=4 +*/ + +.throbber_1 +{ + background-color: #0E3460; +} + +.throbber_2 +{ + background-color: #2D5387; +} + +.throbber_3 +{ + background-color: #4D73AE; +} + +.throbber_4 +{ + background-color: #6C92D5; +} + +.throbber_5 +{ + background-color: #8CB2FD; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/fck_dialog_ie6.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/fck_dialog_ie6.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/fck_dialog_ie6.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,110 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + */ + +(function() +{ + // IE6 doens't handle absolute positioning properly (it is always in quirks + // mode). This function fixes the sizes and positions of many elements that + // compose the skin (this is skin specific). + var fixSizes = window.DoResizeFixes = function() + { + var fckDlg = window.document.body ; + + for ( var i = 0 ; i < fckDlg.childNodes.length ; i++ ) + { + var child = fckDlg.childNodes[i] ; + switch ( child.className ) + { + case 'contents' : + child.style.width = Math.max( 0, fckDlg.offsetWidth - 16 - 16 ) ; // -left -right + child.style.height = Math.max( 0, fckDlg.clientHeight - 20 - 2 ) ; // -bottom -top + break ; + + case 'blocker' : + case 'cover' : + child.style.width = Math.max( 0, fckDlg.offsetWidth - 16 - 16 + 4 ) ; // -left -right + 4 + child.style.height = Math.max( 0, fckDlg.clientHeight - 20 - 2 + 4 ) ; // -bottom -top + 4 + break ; + + case 'tr' : + child.style.left = Math.max( 0, fckDlg.clientWidth - 16 ) ; + break ; + + case 'tc' : + child.style.width = Math.max( 0, fckDlg.clientWidth - 16 - 16 ) ; + break ; + + case 'ml' : + child.style.height = Math.max( 0, fckDlg.clientHeight - 16 - 51 ) ; + break ; + + case 'mr' : + child.style.left = Math.max( 0, fckDlg.clientWidth - 16 ) ; + child.style.height = Math.max( 0, fckDlg.clientHeight - 16 - 51 ) ; + break ; + + case 'bl' : + child.style.top = Math.max( 0, fckDlg.clientHeight - 51 ) ; + break ; + + case 'br' : + child.style.left = Math.max( 0, fckDlg.clientWidth - 30 ) ; + child.style.top = Math.max( 0, fckDlg.clientHeight - 51 ) ; + break ; + + case 'bc' : + child.style.width = Math.max( 0, fckDlg.clientWidth - 30 - 30 ) ; + child.style.top = Math.max( 0, fckDlg.clientHeight - 51 ) ; + break ; + } + } + } + + var closeButtonOver = function() + { + this.style.backgroundPosition = '-16px -687px' ; + } ; + + var closeButtonOut = function() + { + this.style.backgroundPosition = '-16px -651px' ; + } ; + + var fixCloseButton = function() + { + var closeButton = document.getElementById ( 'closeButton' ) ; + + closeButton.onmouseover = closeButtonOver ; + closeButton.onmouseout = closeButtonOut ; + } + + var onLoad = function() + { + fixSizes() ; + fixCloseButton() ; + + window.attachEvent( 'onresize', fixSizes ) ; + window.detachEvent( 'onload', onLoad ) ; + } + + window.attachEvent( 'onload', onLoad ) ; + +})() ; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/fck_editor.css =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/fck_editor.css (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/fck_editor.css 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,476 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Styles used by the editor IFRAME and Toolbar. + */ + +/* + ### Basic Editor IFRAME Styles. +*/ + +body +{ + padding: 1px; + margin: 0; + background-color: #ffffff; +} + +#xEditingArea +{ + border: #696969 1px solid; +} + +.SourceField +{ + padding: 5px; + margin: 0px; + font-family: Monospace; +} + +/* + Toolbar +*/ + +.TB_ToolbarSet, .TB_Expand, .TB_Collapse +{ + cursor: default; + background-color: #f7f8fd; +} + +.TB_ToolbarSet +{ + border-top: #f7f8fd 1px outset; + border-bottom: #f7f8fd 1px outset; +} + +.TB_ToolbarSet TD +{ + font-size: 11px; + font-family: 'Microsoft Sans Serif' , Tahoma, Arial, Verdana, Sans-Serif; +} + +.TB_Toolbar +{ + background-color: #d6dff7; + background-image: url(images/toolbar.bg.gif); + background-repeat: repeat-x; + display: inline-table; +} + +.TB_Separator +{ + width: 1px; + height: 16px; + margin: 2px; + background-color: #B2CBFF; +} + +.TB_Start +{ + background-image: url(images/toolbar.start.gif); + background-repeat: no-repeat; + background-position: center center; + margin: 0px; + width: 7px; + height: 24px; +} + +.TB_End +{ + background-image: url(images/toolbar.end.gif); + background-repeat: no-repeat; + background-position: center left; + height: 24px; + width: 4px; +} + +.TB_ExpandImg +{ + background-image: url(images/toolbar.expand.gif); + background-repeat: no-repeat; +} + +.TB_CollapseImg +{ + background-image: url(images/toolbar.collapse.gif); + background-repeat: no-repeat; +} + +.TB_SideBorder +{ + background-color: #696969; +} + +.TB_Expand, .TB_Collapse +{ + padding: 2px 2px 2px 2px; + border: #f7f8fd 1px outset; +} + +.TB_Collapse +{ + width: 5px; +} + +.TB_Break +{ + height: 24px; /* IE needs the height to be set, otherwise no break */ +} + +/* + Toolbar Button +*/ + +.TB_Button_On, .TB_Button_Off, .TB_Button_On_Over, .TB_Button_Off_Over, .TB_Button_Disabled +{ + margin: 1px; + height: 22px; /* The height is necessary, otherwise IE will not apply the alpha */ +} + +.TB_Button_On +{ + margin: 0px; + border: #316ac5 1px solid; + background-color: #c1d2ee; +} + +.TB_Button_On_Over, .TB_Button_Off_Over +{ + margin: 0px ; + border: #316ac5 1px solid; + background-color: #dff1ff; +} + +.TB_Button_Off +{ + filter: alpha(opacity=70); /* IE */ + opacity: 0.70; /* Safari, Opera and Mozilla */ +} + +.TB_Button_Disabled +{ + filter: gray() alpha(opacity=30); /* IE */ + opacity: 0.30; /* Safari, Opera and Mozilla */ +} + +.TB_Button_Padding +{ + visibility: hidden; + width: 3px; + height: 22px; +} + +.TB_Button_Image +{ + overflow: hidden; + width: 16px; + height: 16px; + margin: 3px; + background-repeat: no-repeat; +} + +.TB_Button_Image img +{ + position: relative; +} + +.TB_Button_Off .TB_Button_Text +{ + background-color: #d6dff7; /* Needed because of a bug on ClearType */ + background-image: url(images/toolbar.bg.gif); + background-repeat: repeat-x; +} + +.TB_ConnectionLine +{ + background-color: #f7f8fd; + height: 1px; + margin-left: 1px; /* ltr */ + margin-right: 1px; /* rtl */ +} + +.TB_Button_Off .TB_Text +{ + background-color: #d6dff7; /* Needed because of a bug on ClearType */ + background-image: url(images/toolbar.bg.gif); + background-repeat: repeat-x; +} + +.TB_Button_On_Over .TB_Text +{ + background-color: #dff1ff ; /* Needed because of a bug on ClearType */ +} + +/* + Menu +*/ + +.MN_Menu +{ + border: 1px solid #8f8f73; + padding: 2px; + background-color: #f7f8fd; + cursor: default; +} + +.MN_Menu, .MN_Menu .MN_Label +{ + font-size: 11px; + font-family: 'Microsoft Sans Serif' , Tahoma, Arial, Verdana, Sans-Serif; +} + +.MN_Item_Padding +{ + visibility: hidden; + width: 3px; + height: 20px; +} + +.MN_Icon +{ + background-color: #d6dff7; + text-align: center; + height: 20px; +} + +.MN_Label +{ + padding-left: 3px; + padding-right: 3px; +} + +.MN_Separator +{ + height: 3px; +} + +.MN_Separator_Line +{ + border-top: #b9b99d 1px solid; +} + +.MN_Item .MN_Icon IMG +{ + filter: alpha(opacity=70); + opacity: 0.70; +} + +.MN_Item_Over +{ + color: #ffffff; + background-color: #7096FA; +} + +.MN_Item_Over .MN_Icon +{ + background-color: #466ca6; +} + +.MN_Item_Disabled IMG +{ + filter: gray() alpha(opacity=30); /* IE */ + opacity: 0.30; /* Safari, Opera and Mozilla */ +} + +.MN_Item_Disabled .MN_Label +{ + color: #b7b7b7; +} + +.MN_Arrow +{ + padding-right: 3px; + padding-left: 3px; +} + +.MN_ConnectionLine +{ + background-color: #f7f8fd; +} + +.Menu .TB_Button_On, .Menu .TB_Button_On_Over +{ + border: #8f8f73 1px solid; + background-color: #f7f8fd; +} + +/* + ### Panel Styles +*/ + +.FCK_Panel +{ + border: #8f8f73 1px solid; + padding: 2px; + background-color: #f7f8fd; +} + +.FCK_Panel, .FCK_Panel TD +{ + font-family: 'Microsoft Sans Serif' , Tahoma, Arial, Verdana, Sans-Serif; + font-size: 11px; +} + +/* + ### Special Combos +*/ + +.SC_Panel +{ + overflow: auto; + white-space: nowrap; + cursor: default; + border: 1px solid #8f8f73; + padding-left: 2px; + padding-right: 2px; +} + +.SC_Panel, .SC_Panel TD +{ + font-size: 11px; + font-family: 'Microsoft Sans Serif' , Tahoma, Arial, Verdana, Sans-Serif; +} + +.SC_Item, .SC_ItemSelected +{ + margin-top: 2px; + margin-bottom: 2px; + background-position: left center; + padding-left: 11px; + padding-right: 3px; + padding-top: 2px; + padding-bottom: 2px; + text-overflow: ellipsis; + overflow: hidden; + background-repeat: no-repeat; + border: #dddddd 1px solid; +} + +.SC_Item *, .SC_ItemSelected * +{ + margin-top: 0px; + margin-bottom: 0px; +} + +.SC_ItemSelected +{ + border: #9a9afb 1px solid; + background-image: url(images/toolbar.arrowright.gif); +} + +.SC_ItemOver +{ + border: #316ac5 1px solid; +} + +.SC_Field +{ + margin-top: 2px ; + border: #b7b7a6 1px solid; + cursor: default; +} + +.SC_FieldCaption +{ + overflow: visible; + padding-right: 5px; + padding-left: 5px; + opacity: 0.75; /* Safari, Opera and Mozilla */ + filter: alpha(opacity=70); /* IE */ /* -moz-opacity: 0.75; Mozilla (Old) */ + height: 23px; + background-color: #d6dff7; /* Needed because of a bug on ClearType */ + background-image: url(images/toolbar.bg.gif); + background-repeat: repeat-x; +/* background-color: inherit; Maybe this is needed wait to check */ +} + +.SC_FieldLabel +{ + white-space: nowrap; + padding: 2px; + width: 100%; + cursor: default; + background-color: #ffffff; + text-overflow: ellipsis; + overflow: hidden; +} + +.SC_FieldButton +{ + background-position: center center; + background-image: url(images/toolbar.buttonarrow.gif); + border-left: #b7b7a6 1px solid; + width: 14px; + background-repeat: no-repeat; +} + +.SC_FieldDisabled .SC_FieldButton, .SC_FieldDisabled .SC_FieldCaption, .SC_FieldDisabled .TB_ButtonType_Text +{ + opacity: 0.30; /* Safari, Opera and Mozilla */ + filter: gray() alpha(opacity=30); /* IE */ /* -moz-opacity: 0.30; Mozilla (Old) */ +} + +.SC_FieldOver +{ + border: #316ac5 1px solid; +} + +.SC_FieldOver .SC_FieldButton +{ + border-left: #316ac5 1px solid; +} + +/* + ### Color Selector Panel +*/ + +.ColorBoxBorder +{ + border: #808080 1px solid; + position: static; +} + +.ColorBox +{ + font-size: 1px; + width: 10px; + position: static; + height: 10px; +} + +.ColorDeselected, .ColorSelected +{ + cursor: default; +} + +.ColorDeselected +{ + border: #ffffff 1px solid; + padding: 2px; + float: left; +} + +.ColorSelected +{ + border: #330066 1px solid; + padding: 2px; + float: left; + background-color: #c4cdd6; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/fck_strip.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/fck_strip.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/dialog.sides.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/dialog.sides.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/dialog.sides.png =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/dialog.sides.png ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/dialog.sides.rtl.png =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/dialog.sides.rtl.png ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/sprites.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/sprites.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/sprites.png =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/sprites.png ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/toolbar.arrowright.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/toolbar.arrowright.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/toolbar.bg.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/toolbar.bg.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/toolbar.buttonarrow.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/toolbar.buttonarrow.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/toolbar.collapse.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/toolbar.collapse.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/toolbar.end.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/toolbar.end.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/toolbar.expand.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/toolbar.expand.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/toolbar.separator.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/toolbar.separator.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/toolbar.start.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/office2003/images/toolbar.start.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/fck_dialog.css =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/fck_dialog.css (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/fck_dialog.css 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,402 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Styles used by the dialog boxes. + */ + +html, body +{ + background-color: transparent; + margin: 0px; + padding: 0px; +} + +body +{ + padding: 10px; +} + +body, td, input, select, textarea +{ + font-size: 11px; + font-family: 'Microsoft Sans Serif' , Arial, Helvetica, Verdana; +} + +body, .BackColor +{ + background-color: #f7f7f7; +} + +.PopupBody +{ + height: 100%; + width: 100%; + overflow: hidden; + background-color: transparent; + padding: 0px; +} + +#header +{ + cursor: move; +} + +.PopupTitle +{ + font-weight: bold; + font-size: 14pt; + color: #504845; + background-color: #dedede; + padding: 3px 10px 3px 10px; +} + +.PopupButtons +{ + position: absolute; + right: 0px; + left: 0px; + bottom: 0px; + border-top: #cec6b5 1px solid; + background-color: #DEDEDE; + padding: 7px 10px 7px 10px; +} + +.Button +{ + border: #7a7261 1px solid; + color: #504845; + background-color: #cec6b5; +} + +#btnOk +{ + width: 100px; +} + +.DarkBackground +{ + background-color: #f2f2f2; +} + +.LightBackground +{ + background-color: #ffffbe; +} + +.PopupTitleBorder +{ + border-bottom: #cec6b5 1px solid; +} + +.PopupTabArea +{ + color: #504845; + background-color: #DEDEDE; +} + +.PopupTabEmptyArea +{ + padding-left: 10px ; + border-bottom: #cec6b5 1px solid; +} + +.PopupTab, .PopupTabSelected +{ + border-right: #cec6b5 1px solid; + border-top: #cec6b5 1px solid; + border-left: #cec6b5 1px solid; + padding: 3px 5px 3px 5px; + color: #504845; +} + +.PopupTab +{ + margin-top: 1px; + border-bottom: #cec6b5 1px solid; + cursor: pointer; + cursor: hand; +} + +.PopupTabSelected +{ + font-weight:bold; + cursor: default; + padding-top: 4px; + border-bottom: #f1f1e3 1px solid; + background-color: #f7f7f7; +} + +.PopupSelectionBox +{ + border: #a9a9a9 1px solid !important; + background-color: #dcdcdc !important; + cursor: pointer; + cursor: hand; +} + +#tdBrowse +{ + vertical-align: bottom; +} + +/** + * Dialog frame related styles. + */ + +.contents +{ + position: absolute; + top: 2px; + left: 16px; + right: 16px; + bottom: 20px; + background-color: #f7f7f7; + overflow: hidden; + z-index: 1; +} + +.tl, .tr, .tc, .bl, .br, .bc +{ + position: absolute; + background-image: url(images/sprites.png); + background-repeat: no-repeat; +} + +* html .tl, * html .tr, * html .tc, * html .bl, * html .br, * html .bc +{ + background-image: url(images/sprites.gif); +} + +.ml, .mr +{ + position: absolute; + background-image: url(images/dialog.sides.png); + background-repeat: repeat-y; +} + +* html .ml, * html .mr +{ + background-image: url(images/dialog.sides.gif); +} + +.rtl .ml, .rtl .mr +{ + position: absolute; + background-image: url(images/dialog.sides.rtl.png); + background-repeat: repeat-y; +} + +* html .rtl .ml, * html .rtl .mr +{ + background-image: url(images/dialog.sides.gif); +} + +.tl +{ + top: 0px; + left: 0px; + width: 16px; + height: 16px; + background-position: -16px -16px; +} + +.rtl .tl +{ + background-position: -16px -397px; +} + +.tr +{ + top: 0px; + right: 0px; + width: 16px; + height: 16px; + background-position: -16px -76px; +} + +.rtl .tr +{ + background-position: -16px -457px; +} + +.tc +{ + top: 0px; + right: 16px; + left: 16px; + height: 16px; + background-position: 0px -136px; + background-repeat: repeat-x; +} + +.ml +{ + top: 16px; + left: 0px; + width: 16px; + bottom: 51px; + background-position: 0px 0px; +} + +.mr +{ + top: 16px; + right: 0px; + width: 16px; + bottom: 51px; + background-position: -16px 0px; +} + +.bl +{ + bottom: 0px; + left: 0px; + width: 30px; + height: 51px; + background-position: -16px -196px; +} + +.rtl .bl +{ + background-position: -16px -517px; +} + +.br +{ + bottom: 0px; + right: 0px; + width: 30px; + height: 51px; + background-position: -16px -263px; +} + +.rtl .br +{ + background-position: -16px -584px; +} + +.bc +{ + bottom: 0px; + right: 30px; + left: 30px; + height: 51px; + background-position: 0px -330px; + background-repeat: repeat-x; +} + +/* For IE6. Do not change it. */ +* html .blocker +{ + position: absolute; + width: 100%; + height: 100%; + z-index: 12; + filter: progid:DXImageTransform.Microsoft.Alpha(opacity=0); +} + +/* The layer used to cover the dialog when opening a child dialog. */ +.cover +{ + position: absolute; + top: 0px; + left: 14px; + right: 14px; + bottom: 18px; + z-index: 11; +} + +#closeButton +{ + position: absolute; + right: 0px; + top: 0px; + margin-top: 5px; + margin-right: 10px; + width: 20px; + height: 20px; + cursor: pointer; + background-image: url(images/sprites.png); + background-repeat: no-repeat; + background-position: -16px -651px; +} + +* html #closeButton +{ + cursor: hand; + background-image: url(images/sprites.gif); +} + +.rtl #closeButton +{ + right: auto; + left: 10px; + margin-right: 0px; +} + +#closeButton:hover +{ + background-position: -16px -687px; +} + +#throbberBlock +{ + z-index: 10; +} + +#throbberBlock div +{ + float: left; + width: 8px; + height: 9px; + margin-left: 2px; + margin-right: 2px; + font-size: 1px; /* IE6 */ +} + +/* + Color Gradient Generator: + http://www.herethere.net/~samson/php/color_gradient/?cbegin=504845&cend=DEDEDE&steps=4 +*/ + +.throbber_1 +{ + background-color: #504845; +} + +.throbber_2 +{ + background-color: #736D6B; +} + +.throbber_3 +{ + background-color: #979391; +} + +.throbber_4 +{ + background-color: #BAB8B7; +} + +.throbber_5 +{ + background-color: #DEDEDE; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/fck_dialog_ie6.js =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/fck_dialog_ie6.js (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/fck_dialog_ie6.js 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,110 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + */ + +(function() +{ + // IE6 doens't handle absolute positioning properly (it is always in quirks + // mode). This function fixes the sizes and positions of many elements that + // compose the skin (this is skin specific). + var fixSizes = window.DoResizeFixes = function() + { + var fckDlg = window.document.body ; + + for ( var i = 0 ; i < fckDlg.childNodes.length ; i++ ) + { + var child = fckDlg.childNodes[i] ; + switch ( child.className ) + { + case 'contents' : + child.style.width = Math.max( 0, fckDlg.offsetWidth - 16 - 16 ) ; // -left -right + child.style.height = Math.max( 0, fckDlg.clientHeight - 20 - 2 ) ; // -bottom -top + break ; + + case 'blocker' : + case 'cover' : + child.style.width = Math.max( 0, fckDlg.offsetWidth - 16 - 16 + 4 ) ; // -left -right + 4 + child.style.height = Math.max( 0, fckDlg.clientHeight - 20 - 2 + 4 ) ; // -bottom -top + 4 + break ; + + case 'tr' : + child.style.left = Math.max( 0, fckDlg.clientWidth - 16 ) ; + break ; + + case 'tc' : + child.style.width = Math.max( 0, fckDlg.clientWidth - 16 - 16 ) ; + break ; + + case 'ml' : + child.style.height = Math.max( 0, fckDlg.clientHeight - 16 - 51 ) ; + break ; + + case 'mr' : + child.style.left = Math.max( 0, fckDlg.clientWidth - 16 ) ; + child.style.height = Math.max( 0, fckDlg.clientHeight - 16 - 51 ) ; + break ; + + case 'bl' : + child.style.top = Math.max( 0, fckDlg.clientHeight - 51 ) ; + break ; + + case 'br' : + child.style.left = Math.max( 0, fckDlg.clientWidth - 30 ) ; + child.style.top = Math.max( 0, fckDlg.clientHeight - 51 ) ; + break ; + + case 'bc' : + child.style.width = Math.max( 0, fckDlg.clientWidth - 30 - 30 ) ; + child.style.top = Math.max( 0, fckDlg.clientHeight - 51 ) ; + break ; + } + } + } + + var closeButtonOver = function() + { + this.style.backgroundPosition = '-16px -687px' ; + } ; + + var closeButtonOut = function() + { + this.style.backgroundPosition = '-16px -651px' ; + } ; + + var fixCloseButton = function() + { + var closeButton = document.getElementById ( 'closeButton' ) ; + + closeButton.onmouseover = closeButtonOver ; + closeButton.onmouseout = closeButtonOut ; + } + + var onLoad = function() + { + fixSizes() ; + fixCloseButton() ; + + window.attachEvent( 'onresize', fixSizes ) ; + window.detachEvent( 'onload', onLoad ) ; + } + + window.attachEvent( 'onload', onLoad ) ; + +})() ; Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/fck_editor.css =================================================================== --- trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/fck_editor.css (rev 0) +++ trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/fck_editor.css 2008-05-18 11:54:29 UTC (rev 48) @@ -0,0 +1,473 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2008 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Styles used by the editor IFRAME and Toolbar. + */ + +/* + ### Basic Editor IFRAME Styles. +*/ + +body +{ + padding: 1px; + margin: 0; + background-color: #ffffff; +} + +#xEditingArea +{ + border: #696969 1px solid; +} + +.SourceField +{ + padding: 5px; + margin: 0px; + font-family: Monospace; +} + +/* + Toolbar +*/ + +.TB_ToolbarSet, .TB_Expand, .TB_Collapse +{ + cursor: default; + background-color: #f7f7f7; +} + +.TB_ToolbarSet +{ + padding: 1px; + border-top: #efefde 1px outset; + border-bottom: #efefde 1px outset; +} + +.TB_ToolbarSet TD +{ + font-size: 11px; + font-family: 'Microsoft Sans Serif' , Tahoma, Arial, Verdana, Sans-Serif; +} + +.TB_Toolbar +{ + display: inline-table; +} + +.TB_Separator +{ + width: 1px; + height: 21px; + margin: 2px; + background-color: #C6C3BD; +} + +.TB_Start +{ + background-image: url(images/toolbar.start.gif); + margin-left: 2px; + margin-right: 2px; + width: 3px; + background-repeat: no-repeat; + height: 27px; + background-position: center center; +} + +.TB_End +{ + display: none; +} + +.TB_ExpandImg +{ + background-image: url(images/toolbar.expand.gif); + background-repeat: no-repeat; +} + +.TB_CollapseImg +{ + background-image: url(images/toolbar.collapse.gif); + background-repeat: no-repeat; +} + +.TB_SideBorder +{ + background-color: #696969; +} + +.TB_Expand, .TB_Collapse +{ + padding: 2px 2px 2px 2px; + border: #efefde 1px outset; +} + +.TB_Collapse +{ + border: #efefde 1px outset; + width: 5px; +} + +.TB_Break +{ + height: 27px; +} + +/* + Toolbar Button +*/ + +.TB_Button_On, .TB_Button_Off, .TB_Button_On_Over, .TB_Button_Off_Over, .TB_Button_Disabled +{ + padding: 1px ; + margin:1px; + height: 21px; +} + +.TB_Button_On, .TB_Button_Off, .TB_Button_On_Over, .TB_Button_Off_Over, .TB_Button_Disabled +{ + border: #cec6b5 1px solid; +} + +.TB_Button_On +{ + border-color: #316ac5; + background-color: #c1d2ee; +} + +.TB_Button_On_Over, .TB_Button_Off_Over +{ + border: #316ac5 1px solid; + background-color: #dff1ff; +} + +.TB_Button_Off +{ + background: #efefef url(images/toolbar.buttonbg.gif) repeat-x; +} + +.TB_Button_Off, .TB_Combo_Off +{ + opacity: 0.70; /* Safari, Opera and Mozilla */ + filter: alpha(opacity=70); /* IE */ + /* -moz-opacity: 0.70; Mozilla (Old) */ +} + +.TB_Button_Disabled +{ + opacity: 0.30; /* Safari, Opera and Mozilla */ + filter: gray() alpha(opacity=30); /* IE */ +} + +.TB_Button_Padding +{ + visibility: hidden; + width: 3px; + height: 21px; +} + +.TB_Button_Image +{ + overflow: hidden; + width: 16px; + height: 16px; + margin: 3px; + margin-top: 4px; + margin-bottom: 2px; + background-repeat: no-repeat; +} + +/* For composed button ( icon + text, icon + arrow ), we must compensate the table */ +.TB_Button_On TABLE .TB_Button_Image, +.TB_Button_Off TABLE .TB_Button_Image, +.TB_Button_On_Over TABLE .TB_Button_Image, +.TB_Button_Off_Over TABLE .TB_Button_Image, +.TB_Button_Disabled TABLE .TB_Button_Image +{ + margin-top: 3px; +} + +.TB_Button_Image img +{ + position: relative; +} + +.TB_ConnectionLine +{ + background-color: #ffffff; + height: 1px; + margin-left: 1px; /* ltr */ + margin-right: 1px; /* rtl */ +} + +/* + Menu +*/ + +.MN_Menu +{ + border: 1px solid #8f8f73; + padding: 2px; + background-color: #f7f7f7; + cursor: default; +} + +.MN_Menu, .MN_Menu .MN_Label +{ + font-size: 11px; + font-family: 'Microsoft Sans Serif' , Tahoma, Arial, Verdana, Sans-Serif; +} + +.MN_Item_Padding +{ + visibility: hidden; + width: 3px; + height: 20px; +} + +.MN_Icon +{ + background-color: #dedede; + text-align: center; + height: 20px; +} + +.MN_Label +{ + padding-left: 3px; + padding-right: 3px; +} + +.MN_Separator +{ + height: 3px; +} + +.MN_Separator_Line +{ + border-top: #b9b99d 1px solid; +} + +.MN_Item .MN_Icon IMG +{ + filter: alpha(opacity=70); + opacity: 0.70; +} + +.MN_Item_Over +{ + color: #ffffff; + background-color: #8a857d; +} + +.MN_Item_Over .MN_Icon +{ + background-color: #6c6761; +} + +.MN_Item_Disabled IMG +{ + filter: gray() alpha(opacity=30); /* IE */ + opacity: 0.30; /* Safari, Opera and Mozilla */ +} + +.MN_Item_Disabled .MN_Label +{ + color: #b7b7b7; +} + +.MN_Arrow +{ + padding-right: 3px; + padding-left: 3px; +} + +.MN_ConnectionLine +{ + background-color: #ffffff; +} + +.Menu .TB_Button_On, .Menu .TB_Button_On_Over +{ + border: #8f8f73 1px solid; + background-color: #ffffff; +} + +/* + ### Panel Styles +*/ + +.FCK_Panel +{ + border: #8f8f73 1px solid; + padding: 2px; + background-color: #ffffff; +} + +.FCK_Panel, .FCK_Panel TD +{ + font-family: 'Microsoft Sans Serif' , Tahoma, Arial, Verdana, Sans-Serif; + font-size: 11px; +} + +/* + ### Special Combos +*/ + +.SC_Panel +{ + overflow: auto; + white-space: nowrap; + cursor: default; + border: 1px solid #8f8f73; + padding-left: 2px; + padding-right: 2px; +} + +.SC_Panel, .SC_Panel TD +{ + font-size: 11px; + font-family: 'Microsoft Sans Serif' , Tahoma, Arial, Verdana, Sans-Serif; +} + +.SC_Item, .SC_ItemSelected +{ + margin-top: 2px; + margin-bottom: 2px; + background-position: left center; + padding-left: 11px; + padding-right: 3px; + padding-top: 2px; + padding-bottom: 2px; + text-overflow: ellipsis; + overflow: hidden; + background-repeat: no-repeat; + border: #dddddd 1px solid; +} + +.SC_Item *, .SC_ItemSelected * +{ + margin-top: 0px; + margin-bottom: 0px; +} + +.SC_ItemSelected +{ + border: #9a9afb 1px solid; + background-image: url(images/toolbar.arrowright.gif); +} + +.SC_ItemOver +{ + border: #316ac5 1px solid; +} + +.SC_Field +{ + margin-top:1px ; + border: #b7b7a6 1px solid; + cursor: default; +} + +.SC_FieldCaption +{ + padding-top: 1px ; + overflow: visible; + padding-right: 5px; + padding-left: 5px; + opacity: 0.75; /* Safari, Opera and Mozilla */ + filter: alpha(opacity=70); /* IE */ /* -moz-opacity: 0.75; Mozilla (Old) */ + height: 23px; + background-color: #f7f7f7; +} + +.SC_FieldLabel +{ + white-space: nowrap; + padding: 2px; + width: 100%; + cursor: default; + background-color: #ffffff; + text-overflow: ellipsis; + overflow: hidden; +} + +.SC_FieldButton +{ + background-position: center center; + background-image: url(images/toolbar.buttonarrow.gif); + border-left: #b7b7a6 1px solid; + width: 14px; + background-repeat: no-repeat; +} + +.SC_FieldDisabled .SC_FieldButton, .SC_FieldDisabled .SC_FieldCaption, .SC_FieldDisabled .TB_ButtonType_Text +{ + opacity: 0.30; /* Safari, Opera and Mozilla */ + filter: gray() alpha(opacity=30); /* IE */ /* -moz-opacity: 0.30; Mozilla (Old) */ +} + +.SC_FieldOver +{ + border: #316ac5 1px solid; +} + +.SC_FieldOver .SC_FieldButton +{ + border-left: #316ac5 1px solid; +} + +/* + ### Color Selector Panel +*/ + +.ColorBoxBorder +{ + border: #808080 1px solid; + position: static; +} + +.ColorBox +{ + font-size: 1px; + width: 10px; + position: static; + height: 10px; +} + +.ColorDeselected, .ColorSelected +{ + cursor: default; +} + +.ColorDeselected +{ + border: #ffffff 1px solid; + padding: 2px; + float: left; +} + +.ColorSelected +{ + border: #316ac5 1px solid; + padding: 2px; + float: left; + background-color: #c1d2ee; +} Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/fck_strip.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/fck_strip.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/dialog.sides.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/dialog.sides.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/dialog.sides.png =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/dialog.sides.png ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/dialog.sides.rtl.png =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/dialog.sides.rtl.png ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/sprites.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/sprites.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/sprites.png =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/sprites.png ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/toolbar.arrowright.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/toolbar.arrowright.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/toolbar.buttonarrow.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/toolbar.buttonarrow.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/toolbar.buttonbg.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/toolbar.buttonbg.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/toolbar.collapse.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/toolbar.collapse.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/toolbar.end.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/toolbar.end.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/toolbar.expand.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/toolbar.expand.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/toolbar.separator.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/toolbar.separator.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/toolbar.start.gif =================================================================== (Binary files differ) Property changes on: trunk/lutinrss/src/main/webapp/fckeditor/editor/skins/silver/images/toolbar.start.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream
participants (1)
-
tchemit@users.labs.libre-entreprise.org